From c36d5e3280fbb8001a4c506f2c21227156cb3771 Mon Sep 17 00:00:00 2001 From: Ross Smyth Date: Sat, 17 Feb 2024 12:43:54 -0500 Subject: [PATCH 01/79] Add MatchKind member to the Match expr for pretty printing & fmt --- clippy_lints/src/redundant_else.rs | 2 +- clippy_lints/src/suspicious_operation_groupings.rs | 2 +- clippy_utils/src/ast_utils.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/redundant_else.rs b/clippy_lints/src/redundant_else.rs index fb434fb7450..3bdf13dbbea 100644 --- a/clippy_lints/src/redundant_else.rs +++ b/clippy_lints/src/redundant_else.rs @@ -105,7 +105,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor { fn visit_expr(&mut self, expr: &'ast Expr) { self.is_break = match expr.kind { ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) => true, - ExprKind::Match(_, ref arms) => arms.iter().all(|arm| + ExprKind::Match(_, ref arms, _) => arms.iter().all(|arm| arm.body.is_none() || arm.body.as_deref().is_some_and(|body| self.check_expr(body)) ), ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els), diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index 60e9d262e7e..ab1b3043f0c 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -552,7 +552,7 @@ fn ident_difference_expr_with_base_location( | (Gen(_, _, _), Gen(_, _, _)) | (Block(_, _), Block(_, _)) | (Closure(_), Closure(_)) - | (Match(_, _), Match(_, _)) + | (Match(_, _, _), Match(_, _, _)) | (Loop(_, _, _), Loop(_, _, _)) | (ForLoop { .. }, ForLoop { .. }) | (While(_, _, _), While(_, _, _)) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 3b3939da7b6..eb916a37f6e 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -198,7 +198,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { }, (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv), (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp), - (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm), + (Match(ls, la, lkind), Match(rs, ra, rkind)) => (lkind == rkind) && eq_expr(ls, rs) && over(la, ra, eq_arm), ( Closure(box ast::Closure { binder: lb, From cbbb0ae7d2c430327e77aec5ac1235014a09b793 Mon Sep 17 00:00:00 2001 From: Arthur Carcano Date: Fri, 5 Jan 2024 16:13:24 +0100 Subject: [PATCH 02/79] fix: allow-one-hash-in-raw-strings option of needless_raw_string_hashes was ignored Fixes: https://github.com/rust-lang/rust-clippy/issues/11481 changelog: Fix `allow-one-hash-in-raw-strings` option of [`needless_raw_string_hashes`] was ignored --- clippy_lints/src/raw_strings.rs | 6 ++- .../clippy.toml | 1 + .../needless_raw_string_hashes.fixed | 9 +++++ .../needless_raw_string_hashes.rs | 9 +++++ .../needless_raw_string_hashes.stderr | 40 +++++++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tests/ui-toml/needless_raw_string_hashes_one_allowed/clippy.toml create mode 100644 tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed create mode 100644 tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs create mode 100644 tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index ac29d27303c..7e71f48c6d9 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -108,7 +108,7 @@ impl EarlyLintPass for RawStrings { } } - let req = { + let mut req = { let mut following_quote = false; let mut req = 0; // `once` so a raw string ending in hashes is still checked @@ -136,7 +136,9 @@ impl EarlyLintPass for RawStrings { ControlFlow::Continue(num) | ControlFlow::Break(num) => num, } }; - + if self.allow_one_hash_in_raw_strings { + req = req.max(1); + } if req < max { span_lint_and_then( cx, diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/clippy.toml b/tests/ui-toml/needless_raw_string_hashes_one_allowed/clippy.toml new file mode 100644 index 00000000000..2f3d60be3a7 --- /dev/null +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/clippy.toml @@ -0,0 +1 @@ +allow-one-hash-in-raw-strings = true diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed new file mode 100644 index 00000000000..fd20bdff6e2 --- /dev/null +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed @@ -0,0 +1,9 @@ +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] + +fn main() { + r#"\aaa"#; + r#"\aaa"#; + r#"Hello "world"!"#; + r####" "### "## "# "####; +} diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs new file mode 100644 index 00000000000..3c6c2463700 --- /dev/null +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs @@ -0,0 +1,9 @@ +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] + +fn main() { + r#"\aaa"#; + r##"\aaa"##; + r##"Hello "world"!"##; + r######" "### "## "# "######; +} diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr new file mode 100644 index 00000000000..421ad66e4c9 --- /dev/null +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr @@ -0,0 +1,40 @@ +error: unnecessary hashes around raw string literal + --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:6:5 + | +LL | r##"\aaa"##; + | ^^^^^^^^^^^ + | + = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_raw_string_hashes)]` +help: remove one hash from both sides of the string literal + | +LL - r##"\aaa"##; +LL + r#"\aaa"#; + | + +error: unnecessary hashes around raw string literal + --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:7:5 + | +LL | r##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: remove one hash from both sides of the string literal + | +LL - r##"Hello "world"!"##; +LL + r#"Hello "world"!"#; + | + +error: unnecessary hashes around raw string literal + --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:8:5 + | +LL | r######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove 2 hashes from both sides of the string literal + | +LL - r######" "### "## "# "######; +LL + r####" "### "## "# "####; + | + +error: aborting due to 3 previous errors + From 4cbe42e00df7ebc951b6ba2152dc0eb27b449cb9 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Mon, 11 Mar 2024 23:32:35 +0100 Subject: [PATCH 03/79] RFC: Document Clippy's teams and team duties I want to be clear: this is just the initial draft outlining what, I think, should be the responsibilities of the team members. It has not yet been discussed with anyone else. --- book/src/SUMMARY.md | 1 + book/src/development/the_team.md | 112 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 book/src/development/the_team.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index a048fbbd8ac..be13fcbe260 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -32,3 +32,4 @@ - [Proposals](development/proposals/README.md) - [Roadmap 2021](development/proposals/roadmap-2021.md) - [Syntax Tree Patterns](development/proposals/syntax-tree-patterns.md) + - [The Team](development/the_team.md) diff --git a/book/src/development/the_team.md b/book/src/development/the_team.md new file mode 100644 index 00000000000..fa7da80de0c --- /dev/null +++ b/book/src/development/the_team.md @@ -0,0 +1,112 @@ +# The team + +Everyone who contributes to Clippy makes the project what it is. Collaboration +and discussions are the lifeblood of every open-source project. Clippy has a +very flat hierarchy. The teams mainly have additional access rights to the repo. + +This document outlines the onboarding process, as well as duties, and access +rights for members of a group. + +## Everyone + +Everyone, including you, is welcome to join discussions and contribute in other +ways, like PRs. + +You also have some triage rights, using `@rustbot` to add labels and claim +issues. See +[labeling with @rustbot](https://forge.rust-lang.org/triagebot/labeling.html) + +A rule for everyone should be to keep a healthy work-life balance. Take a break +when you need one. + +## Clippy-Contributors + +This is a group of regular contributors to Clippy to help with triaging. + +### Duties + +This team exists to make contributing easier for regular members. It doesn't +carry any duties that need to be done. However, we want to encourage members of +this group to help with triaging, which can include: + +1. **Labeling issues** + + For the `good-first-issue` label, it can still be good to use `@rustbot` to + subscribe to the issue and help interested parties, if they post questions + in the comments. + +2. **Closing duplicate or resolved issues** + + When you manually close and issue, it's often a good idea, to add a short + comment explaining the reason. + +3. **Ping people after two weeks of inactivity** + + We try to keep issue assignments and PRs fairly up-to-date. After two weeks, + it can be good to send a friendly ping to the delaying party. + + You might close a PR with the `I-inactive-closed` label if the author is + busy or wants to abandon it. If the reviewer is busy, the PR can be + reassigned to someone else. + + Checkout: https://triage.rust-lang.org/triage/rust-lang/rust-clippy to + monitor PRs. + +### Membership + +If you have been contributing to Clippy for some time, we'll probably ask you if +you want to join this team. Members of this team are also welcome to suggest +people who they think would make a great addition to this group. + +For this group, there is no direct onboarding process. You're welcome to just +continue what you've been doing. If you like, you can ask for someone to mentor +you, either in the Clippy stream on Zulip or privately via a PM. + +If you have been inactive in Clippy for over three months, we'll probably move +you to the alumni group. You're always welcome to come back. + +## The Clippy Team + +[The Clippy team](https://www.rust-lang.org/governance/teams/dev-tools#Clippy%20team) +is responsible for maintaining Clippy. + +### Duties + +1. **Respond to PRs in a timely manner** + + It's totally fine, if you don't have the time for reviews right now. + You can reassign the PR to a random member by commenting `r? clippy`. + +2. **Take a break when you need one.** + + You are valuable! Clippy wouldn't be what it is without you. So take a break + early and recharge some energy when you need to. + +3. **Sync Clippy with the rust-lang/rust repo** + + This should be done roughly every two weeks. This is usually done by our + king @flip1995. + +4. **Update the changelog** + + This needs to be done for every release, every six weeks. This is usually + done by @xFrednet. + +### Membership + +If you have been in the *Clippy-Contributors* team for some time, we'll probably +reach out and ask if you want to help with reviews and eventually join the +Clippy team. + +During the onboarding process, you'll have an active Clippy team member as a +mentor, who assigns PRs to you. They will shadow your reviews, meaning that +they'll keep an eye on your PRs, help you with any questions, and once you're +done, perform a full review. When everything looks good, they'll r+ the PR in +the name of both of you. + +When you've done several reviews and seem confident in the role, you'll be +invited to join the team officially, as long as you're still interested. This +onboarding phase typically takes a couple of weeks to a few months. + +If you have been inactive in Clippy for over three months, we'll probably move +you to the alumni group. You're always welcome to come back. From 79766577f2206306e342c8adae1c95f8ab0b9413 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Feb 2024 22:01:18 +0100 Subject: [PATCH 04/79] Add `missing_transmute_annotation` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + .../missing_transmute_annotations.rs | 53 +++++++++++++++++++ clippy_lints/src/transmute/mod.rs | 34 ++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 clippy_lints/src/transmute/missing_transmute_annotations.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c4651cee057..1ab3d528e05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5426,6 +5426,7 @@ Released 2018-09-13 [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods +[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_transmute_annotations [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5d1eadfc7a4..66b81555952 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -677,6 +677,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO, crate::transmute::CROSSPOINTER_TRANSMUTE_INFO, crate::transmute::EAGER_TRANSMUTE_INFO, + crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO, crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO, crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO, crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO, diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs new file mode 100644 index 00000000000..cbc52b6b801 --- /dev/null +++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -0,0 +1,53 @@ +use rustc_errors::Applicability; +use rustc_hir::{GenericArg, HirId, Node, Path, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::Ty; + +use clippy_utils::diagnostics::span_lint_and_sugg; + +use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + path: &Path<'tcx>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + expr_hir_id: HirId, +) -> bool { + let last = path.segments.last().unwrap(); + if in_external_macro(cx.tcx.sess, last.ident.span) { + // If it comes from a non-local macro, we ignore it. + return false; + } + let args = last.args; + let missing_generic = match args { + Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg { + GenericArg::Infer(_) => true, + GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer), + _ => false, + }), + _ => true, + }; + if !missing_generic { + return false; + } + // If it's being set as a local variable value... + if let Some((_, node)) = cx.tcx.hir().parent_iter(expr_hir_id).next() + && let Node::Local(local) = node + // ... which does have type annotations. + && local.ty.is_some() + { + return false; + } + span_lint_and_sugg( + cx, + MISSING_TRANSMUTE_ANNOTATIONS, + last.ident.span.with_hi(path.span.hi()), + "transmute used without annotations", + "consider adding missing annotations", + format!("{}::<{from_ty}, {to_ty}>", last.ident.as_str()), + Applicability::MaybeIncorrect, + ); + true +} diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index e47b14bf63b..a21c71e3048 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,5 +1,6 @@ mod crosspointer_transmute; mod eager_transmute; +mod missing_transmute_annotations; mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; @@ -520,6 +521,37 @@ declare_clippy_lint! { "eager evaluation of `transmute`" } +declare_clippy_lint! { + /// ### What it does + /// Checks if transmute calls have all generics specified. + /// + /// ### Why is this bad? + /// If not set, some unexpected output type could be retrieved instead of the expected one, + /// potentially leading to invalid code. + /// + /// This is particularly dangerous in case a seemingly innocent/unrelated change can cause type + /// inference to start inferring a different type. E.g. the transmute is the tail expression of + /// an `if` branch, and a different branches type changes, causing the transmute to silently + /// have a different type, instead of a proper error. + /// + /// ### Example + /// ```no_run + /// # unsafe { + /// let x: i32 = std::mem::transmute([1u16, 2u16]); + /// # } + /// ``` + /// Use instead: + /// ```no_run + /// # unsafe { + /// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + /// # } + /// ``` + #[clippy::version = "1.77.0"] + pub MISSING_TRANSMUTE_ANNOTATIONS, + suspicious, + "warns if a transmute call doesn't have all generics specified" +} + pub struct Transmute { msrv: Msrv, } @@ -542,6 +574,7 @@ impl_lint_pass!(Transmute => [ TRANSMUTING_NULL, TRANSMUTE_NULL_TO_FN, EAGER_TRANSMUTE, + MISSING_TRANSMUTE_ANNOTATIONS, ]); impl Transmute { #[must_use] @@ -579,6 +612,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | transmuting_null::check(cx, e, arg, to_ty) | transmute_null_to_fn::check(cx, e, arg, to_ty) | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) + | missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id) | 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) From f9a9c4bf3bc8c8675ef12c6f3580aea6a9df667c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sat, 9 Mar 2024 20:32:36 +0000 Subject: [PATCH 05/79] Note that type param is chosen by caller when suggesting return impl Trait --- tests/ui/builtin_type_shadow.stderr | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/builtin_type_shadow.stderr b/tests/ui/builtin_type_shadow.stderr index 1e15cdee772..033204af925 100644 --- a/tests/ui/builtin_type_shadow.stderr +++ b/tests/ui/builtin_type_shadow.stderr @@ -19,6 +19,7 @@ LL | 42 | = note: expected type parameter `u32` found type `{integer}` + = note: the caller chooses a type for `u32` which can be different from `i32` error: aborting due to 2 previous errors From b34afba5fbfd14cb9aa30bfc76fbfe700c5b4072 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Mon, 18 Mar 2024 14:31:00 +0100 Subject: [PATCH 06/79] Apply pretty review comments =^.^= --- book/src/development/the_team.md | 54 +++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/book/src/development/the_team.md b/book/src/development/the_team.md index fa7da80de0c..10341791cec 100644 --- a/book/src/development/the_team.md +++ b/book/src/development/the_team.md @@ -7,14 +7,16 @@ very flat hierarchy. The teams mainly have additional access rights to the repo. This document outlines the onboarding process, as well as duties, and access rights for members of a group. +All regular events mentioned in this chapter are tracked in the [calendar repository]. +The calendar file is also available for download: [clippy.ics] + ## Everyone Everyone, including you, is welcome to join discussions and contribute in other ways, like PRs. You also have some triage rights, using `@rustbot` to add labels and claim -issues. See -[labeling with @rustbot](https://forge.rust-lang.org/triagebot/labeling.html) +issues. See [labeling with @rustbot]. A rule for everyone should be to keep a healthy work-life balance. Take a break when you need one. @@ -37,7 +39,7 @@ this group to help with triaging, which can include: 2. **Closing duplicate or resolved issues** - When you manually close and issue, it's often a good idea, to add a short + When you manually close an issue, it's often a good idea, to add a short comment explaining the reason. 3. **Ping people after two weeks of inactivity** @@ -52,6 +54,9 @@ this group to help with triaging, which can include: Checkout: https://triage.rust-lang.org/triage/rust-lang/rust-clippy to monitor PRs. +While not part of their duties, contributors are encouraged to review PRs +and help on Zulip. The team always appreciates help! + ### Membership If you have been contributing to Clippy for some time, we'll probably ask you if @@ -77,36 +82,49 @@ is responsible for maintaining Clippy. It's totally fine, if you don't have the time for reviews right now. You can reassign the PR to a random member by commenting `r? clippy`. -2. **Take a break when you need one.** +2. **Take a break when you need one** You are valuable! Clippy wouldn't be what it is without you. So take a break early and recharge some energy when you need to. -3. **Sync Clippy with the rust-lang/rust repo** +3. **Be responsive on Zulip** - This should be done roughly every two weeks. This is usually done by our - king @flip1995. + This means in a reasonable time frame, so responding within one or two days + is totally fine. -4. **Update the changelog** + It's also good, if you answer threads on Zulip and take part in our Clippy + meetings, every two weeks. The meeting dates are tracked in the [calendar repository]. + + +4. **Sync Clippy with the rust-lang/rust repo** + + This is done every two weeks, usually by @flip1995. + +5. **Update the changelog** This needs to be done for every release, every six weeks. This is usually done by @xFrednet. ### Membership -If you have been in the *Clippy-Contributors* team for some time, we'll probably -reach out and ask if you want to help with reviews and eventually join the -Clippy team. +If you have been active for some time, we'll probably reach out and ask +if you want to help with reviews and eventually join the Clippy team. -During the onboarding process, you'll have an active Clippy team member as a -mentor, who assigns PRs to you. They will shadow your reviews, meaning that -they'll keep an eye on your PRs, help you with any questions, and once you're -done, perform a full review. When everything looks good, they'll r+ the PR in -the name of both of you. +During the onboarding process, you'll be assigned pull requests to review. +You'll also have an active team member as a mentor who'll stay in contact via +Zulip DMs to provide advice and feedback. If you have questions, you're always +welcome to ask, that is the best way to learn. Once you're done with the review, +you can ping your mentor for a full review and to r+ the PR in both of your names. -When you've done several reviews and seem confident in the role, you'll be -invited to join the team officially, as long as you're still interested. This +When your mentor is confident that you can handle reviews on your own, they'll +start an informal vote among the active team members to officially add you to +the team. This vote is usually accepted unanimously. Then you'll be added to +the team once you've confirmed that you're still interested in joining. The onboarding phase typically takes a couple of weeks to a few months. If you have been inactive in Clippy for over three months, we'll probably move you to the alumni group. You're always welcome to come back. + +[calendar repository]: https://github.com/rust-lang/calendar/blob/main/clippy.toml +[clippy.ics]: https://rust-lang.github.io/calendar/clippy.ics +[labeling with @rustbot]: https://forge.rust-lang.org/triagebot/labeling.html From 3930f8b45d4ed1a6a51caed7efbcb7894f454e73 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 18 Mar 2024 23:58:09 +0100 Subject: [PATCH 07/79] fix infinite loop when peeling unwrap method calls --- clippy_lints/src/casts/cast_sign_loss.rs | 5 +- tests/ui/cast.rs | 12 +- tests/ui/cast.stderr | 190 +++++++++++++---------- 3 files changed, 118 insertions(+), 89 deletions(-) diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 8fd95d9654c..90786175562 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -118,7 +118,7 @@ enum Sign { Uncertain, } -fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into>>) -> Sign { +fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: impl Into>>) -> Sign { // Try evaluate this expr first to see if it's positive if let Some(val) = get_const_signed_int_eval(cx, expr, ty) { return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative }; @@ -134,11 +134,12 @@ fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into usize { + let bar: Result, u32> = Ok(Some(10)); + bar.unwrap().unwrap() as usize +} diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index dd5d339b81b..3736e8aee0a 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:17:5 + --> tests/ui/cast.rs:22:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -8,37 +8,37 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:21:5 + --> tests/ui/cast.rs:26:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:23:5 + --> tests/ui/cast.rs:28:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:26:5 + --> tests/ui/cast.rs:31:5 | LL | x2 as f32; | ^^^^^^^^^ error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:29:5 + --> tests/ui/cast.rs:34:5 | LL | x3 as f32; | ^^^^^^^^^ error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:31:5 + --> tests/ui/cast.rs:36:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:34:5 + --> tests/ui/cast.rs:39:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | 1f32 as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:36:5 + --> tests/ui/cast.rs:41:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | 1f32 as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:36:5 + --> tests/ui/cast.rs:41:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | 1f32 as u32; = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]` error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:40:5 + --> tests/ui/cast.rs:45:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | 1f64 as f32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:42:5 + --> tests/ui/cast.rs:47:5 | LL | 1i32 as i8; | ^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | i8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `i32` to `u8` may truncate the value - --> tests/ui/cast.rs:44:5 + --> tests/ui/cast.rs:49:5 | LL | 1i32 as u8; | ^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | u8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `f64` to `isize` may truncate the value - --> tests/ui/cast.rs:46:5 + --> tests/ui/cast.rs:51:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | 1f64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may truncate the value - --> tests/ui/cast.rs:48:5 + --> tests/ui/cast.rs:53:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ @@ -113,13 +113,13 @@ LL | 1f64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:48:5 + --> tests/ui/cast.rs:53:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting `u32` to `u16` may truncate the value - --> tests/ui/cast.rs:51:5 + --> tests/ui/cast.rs:56:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | u16::try_from(1f32 as u32); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:51:5 + --> tests/ui/cast.rs:56:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ @@ -139,13 +139,13 @@ LL | 1f32 as u32 as u16; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:51:5 + --> tests/ui/cast.rs:56:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:56:22 + --> tests/ui/cast.rs:61:22 | LL | let _x: i8 = 1i32 as _; | ^^^^^^^^^ @@ -157,7 +157,7 @@ LL | let _x: i8 = 1i32.try_into(); | ~~~~~~~~~~~~~~~ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:58:9 + --> tests/ui/cast.rs:63:9 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | 1f32 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `i32` may truncate the value - --> tests/ui/cast.rs:60:9 + --> tests/ui/cast.rs:65:9 | LL | 1f64 as i32; | ^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | 1f64 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may truncate the value - --> tests/ui/cast.rs:62:9 + --> tests/ui/cast.rs:67:9 | LL | 1f32 as u8; | ^^^^^^^^^^ @@ -181,13 +181,13 @@ LL | 1f32 as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:62:9 + --> tests/ui/cast.rs:67:9 | LL | 1f32 as u8; | ^^^^^^^^^^ error: casting `u8` to `i8` may wrap around the value - --> tests/ui/cast.rs:67:5 + --> tests/ui/cast.rs:72:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -196,31 +196,31 @@ LL | 1u8 as i8; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `u16` to `i16` may wrap around the value - --> tests/ui/cast.rs:70:5 + --> tests/ui/cast.rs:75:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> tests/ui/cast.rs:72:5 + --> tests/ui/cast.rs:77:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> tests/ui/cast.rs:74:5 + --> tests/ui/cast.rs:79:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> tests/ui/cast.rs:76:5 + --> tests/ui/cast.rs:81:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `usize` to `i8` may truncate the value - --> tests/ui/cast.rs:79:5 + --> tests/ui/cast.rs:84:5 | LL | 1usize as i8; | ^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | i8::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may truncate the value - --> tests/ui/cast.rs:82:5 + --> tests/ui/cast.rs:87:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -244,7 +244,7 @@ LL | i16::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:82:5 + --> tests/ui/cast.rs:87:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | 1usize as i16; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:87:5 + --> tests/ui/cast.rs:92:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -265,19 +265,19 @@ LL | i32::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:87:5 + --> tests/ui/cast.rs:92:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:91:5 + --> tests/ui/cast.rs:96:5 | LL | 1usize as i64; | ^^^^^^^^^^^^^ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:96:5 + --> tests/ui/cast.rs:101:5 | LL | 1u16 as isize; | ^^^^^^^^^^^^^ @@ -286,13 +286,13 @@ LL | 1u16 as isize; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:100:5 + --> tests/ui/cast.rs:105:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:103:5 + --> tests/ui/cast.rs:108:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -304,55 +304,55 @@ LL | isize::try_from(1u64); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:103:5 + --> tests/ui/cast.rs:108:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:108:5 + --> tests/ui/cast.rs:113:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:111:5 + --> tests/ui/cast.rs:116:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i8` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:122:5 + --> tests/ui/cast.rs:127:5 | LL | (i8::MIN).abs() as u8; | ^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:126:5 + --> tests/ui/cast.rs:131:5 | LL | (-1i64).abs() as u64; | ^^^^^^^^^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:127:5 + --> tests/ui/cast.rs:132:5 | LL | (-1isize).abs() as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:134:5 + --> tests/ui/cast.rs:139:5 | LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:149:5 + --> tests/ui/cast.rs:154:5 | LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> tests/ui/cast.rs:200:5 + --> tests/ui/cast.rs:205:5 | LL | (-99999999999i64).min(1) as i8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -364,7 +364,7 @@ LL | i8::try_from((-99999999999i64).min(1)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:214:5 + --> tests/ui/cast.rs:219:5 | LL | 999999u64.clamp(0, 256) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,7 +376,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E2` to `u8` may truncate the value - --> tests/ui/cast.rs:237:21 + --> tests/ui/cast.rs:242:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -388,7 +388,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> tests/ui/cast.rs:239:21 + --> tests/ui/cast.rs:244:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -397,7 +397,7 @@ LL | let _ = Self::B as u8; = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]` error: casting `main::E5` to `i8` may truncate the value - --> tests/ui/cast.rs:281:21 + --> tests/ui/cast.rs:286:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -409,13 +409,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> tests/ui/cast.rs:283:21 + --> tests/ui/cast.rs:288:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> tests/ui/cast.rs:300:21 + --> tests/ui/cast.rs:305:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -427,7 +427,7 @@ LL | let _ = i16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:319:21 + --> tests/ui/cast.rs:324:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -439,7 +439,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> tests/ui/cast.rs:366:21 + --> tests/ui/cast.rs:371:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -451,7 +451,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:377:13 + --> tests/ui/cast.rs:382:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -463,7 +463,7 @@ LL | let c = u8::try_from(q >> 16); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:381:13 + --> tests/ui/cast.rs:386:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -475,85 +475,85 @@ LL | let c = u8::try_from(q / 1000); | ~~~~~~~~~~~~~~~~~~~~~~ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:393:9 + --> tests/ui/cast.rs:398:9 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:398:32 + --> tests/ui/cast.rs:403:32 | LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 }; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:400:5 + --> tests/ui/cast.rs:405:5 | LL | (2_i32).checked_pow(3).unwrap() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:401:5 + --> tests/ui/cast.rs:406:5 | LL | (-2_i32).pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:406:5 + --> tests/ui/cast.rs:411:5 | LL | (-5_i32 % 2) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:408:5 + --> tests/ui/cast.rs:413:5 | LL | (-5_i32 % -2) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:411:5 + --> tests/ui/cast.rs:416:5 | LL | (-2_i32 >> 1) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:415:5 + --> tests/ui/cast.rs:420:5 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:416:5 + --> tests/ui/cast.rs:421:5 | LL | (x * x * x) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:420:5 + --> tests/ui/cast.rs:425:5 | LL | (y * y * y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:422:5 + --> tests/ui/cast.rs:427:5 | LL | (y * y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:423:5 + --> tests/ui/cast.rs:428:5 | LL | (y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:425:5 + --> tests/ui/cast.rs:430:5 | LL | (y / y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `/` - --> tests/ui/cast.rs:425:6 + --> tests/ui/cast.rs:430:6 | LL | (y / y * y * -2) as u16; | ^^^^^ @@ -561,94 +561,112 @@ LL | (y / y * y * -2) as u16; = note: `#[deny(clippy::eq_op)]` on by default error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:428:5 + --> tests/ui/cast.rs:433:5 | LL | (y + y + y + -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:430:5 + --> tests/ui/cast.rs:435:5 | LL | (y + y + y + 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:434:5 + --> tests/ui/cast.rs:439:5 | LL | (z + -2) as u16; | ^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:436:5 + --> tests/ui/cast.rs:441:5 | LL | (z + z + 2) as u16; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:439:9 + --> tests/ui/cast.rs:444:9 | LL | (a * a * b * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:440:9 + --> tests/ui/cast.rs:445:9 | LL | (a * b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:442:9 + --> tests/ui/cast.rs:447:9 | LL | (a * -b * c) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:444:9 + --> tests/ui/cast.rs:449:9 | LL | (a * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:445:9 + --> tests/ui/cast.rs:450:9 | LL | (a * -2) as u32; | ^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:447:9 + --> tests/ui/cast.rs:452:9 | LL | (a * b * c * -2) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:449:9 + --> tests/ui/cast.rs:454:9 | LL | (a / b) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:450:9 + --> tests/ui/cast.rs:455:9 | LL | (a / b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:452:9 + --> tests/ui/cast.rs:457:9 | LL | (a / b + b * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:454:9 + --> tests/ui/cast.rs:459:9 | LL | a.saturating_pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:456:9 + --> tests/ui/cast.rs:461:9 | LL | (a.abs() * b.pow(2) / c.abs()) as u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 85 previous errors +error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers + --> tests/ui/cast.rs:468:5 + | +LL | bar.unwrap().unwrap() as usize + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | usize::try_from(bar.unwrap().unwrap()) + | + +error: casting `i64` to `usize` may lose the sign of the value + --> tests/ui/cast.rs:468:5 + | +LL | bar.unwrap().unwrap() as usize + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 87 previous errors From 54d1260174c4c587fe56323459332f667978e8b4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Mar 2024 16:47:11 +0100 Subject: [PATCH 08/79] Rename `hir::Let` into `hir::LetExpr` --- clippy_lints/src/pattern_type_mismatch.rs | 4 ++-- clippy_lints/src/shadow.rs | 4 ++-- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_utils/src/higher.rs | 4 ++-- clippy_utils/src/hir_utils.rs | 4 ++-- clippy_utils/src/visitors.rs | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index fbca4329342..127801de7de 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, Let, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind}; +use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; @@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { } } } - if let ExprKind::Let(Let { pat, .. }) = expr.kind { + if let ExprKind::Let(LetExpr { pat, .. }) = expr.kind { apply_lint(cx, pat, DerefPossible::Possible); } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c74364d89d6..df7bd4c8d1d 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::hir_id::ItemLocalId; -use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, Let, Node, Pat, PatKind, QPath, UnOp}; +use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, LetExpr, Node, Pat, PatKind, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol}; @@ -238,7 +238,7 @@ fn find_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<' let init = match node { Node::Arm(_) | Node::Pat(_) => continue, Node::Expr(expr) => match expr.kind { - ExprKind::Match(e, _, _) | ExprKind::Let(&Let { init: e, .. }) => Some(e), + ExprKind::Match(e, _, _) | ExprKind::Let(&LetExpr { init: e, .. }) => Some(e), _ => None, }, Node::Local(local) => local.init, diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index eb64dd633f6..1497d883dfc 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -131,7 +131,7 @@ fn non_consuming_ok_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool { fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { match expr.kind { hir::ExprKind::If(cond, _, _) - if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind + if let ExprKind::Let(hir::LetExpr { pat, init, .. }) = cond.kind && is_ok_wild_or_dotdot_pattern(cx, pat) && let Some(op) = should_lint(cx, init) => { diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index ba682813dad..8ce19998a08 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -102,7 +102,7 @@ impl<'hir> IfLet<'hir> { if let ExprKind::If( Expr { kind: - ExprKind::Let(&hir::Let { + ExprKind::Let(&hir::LetExpr { pat: let_pat, init: let_expr, span: let_span, @@ -379,7 +379,7 @@ impl<'hir> WhileLet<'hir> { ExprKind::If( Expr { kind: - ExprKind::Let(&hir::Let { + ExprKind::Let(&hir::LetExpr { pat: let_pat, init: let_expr, span: let_span, diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 106d1d0d77f..162bf24d85d 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -8,7 +8,7 @@ use rustc_hir::def::Res; use rustc_hir::MatchSource::TryDesugar; use rustc_hir::{ ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, - GenericArgs, HirId, HirIdMap, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, + GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lexer::{tokenize, TokenKind}; @@ -837,7 +837,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } }, - ExprKind::Let(Let { pat, init, ty, .. }) => { + ExprKind::Let(LetExpr { pat, init, ty, .. }) => { self.hash_expr(init); if let Some(ty) = ty { self.hash_ty(ty); diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index ebc38e531fe..0a05ac029ea 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; use rustc_hir::{ - AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Let, Pat, QPath, + AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, Stmt, UnOp, UnsafeSource, Unsafety, }; use rustc_lint::LateContext; @@ -624,7 +624,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( | ExprKind::Field(e, _) | ExprKind::Unary(UnOp::Deref, e) | ExprKind::Match(e, ..) - | ExprKind::Let(&Let { init: e, .. }) => { + | ExprKind::Let(&LetExpr { init: e, .. }) => { helper(typeck, false, e, f)?; }, ExprKind::Block(&Block { expr: Some(e), .. }, _) | ExprKind::Cast(e, _) | ExprKind::Unary(_, e) => { From 1dbabc1767d080066ddf6f16f3aad01e46257d9c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 20 Mar 2024 12:52:54 -0400 Subject: [PATCH 09/79] Bless test fallout (duplicate diagnostics) --- clippy_lints/src/future_not_send.rs | 2 +- clippy_utils/src/ty.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index 9fb59a320d4..18f4e51ebd6 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() { - let preds = cx.tcx.explicit_item_bounds(def_id); + let preds = cx.tcx.explicit_item_super_predicates(def_id); let mut is_future = false; for (p, _span) in preds.iter_instantiated_copied(cx.tcx, args) { if let Some(trait_pred) = p.as_trait_clause() { diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 6e011a28bb7..801452e444c 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -96,7 +96,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { + for (predicate, _span) in cx.tcx.explicit_item_super_predicates(def_id).instantiate_identity_iter_copied() { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. @@ -328,7 +328,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { + for (predicate, _) in cx.tcx.explicit_item_super_predicates(def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; @@ -729,7 +729,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).iter_instantiated(cx.tcx, args), + cx.tcx.item_super_predicates(def_id).iter_instantiated(cx.tcx, args), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -807,7 +807,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option for (pred, _) in cx .tcx - .explicit_item_bounds(ty.def_id) + .explicit_item_super_predicates(ty.def_id) .iter_instantiated_copied(cx.tcx, ty.args) { match pred.kind().skip_binder() { From 9022122b8b33e5a1fb9c07fcb3984005ef1a63e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Mar 2024 22:50:32 +0000 Subject: [PATCH 10/79] Replace closures with `_` when suggesting fully qualified path for method call ``` error[E0283]: type annotations needed --> $DIR/into-inference-needs-type.rs:12:10 | LL | .into()?; | ^^^^ | = note: cannot satisfy `_: From<...>` = note: required for `FilterMap<...>` to implement `Into<_>` help: try using a fully qualified path to specify the expected types | LL ~ let list = , _>, _> as Into>::into(vec LL | .iter() LL | .map(|s| s.strip_prefix("t")) LL ~ .filter_map(Option::Some))?; | ``` Fix #122569. --- clippy_lints/src/box_default.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index 779ae03c464..66206d1a059 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -70,7 +70,9 @@ impl LateLintPass<'_> for BoxDefault { "try", if is_plain_default(cx, arg_path) || given_type(cx, expr) { "Box::default()".into() - } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { + } else if let Some(arg_ty) = + cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true, None) + { // Check if we can copy from the source expression in the replacement. // We need the call to have no argument (see `explicit_default_type`). if inner_call_args.is_empty() From 87b93520a82719c1f2f3aba35dd432ededbcff99 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 21 Mar 2024 15:41:12 +0000 Subject: [PATCH 11/79] Correct version for incompatible_msrv Unsure what happened here Probably what caused https://github.com/rust-lang/blog.rust-lang.org/issues/1277 --- clippy_lints/src/incompatible_msrv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index cd000fcd184..23bcd19ddd3 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -33,7 +33,7 @@ declare_clippy_lint! { /// /// To fix this problem, either increase your MSRV or use another item /// available in your current MSRV. - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub INCOMPATIBLE_MSRV, suspicious, "ensures that all items used in the crate are available for the current MSRV" From bc0965e2ff3a44850983fddd5ade495711adbd8d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 20 Mar 2024 16:53:50 -0400 Subject: [PATCH 12/79] Implement macro-based deref!() syntax for deref patterns Stop using `box PAT` syntax for deref patterns, as it's misleading and also causes their semantics being tangled up. --- clippy_lints/src/equatable_if_let.rs | 2 +- clippy_lints/src/matches/match_same_arms.rs | 2 +- clippy_lints/src/unnested_or_patterns.rs | 2 ++ clippy_lints/src/utils/author.rs | 5 +++++ clippy_utils/src/hir_utils.rs | 1 + clippy_utils/src/lib.rs | 2 +- 6 files changed, 11 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 4e728d61b85..37442bf3e28 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -55,7 +55,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Err(_) => false, PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), - PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), + PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) => unary_pattern(x), PatKind::Path(_) | PatKind::Lit(_) => true, } } diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index c7c453b7f6e..cd61e733694 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -243,7 +243,7 @@ impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { PatKind::Wild | PatKind::Binding(.., None) => Self::Wild, - PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => { + PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Deref(pat) | PatKind::Ref(pat, _) => { Self::from_pat(cx, arena, pat) }, PatKind::Never => Self::Never, diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 7246214f9bf..d4dd31e1178 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -242,6 +242,8 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us |k| matches!(k, Box(_)), |k| always_pat!(k, Box(p) => p), ), + // FIXME(deref_patterns): Should we merge patterns here? + Deref(_) => false, // Transform `&mut x | ... | &mut y` into `&mut (x | y)`. Ref(target, Mutability::Mut) => extend_with_matching( target, start, alternatives, diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 187bfda129c..5319915b2ea 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -689,6 +689,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Box({pat})"); self.pat(pat); }, + PatKind::Deref(pat) => { + bind!(self, pat); + kind!("Deref({pat})"); + self.pat(pat); + }, PatKind::Ref(pat, muta) => { bind!(self, pat); kind!("Ref({pat}, Mutability::{muta:?})"); diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 162bf24d85d..7a4eba9790e 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -955,6 +955,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, PatKind::Box(pat) => self.hash_pat(pat), + PatKind::Deref(pat) => self.hash_pat(pat), PatKind::Lit(expr) => self.hash_expr(expr), PatKind::Or(pats) => { for pat in pats { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index a38db0ebec0..b4cc747e0e6 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1678,7 +1678,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { match pat.kind { PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), - PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), + PatKind::Box(pat) | PatKind::Deref(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Or(pats) => { // TODO: should be the honest check, that pats is exhaustive set From 15da6e735a43cd3b49847d4d484d6ec75b33dad6 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Thu, 21 Mar 2024 14:06:45 -0700 Subject: [PATCH 13/79] Mention `size_hint()` effect in `flat_map_option` lint documentation. --- clippy_lints/src/methods/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b6c474212cd..e3137a868a0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -231,8 +231,12 @@ declare_clippy_lint! { /// used instead. /// /// ### Why is this bad? - /// When applicable, `filter_map()` is more clear since it shows that - /// `Option` is used to produce 0 or 1 items. + /// `filter_map()` is known to always produce 0 or 1 output items per input item, + /// rather than however many the inner iterator type produces. + /// Therefore, it maintains the upper bound in `Iterator::size_hint()`, + /// and communicates to the reader that the input items are not being expanded into + /// multiple output items without their having to notice that the mapping function + /// returns an `Option`. /// /// ### Example /// ```no_run From 0e62b184353c0c76b5e908746c0dc99dea05f7a5 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 21 Mar 2024 22:20:40 +0100 Subject: [PATCH 14/79] Merge commit '9d6f41691ed9dbfaec2a2df2661c42451f2fe0d3' into clippy-subtree-update --- .github/workflows/clippy.yml | 10 +- .github/workflows/clippy_bors.yml | 25 +-- CHANGELOG.md | 63 +++++- Cargo.toml | 12 +- book/src/development/macro_expansions.md | 4 +- book/src/lint_configuration.md | 1 + clippy.toml | 13 +- clippy_config/Cargo.toml | 2 +- clippy_config/src/conf.rs | 2 +- clippy_config/src/msrvs.rs | 1 + clippy_dev/src/update_lints.rs | 2 + clippy_lints/Cargo.toml | 2 +- clippy_lints/src/assigning_clones.rs | 29 ++- .../src/attrs/duplicated_attributes.rs | 64 +++++++ clippy_lints/src/attrs/mod.rs | 35 +++- clippy_lints/src/casts/cast_lossless.rs | 43 +++-- clippy_lints/src/casts/mod.rs | 2 +- clippy_lints/src/dbg_macro.rs | 51 +++-- clippy_lints/src/declared_lints.rs | 5 + clippy_lints/src/doc/markdown.rs | 17 +- clippy_lints/src/doc/mod.rs | 24 ++- clippy_lints/src/else_if_without_else.rs | 26 ++- clippy_lints/src/entry.rs | 5 +- clippy_lints/src/functions/mod.rs | 2 +- .../src/integer_division_remainder_used.rs | 50 +++++ clippy_lints/src/let_if_seq.rs | 5 +- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/loops/needless_range_loop.rs | 2 +- clippy_lints/src/loops/never_loop.rs | 4 +- .../src/loops/unused_enumerate_index.rs | 81 +++----- .../src/loops/while_immutable_condition.rs | 2 +- clippy_lints/src/manual_retain.rs | 11 +- clippy_lints/src/manual_unwrap_or_default.rs | 181 ++++++++++++++++++ clippy_lints/src/matches/single_match.rs | 31 +-- clippy_lints/src/methods/expect_fun_call.rs | 2 +- clippy_lints/src/methods/is_empty.rs | 49 +++++ clippy_lints/src/methods/iter_nth.rs | 49 ++--- clippy_lints/src/methods/map_clone.rs | 11 +- clippy_lints/src/methods/mod.rs | 143 +++++++++----- clippy_lints/src/methods/no_effect_replace.rs | 1 + .../src/methods/unused_enumerate_index.rs | 135 +++++++++++++ clippy_lints/src/missing_doc.rs | 64 ++++++- .../src/multiple_unsafe_ops_per_block.rs | 17 +- clippy_lints/src/mut_mut.rs | 70 ++++--- clippy_lints/src/non_copy_const.rs | 11 +- clippy_lints/src/read_zero_byte_vec.rs | 60 +++--- clippy_lints/src/redundant_closure_call.rs | 5 +- clippy_lints/src/returns.rs | 35 ++-- clippy_lints/src/std_instead_of_core.rs | 2 + ...ead_local_initializer_can_be_made_const.rs | 2 +- clippy_lints/src/transmute/mod.rs | 2 +- clippy_lints/src/types/mod.rs | 4 + clippy_lints/src/unconditional_recursion.rs | 56 ++++-- clippy_lints/src/unused_io_amount.rs | 16 +- clippy_lints/src/unused_peekable.rs | 10 +- clippy_lints/src/use_self.rs | 53 ++++- .../internal_lints/metadata_collector.rs | 2 +- .../internal_lints/unnecessary_def_path.rs | 2 +- clippy_lints/src/wildcard_imports.rs | 2 +- clippy_lints/src/zero_repeat_side_effects.rs | 154 +++++++++++++++ clippy_utils/Cargo.toml | 2 +- clippy_utils/src/consts.rs | 107 ++++++++++- clippy_utils/src/diagnostics.rs | 118 ++++++++++++ clippy_utils/src/lib.rs | 19 +- clippy_utils/src/paths.rs | 2 + declare_clippy_lint/Cargo.toml | 2 +- rust-toolchain | 2 +- tests/ui-internal/disallow_span_lint.stderr | 3 + tests/ui-toml/dbg_macro/dbg_macro.fixed | 38 ++++ tests/ui-toml/dbg_macro/dbg_macro.rs | 5 +- tests/ui-toml/dbg_macro/dbg_macro.stderr | 34 +--- tests/ui/allow_attributes_without_reason.rs | 2 +- .../ui/allow_attributes_without_reason.stderr | 4 +- tests/ui/assigning_clones.fixed | 13 ++ tests/ui/assigning_clones.rs | 13 ++ tests/ui/assigning_clones.stderr | 32 +++- tests/ui/auxiliary/proc_macro_attr.rs | 43 ++++- tests/ui/await_holding_lock.rs | 1 + tests/ui/await_holding_lock.stderr | 52 ++--- tests/ui/bool_assert_comparison.fixed | 2 +- tests/ui/bool_assert_comparison.rs | 2 +- tests/ui/cast_lossless_bool.fixed | 4 + tests/ui/cast_lossless_bool.rs | 4 + tests/ui/cast_lossless_bool.stderr | 36 ++-- tests/ui/cast_lossless_float.fixed | 5 + tests/ui/cast_lossless_float.rs | 5 + tests/ui/cast_lossless_float.stderr | 36 ++-- tests/ui/cast_lossless_integer.fixed | 10 + tests/ui/cast_lossless_integer.rs | 10 + tests/ui/cast_lossless_integer.stderr | 50 ++--- tests/ui/const_is_empty.rs | 174 +++++++++++++++++ tests/ui/const_is_empty.stderr | 161 ++++++++++++++++ tests/ui/crashes/ice-12491.fixed | 7 + tests/ui/crashes/ice-12491.rs | 8 + tests/ui/crashes/ice-12491.stderr | 19 ++ tests/ui/dbg_macro/dbg_macro.fixed | 111 +++++++++++ tests/ui/dbg_macro/dbg_macro.rs | 20 +- tests/ui/dbg_macro/dbg_macro.stderr | 108 ++++++----- tests/ui/dbg_macro/dbg_macro_unfixable.rs | 12 ++ tests/ui/dbg_macro/dbg_macro_unfixable.stderr | 71 +++++++ tests/ui/doc/issue_10262.fixed | 12 ++ tests/ui/doc/issue_10262.rs | 12 ++ tests/ui/doc/issue_10262.stderr | 15 ++ tests/ui/duplicated_attributes.rs | 17 ++ tests/ui/duplicated_attributes.stderr | 123 ++++++++++++ tests/ui/else_if_without_else.rs | 68 ++++++- tests/ui/else_if_without_else.stderr | 30 ++- tests/ui/empty_docs.rs | 17 ++ tests/ui/empty_docs.stderr | 18 +- tests/ui/empty_line_after_doc_comments.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/entry.fixed | 10 + tests/ui/entry.rs | 10 + tests/ui/entry.stderr | 23 ++- tests/ui/integer_division_remainder_used.rs | 41 ++++ .../ui/integer_division_remainder_used.stderr | 59 ++++++ tests/ui/iter_nth.fixed | 60 ++++++ tests/ui/iter_nth.rs | 3 + tests/ui/iter_nth.stderr | 48 ++++- tests/ui/len_zero.fixed | 8 +- tests/ui/len_zero.rs | 8 +- tests/ui/len_zero.stderr | 46 ++--- tests/ui/let_if_seq.rs | 11 ++ tests/ui/let_if_seq.stderr | 8 +- tests/ui/manual_let_else.rs | 3 +- tests/ui/manual_let_else.stderr | 62 +++--- tests/ui/manual_retain.fixed | 2 - tests/ui/manual_retain.rs | 2 - tests/ui/manual_retain.stderr | 76 ++++---- tests/ui/manual_unwrap_or.fixed | 7 +- tests/ui/manual_unwrap_or.rs | 7 +- tests/ui/manual_unwrap_or.stderr | 28 +-- tests/ui/manual_unwrap_or_default.fixed | 19 ++ tests/ui/manual_unwrap_or_default.rs | 40 ++++ tests/ui/manual_unwrap_or_default.stderr | 56 ++++++ tests/ui/map_clone.fixed | 16 +- tests/ui/map_clone.rs | 16 +- tests/ui/map_clone.stderr | 30 +-- tests/ui/match_result_ok.fixed | 2 +- tests/ui/match_result_ok.rs | 2 +- tests/ui/missing_doc.rs | 12 ++ tests/ui/missing_doc.stderr | 26 +-- tests/ui/mixed_attributes_style.rs | 1 + tests/ui/mixed_attributes_style.stderr | 6 +- tests/ui/mut_mut.rs | 6 +- tests/ui/mut_mut.stderr | 18 +- tests/ui/needless_bitwise_bool.fixed | 1 + tests/ui/needless_bitwise_bool.rs | 1 + tests/ui/needless_bitwise_bool.stderr | 2 +- tests/ui/needless_return.fixed | 7 + tests/ui/needless_return.rs | 7 + tests/ui/no_effect_replace.rs | 2 - tests/ui/no_effect_replace.stderr | 16 +- tests/ui/option_if_let_else.fixed | 3 +- tests/ui/option_if_let_else.rs | 3 +- tests/ui/option_if_let_else.stderr | 50 ++--- tests/ui/option_option.rs | 4 +- tests/ui/option_option.stderr | 26 +-- tests/ui/read_zero_byte_vec.rs | 6 + tests/ui/redundant_as_str.fixed | 1 + tests/ui/redundant_as_str.rs | 1 + tests/ui/redundant_as_str.stderr | 4 +- tests/ui/rename.fixed | 1 + tests/ui/rename.rs | 1 + tests/ui/rename.stderr | 116 +++++------ tests/ui/single_match.fixed | 5 +- tests/ui/single_match.rs | 5 +- tests/ui/single_match.stderr | 36 ++-- tests/ui/single_match_else.fixed | 1 - tests/ui/single_match_else.rs | 1 - tests/ui/single_match_else.stderr | 18 +- tests/ui/std_instead_of_core.fixed | 2 +- tests/ui/std_instead_of_core.stderr | 8 +- tests/ui/unconditional_recursion.rs | 50 ++++- tests/ui/unconditional_recursion.stderr | 136 ++++++------- tests/ui/unused_enumerate_index.fixed | 50 ++++- tests/ui/unused_enumerate_index.rs | 50 ++++- tests/ui/unused_enumerate_index.stderr | 78 +++++++- tests/ui/unused_io_amount.rs | 5 + tests/ui/unused_peekable.rs | 6 + tests/ui/use_self.fixed | 18 +- tests/ui/use_self.rs | 16 +- tests/ui/use_self.stderr | 92 ++++----- tests/ui/zero_repeat_side_effects.fixed | 60 ++++++ tests/ui/zero_repeat_side_effects.rs | 60 ++++++ tests/ui/zero_repeat_side_effects.stderr | 77 ++++++++ triagebot.toml | 2 +- 187 files changed, 4185 insertions(+), 1050 deletions(-) create mode 100644 clippy_lints/src/attrs/duplicated_attributes.rs create mode 100644 clippy_lints/src/integer_division_remainder_used.rs create mode 100644 clippy_lints/src/manual_unwrap_or_default.rs create mode 100644 clippy_lints/src/methods/is_empty.rs create mode 100644 clippy_lints/src/methods/unused_enumerate_index.rs create mode 100644 clippy_lints/src/zero_repeat_side_effects.rs create mode 100644 tests/ui-toml/dbg_macro/dbg_macro.fixed create mode 100644 tests/ui/const_is_empty.rs create mode 100644 tests/ui/const_is_empty.stderr create mode 100644 tests/ui/crashes/ice-12491.fixed create mode 100644 tests/ui/crashes/ice-12491.rs create mode 100644 tests/ui/crashes/ice-12491.stderr create mode 100644 tests/ui/dbg_macro/dbg_macro.fixed create mode 100644 tests/ui/dbg_macro/dbg_macro_unfixable.rs create mode 100644 tests/ui/dbg_macro/dbg_macro_unfixable.stderr create mode 100644 tests/ui/doc/issue_10262.fixed create mode 100644 tests/ui/doc/issue_10262.rs create mode 100644 tests/ui/doc/issue_10262.stderr create mode 100644 tests/ui/duplicated_attributes.rs create mode 100644 tests/ui/duplicated_attributes.stderr create mode 100644 tests/ui/integer_division_remainder_used.rs create mode 100644 tests/ui/integer_division_remainder_used.stderr create mode 100644 tests/ui/iter_nth.fixed create mode 100644 tests/ui/manual_unwrap_or_default.fixed create mode 100644 tests/ui/manual_unwrap_or_default.rs create mode 100644 tests/ui/manual_unwrap_or_default.stderr create mode 100644 tests/ui/zero_repeat_side_effects.fixed create mode 100644 tests/ui/zero_repeat_side_effects.rs create mode 100644 tests/ui/zero_repeat_side_effects.stderr diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 603f91a910b..8179e3e65b5 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -26,6 +26,12 @@ env: NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 +concurrency: + # For a given workflow, if we push to the same PR, cancel all previous builds on that PR. + # If the push is not attached to a PR, we will cancel all builds on the same branch. + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + jobs: base: # NOTE: If you modify this job, make sure you copy the changes to clippy_bors.yml @@ -33,10 +39,6 @@ jobs: steps: # Setup - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 0bc28c1f9d9..94515987eba 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -12,6 +12,11 @@ env: NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 +concurrency: + # For a given workflow, if we push to the same branch, cancel all previous builds on that branch. + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + defaults: run: shell: bash @@ -21,10 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 with: @@ -67,10 +68,6 @@ jobs: # NOTE: If you modify this job, make sure you copy the changes to clippy.yml steps: # Setup - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 @@ -131,10 +128,6 @@ jobs: steps: # Setup - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 @@ -155,10 +148,6 @@ jobs: steps: # Setup - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 @@ -211,10 +200,6 @@ jobs: steps: # Setup - - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - - name: Checkout uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index d3b2c0a7bf6..76ef84a48b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,65 @@ document. ## Unreleased / Beta / In Rust Nightly -[a859e5cc...master](https://github.com/rust-lang/rust-clippy/compare/a859e5cc...master) +[66c29b97...master](https://github.com/rust-lang/rust-clippy/compare/66c29b97...master) + +## Rust 1.77 + +Current stable, released 2024-03-18 + +[View all 93 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-12-16T18%3A20%3A00Z..2024-01-25T18%3A15%3A56Z+base%3Amaster) + +### New Lints + +* [`suspicious_open_options`] + [#11608](https://github.com/rust-lang/rust-clippy/pull/11608) +* [`option_as_ref_cloned`] + [#12051](https://github.com/rust-lang/rust-clippy/pull/12051) +* [`thread_local_initializer_can_be_made_const`] + [#12026](https://github.com/rust-lang/rust-clippy/pull/12026) +* [`str_split_at_newline`] + [#11987](https://github.com/rust-lang/rust-clippy/pull/11987) +* [`empty_enum_variants_with_brackets`] + [#12047](https://github.com/rust-lang/rust-clippy/pull/12047) +* [`manual_is_variant_and`] + [#11865](https://github.com/rust-lang/rust-clippy/pull/11865) +* [`pub_underscore_fields`] + [#10283](https://github.com/rust-lang/rust-clippy/pull/10283) +* [`eager_transmute`] + [#11981](https://github.com/rust-lang/rust-clippy/pull/11981) +* [`iter_filter_is_some`] + [#12004](https://github.com/rust-lang/rust/pull/12004) +* [`iter_filter_is_ok`] + [#12004](https://github.com/rust-lang/rust/pull/12004) +* [`result_filter_map`] + [#11869](https://github.com/rust-lang/rust-clippy/pull/11869) +* [`unconditional_recursion`] + [#11938](https://github.com/rust-lang/rust-clippy/pull/11938) + +### Enhancements + +* [`multiple_crate_versions`]: Added the [`allowed-duplicate-crates`] configuration to allow specific crates + [#12179](https://github.com/rust-lang/rust-clippy/pull/12179) +* [`single_call_fn`]: No longer ignores `#[allow]` attributes + [#12183](https://github.com/rust-lang/rust-clippy/pull/12183) +* [`read_zero_byte_vec`]: Updated the heuristics used for linting + [#11766](https://github.com/rust-lang/rust-clippy/pull/11766) + +### ICE Fixes + +* [`unit_arg`]: No longer crashes when checking for const in nested bodies + [#11977](https://github.com/rust-lang/rust-clippy/pull/11977) +* [`indexing_slicing`]: No longer crashes when the array index exceeds `usize` + [#12266](https://github.com/rust-lang/rust-clippy/pull/12266) + +### Others + +* Warnings about invalid fields inside `clippy.toml` files now include suggestions for existing fields + [#12180](https://github.com/rust-lang/rust-clippy/pull/12180) ## Rust 1.76 -Current stable, released 2024-02-08 +Released 2024-02-08 [View all 85 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-11-02T20%3A23%3A40Z..2023-12-16T13%3A11%3A08Z+base%3Amaster) @@ -5110,6 +5164,7 @@ Released 2018-09-13 [`collection_is_never_read`]: https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty +[`const_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_is_empty [`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator [`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/master/index.html#crate_in_macro_def @@ -5156,6 +5211,7 @@ Released 2018-09-13 [`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument +[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else @@ -5279,6 +5335,7 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division +[`integer_division_remainder_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division_remainder_used [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter @@ -5376,6 +5433,7 @@ Released 2018-09-13 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or +[`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default [`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone @@ -5813,6 +5871,7 @@ Released 2018-09-13 [`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_divided_by_zero [`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal [`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr +[`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects [`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset diff --git a/Cargo.toml b/Cargo.toml index 5d1d0ce2c42..2b37b54c004 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.78" +version = "0.1.79" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -24,7 +24,7 @@ path = "src/driver.rs" clippy_config = { path = "clippy_config" } clippy_lints = { path = "clippy_lints" } rustc_tools_util = "0.3.0" -tempfile = { version = "3.2", optional = true } +tempfile = { version = "3.3", optional = true } termize = "0.1" color-print = "0.3.4" anstream = "0.6.0" @@ -32,18 +32,18 @@ anstream = "0.6.0" [dev-dependencies] ui_test = "0.22.2" tester = "0.9" -regex = "1.5" +regex = "1.5.5" toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. -filetime = "0.2" +filetime = "0.2.9" itertools = "0.12" # UI test dependencies clippy_utils = { path = "clippy_utils" } if_chain = "1.0" -quote = "1.0" -serde = { version = "1.0.125", features = ["derive"] } +quote = "1.0.25" +serde = { version = "1.0.145", features = ["derive"] } syn = { version = "2.0", features = ["full"] } futures = "0.3" parking_lot = "0.12" diff --git a/book/src/development/macro_expansions.md b/book/src/development/macro_expansions.md index aecca9ef72e..125b6c4bc5b 100644 --- a/book/src/development/macro_expansions.md +++ b/book/src/development/macro_expansions.md @@ -52,7 +52,7 @@ if expr.span.from_expansion() { ### `Span.ctxt` method -The `span`'s context, given by the method [`ctxt`] and returning [SpanContext], +The `span`'s context, given by the method [`ctxt`] and returning [SyntaxContext], represents if the span is from a macro expansion and, if it is, which macro call expanded this span. @@ -155,4 +155,4 @@ if in_external_macro(cx.sess(), foo_span) { [`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html [Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html -[SpanContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html +[SyntaxContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index a985346b3c0..a9234899746 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -602,6 +602,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio **Affected lints:** * [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) * [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) +* [`assigning_clones`](https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones) * [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) * [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) * [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) diff --git a/clippy.toml b/clippy.toml index 8c405ac6a4e..62ed55beb1f 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,7 +1,10 @@ avoid-breaking-exported-api = false -# use the various `span_lint_*` methods instead, which also add a link to the docs -disallowed-methods = [ - "rustc_lint::context::LintContext::span_lint", - "rustc_middle::ty::context::TyCtxt::node_span_lint" -] +[[disallowed-methods]] +path = "rustc_lint::context::LintContext::span_lint" +reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead" + + +[[disallowed-methods]] +path = "rustc_middle::ty::context::TyCtxt::node_span_lint" +reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 2edc5ed592c..8ba2ab56625 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.78" +version = "0.1.79" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 673b6328b39..3218fe7f456 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -262,7 +262,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index a8a32f7ed20..bf4da5f14fe 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -23,6 +23,7 @@ msrv_aliases! { 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } + 1,63,0 { ASSIGNING_CLONES } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } 1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 2222abff7ad..76ae26dddf4 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -689,6 +689,8 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String { fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String { let mut seen_lints = HashSet::new(); let mut res: String = GENERATED_FILE_COMMENT.into(); + + res.push_str("#![allow(clippy::duplicated_attributes)]\n"); for lint in lints { if seen_lints.insert(&lint.new_name) { writeln!(res, "#![allow({})]", lint.new_name).unwrap(); diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 6ae089b3e03..1d954607eee 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.78" +version = "0.1.79" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index b1c552c7a8d..88d9f762a87 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -1,3 +1,4 @@ +use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::HirNode; use clippy_utils::sugg::Sugg; @@ -6,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{self as hir, Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Instance, Mutability}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; use rustc_span::symbol::sym; use rustc_span::ExpnKind; @@ -49,7 +50,19 @@ declare_clippy_lint! { perf, "assigning the result of cloning may be inefficient" } -declare_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); + +pub struct AssigningClones { + msrv: Msrv, +} + +impl AssigningClones { + #[must_use] + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); impl<'tcx> LateLintPass<'tcx> for AssigningClones { fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) { @@ -68,10 +81,12 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { return; }; - if is_ok_to_suggest(cx, lhs, &call) { + if is_ok_to_suggest(cx, lhs, &call, &self.msrv) { suggest(cx, assign_expr, lhs, &call); } } + + extract_msrv_attr!(LateContext); } // Try to resolve the call to `Clone::clone` or `ToOwned::to_owned`. @@ -135,7 +150,13 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option< // Return true if we find that the called method has a custom implementation and isn't derived or // provided by default by the corresponding trait. -fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) -> bool { +fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>, msrv: &Msrv) -> bool { + // For calls to .to_owned we suggest using .clone_into(), which was only stablilized in 1.63. + // If the current MSRV is below that, don't suggest the lint. + if !msrv.meets(msrvs::ASSIGNING_CLONES) && matches!(call.target, TargetTrait::ToOwned) { + return false; + } + // If the left-hand side is a local variable, it might be uninitialized at this point. // In that case we do not want to suggest the lint. if let Some(local) = path_to_local(lhs) { diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs new file mode 100644 index 00000000000..3c5ac597fd5 --- /dev/null +++ b/clippy_lints/src/attrs/duplicated_attributes.rs @@ -0,0 +1,64 @@ +use super::DUPLICATED_ATTRIBUTES; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::{Attribute, MetaItem}; +use rustc_data_structures::fx::FxHashMap; +use rustc_lint::EarlyContext; +use rustc_span::{sym, Span}; +use std::collections::hash_map::Entry; + +fn emit_if_duplicated( + cx: &EarlyContext<'_>, + attr: &MetaItem, + attr_paths: &mut FxHashMap, + complete_path: String, +) { + match attr_paths.entry(complete_path) { + Entry::Vacant(v) => { + v.insert(attr.span); + }, + Entry::Occupied(o) => { + span_lint_and_then(cx, DUPLICATED_ATTRIBUTES, attr.span, "duplicated attribute", |diag| { + diag.span_note(*o.get(), "first defined here"); + diag.span_help(attr.span, "remove this attribute"); + }); + }, + } +} + +fn check_duplicated_attr( + cx: &EarlyContext<'_>, + attr: &MetaItem, + attr_paths: &mut FxHashMap, + parent: &mut Vec, +) { + let Some(ident) = attr.ident() else { return }; + let name = ident.name; + if name == sym::doc || name == sym::cfg_attr { + // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg + // conditions are the same. + return; + } + if let Some(value) = attr.value_str() { + emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":"))); + } else if let Some(sub_attrs) = attr.meta_item_list() { + parent.push(name.as_str().to_string()); + for sub_attr in sub_attrs { + if let Some(meta) = sub_attr.meta_item() { + check_duplicated_attr(cx, meta, attr_paths, parent); + } + } + parent.pop(); + } else { + emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}", parent.join(":"))); + } +} + +pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { + let mut attr_paths = FxHashMap::default(); + + for attr in attrs { + if let Some(meta) = attr.meta() { + check_duplicated_attr(cx, &meta, &mut attr_paths, &mut Vec::new()); + } + } +} diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index c4c65d3248a..675c428948f 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -4,6 +4,7 @@ mod allow_attributes_without_reason; mod blanket_clippy_restriction_lints; mod deprecated_cfg_attr; mod deprecated_semver; +mod duplicated_attributes; mod empty_line_after; mod inline_always; mod maybe_misused_cfg; @@ -16,7 +17,7 @@ mod useless_attribute; mod utils; use clippy_config::msrvs::Msrv; -use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem}; +use rustc_ast::{Attribute, Crate, MetaItemKind, NestedMetaItem}; use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, impl_lint_pass}; @@ -489,6 +490,32 @@ declare_clippy_lint! { "item has both inner and outer attributes" } +declare_clippy_lint! { + /// ### What it does + /// Checks for attributes that appear two or more times. + /// + /// ### Why is this bad? + /// Repeating an attribute on the same item (or globally on the same crate) + /// is unnecessary and doesn't have an effect. + /// + /// ### Example + /// ```no_run + /// #[allow(dead_code)] + /// #[allow(dead_code)] + /// fn foo() {} + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[allow(dead_code)] + /// fn foo() {} + /// ``` + #[clippy::version = "1.78.0"] + pub DUPLICATED_ATTRIBUTES, + suspicious, + "duplicated attribute" +} + declare_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, @@ -568,12 +595,18 @@ impl_lint_pass!(EarlyAttributes => [ DEPRECATED_CLIPPY_CFG_ATTR, UNNECESSARY_CLIPPY_CFG, MIXED_ATTRIBUTES_STYLE, + DUPLICATED_ATTRIBUTES, ]); impl EarlyLintPass for EarlyAttributes { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + duplicated_attributes::check(cx, &krate.attrs); + } + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { empty_line_after::check(cx, item); mixed_attributes_style::check(cx, item); + duplicated_attributes::check(cx, &item.attrs); } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index fe2455f4b23..86f4332d05a 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -1,12 +1,12 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::in_constant; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{snippet_opt, snippet_with_applicability}; use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, FloatTy, Ty}; +use rustc_middle::ty::{self, FloatTy, Ty, UintTy}; use super::{utils, CAST_LOSSLESS}; @@ -16,6 +16,7 @@ pub(super) fn check( cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, + cast_to_hir: &rustc_hir::Ty<'_>, msrv: &Msrv, ) { if !should_lint(cx, expr, cast_from, cast_to, msrv) { @@ -24,11 +25,11 @@ pub(super) fn check( // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. - let mut applicability = Applicability::MachineApplicable; + let mut app = Applicability::MachineApplicable; let opt = snippet_opt(cx, cast_op.span.source_callsite()); let sugg = opt.as_ref().map_or_else( || { - applicability = Applicability::HasPlaceholders; + app = Applicability::HasPlaceholders; ".." }, |snip| { @@ -40,10 +41,27 @@ pub(super) fn check( }, ); - let message = if cast_from.is_bool() { - format!("casting `{cast_from:}` to `{cast_to:}` is more cleanly stated with `{cast_to:}::from(_)`") + // Display the type alias instead of the aliased type. Fixes #11285 + // + // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead, + // this will allow us to display the right type with `cast_from` as well. + let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind + // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast + // shouldn't have these if they're primitives, which are the only things we deal with. + // + // This could be removed for performance if this check is determined to have a pretty major + // effect. + && path.segments.iter().all(|segment| segment.args.is_none()) + { + snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app) } else { - format!("casting `{cast_from}` to `{cast_to}` may become silently lossy if you later change the type") + cast_to.to_string().into() + }; + + let message = if cast_from.is_bool() { + format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`") + } else { + format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type") }; span_lint_and_sugg( @@ -52,14 +70,17 @@ pub(super) fn check( expr.span, &message, "try", - format!("{cast_to}::from({sugg})"), - applicability, + format!("{cast_to_fmt}::from({sugg})"), + app, ); } 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) { + // + // If destination is u128, do not lint because source type cannot be larger + // If source is bool, still lint due to the lint message differing (refers to style) + if in_constant(cx, expr.hir_id) || (!cast_from.is_bool() && matches!(cast_to.kind(), ty::Uint(UintTy::U128))) { return false; } diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 14f2f4a7f59..063aab28238 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -791,7 +791,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { 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, cast_to_hir, &self.msrv); cast_enum_constructor::check(cx, expr, cast_expr, cast_from); } diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index ec66556cebf..e2296767431 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,12 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::root_macro_call_first_node; +use clippy_utils::macros::{macro_backtrace, MacroCall}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_in_cfg_test, is_in_test_function}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Node}; +use rustc_hir::{Expr, ExprKind, HirId, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; -use rustc_span::sym; +use rustc_span::{sym, Span, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -31,31 +33,38 @@ declare_clippy_lint! { "`dbg!` macro is intended as a debugging tool" } -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct DbgMacro { allow_dbg_in_tests: bool, + /// Tracks the `dbg!` macro callsites that are already checked. + checked_dbg_call_site: FxHashSet, + /// Tracks the previous `SyntaxContext`, to avoid walking the same context chain. + prev_ctxt: SyntaxContext, } impl_lint_pass!(DbgMacro => [DBG_MACRO]); impl DbgMacro { pub fn new(allow_dbg_in_tests: bool) -> Self { - DbgMacro { allow_dbg_in_tests } + DbgMacro { + allow_dbg_in_tests, + checked_dbg_call_site: FxHashSet::default(), + prev_ctxt: SyntaxContext::root(), + } } } impl LateLintPass<'_> for DbgMacro { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - let Some(macro_call) = root_macro_call_first_node(cx, expr) else { - return; - }; - if cx.tcx.is_diagnostic_item(sym::dbg_macro, macro_call.def_id) { + let cur_syntax_ctxt = expr.span.ctxt(); + + if cur_syntax_ctxt != self.prev_ctxt && + let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) && + !in_external_macro(cx.sess(), macro_call.span) && + self.checked_dbg_call_site.insert(macro_call.span) && // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml - if self.allow_dbg_in_tests - && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) - { - return; - } + !(self.allow_dbg_in_tests && is_in_test(cx, expr.hir_id)) + { let mut applicability = Applicability::MachineApplicable; let (sugg_span, suggestion) = match expr.peel_drop_temps().kind { @@ -101,6 +110,8 @@ impl LateLintPass<'_> for DbgMacro { _ => return, }; + self.prev_ctxt = cur_syntax_ctxt; + span_lint_and_sugg( cx, DBG_MACRO, @@ -112,4 +123,16 @@ impl LateLintPass<'_> for DbgMacro { ); } } + + fn check_crate_post(&mut self, _: &LateContext<'_>) { + self.checked_dbg_call_site = FxHashSet::default(); + } +} + +fn is_in_test(cx: &LateContext<'_>, hir_id: HirId) -> bool { + is_in_test_function(cx.tcx, hir_id) || is_in_cfg_test(cx.tcx, hir_id) +} + +fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option { + macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 2b324f5f96e..c8e148598a2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -54,6 +54,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::DEPRECATED_CFG_ATTR_INFO, crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO, crate::attrs::DEPRECATED_SEMVER_INFO, + crate::attrs::DUPLICATED_ATTRIBUTES_INFO, crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO, crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO, crate::attrs::INLINE_ALWAYS_INFO, @@ -235,6 +236,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::instant_subtraction::MANUAL_INSTANT_ELAPSED_INFO, crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO, crate::int_plus_one::INT_PLUS_ONE_INFO, + crate::integer_division_remainder_used::INTEGER_DIVISION_REMAINDER_USED_INFO, crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO, crate::item_name_repetitions::ENUM_VARIANT_NAMES_INFO, crate::item_name_repetitions::MODULE_INCEPTION_INFO, @@ -310,6 +312,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, + crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, @@ -353,6 +356,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::CLONE_ON_COPY_INFO, crate::methods::CLONE_ON_REF_PTR_INFO, crate::methods::COLLAPSIBLE_STR_REPLACE_INFO, + crate::methods::CONST_IS_EMPTY_INFO, crate::methods::DRAIN_COLLECT_INFO, crate::methods::ERR_EXPECT_INFO, crate::methods::EXPECT_FUN_CALL_INFO, @@ -750,5 +754,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::write::WRITE_LITERAL_INFO, crate::write::WRITE_WITH_NEWLINE_INFO, crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO, + crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO, crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO, ]; diff --git a/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs index d2f14756591..1add02af310 100644 --- a/clippy_lints/src/doc/markdown.rs +++ b/clippy_lints/src/doc/markdown.rs @@ -8,7 +8,14 @@ use url::Url; use crate::doc::DOC_MARKDOWN; -pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span, code_level: isize) { +pub fn check( + cx: &LateContext<'_>, + valid_idents: &FxHashSet, + text: &str, + span: Span, + code_level: isize, + blockquote_level: isize, +) { for orig_word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ @@ -46,11 +53,11 @@ pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str, span.parent(), ); - check_word(cx, word, span, code_level); + check_word(cx, word, span, code_level, blockquote_level); } } -fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) { +fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, blockquote_level: isize) { /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case /// letter (`NASA` is ok). @@ -97,7 +104,9 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) { } // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) - if code_level > 0 || (has_underscore(word) && has_hyphen(word)) { + // + // We also assume that backticks are not necessary if inside a quote. (Issue #10262) + if code_level > 0 || blockquote_level > 0 || (has_underscore(word) && has_hyphen(word)) { return; } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 003d26b7b89..b135e4e3577 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -7,14 +7,14 @@ use clippy_utils::{is_entrypoint_fn, method_chain_args}; use pulldown_cmark::Event::{ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, }; -use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph}; +use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph}; use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Expr}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; @@ -538,7 +538,16 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ suspicious_doc_comments::check(cx, attrs); - let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); + let (fragments, _) = attrs_to_doc_fragments( + attrs.iter().filter_map(|attr| { + if in_external_macro(cx.sess(), attr.span) { + None + } else { + Some((attr, None)) + } + }), + true, + ); let mut doc = fragments.iter().fold(String::new(), |mut acc, fragment| { add_doc_fragment(&mut acc, fragment); acc @@ -602,6 +611,7 @@ fn check_doc<'a, Events: Iterator, Range, Range, isize)> = Vec::new(); let mut paragraph_range = 0..0; let mut code_level = 0; + let mut blockquote_level = 0; for (event, range) in events { match event { @@ -610,8 +620,14 @@ fn check_doc<'a, Events: Iterator, Range blockquote_level += 1, + End(BlockQuote) => blockquote_level -= 1, Start(CodeBlock(ref kind)) => { in_code = true; if let CodeBlockKind::Fenced(lang) = kind { @@ -663,7 +679,7 @@ fn check_doc<'a, Events: Iterator, Range [ELSE_IF_WITHOUT_ELSE]); impl EarlyLintPass for ElseIfWithoutElse { - fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { if in_external_macro(cx.sess(), item.span) { return; } - while let ExprKind::If(_, _, Some(ref els)) = item.kind { - if let ExprKind::If(_, _, None) = els.kind { - span_lint_and_help( - cx, - ELSE_IF_WITHOUT_ELSE, - els.span, - "`if` expression with an `else if`, but without a final `else`", - None, - "add an `else` block here", - ); - } - - item = els; + if let ExprKind::If(_, _, Some(ref els)) = item.kind + && let ExprKind::If(_, _, None) = els.kind + { + span_lint_and_help( + cx, + ELSE_IF_WITHOUT_ELSE, + els.span, + "`if` expression with an `else if`, but without a final `else`", + None, + "add an `else` block here", + ); } } } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index ebda2ad8387..dafbf6c8846 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -358,7 +358,7 @@ struct InsertSearcher<'cx, 'tcx> { can_use_entry: bool, /// Whether this expression is the final expression in this code path. This may be a statement. in_tail_pos: bool, - // Is this expression a single insert. A slightly better suggestion can be made in this case. + /// Is this expression a single insert. A slightly better suggestion can be made in this case. is_single_insert: bool, /// If the visitor has seen the map being used. is_map_used: bool, @@ -431,6 +431,9 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { self.is_single_insert = false; self.visit_expr(e); } + if let Some(els) = &l.els { + self.visit_block(els); + } }, StmtKind::Item(_) => { self.allow_insert_closure &= !self.in_tail_pos; diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 96da2ec2a1a..9cc51fa8cd5 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -250,7 +250,7 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// A `Result` is at least as large as the `Err`-variant. While we - /// expect that variant to be seldomly used, the compiler needs to reserve + /// expect that variant to be seldom used, the compiler needs to reserve /// and move that much memory every single time. /// Furthermore, errors are often simply passed up the call-stack, making /// use of the `?`-operator and its type-conversion mechanics. If the diff --git a/clippy_lints/src/integer_division_remainder_used.rs b/clippy_lints/src/integer_division_remainder_used.rs new file mode 100644 index 00000000000..36dc45ca788 --- /dev/null +++ b/clippy_lints/src/integer_division_remainder_used.rs @@ -0,0 +1,50 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::BinOpKind; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self}; +use rustc_session::declare_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of division (/) and remainder (%) operations + /// when performed on any integer types using the default Div and Rem trait implementations. + /// + /// ### Why is this bad? + /// In cryptographic contexts, division can result in timing sidechannel vulnerabilities, + /// and needs to be replaced with constant-time code instead (e.g. Barrett reduction). + /// + /// ### Example + /// ```no_run + /// let my_div = 10 / 2; + /// ``` + /// Use instead: + /// ```no_run + /// let my_div = 10 >> 1; + /// ``` + #[clippy::version = "1.78.0"] + pub INTEGER_DIVISION_REMAINDER_USED, + restriction, + "use of disallowed default division and remainder operations" +} + +declare_lint_pass!(IntegerDivisionRemainderUsed => [INTEGER_DIVISION_REMAINDER_USED]); + +impl LateLintPass<'_> for IntegerDivisionRemainderUsed { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind + && let BinOpKind::Div | BinOpKind::Rem = op.node + && let lhs_ty = cx.typeck_results().expr_ty(lhs) + && let rhs_ty = cx.typeck_results().expr_ty(rhs) + && let ty::Int(_) | ty::Uint(_) = lhs_ty.peel_refs().kind() + && let ty::Int(_) | ty::Uint(_) = rhs_ty.peel_refs().kind() + { + span_lint( + cx, + INTEGER_DIVISION_REMAINDER_USED, + expr.span.source_callsite(), + &format!("use of {} has been disallowed in this context", op.node.as_str()), + ); + } + } +} diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index f084d89ccc2..d4ddf76fb8a 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::path_to_local_id; use clippy_utils::source::snippet; use clippy_utils::visitors::is_local_used; @@ -122,9 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { value=snippet(cx, value.span, ""), default=snippet(cx, default.span, ""), ); - span_lint_and_then( + span_lint_hir_and_then( cx, USELESS_LET_IF_SEQ, + local.hir_id, span, "`if _ { .. } else { .. }` is an expression", |diag| { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b930175c4d8..57fac351042 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -172,6 +172,7 @@ mod init_numbered_fields; mod inline_fn_without_body; mod instant_subtraction; mod int_plus_one; +mod integer_division_remainder_used; mod invalid_upcast_comparisons; mod item_name_repetitions; mod items_after_statements; @@ -211,6 +212,7 @@ mod manual_retain; mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; +mod manual_unwrap_or_default; mod map_unit_fn; mod match_result_ok; mod matches; @@ -373,6 +375,7 @@ mod visibility; mod wildcard_imports; mod write; mod zero_div_zero; +mod zero_repeat_side_effects; mod zero_sized_map_values; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -1119,7 +1122,10 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv()))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); - store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones)); + store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(msrv()))); + store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects)); + store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault)); + store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index 47dc3807e62..cf34c904dfe 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { } return false; // no need to walk further *on the variable* }, - Res::Def(DefKind::Static{..} | DefKind::Const, ..) => { + Res::Def(DefKind::Static { .. } | DefKind::Const, ..) => { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 6cc79440f39..8aae7be4593 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -255,9 +255,7 @@ fn never_loop_expr<'tcx>( InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => { NeverLoopResult::Normal }, - InlineAsmOperand::Label { block } => { - never_loop_block(cx, block, local_labels, main_loop_id) - } + InlineAsmOperand::Label { block } => never_loop_block(cx, block, local_labels, main_loop_id), })), ExprKind::OffsetOf(_, _) | ExprKind::Yield(_, _) diff --git a/clippy_lints/src/loops/unused_enumerate_index.rs b/clippy_lints/src/loops/unused_enumerate_index.rs index dd7fae79d9b..31f0f1cfeba 100644 --- a/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/clippy_lints/src/loops/unused_enumerate_index.rs @@ -1,62 +1,41 @@ use super::UNUSED_ENUMERATE_INDEX; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; -use clippy_utils::{pat_is_wild, sugg}; +use clippy_utils::{match_def_path, pat_is_wild, sugg}; use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; /// Checks for the `UNUSED_ENUMERATE_INDEX` lint. -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { - let PatKind::Tuple([index, elem], _) = pat.kind else { - return; - }; - - let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind else { - return; - }; - - let ty = cx.typeck_results().expr_ty(arg); - - if !pat_is_wild(cx, &index.kind, body) { - return; +/// +/// The lint is also partially implemented in `clippy_lints/src/methods/unused_enumerate_index.rs`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, arg: &Expr<'_>, body: &'tcx Expr<'tcx>) { + if let PatKind::Tuple([index, elem], _) = pat.kind + && let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind + && let ty = cx.typeck_results().expr_ty(arg) + && pat_is_wild(cx, &index.kind, body) + && let ty::Adt(base, _) = *ty.kind() + && match_def_path(cx, base.did(), &clippy_utils::paths::CORE_ITER_ENUMERATE_STRUCT) + && let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id) + && match_def_path(cx, call_id, &clippy_utils::paths::CORE_ITER_ENUMERATE_METHOD) + { + span_lint_and_then( + cx, + UNUSED_ENUMERATE_INDEX, + arg.span, + "you seem to use `.enumerate()` and immediately discard the index", + |diag| { + let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter"); + multispan_sugg( + diag, + "remove the `.enumerate()` call", + vec![ + (pat.span, snippet(cx, elem.span, "..").into_owned()), + (arg.span, base_iter.to_string()), + ], + ); + }, + ); } - - let name = match *ty.kind() { - ty::Adt(base, _substs) => cx.tcx.def_path_str(base.did()), - _ => return, - }; - - if name != "std::iter::Enumerate" && name != "core::iter::Enumerate" { - return; - } - - let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id) else { - return; - }; - - let call_name = cx.tcx.def_path_str(call_id); - - if call_name != "std::iter::Iterator::enumerate" && call_name != "core::iter::Iterator::enumerate" { - return; - } - - span_lint_and_then( - cx, - UNUSED_ENUMERATE_INDEX, - arg.span, - "you seem to use `.enumerate()` and immediately discard the index", - |diag| { - let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter"); - multispan_sugg( - diag, - "remove the `.enumerate()` call", - vec![ - (pat.span, snippet(cx, elem.span, "..").into_owned()), - (arg.span, base_iter.to_string()), - ], - ); - }, - ); } diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs index 3511d24e813..3dff826cb85 100644 --- a/clippy_lints/src/loops/while_immutable_condition.rs +++ b/clippy_lints/src/loops/while_immutable_condition.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { Res::Local(hir_id) => { self.ids.insert(hir_id); }, - Res::Def(DefKind::Static{..}, def_id) => { + Res::Def(DefKind::Static { .. }, def_id) => { let mutable = self.cx.tcx.is_mutable_static(def_id); self.def_ids.insert(def_id, mutable); }, diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 6f15fca089e..3ddb06a1e08 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq}; +use clippy_utils::{match_def_path, paths, SpanlessEq}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -69,17 +69,16 @@ impl_lint_pass!(ManualRetain => [MANUAL_RETAIN]); impl<'tcx> LateLintPass<'tcx> for ManualRetain { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let Some(parent_expr) = get_parent_expr(cx, expr) - && let Assign(left_expr, collect_expr, _) = &parent_expr.kind + if let Assign(left_expr, collect_expr, _) = &expr.kind && let hir::ExprKind::MethodCall(seg, ..) = &collect_expr.kind && seg.args.is_none() && 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) && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id) { - check_into_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv); - check_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv); - check_to_owned(cx, left_expr, target_expr, parent_expr.span, &self.msrv); + check_into_iter(cx, left_expr, target_expr, expr.span, &self.msrv); + check_iter(cx, left_expr, target_expr, expr.span, &self.msrv); + check_to_owned(cx, left_expr, target_expr, expr.span, &self.msrv); } } diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs new file mode 100644 index 00000000000..ddaf97c463a --- /dev/null +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -0,0 +1,181 @@ +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; + +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_default_equivalent; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; + +declare_clippy_lint! { + /// ### What it does + /// Checks if a `match` or `if let` expression can be simplified using + /// `.unwrap_or_default()`. + /// + /// ### Why is this bad? + /// It can be done in one call with `.unwrap_or_default()`. + /// + /// ### Example + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = match x { + /// Some(v) => v, + /// None => String::new(), + /// }; + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = if let Some(v) = x { + /// v + /// } else { + /// Vec::new() + /// }; + /// ``` + /// Use instead: + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = x.unwrap_or_default(); + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = x.unwrap_or_default(); + /// ``` + #[clippy::version = "1.78.0"] + pub MANUAL_UNWRAP_OR_DEFAULT, + suspicious, + "check if a `match` or `if let` can be simplified with `unwrap_or_default`" +} + +declare_lint_pass!(ManualUnwrapOrDefault => [MANUAL_UNWRAP_OR_DEFAULT]); + +fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option { + if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id) + { + let mut bindings = Vec::new(); + pat.each_binding(|_, id, _, _| bindings.push(id)); + if let &[id] = bindings.as_slice() { + Some(id) + } else { + None + } + } else { + None + } +} + +fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let PatKind::Path(QPath::Resolved(_, path)) = arm.pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id) + { + Some(arm.body) + } else if let PatKind::Wild = arm.pat.kind { + // We consider that the `Some` check will filter it out if it's not right. + Some(arm.body) + } else { + None + } +} + +fn get_some_and_none_bodies<'tcx>( + cx: &LateContext<'tcx>, + arm1: &'tcx Arm<'tcx>, + arm2: &'tcx Arm<'tcx>, +) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> { + if let Some(binding_id) = get_some(cx, arm1.pat) + && let Some(body_none) = get_none(cx, arm2) + { + Some(((arm1.body, binding_id), body_none)) + } else if let Some(binding_id) = get_some(cx, arm2.pat) + && let Some(body_none) = get_none(cx, arm1) + { + Some(((arm2.body, binding_id), body_none)) + } else { + None + } +} + +fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else { + return false; + }; + // We don't want conditions on the arms to simplify things. + if arm1.guard.is_none() + && arm2.guard.is_none() + // We check that the returned type implements the `Default` trait. + && let match_ty = cx.typeck_results().expr_ty(expr) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + && implements_trait(cx, match_ty, default_trait_id, &[]) + // We now get the bodies for both the `Some` and `None` arms. + && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) + // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. + && let ExprKind::Path(QPath::Resolved(_, path)) = body_some.peel_blocks().kind + && let Res::Local(local_id) = path.res + && local_id == binding_id + // We now check the `None` arm is calling a method equivalent to `Default::default`. + && let body_none = body_none.peel_blocks() + && is_default_equivalent(cx, body_none) + && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span) + { + span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR_DEFAULT, + expr.span, + "match can be simplified with `.unwrap_or_default()`", + "replace it with", + format!("{match_expr_snippet}.unwrap_or_default()"), + Applicability::MachineApplicable, + ); + } + true +} + +fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::If(cond, if_block, Some(else_expr)) = expr.kind + && let ExprKind::Let(let_) = cond.kind + && let ExprKind::Block(_, _) = else_expr.kind + // We check that the returned type implements the `Default` trait. + && let match_ty = cx.typeck_results().expr_ty(expr) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + && implements_trait(cx, match_ty, default_trait_id, &[]) + && let Some(binding_id) = get_some(cx, let_.pat) + // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. + && let ExprKind::Path(QPath::Resolved(_, path)) = if_block.peel_blocks().kind + && let Res::Local(local_id) = path.res + && local_id == binding_id + // We now check the `None` arm is calling a method equivalent to `Default::default`. + && let body_else = else_expr.peel_blocks() + && is_default_equivalent(cx, body_else) + && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span) + { + span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR_DEFAULT, + expr.span, + "if let can be simplified with `.unwrap_or_default()`", + "replace it with", + format!("{if_let_expr_snippet}.unwrap_or_default()"), + Applicability::MachineApplicable, + ); + } +} + +impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if expr.span.from_expansion() { + return; + } + if !handle_match(cx, expr) { + handle_if_let(cx, expr); + } + } +} diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 86c414dafcc..a0db8e2db1f 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -55,23 +55,15 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: }; let ty = cx.typeck_results().expr_ty(ex); - if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) { - check_single_pattern(cx, ex, arms, expr, els); - check_opt_like(cx, ex, arms, expr, ty, els); + if (*ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id)) && + (check_single_pattern(arms) || check_opt_like(cx, arms, ty)) { + report_single_pattern(cx, ex, arms, expr, els); } } } -fn check_single_pattern( - cx: &LateContext<'_>, - ex: &Expr<'_>, - arms: &[Arm<'_>], - expr: &Expr<'_>, - els: Option<&Expr<'_>>, -) { - if is_wild(arms[1].pat) { - report_single_pattern(cx, ex, arms, expr, els); - } +fn check_single_pattern(arms: &[Arm<'_>]) -> bool { + is_wild(arms[1].pat) } fn report_single_pattern( @@ -140,19 +132,10 @@ fn report_single_pattern( span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app); } -fn check_opt_like<'a>( - cx: &LateContext<'a>, - ex: &Expr<'_>, - arms: &[Arm<'_>], - expr: &Expr<'_>, - ty: Ty<'a>, - els: Option<&Expr<'_>>, -) { +fn check_opt_like<'a>(cx: &LateContext<'a>, arms: &[Arm<'_>], ty: Ty<'a>) -> bool { // We don't want to lint if the second arm contains an enum which could // have more variants in the future. - if form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat) { - report_single_pattern(cx, ex, arms, expr, els); - } + form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat) } /// Returns `true` if all of the types in the pattern are enums which we know diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index e2c2997594a..4d8fb217f7f 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -91,7 +91,7 @@ pub(super) fn check<'tcx>( }, hir::ExprKind::Path(ref p) => matches!( cx.qpath_res(p, arg.hir_id), - hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static{..}, _) + hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static { .. }, _) ), _ => false, } diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs new file mode 100644 index 00000000000..7fe66062251 --- /dev/null +++ b/clippy_lints/src/methods/is_empty.rs @@ -0,0 +1,49 @@ +use clippy_utils::consts::constant_is_empty; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{find_binding_init, path_to_local}; +use rustc_hir::{Expr, HirId}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::sym; + +use super::CONST_IS_EMPTY; + +/// Expression whose initialization depend on a constant conditioned by a `#[cfg(…)]` directive will +/// not trigger the lint. +pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_>) { + if in_external_macro(cx.sess(), expr.span) || !receiver.span.eq_ctxt(expr.span) { + return; + } + let init_expr = expr_or_init(cx, receiver); + if !receiver.span.eq_ctxt(init_expr.span) { + return; + } + if let Some(init_is_empty) = constant_is_empty(cx, init_expr) { + span_lint( + cx, + CONST_IS_EMPTY, + expr.span, + &format!("this expression always evaluates to {init_is_empty:?}"), + ); + } +} + +fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { + cx.tcx + .hir() + .parent_id_iter(id) + .any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) +} + +/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization +/// value depends on a `#[cfg(…)]` directive. +fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> { + while let Some(init) = path_to_local(expr) + .and_then(|id| find_binding_init(cx, id)) + .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty()) + .filter(|init| !is_under_cfg(cx, init.hir_id)) + { + expr = init; + } + expr +} diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index 12104310405..5b0b70b4b96 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -1,10 +1,10 @@ -use super::utils::derefs_to_slice; -use crate::methods::iter_nth_zero; -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::get_type_diagnostic_name; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::symbol::sym; +use rustc_span::Span; use super::ITER_NTH; @@ -12,28 +12,33 @@ pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, iter_recv: &'tcx hir::Expr<'tcx>, - nth_recv: &hir::Expr<'_>, - nth_arg: &hir::Expr<'_>, - is_mut: bool, -) { - let mut_str = if is_mut { "_mut" } else { "" }; - let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() { - "slice" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) { - "`Vec`" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) { - "`VecDeque`" - } else { - iter_nth_zero::check(cx, expr, nth_recv, nth_arg); - return; // caller is not a type that we want to lint + iter_method: &str, + iter_span: Span, + nth_span: Span, +) -> bool { + let caller_type = match get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(iter_recv).peel_refs()) { + Some(sym::Vec) => "`Vec`", + Some(sym::VecDeque) => "`VecDeque`", + _ if cx.typeck_results().expr_ty_adjusted(iter_recv).peel_refs().is_slice() => "slice", + // caller is not a type that we want to lint + _ => return false, }; - span_lint_and_help( + span_lint_and_then( cx, ITER_NTH, expr.span, - &format!("called `.iter{mut_str}().nth()` on a {caller_type}"), - None, - &format!("calling `.get{mut_str}()` is both faster and more readable"), + &format!("called `.{iter_method}().nth()` on a {caller_type}"), + |diag| { + let get_method = if iter_method == "iter_mut" { "get_mut" } else { "get" }; + diag.span_suggestion_verbose( + iter_span.to(nth_span), + format!("`{get_method}` is equivalent but more concise"), + get_method, + Applicability::MachineApplicable, + ); + }, ); + + true } diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 27e17b43b01..c3c7a3a0033 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -86,8 +86,11 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ } } }, - hir::ExprKind::Call(call, [_]) => { - if let hir::ExprKind::Path(qpath) = call.kind { + hir::ExprKind::Call(call, args) => { + if let hir::ExprKind::Path(qpath) = call.kind + && let [arg] = args + && ident_eq(name, arg) + { handle_path(cx, call, &qpath, e, recv); } }, @@ -118,7 +121,9 @@ fn handle_path( if let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind() && let args = args.as_slice() && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type()) - && ty.is_ref() + && let ty::Ref(_, ty, Mutability::Not) = ty.kind() + && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind() + && lst.iter().all(|l| l.as_type() == Some(*ty)) { lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs())); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 8a24ccea3a1..b6c474212cd 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -36,6 +36,7 @@ mod inefficient_to_string; mod inspect_for_each; mod into_iter_on_ref; mod is_digit_ascii_radix; +mod is_empty; mod iter_cloned_collect; mod iter_count; mod iter_filter; @@ -118,6 +119,7 @@ mod unnecessary_literal_unwrap; mod unnecessary_result_map_or_else; mod unnecessary_sort_by; mod unnecessary_to_owned; +mod unused_enumerate_index; mod unwrap_expect_used; mod useless_asref; mod utils; @@ -1235,12 +1237,11 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `.iter().nth()` (and the related - /// `.iter_mut().nth()`) on standard library types with *O*(1) element access. + /// Checks for usage of `.iter().nth()`/`.iter_mut().nth()` on standard library types that have + /// equivalent `.get()`/`.get_mut()` methods. /// /// ### Why is this bad? - /// `.get()` and `.get_mut()` are more efficient and more - /// readable. + /// `.get()` and `.get_mut()` are equivalent but more concise. /// /// ### Example /// ```no_run @@ -1256,7 +1257,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "pre 1.29.0"] pub ITER_NTH, - perf, + style, "using `.iter().nth()` on a standard library type with O(1) element access" } @@ -2848,7 +2849,7 @@ declare_clippy_lint! { /// the file is created from scratch, or ensure `truncate` is /// called so that the truncation behaviour is explicit. `truncate(true)` /// will ensure the file is entirely overwritten with new data, whereas - /// `truncate(false)` will explicitely keep the default behavior. + /// `truncate(false)` will explicitly keep the default behavior. /// /// ### Example /// ```rust,no_run @@ -2862,7 +2863,7 @@ declare_clippy_lint! { /// /// OpenOptions::new().create(true).truncate(true); /// ``` - #[clippy::version = "1.75.0"] + #[clippy::version = "1.77.0"] pub SUSPICIOUS_OPEN_OPTIONS, suspicious, "suspicious combination of options for opening a file" @@ -3182,8 +3183,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// - /// Checks an argument of `seek` method of `Seek` trait - /// and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead. + /// Checks if the `seek` method of the `Seek` trait is called with `SeekFrom::Current(0)`, + /// and if it is, suggests using `stream_position` instead. /// /// ### Why is this bad? /// @@ -3590,7 +3591,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.73.0"] pub READONLY_WRITE_LOCK, - nursery, + perf, "acquiring a write lock when a read lock would work" } @@ -3816,7 +3817,7 @@ declare_clippy_lint! { /// ```no_run /// let _ = std::iter::empty::>().flatten(); /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub RESULT_FILTER_MAP, complexity, "filtering `Result` for `Ok` then force-unwrapping, which can be one type-safe operation" @@ -3825,7 +3826,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for usage of `.filter(Option::is_some)` that may be replaced with a `.flatten()` call. - /// This lint will require additional changes to the follow-up calls as it appects the type. + /// This lint will require additional changes to the follow-up calls as it affects the type. /// /// ### Why is this bad? /// This pattern is often followed by manual unwrapping of the `Option`. The simplification @@ -3842,7 +3843,7 @@ declare_clippy_lint! { /// // example code which does not raise clippy warning /// vec![Some(1)].into_iter().flatten(); /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub ITER_FILTER_IS_SOME, pedantic, "filtering an iterator over `Option`s for `Some` can be achieved with `flatten`" @@ -3851,7 +3852,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for usage of `.filter(Result::is_ok)` that may be replaced with a `.flatten()` call. - /// This lint will require additional changes to the follow-up calls as it appects the type. + /// This lint will require additional changes to the follow-up calls as it affects the type. /// /// ### Why is this bad? /// This pattern is often followed by manual unwrapping of `Result`. The simplification @@ -3868,7 +3869,7 @@ declare_clippy_lint! { /// // example code which does not raise clippy warning /// vec![Ok::(1)].into_iter().flatten(); /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub ITER_FILTER_IS_OK, pedantic, "filtering an iterator over `Result`s for `Ok` can be achieved with `flatten`" @@ -3895,7 +3896,7 @@ declare_clippy_lint! { /// option.is_some_and(|a| a > 10); /// result.is_ok_and(|a| a > 10); /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub MANUAL_IS_VARIANT_AND, pedantic, "using `.map(f).unwrap_or_default()`, which is more succinctly expressed as `is_some_and(f)` or `is_ok_and(f)`" @@ -3925,7 +3926,7 @@ declare_clippy_lint! { /// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is /// valid. /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub STR_SPLIT_AT_NEWLINE, pedantic, "splitting a trimmed string at hard-coded newlines" @@ -4044,6 +4045,31 @@ declare_clippy_lint! { "calling `.get().is_some()` or `.get().is_none()` instead of `.contains()` or `.contains_key()`" } +declare_clippy_lint! { + /// ### What it does + /// It identifies calls to `.is_empty()` on constant values. + /// + /// ### Why is this bad? + /// String literals and constant values are known at compile time. Checking if they + /// are empty will always return the same value. This might not be the intention of + /// the expression. + /// + /// ### Example + /// ```no_run + /// let value = ""; + /// if value.is_empty() { + /// println!("the string is empty"); + /// } + /// ``` + /// Use instead: + /// ```no_run + /// println!("the string is empty"); + /// ``` + #[clippy::version = "1.78.0"] + pub CONST_IS_EMPTY, + suspicious, + "is_empty() called on strings known at compile time" +} pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -4092,6 +4118,7 @@ impl_lint_pass!(Methods => [ CLONE_ON_COPY, CLONE_ON_REF_PTR, COLLAPSIBLE_STR_REPLACE, + CONST_IS_EMPTY, ITER_OVEREAGER_CLONED, CLONED_INSTEAD_OF_COPIED, FLAT_MAP_OPTION, @@ -4403,6 +4430,7 @@ impl Methods { zst_offset::check(cx, expr, recv); }, ("all", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); if let Some(("cloned", recv2, [], _, _)) = method_call(recv) { iter_overeager_cloned::check( cx, @@ -4421,23 +4449,26 @@ impl Methods { unnecessary_lazy_eval::check(cx, expr, recv, arg, "and"); } }, - ("any", [arg]) => match method_call(recv) { - Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( - cx, - expr, - recv, - recv2, - iter_overeager_cloned::Op::NeedlessMove(arg), - false, - ), - Some(("chars", recv, _, _, _)) - if let ExprKind::Closure(arg) = arg.kind - && let body = cx.tcx.hir().body(arg.body) - && let [param] = body.params => - { - string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv); - }, - _ => {}, + ("any", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); + match method_call(recv) { + Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( + cx, + expr, + recv, + recv2, + iter_overeager_cloned::Op::NeedlessMove(arg), + false, + ), + Some(("chars", recv, _, _, _)) + if let ExprKind::Closure(arg) = arg.kind + && let body = cx.tcx.hir().body(arg.body) + && let [param] = body.params => + { + string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv); + }, + _ => {}, + } }, ("arg", [arg]) => { suspicious_command_arg_space::check(cx, recv, arg, span); @@ -4445,7 +4476,7 @@ impl Methods { ("as_deref" | "as_deref_mut", []) => { needless_option_as_deref::check(cx, expr, recv, name); }, - ("as_bytes" | "is_empty", []) => { + ("as_bytes", []) => { if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) { redundant_as_str::check(cx, expr, recv, as_str_span, span); } @@ -4570,14 +4601,17 @@ impl Methods { } }, ("filter_map", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); unnecessary_filter_map::check(cx, expr, arg, name); filter_map_bool_then::check(cx, expr, arg, call_span); filter_map_identity::check(cx, expr, arg, span); }, ("find_map", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); unnecessary_filter_map::check(cx, expr, arg, name); }, ("flat_map", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); flat_map_identity::check(cx, expr, arg, span); flat_map_option::check(cx, expr, arg, span); }, @@ -4599,17 +4633,20 @@ impl Methods { manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv); unnecessary_fold::check(cx, expr, init, acc, span); }, - ("for_each", [arg]) => match method_call(recv) { - Some(("inspect", _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2), - Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( - cx, - expr, - recv, - recv2, - iter_overeager_cloned::Op::NeedlessMove(arg), - false, - ), - _ => {}, + ("for_each", [arg]) => { + unused_enumerate_index::check(cx, expr, recv, arg); + match method_call(recv) { + Some(("inspect", _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2), + Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( + cx, + expr, + recv, + recv2, + iter_overeager_cloned::Op::NeedlessMove(arg), + false, + ), + _ => {}, + } }, ("get", [arg]) => { get_first::check(cx, expr, recv, arg); @@ -4619,6 +4656,12 @@ impl Methods { ("hash", [arg]) => { unit_hash::check(cx, expr, recv, arg); }, + ("is_empty", []) => { + if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) { + redundant_as_str::check(cx, expr, recv, as_str_span, span); + } + is_empty::check(cx, expr, recv); + }, ("is_file", []) => filetype_is_file::check(cx, expr, recv), ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, &self.msrv), ("is_none", []) => check_is_some_is_none(cx, expr, recv, call_span, false), @@ -4650,6 +4693,7 @@ impl Methods { }, (name @ ("map" | "map_err"), [m_arg]) => { if name == "map" { + unused_enumerate_index::check(cx, expr, recv, m_arg); map_clone::check(cx, expr, recv, m_arg, &self.msrv); match method_call(recv) { Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => { @@ -4723,8 +4767,11 @@ impl Methods { iter_overeager_cloned::Op::LaterCloned, false, ), - Some(("iter", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false), - Some(("iter_mut", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true), + Some((iter_method @ ("iter" | "iter_mut"), iter_recv, [], iter_span, _)) => { + if !iter_nth::check(cx, expr, iter_recv, iter_method, iter_span, span) { + iter_nth_zero::check(cx, expr, recv, n_arg); + } + }, _ => iter_nth_zero::check(cx, expr, recv, n_arg), }, ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"), diff --git a/clippy_lints/src/methods/no_effect_replace.rs b/clippy_lints/src/methods/no_effect_replace.rs index 81df32bdee2..a301a5f7d65 100644 --- a/clippy_lints/src/methods/no_effect_replace.rs +++ b/clippy_lints/src/methods/no_effect_replace.rs @@ -25,6 +25,7 @@ pub(super) fn check<'tcx>( && param1 == param2.as_str() { span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself"); + return; } if SpanlessEq::new(cx).eq_expr(arg1, arg2) { diff --git a/clippy_lints/src/methods/unused_enumerate_index.rs b/clippy_lints/src/methods/unused_enumerate_index.rs new file mode 100644 index 00000000000..e5cc898612e --- /dev/null +++ b/clippy_lints/src/methods/unused_enumerate_index.rs @@ -0,0 +1,135 @@ +use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_hir_and_then}; +use clippy_utils::paths::{CORE_ITER_ENUMERATE_METHOD, CORE_ITER_ENUMERATE_STRUCT}; +use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::{expr_or_init, is_trait_method, match_def_path, pat_is_wild}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::AdtDef; +use rustc_span::{sym, Span}; + +use crate::loops::UNUSED_ENUMERATE_INDEX; + +/// Check for the `UNUSED_ENUMERATE_INDEX` lint outside of loops. +/// +/// The lint is declared in `clippy_lints/src/loops/mod.rs`. There, the following pattern is +/// checked: +/// ```ignore +/// for (_, x) in some_iter.enumerate() { +/// // Index is ignored +/// } +/// ``` +/// +/// This `check` function checks for chained method calls constructs where we can detect that the +/// index is unused. Currently, this checks only for the following patterns: +/// ```ignore +/// some_iter.enumerate().map_function(|(_, x)| ..) +/// let x = some_iter.enumerate(); +/// x.map_function(|(_, x)| ..) +/// ``` +/// where `map_function` is one of `all`, `any`, `filter_map`, `find_map`, `flat_map`, `for_each` or +/// `map`. +/// +/// # Preconditions +/// This function must be called not on the `enumerate` call expression itself, but on any of the +/// map functions listed above. It will ensure that `recv` is a `std::iter::Enumerate` instance and +/// that the method call is one of the `std::iter::Iterator` trait. +/// +/// * `call_expr`: The map function call expression +/// * `recv`: The receiver of the call +/// * `closure_arg`: The argument to the map function call containing the closure/function to apply +pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>) { + let recv_ty = cx.typeck_results().expr_ty(recv); + if let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did) + // If we call a method on a `std::iter::Enumerate` instance + && match_def_path(cx, recv_ty_defid, &CORE_ITER_ENUMERATE_STRUCT) + // If we are calling a method of the `Iterator` trait + && is_trait_method(cx, call_expr, sym::Iterator) + // And the map argument is a closure + && let ExprKind::Closure(closure) = closure_arg.kind + && let closure_body = cx.tcx.hir().body(closure.body) + // And that closure has one argument ... + && let [closure_param] = closure_body.params + // .. which is a tuple of 2 elements + && let PatKind::Tuple([index, elem], ..) = closure_param.pat.kind + // And that the first element (the index) is either `_` or unused in the body + && pat_is_wild(cx, &index.kind, closure_body) + // Try to find the initializer for `recv`. This is needed in case `recv` is a local_binding. In the + // first example below, `expr_or_init` would return `recv`. + // ``` + // iter.enumerate().map(|(_, x)| x) + // ^^^^^^^^^^^^^^^^ `recv`, a call to `std::iter::Iterator::enumerate` + // + // let binding = iter.enumerate(); + // ^^^^^^^^^^^^^^^^ `recv_init_expr` + // binding.map(|(_, x)| x) + // ^^^^^^^ `recv`, not a call to `std::iter::Iterator::enumerate` + // ``` + && let recv_init_expr = expr_or_init(cx, recv) + // Make sure the initializer is a method call. It may be that the `Enumerate` comes from something + // that we cannot control. + // This would for instance happen with: + // ``` + // external_lib::some_function_returning_enumerate().map(|(_, x)| x) + // ``` + && let ExprKind::MethodCall(_, enumerate_recv, _, enumerate_span) = recv_init_expr.kind + && let Some(enumerate_defid) = cx.typeck_results().type_dependent_def_id(recv_init_expr.hir_id) + // Make sure the method call is `std::iter::Iterator::enumerate`. + && match_def_path(cx, enumerate_defid, &CORE_ITER_ENUMERATE_METHOD) + { + // Check if the tuple type was explicit. It may be the type system _needs_ the type of the element + // that would be explicited in the closure. + let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) { + // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`. + // Fallback to `..` if we fail getting either snippet. + Some(ty_span) => snippet_opt(cx, elem.span) + .and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}"))) + .unwrap_or_else(|| "..".to_string()), + // Otherwise, we have no explicit type. We can replace with the binding name of the element. + None => snippet(cx, elem.span, "..").into_owned(), + }; + + // Suggest removing the tuple from the closure and the preceding call to `enumerate`, whose span we + // can get from the `MethodCall`. + span_lint_hir_and_then( + cx, + UNUSED_ENUMERATE_INDEX, + recv_init_expr.hir_id, + enumerate_span, + "you seem to use `.enumerate()` and immediately discard the index", + |diag| { + multispan_sugg_with_applicability( + diag, + "remove the `.enumerate()` call", + Applicability::MachineApplicable, + vec![ + (closure_param.span, new_closure_param), + ( + enumerate_span.with_lo(enumerate_recv.span.source_callsite().hi()), + String::new(), + ), + ], + ); + }, + ); + } +} + +/// Find the span of the explicit type of the element. +/// +/// # Returns +/// If the tuple argument: +/// * Has no explicit type, returns `None` +/// * Has an explicit tuple type with an implicit element type (`(usize, _)`), returns `None` +/// * Has an explicit tuple type with an explicit element type (`(_, i32)`), returns the span for +/// the element type. +fn find_elem_explicit_type_span(fn_decl: &FnDecl<'_>) -> Option { + if let [tuple_ty] = fn_decl.inputs + && let TyKind::Tup([_idx_ty, elem_ty]) = tuple_ty.kind + && !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer) + { + Some(elem_ty.span) + } else { + None + } +} diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index bf4af7946f4..6878fb3349d 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -8,6 +8,7 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_from_proc_macro; +use clippy_utils::source::snippet_opt; use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -32,6 +33,13 @@ declare_clippy_lint! { "detects missing documentation for private members" } +macro_rules! note_prev_span_then_ret { + ($prev_span:expr, $span:expr) => {{ + $prev_span = Some($span); + return; + }}; +} + pub struct MissingDoc { /// Whether to **only** check for missing documentation in items visible within the current /// crate. For example, `pub(crate)` items. @@ -39,6 +47,8 @@ pub struct MissingDoc { /// Stack of whether #[doc(hidden)] is set /// at each level which has lint attributes. doc_hidden_stack: Vec, + /// Used to keep tracking of the previous item, field or variants etc, to get the search span. + prev_span: Option, } impl Default for MissingDoc { @@ -54,6 +64,7 @@ impl MissingDoc { Self { crate_items_only, doc_hidden_stack: vec![false], + prev_span: None, } } @@ -108,7 +119,8 @@ impl MissingDoc { let has_doc = attrs .iter() - .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())); + .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())) + || matches!(self.search_span(sp), Some(span) if span_to_snippet_contains_docs(cx, span)); if !has_doc { span_lint( @@ -119,6 +131,32 @@ impl MissingDoc { ); } } + + /// Return a span to search for doc comments manually. + /// + /// # Example + /// ```ignore + /// fn foo() { ... } + /// ^^^^^^^^^^^^^^^^ prev_span + /// ↑ + /// | search_span | + /// ↓ + /// fn bar() { ... } + /// ^^^^^^^^^^^^^^^^ cur_span + /// ``` + fn search_span(&self, cur_span: Span) -> Option { + let prev_span = self.prev_span?; + let start_pos = if prev_span.contains(cur_span) { + // In case when the prev_span is an entire struct, or enum, + // and the current span is a field, or variant, we need to search from + // the starting pos of the previous span. + prev_span.lo() + } else { + prev_span.hi() + }; + let search_span = cur_span.with_lo(start_pos).with_hi(cur_span.lo()); + Some(search_span) + } } impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); @@ -138,6 +176,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate"); } + fn check_crate_post(&mut self, _: &LateContext<'tcx>) { + self.prev_span = None; + } + fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { match it.kind { hir::ItemKind::Fn(..) => { @@ -145,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { if it.ident.name == sym::main { let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID; if at_root { - return; + note_prev_span_then_ret!(self.prev_span, it.span); } } }, @@ -164,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Impl { .. } - | hir::ItemKind::Use(..) => return, + | hir::ItemKind::Use(..) => note_prev_span_then_ret!(self.prev_span, it.span), }; let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); @@ -173,6 +215,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { if !is_from_proc_macro(cx, it) { self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc); } + self.prev_span = Some(it.span); } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { @@ -182,16 +225,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { if !is_from_proc_macro(cx, trait_item) { self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc); } + self.prev_span = Some(trait_item.span); } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) { if cx.tcx.impl_trait_ref(cid).is_some() { - return; + note_prev_span_then_ret!(self.prev_span, impl_item.span); } } else { - return; + note_prev_span_then_ret!(self.prev_span, impl_item.span); } let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); @@ -199,6 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { if !is_from_proc_macro(cx, impl_item) { self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc); } + self.prev_span = Some(impl_item.span); } fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) { @@ -208,6 +253,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field"); } } + self.prev_span = Some(sf.span); } fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) { @@ -215,5 +261,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { if !is_from_proc_macro(cx, v) { self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant"); } + self.prev_span = Some(v.span); } } + +fn span_to_snippet_contains_docs(cx: &LateContext<'_>, search_span: Span) -> bool { + let Some(snippet) = snippet_opt(cx, search_span) else { + return false; + }; + snippet.lines().rev().any(|line| line.trim().starts_with("///")) +} diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 70fd07cd93c..648d780ac09 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -109,7 +109,14 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), + res: + Res::Def( + DefKind::Static { + mutability: Mutability::Mut, + .. + }, + _, + ), .. }, )) => { @@ -149,7 +156,13 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), + res: Res::Def( + DefKind::Static { + mutability: Mutability::Mut, + .. + }, + _ + ), .. } )) diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 72a2cca1e40..bc7b2c6b7c1 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::{span_lint, span_lint_hir}; use clippy_utils::higher; use rustc_hir as hir; use rustc_hir::intravisit; @@ -35,9 +35,34 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) { - use rustc_hir::intravisit::Visitor; + if in_external_macro(cx.sess(), ty.span) { + return; + } - MutVisitor { cx }.visit_ty(ty); + if let hir::TyKind::Ref( + _, + hir::MutTy { + ty: pty, + mutbl: hir::Mutability::Mut, + }, + ) = ty.kind + { + if let hir::TyKind::Ref( + _, + hir::MutTy { + mutbl: hir::Mutability::Mut, + .. + }, + ) = pty.kind + { + span_lint( + cx, + MUT_MUT, + ty.span, + "generally you want to avoid `&mut &mut _` if possible", + ); + } + } } } @@ -62,17 +87,19 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { intravisit::walk_expr(self, body); } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e) = expr.kind { if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) = e.kind { - span_lint( + span_lint_hir( self.cx, MUT_MUT, + expr.hir_id, expr.span, "generally you want to avoid `&mut &mut _` if possible", ); } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) { - span_lint( + span_lint_hir( self.cx, MUT_MUT, + expr.hir_id, expr.span, "this expression mutably borrows a mutable reference. Consider reborrowing", ); @@ -80,37 +107,4 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } } } - - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { - if in_external_macro(self.cx.sess(), ty.span) { - return; - } - - if let hir::TyKind::Ref( - _, - hir::MutTy { - ty: pty, - mutbl: hir::Mutability::Mut, - }, - ) = ty.kind - { - if let hir::TyKind::Ref( - _, - hir::MutTy { - mutbl: hir::Mutability::Mut, - .. - }, - ) = pty.kind - { - span_lint( - self.cx, - MUT_MUT, - ty.span, - "generally you want to avoid `&mut &mut _` if possible", - ); - } - } - - intravisit::walk_ty(self, ty); - } } diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index cebd2385656..6cb84bb78b6 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -290,14 +290,21 @@ impl NonCopyConst { promoted: None, }; let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); - let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP); + let result = cx + .tcx + .const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP); self.is_value_unfrozen_raw(cx, result, ty) } fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); - let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), rustc_span::DUMMY_SP); + let result = Self::const_eval_resolve( + cx.tcx, + cx.param_env, + ty::UnevaluatedConst::new(def_id, args), + rustc_span::DUMMY_SP, + ); self.is_value_unfrozen_raw(cx, result, ty) } diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index d0b37cd92e0..0ebdb031d5a 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::get_enclosing_block; use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; use clippy_utils::source::snippet; @@ -77,36 +77,52 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { if let Some(expr) = visitor.read_zero_expr { let applicability = Applicability::MaybeIncorrect; match vec_init_kind { - VecInitKind::WithConstCapacity(len) => { - span_lint_and_sugg( - cx, - READ_ZERO_BYTE_VEC, - expr.span, - "reading zero byte data to `Vec`", - "try", - format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")), - applicability, - ); - }, + VecInitKind::WithConstCapacity(len) => span_lint_hir_and_then( + cx, + READ_ZERO_BYTE_VEC, + expr.hir_id, + expr.span, + "reading zero byte data to `Vec`", + |diag| { + diag.span_suggestion( + expr.span, + "try", + format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")), + applicability, + ); + }, + ), VecInitKind::WithExprCapacity(hir_id) => { let e = cx.tcx.hir().expect_expr(hir_id); - span_lint_and_sugg( + span_lint_hir_and_then( cx, READ_ZERO_BYTE_VEC, + expr.hir_id, expr.span, "reading zero byte data to `Vec`", - "try", - format!( - "{}.resize({}, 0); {}", - ident.as_str(), - snippet(cx, e.span, ".."), - snippet(cx, expr.span, "..") - ), - applicability, + |diag| { + diag.span_suggestion( + expr.span, + "try", + format!( + "{}.resize({}, 0); {}", + ident.as_str(), + snippet(cx, e.span, ".."), + snippet(cx, expr.span, "..") + ), + applicability, + ); + }, ); }, _ => { - span_lint(cx, READ_ZERO_BYTE_VEC, expr.span, "reading zero byte data to `Vec`"); + span_lint_hir( + cx, + READ_ZERO_BYTE_VEC, + expr.hir_id, + expr.span, + "reading zero byte data to `Vec`", + ); }, } } diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index c2673bc409f..435899ddaa7 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -1,5 +1,5 @@ use crate::rustc_lint::LintContext; -use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir}; use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; use hir::Param; @@ -273,9 +273,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { && ident == path.segments[0].ident && count_closure_usage(cx, block, path) == 1 { - span_lint( + span_lint_hir( cx, REDUNDANT_CLOSURE_CALL, + second.hir_id, second.span, "closure called just once immediately after it was declared", ); diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 19697527467..8bc24eda465 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; @@ -380,7 +380,7 @@ fn check_final_expr<'tcx>( return; } - emit_return_lint(cx, ret_span, semi_spans, &replacement); + emit_return_lint(cx, ret_span, semi_spans, &replacement, expr.hir_id); }, ExprKind::If(_, then, else_clause_opt) => { check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone()); @@ -415,18 +415,31 @@ fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool { contains_if(expr, false) } -fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec, replacement: &RetReplacement<'_>) { +fn emit_return_lint( + cx: &LateContext<'_>, + ret_span: Span, + semi_spans: Vec, + replacement: &RetReplacement<'_>, + at: HirId, +) { if ret_span.from_expansion() { return; } - span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { - let suggestions = std::iter::once((ret_span, replacement.to_string())) - .chain(semi_spans.into_iter().map(|span| (span, String::new()))) - .collect(); + span_lint_hir_and_then( + cx, + NEEDLESS_RETURN, + at, + ret_span, + "unneeded `return` statement", + |diag| { + let suggestions = std::iter::once((ret_span, replacement.to_string())) + .chain(semi_spans.into_iter().map(|span| (span, String::new()))) + .collect(); - diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability()); - }); + diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability()); + }, + ); } fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { @@ -452,8 +465,8 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) // Go backwards while encountering whitespace and extend the given Span to that point. fn extend_span_to_previous_non_ws(cx: &LateContext<'_>, sp: Span) -> Span { if let Ok(prev_source) = cx.sess().source_map().span_to_prev_source(sp) { - let ws = [' ', '\t', '\n']; - if let Some(non_ws_pos) = prev_source.rfind(|c| !ws.contains(&c)) { + let ws = [b' ', b'\t', b'\n']; + if let Some(non_ws_pos) = prev_source.bytes().rposition(|c| !ws.contains(&c)) { let len = prev_source.len() - non_ws_pos - 1; return sp.with_lo(sp.lo() - BytePos::from_usize(len)); } diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index c0e4f3c368a..cf839941123 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -109,6 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { sym::core => (STD_INSTEAD_OF_CORE, "std", "core"), sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"), _ => { + self.prev_span = first_segment.ident.span; return; }, }, @@ -116,6 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { if cx.tcx.crate_name(def_id.krate) == sym::core { (ALLOC_INSTEAD_OF_CORE, "alloc", "core") } else { + self.prev_span = first_segment.ident.span; return; } }, diff --git a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs index 1af3733ebfa..f8bdb866ca3 100644 --- a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs +++ b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// static BUF: String = const { String::new() }; /// } /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST, perf, "suggest using `const` in `thread_local!` macro" diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index e47b14bf63b..3c11b481310 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -514,7 +514,7 @@ declare_clippy_lint! { /// ^^^^ ^^ `bool::then` only executes the closure if the condition is true! /// } /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub EAGER_TRANSMUTE, correctness, "eager evaluation of `transmute`" diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index bdef82e9c5e..2ad15ac8312 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -392,6 +392,10 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) { + if field.span.from_expansion() { + return; + } + let is_exported = cx.effective_visibilities.is_exported(field.def_id); self.check_ty( diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index 224ec475c51..d638af2b78b 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{expr_or_init, get_trait_def_id, path_def_id}; +use clippy_utils::{expr_or_init, fn_def_id_with_node_args, path_def_id}; use rustc_ast::BinOpKind; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -19,11 +19,11 @@ use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; declare_clippy_lint! { /// ### What it does - /// Checks that there isn't an infinite recursion in `PartialEq` trait - /// implementation. + /// Checks that there isn't an infinite recursion in trait + /// implementations. /// /// ### Why is this bad? - /// This is a hard to find infinite recursion which will crashing any code + /// This is a hard to find infinite recursion that will crash any code. /// using it. /// /// ### Example @@ -42,7 +42,7 @@ declare_clippy_lint! { /// Use instead: /// /// In such cases, either use `#[derive(PartialEq)]` or don't implement it. - #[clippy::version = "1.76.0"] + #[clippy::version = "1.77.0"] pub UNCONDITIONAL_RECURSION, suspicious, "detect unconditional recursion in some traits implementation" @@ -201,7 +201,6 @@ fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: Loca } } -#[allow(clippy::unnecessary_def_path)] fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, name: Ident, expr: &Expr<'_>) { let args = cx .tcx @@ -224,7 +223,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local && let Some(trait_) = impl_.of_trait && let Some(trait_def_id) = trait_.trait_def_id() // The trait is `ToString`. - && Some(trait_def_id) == get_trait_def_id(cx, &["alloc", "string", "ToString"]) + && cx.tcx.is_diagnostic_item(sym::ToString, trait_def_id) { let is_bad = match expr.kind { ExprKind::MethodCall(segment, _receiver, &[_arg], _) if segment.ident.name == name.name => { @@ -291,7 +290,6 @@ where self.map } - #[allow(clippy::unnecessary_def_path)] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { if self.found_default_call { return; @@ -303,7 +301,7 @@ where && is_default_method_on_current_ty(self.cx.tcx, qpath, self.implemented_ty_id) && let Some(method_def_id) = path_def_id(self.cx, f) && let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id) - && Some(trait_def_id) == get_trait_def_id(self.cx, &["core", "default", "Default"]) + && self.cx.tcx.is_diagnostic_item(sym::Default, trait_def_id) { self.found_default_call = true; span_error(self.cx, self.method_span, expr); @@ -312,10 +310,9 @@ where } impl UnconditionalRecursion { - #[allow(clippy::unnecessary_def_path)] fn init_default_impl_for_type_if_needed(&mut self, cx: &LateContext<'_>) { if self.default_impl_for_type.is_empty() - && let Some(default_trait_id) = get_trait_def_id(cx, &["core", "default", "Default"]) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) { let impls = cx.tcx.trait_impls_of(default_trait_id); for (ty, impl_def_ids) in impls.non_blanket_impls() { @@ -394,6 +391,34 @@ impl UnconditionalRecursion { } } +fn check_from(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, expr: &Expr<'_>) { + let Some(sig) = cx + .typeck_results() + .liberated_fn_sigs() + .get(cx.tcx.local_def_id_to_hir_id(method_def_id)) + else { + return; + }; + + // Check if we are calling `Into::into` where the node args match with our `From::from` signature: + // From::from signature: fn(S1) -> S2 + // >::into(s1), node_args=[S1, S2] + // If they do match, then it must mean that it is the blanket impl, + // which calls back into our `From::from` again (`Into` is not specializable). + // rustc's unconditional_recursion already catches calling `From::from` directly + if let Some((fn_def_id, node_args)) = fn_def_id_with_node_args(cx, expr) + && let [s1, s2] = **node_args + && let (Some(s1), Some(s2)) = (s1.as_type(), s2.as_type()) + && let Some(trait_def_id) = cx.tcx.trait_of_item(fn_def_id) + && cx.tcx.is_diagnostic_item(sym::Into, trait_def_id) + && get_impl_trait_def_id(cx, method_def_id) == cx.tcx.get_diagnostic_item(sym::From) + && s1 == sig.inputs()[0] + && s2 == sig.output() + { + span_error(cx, method_span, expr); + } +} + impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion { fn check_fn( &mut self, @@ -410,10 +435,11 @@ impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion { // Doesn't have a conditional return. && !has_conditional_return(body, expr) { - if name.name == sym::eq || name.name == sym::ne { - check_partial_eq(cx, method_span, method_def_id, name, expr); - } else if name.name == sym::to_string { - check_to_string(cx, method_span, method_def_id, name, expr); + match name.name { + sym::eq | sym::ne => check_partial_eq(cx, method_span, method_def_id, name, expr), + sym::to_string => check_to_string(cx, method_span, method_def_id, name, expr), + sym::from => check_from(cx, method_span, method_def_id, expr), + _ => {}, } self.check_default_new(cx, decl, body, method_span, method_def_id); } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1497d883dfc..d8c5f1b7382 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,7 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths, peel_blocks}; -use hir::{ExprKind, PatKind}; +use hir::{ExprKind, HirId, PatKind}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -135,22 +135,22 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { && is_ok_wild_or_dotdot_pattern(cx, pat) && let Some(op) = should_lint(cx, init) => { - emit_lint(cx, cond.span, op, &[pat.span]); + emit_lint(cx, cond.span, cond.hir_id, op, &[pat.span]); }, // we will capture only the case where the match is Ok( ) or Err( ) // prefer to match the minimum possible, and expand later if needed // to avoid false positives on something as used as this hir::ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { if non_consuming_ok_arm(cx, arm1) && non_consuming_err_arm(cx, arm2) { - emit_lint(cx, expr.span, op, &[arm1.pat.span]); + emit_lint(cx, expr.span, expr.hir_id, op, &[arm1.pat.span]); } if non_consuming_ok_arm(cx, arm2) && non_consuming_err_arm(cx, arm1) { - emit_lint(cx, expr.span, op, &[arm2.pat.span]); + emit_lint(cx, expr.span, expr.hir_id, op, &[arm2.pat.span]); } }, hir::ExprKind::Match(_, _, hir::MatchSource::Normal) => {}, _ if let Some(op) = should_lint(cx, expr) => { - emit_lint(cx, expr.span, op, &[]); + emit_lint(cx, expr.span, expr.hir_id, op, &[]); }, _ => {}, }; @@ -279,7 +279,7 @@ fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option { } } -fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) { +fn emit_lint(cx: &LateContext<'_>, span: Span, at: HirId, op: IoOp, wild_cards: &[Span]) { let (msg, help) = match op { IoOp::AsyncRead(false) => ( "read amount is not handled", @@ -301,7 +301,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) { IoOp::SyncWrite(true) | IoOp::AsyncWrite(true) => ("written amount is not handled", None), }; - span_lint_and_then(cx, UNUSED_IO_AMOUNT, span, msg, |diag| { + span_lint_hir_and_then(cx, UNUSED_IO_AMOUNT, at, span, msg, |diag| { if let Some(help_str) = help { diag.help(help_str); } diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index f1d0c22b1ae..3f4ab3e31cf 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable}; use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators}; use rustc_ast::Mutability; @@ -79,13 +79,15 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { } if !vis.found_peek_call { - span_lint_and_help( + span_lint_hir_and_then( cx, UNUSED_PEEKABLE, + local.hir_id, ident.span, "`peek` never called on `Peekable` iterator", - None, - "consider removing the call to `peekable`", + |diag| { + diag.help("consider removing the call to `peekable`"); + }, ); } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index a1b08d105b9..b28037db112 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -8,11 +8,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor}; use rustc_hir::{ - self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, - HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, + self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, + ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty as MiddleTy; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -95,10 +96,9 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { let stack_item = if let ItemKind::Impl(Impl { self_ty, generics, .. }) = item.kind && let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args - && parameters.as_ref().map_or(true, |params| { - params.parenthesized == GenericArgsParentheses::No - && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) - }) + && parameters + .as_ref() + .map_or(true, |params| params.parenthesized == GenericArgsParentheses::No) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) // expensive, should be last check @@ -226,7 +226,12 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } else { hir_ty_to_ty(cx.tcx, hir_ty) } - && same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity()) + && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() + && same_type_and_consts(ty, impl_ty) + // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that + // the lifetime parameters of `ty` are ellided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in + // which case we must still trigger the lint. + && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty)) { span_lint(cx, hir_ty.span); } @@ -318,3 +323,37 @@ fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) { span_lint(cx, span); } } + +/// Returns `true` if types `a` and `b` have the same lifetime parameters, otherwise returns +/// `false`. +/// +/// This function does not check that types `a` and `b` are the same types. +fn same_lifetimes<'tcx>(a: MiddleTy<'tcx>, b: MiddleTy<'tcx>) -> bool { + use rustc_middle::ty::{Adt, GenericArgKind}; + match (&a.kind(), &b.kind()) { + (&Adt(_, args_a), &Adt(_, args_b)) => { + args_a + .iter() + .zip(args_b.iter()) + .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) { + // TODO: Handle inferred lifetimes + (GenericArgKind::Lifetime(inner_a), GenericArgKind::Lifetime(inner_b)) => inner_a == inner_b, + (GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => same_lifetimes(type_a, type_b), + _ => true, + }) + }, + _ => a == b, + } +} + +/// Returns `true` if `ty` has no lifetime parameter, otherwise returns `false`. +fn has_no_lifetime(ty: MiddleTy<'_>) -> bool { + use rustc_middle::ty::{Adt, GenericArgKind}; + match ty.kind() { + &Adt(_, args) => !args + .iter() + // TODO: Handle inferred lifetimes + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(..))), + _ => true, + } +} diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 97b509a84f9..1ebe1d6a2c4 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -925,7 +925,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> { && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)) && match_type(self.cx, expr_ty, &paths::LINT) { - if let hir::def::Res::Def(DefKind::Static(..), _) = path.res { + if let hir::def::Res::Def(DefKind::Static { .. }, _) = path.res { let lint_name = last_path_segment(qpath).ident.name; self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); } else if let Some(local) = get_parent_local(self.cx, expr) { diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 38c832931fc..f4e277fd0c4 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -223,7 +223,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option read_mir_alloc_def_path( + Res::Def(DefKind::Static { .. }, def_id) => read_mir_alloc_def_path( cx, cx.tcx.eval_static_initializer(def_id).ok()?.inner(), cx.tcx.type_of(def_id).instantiate_identity(), diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 5410e8ac117..436f0cb79fb 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -213,7 +213,7 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { // Allow skipping imports containing user configured segments, // i.e. "...::utils::...::*" if user put `allowed-wildcard-imports = ["utils"]` in `Clippy.toml` fn is_allowed_via_config(segments: &[PathSegment<'_>], allowed_segments: &FxHashSet) -> bool { - // segment matching need to be exact instead of using 'contains', in case user unintentionaly put + // segment matching need to be exact instead of using 'contains', in case user unintentionally put // a single character in the config thus skipping most of the warnings. segments.iter().any(|seg| allowed_segments.contains(seg.ident.as_str())) } diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs new file mode 100644 index 00000000000..852d04cd21b --- /dev/null +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -0,0 +1,154 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher::VecArgs; +use clippy_utils::source::snippet; +use clippy_utils::visitors::for_each_expr; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{ExprKind, Node}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, ConstKind, Ty}; +use rustc_session::declare_lint_pass; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for array or vec initializations which call a function or method, + /// but which have a repeat count of zero. + /// + /// ### Why is this bad? + /// Such an initialization, despite having a repeat length of 0, will still call the inner function. + /// This may not be obvious and as such there may be unintended side effects in code. + /// + /// ### Example + /// ```no_run + /// fn side_effect() -> i32 { + /// println!("side effect"); + /// 10 + /// } + /// let a = [side_effect(); 0]; + /// ``` + /// Use instead: + /// ```no_run + /// fn side_effect() -> i32 { + /// println!("side effect"); + /// 10 + /// } + /// side_effect(); + /// let a: [i32; 0] = []; + /// ``` + #[clippy::version = "1.75.0"] + pub ZERO_REPEAT_SIDE_EFFECTS, + suspicious, + "usage of zero-sized initializations of arrays or vecs causing side effects" +} + +declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]); + +impl LateLintPass<'_> for ZeroRepeatSideEffects { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) { + if let Some(args) = VecArgs::hir(cx, expr) + && let VecArgs::Repeat(inner_expr, len) = args + && let ExprKind::Lit(l) = len.kind + && let LitKind::Int(i, _) = l.node + && i.0 == 0 + { + inner_check(cx, expr, inner_expr, true); + } else if let ExprKind::Repeat(inner_expr, _) = expr.kind + && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind() + && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() + && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) + && element_count == 0 + { + inner_check(cx, expr, inner_expr, false); + } + } +} + +fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr: &'_ rustc_hir::Expr<'_>, is_vec: bool) { + // check if expr is a call or has a call inside it + if for_each_expr(inner_expr, |x| { + if let ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _) = x.kind { + std::ops::ControlFlow::Break(()) + } else { + std::ops::ControlFlow::Continue(()) + } + }) + .is_some() + { + let parent_hir_node = cx.tcx.parent_hir_node(expr.hir_id); + let return_type = cx.typeck_results().expr_ty(expr); + + if let Node::Local(l) = parent_hir_node { + array_span_lint( + cx, + l.span, + inner_expr.span, + l.pat.span, + Some(return_type), + is_vec, + false, + ); + } else if let Node::Expr(x) = parent_hir_node + && let ExprKind::Assign(l, _, _) = x.kind + { + array_span_lint(cx, x.span, inner_expr.span, l.span, Some(return_type), is_vec, true); + } else { + span_lint_and_sugg( + cx, + ZERO_REPEAT_SIDE_EFFECTS, + expr.span.source_callsite(), + "function or method calls as the initial value in zero-sized array initializers may cause side effects", + "consider using", + format!( + "{{ {}; {}[] as {return_type} }}", + snippet(cx, inner_expr.span.source_callsite(), ".."), + if is_vec { "vec!" } else { "" }, + ), + Applicability::Unspecified, + ); + } + } +} + +fn array_span_lint( + cx: &LateContext<'_>, + expr_span: Span, + func_call_span: Span, + variable_name_span: Span, + expr_ty: Option>, + is_vec: bool, + is_assign: bool, +) { + let has_ty = expr_ty.is_some(); + + span_lint_and_sugg( + cx, + ZERO_REPEAT_SIDE_EFFECTS, + expr_span.source_callsite(), + "function or method calls as the initial value in zero-sized array initializers may cause side effects", + "consider using", + format!( + "{}; {}{}{} = {}[]{}{}", + snippet(cx, func_call_span.source_callsite(), ".."), + if has_ty && !is_assign { "let " } else { "" }, + snippet(cx, variable_name_span.source_callsite(), ".."), + if let Some(ty) = expr_ty + && !is_assign + { + format!(": {ty}") + } else { + String::new() + }, + if is_vec { "vec!" } else { "" }, + if let Some(ty) = expr_ty + && is_assign + { + format!(" as {ty}") + } else { + String::new() + }, + if is_assign { "" } else { ";" } + ), + Applicability::Unspecified, + ); +} diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index bf55040ddbc..d2bb719a517 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.78" +version = "0.1.79" edition = "2021" publish = false diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index e75d5953fae..046087d3298 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -10,8 +10,10 @@ use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; +use rustc_middle::mir::ConstValue; use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy}; use rustc_middle::{bug, mir, span_bug}; +use rustc_span::def_id::DefId; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; use rustc_target::abi::Size; @@ -307,6 +309,12 @@ impl ConstantSource { } } +/// Attempts to check whether the expression is a constant representing an empty slice, str, array, +/// etc… +pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option { + ConstEvalLateContext::new(lcx, lcx.typeck_results()).expr_is_empty(e) +} + /// Attempts to evaluate the expression as a constant. pub fn constant<'tcx>( lcx: &LateContext<'tcx>, @@ -406,7 +414,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { match e.kind { ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e), - ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), + ExprKind::Path(ref qpath) => { + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { + let result = mir_to_const(this.lcx, result)?; + this.source = ConstantSource::Constant; + Some(result) + }) + }, ExprKind::Block(block, _) => self.block(block), ExprKind::Lit(lit) => { if is_direct_expn_of(e.span, "cfg").is_some() { @@ -472,6 +486,49 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } + /// Simple constant folding to determine if an expression is an empty slice, str, array, … + /// `None` will be returned if the constness cannot be determined, or if the resolution + /// leaves the local crate. + pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option { + match e.kind { + ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value), + ExprKind::DropTemps(e) => self.expr_is_empty(e), + ExprKind::Path(ref qpath) => { + if !self + .typeck_results + .qpath_res(qpath, e.hir_id) + .opt_def_id() + .is_some_and(DefId::is_local) + { + return None; + } + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { + mir_is_empty(this.lcx, result) + }) + }, + ExprKind::Lit(lit) => { + if is_direct_expn_of(e.span, "cfg").is_some() { + None + } else { + match &lit.node { + LitKind::Str(is, _) => Some(is.is_empty()), + LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => Some(s.is_empty()), + _ => None, + } + } + }, + ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()), + ExprKind::Repeat(..) => { + if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() { + Some(n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)? == 0) + } else { + span_bug!(e.span, "typeck error"); + } + }, + _ => None, + } + } + #[expect(clippy::cast_possible_wrap)] fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option> { use self::Constant::{Bool, Int}; @@ -519,8 +576,11 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { vec.iter().map(|elem| self.expr(elem)).collect::>() } - /// Lookup a possibly constant expression from an `ExprKind::Path`. - fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option> { + /// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it. + fn fetch_path_and_apply(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option + where + F: FnOnce(&mut Self, rustc_middle::mir::Const<'tcx>) -> Option, + { let res = self.typeck_results.qpath_res(qpath, id); match res { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { @@ -553,9 +613,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() .map(|val| rustc_middle::mir::Const::from_value(val, ty))?; - let result = mir_to_const(self.lcx, result)?; - self.source = ConstantSource::Constant; - Some(result) + f(self, result) }, _ => None, } @@ -746,7 +804,6 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option> { - use rustc_middle::mir::ConstValue; let mir::Const::Val(val, _) = result else { // We only work on evaluated consts. return None; @@ -794,6 +851,42 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> } } +fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option { + let mir::Const::Val(val, _) = result else { + // We only work on evaluated consts. + return None; + }; + match (val, result.ty().kind()) { + (_, ty::Ref(_, inner_ty, _)) => match inner_ty.kind() { + ty::Str | ty::Slice(_) => { + if let ConstValue::Indirect { alloc_id, offset } = val { + // Get the length from the slice, using the same formula as + // [`ConstValue::try_get_slice_bytes_for_diagnostics`]. + let a = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner(); + let ptr_size = lcx.tcx.data_layout.pointer_size; + if a.size() < offset + 2 * ptr_size { + // (partially) dangling reference + return None; + } + let len = a + .read_scalar(&lcx.tcx, alloc_range(offset + ptr_size, ptr_size), false) + .ok()? + .to_target_usize(&lcx.tcx) + .ok()?; + Some(len == 0) + } else { + None + } + }, + ty::Array(_, len) => Some(len.try_to_target_usize(lcx.tcx)? == 0), + _ => None, + }, + (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(lcx.tcx)? == 0), + (ConstValue::ZeroSized, _) => Some(true), + _ => None, + } +} + fn field_of_struct<'tcx>( adt_def: ty::AdtDef<'tcx>, lcx: &LateContext<'tcx>, diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 6ed46e5dde0..0352696f93e 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -36,6 +36,20 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// Usually it's nicer to provide more context for lint messages. /// Be sure the output is understandable when you use this method. /// +/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine +/// the lint level. +/// For the `span_lint` function, the node that was passed into the `LintPass::check_*` function is +/// used. +/// +/// If you're emitting the lint at the span of a different node than the one provided by the +/// `LintPass::check_*` function, consider using [`span_lint_hir`] instead. +/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node +/// highlighted in the displayed warning. +/// +/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// where you would expect it to. +/// If it doesn't, you likely need to use [`span_lint_hir`] instead. +/// /// # Example /// /// ```ignore @@ -61,6 +75,20 @@ pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into( /// /// If you change the signature, remember to update the internal lint `CollapsibleCalls` /// +/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine +/// the lint level. +/// For the `span_lint_and_note` function, the node that was passed into the `LintPass::check_*` +/// function is used. +/// +/// If you're emitting the lint at the span of a different node than the one provided by the +/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead. +/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node +/// highlighted in the displayed warning. +/// +/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// where you would expect it to. +/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. +/// /// # Example /// /// ```text @@ -139,6 +181,20 @@ pub fn span_lint_and_note( /// /// If you need to customize your lint output a lot, use this function. /// If you change the signature, remember to update the internal lint `CollapsibleCalls` +/// +/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine +/// the lint level. +/// For the `span_lint_and_then` function, the node that was passed into the `LintPass::check_*` +/// function is used. +/// +/// If you're emitting the lint at the span of a different node than the one provided by the +/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead. +/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node +/// highlighted in the displayed warning. +/// +/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// where you would expect it to. +/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. pub fn span_lint_and_then(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F) where C: LintContext, @@ -152,6 +208,30 @@ where }); } +/// Like [`span_lint`], but emits the lint at the node identified by the given `HirId`. +/// +/// This is in contrast to [`span_lint`], which always emits the lint at the node that was last +/// passed to the `LintPass::check_*` function. +/// +/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined +/// via the `#[expect]` attribute. +/// +/// For example: +/// ```ignore +/// fn f() { /* */ +/// +/// #[allow(clippy::some_lint)] +/// let _x = /* */; +/// } +/// ``` +/// If `some_lint` does its analysis in `LintPass::check_fn` (at ``) and emits a lint at +/// `` using [`span_lint`], then allowing the lint at `` as attempted in the snippet +/// will not work! +/// Even though that is where the warning points at, which would be confusing to users. +/// +/// Instead, use this function and also pass the `HirId` of ``, which will let +/// the compiler check lint level attributes at the place of the expression and +/// the `#[allow]` will work. pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { #[expect(clippy::disallowed_methods)] cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| { @@ -159,6 +239,30 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s }); } +/// Like [`span_lint_and_then`], but emits the lint at the node identified by the given `HirId`. +/// +/// This is in contrast to [`span_lint_and_then`], which always emits the lint at the node that was +/// last passed to the `LintPass::check_*` function. +/// +/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined +/// via the `#[expect]` attribute. +/// +/// For example: +/// ```ignore +/// fn f() { /* */ +/// +/// #[allow(clippy::some_lint)] +/// let _x = /* */; +/// } +/// ``` +/// If `some_lint` does its analysis in `LintPass::check_fn` (at ``) and emits a lint at +/// `` using [`span_lint`], then allowing the lint at `` as attempted in the snippet +/// will not work! +/// Even though that is where the warning points at, which would be confusing to users. +/// +/// Instead, use this function and also pass the `HirId` of ``, which will let +/// the compiler check lint level attributes at the place of the expression and +/// the `#[allow]` will work. pub fn span_lint_hir_and_then( cx: &LateContext<'_>, lint: &'static Lint, @@ -182,6 +286,20 @@ pub fn span_lint_hir_and_then( /// /// If you change the signature, remember to update the internal lint `CollapsibleCalls` /// +/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine +/// the lint level. +/// For the `span_lint_and_sugg` function, the node that was passed into the `LintPass::check_*` +/// function is used. +/// +/// If you're emitting the lint at the span of a different node than the one provided by the +/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead. +/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node +/// highlighted in the displayed warning. +/// +/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// where you would expect it to. +/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. +/// /// # Example /// /// ```text diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index b4cc747e0e6..11b56ed47de 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2246,8 +2246,21 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { /// Returns the `DefId` of the callee if the given expression is a function or method call. pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { + fn_def_id_with_node_args(cx, expr).map(|(did, _)| did) +} + +/// Returns the `DefId` of the callee if the given expression is a function or method call, +/// as well as its node args. +pub fn fn_def_id_with_node_args<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'_>, +) -> Option<(DefId, rustc_ty::GenericArgsRef<'tcx>)> { + let typeck = cx.typeck_results(); match &expr.kind { - ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id), + ExprKind::MethodCall(..) => Some(( + typeck.type_dependent_def_id(expr.hir_id)?, + typeck.node_args(expr.hir_id), + )), ExprKind::Call( Expr { kind: ExprKind::Path(qpath), @@ -2259,9 +2272,9 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or // deref to fn pointers, dyn Fn, impl Fn - #8850 if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) = - cx.typeck_results().qpath_res(qpath, *path_hir_id) + typeck.qpath_res(qpath, *path_hir_id) { - Some(id) + Some((id, typeck.node_args(*path_hir_id))) } else { None } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 987f28192a8..456b8019e95 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -19,6 +19,8 @@ pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "B pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"]; pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"]; +pub const CORE_ITER_ENUMERATE_METHOD: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "enumerate"]; +pub const CORE_ITER_ENUMERATE_STRUCT: [&str; 5] = ["core", "iter", "adapters", "enumerate", "Enumerate"]; pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 296eb8dd340..9a3a41e1d1e 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.78" +version = "0.1.79" edition = "2021" publish = false diff --git a/rust-toolchain b/rust-toolchain index 070b62887d5..a63e66f3214 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-03-07" +channel = "nightly-2024-03-21" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/tests/ui-internal/disallow_span_lint.stderr b/tests/ui-internal/disallow_span_lint.stderr index ae5d6843406..cfc590bed36 100644 --- a/tests/ui-internal/disallow_span_lint.stderr +++ b/tests/ui-internal/disallow_span_lint.stderr @@ -4,6 +4,7 @@ error: use of a disallowed method `rustc_lint::context::LintContext::span_lint` LL | cx.span_lint(lint, span, msg, |_| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml) = note: `-D clippy::disallowed-methods` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` @@ -12,6 +13,8 @@ error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_ | LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml) error: aborting due to 2 previous errors diff --git a/tests/ui-toml/dbg_macro/dbg_macro.fixed b/tests/ui-toml/dbg_macro/dbg_macro.fixed new file mode 100644 index 00000000000..d42b29ba21a --- /dev/null +++ b/tests/ui-toml/dbg_macro/dbg_macro.fixed @@ -0,0 +1,38 @@ +//@compile-flags: --test +#![warn(clippy::dbg_macro)] +#![allow(clippy::unnecessary_operation, clippy::no_effect)] + +fn foo(n: u32) -> u32 { + if let Some(n) = n.checked_sub(4) { n } else { n } +} + +fn factorial(n: u32) -> u32 { + if n <= 1 { + 1 + } else { + n * factorial(n - 1) + } +} + +fn main() { + 42; + foo(3) + factorial(4); + (1, 2, 3, 4, 5); +} + +#[test] +pub fn issue8481() { + dbg!(1); +} + +#[cfg(test)] +fn foo2() { + dbg!(1); +} + +#[cfg(test)] +mod mod1 { + fn func() { + dbg!(1); + } +} diff --git a/tests/ui-toml/dbg_macro/dbg_macro.rs b/tests/ui-toml/dbg_macro/dbg_macro.rs index 67129e62477..bd189b1576f 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.rs +++ b/tests/ui-toml/dbg_macro/dbg_macro.rs @@ -1,6 +1,7 @@ //@compile-flags: --test #![warn(clippy::dbg_macro)] -//@no-rustfix +#![allow(clippy::unnecessary_operation, clippy::no_effect)] + fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } } @@ -15,9 +16,7 @@ fn factorial(n: u32) -> u32 { fn main() { dbg!(42); - dbg!(dbg!(dbg!(42))); foo(3) + dbg!(factorial(4)); - dbg!(1, 2, dbg!(3, 4)); dbg!(1, 2, 3, 4, 5); } diff --git a/tests/ui-toml/dbg_macro/dbg_macro.stderr b/tests/ui-toml/dbg_macro/dbg_macro.stderr index 8ffc426be2d..129fab5ff97 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.stderr +++ b/tests/ui-toml/dbg_macro/dbg_macro.stderr @@ -1,5 +1,5 @@ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:5:22 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:6:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:9:8 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:10:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | if n <= 1 { | ~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:10:9 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:11:9 | LL | dbg!(1) | ^^^^^^^ @@ -34,7 +34,7 @@ LL | 1 | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:12:9 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:13:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:17:5 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:18:5 | LL | dbg!(42); | ^^^^^^^^ @@ -55,17 +55,6 @@ help: remove the invocation before committing it to a version control system LL | 42; | ~~ -error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:18:5 - | -LL | dbg!(dbg!(dbg!(42))); - | ^^^^^^^^^^^^^^^^^^^^ - | -help: remove the invocation before committing it to a version control system - | -LL | dbg!(dbg!(42)); - | ~~~~~~~~~~~~~~ - error: the `dbg!` macro is intended as a debugging tool --> tests/ui-toml/dbg_macro/dbg_macro.rs:19:14 | @@ -80,17 +69,6 @@ LL | foo(3) + factorial(4); error: the `dbg!` macro is intended as a debugging tool --> tests/ui-toml/dbg_macro/dbg_macro.rs:20:5 | -LL | dbg!(1, 2, dbg!(3, 4)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: remove the invocation before committing it to a version control system - | -LL | (1, 2, dbg!(3, 4)); - | ~~~~~~~~~~~~~~~~~~ - -error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:21:5 - | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ | @@ -99,5 +77,5 @@ help: remove the invocation before committing it to a version control system LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 663c2eb2c37..523148d6586 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -1,7 +1,7 @@ //@aux-build:proc_macros.rs #![feature(lint_reasons)] #![deny(clippy::allow_attributes_without_reason)] -#![allow(unfulfilled_lint_expectations)] +#![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)] extern crate proc_macros; use proc_macros::{external, with_span}; diff --git a/tests/ui/allow_attributes_without_reason.stderr b/tests/ui/allow_attributes_without_reason.stderr index 3c81233bf77..770a771ec3d 100644 --- a/tests/ui/allow_attributes_without_reason.stderr +++ b/tests/ui/allow_attributes_without_reason.stderr @@ -1,8 +1,8 @@ error: `allow` attribute without specifying a reason --> tests/ui/allow_attributes_without_reason.rs:4:1 | -LL | #![allow(unfulfilled_lint_expectations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` note: the lint level is defined here diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed index c66e0c1f602..160f3b94663 100644 --- a/tests/ui/assigning_clones.fixed +++ b/tests/ui/assigning_clones.fixed @@ -128,6 +128,19 @@ fn ignore_generic_clone(a: &mut T, b: &T) { *a = b.clone(); } +#[clippy::msrv = "1.62"] +fn msrv_1_62(mut a: String, b: String, c: &str) { + a.clone_from(&b); + // Should not be linted, as clone_into wasn't stabilized until 1.63 + a = c.to_owned(); +} + +#[clippy::msrv = "1.63"] +fn msrv_1_63(mut a: String, b: String, c: &str) { + a.clone_from(&b); + c.clone_into(&mut a); +} + macro_rules! clone_inside { ($a:expr, $b: expr) => { $a = $b.clone(); diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs index b9f994d3e03..14ba1d4db9a 100644 --- a/tests/ui/assigning_clones.rs +++ b/tests/ui/assigning_clones.rs @@ -128,6 +128,19 @@ fn ignore_generic_clone(a: &mut T, b: &T) { *a = b.clone(); } +#[clippy::msrv = "1.62"] +fn msrv_1_62(mut a: String, b: String, c: &str) { + a = b.clone(); + // Should not be linted, as clone_into wasn't stabilized until 1.63 + a = c.to_owned(); +} + +#[clippy::msrv = "1.63"] +fn msrv_1_63(mut a: String, b: String, c: &str) { + a = b.clone(); + a = c.to_owned(); +} + macro_rules! clone_inside { ($a:expr, $b: expr) => { $a = $b.clone(); diff --git a/tests/ui/assigning_clones.stderr b/tests/ui/assigning_clones.stderr index b76323f3606..ba59f067431 100644 --- a/tests/ui/assigning_clones.stderr +++ b/tests/ui/assigning_clones.stderr @@ -67,41 +67,59 @@ error: assigning the result of `Clone::clone()` may be inefficient LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:133:5 + | +LL | a = b.clone(); + | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:140:5 + | +LL | a = b.clone(); + | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` + error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:145:5 + --> tests/ui/assigning_clones.rs:141:5 + | +LL | a = c.to_owned(); + | ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:158:5 | LL | *mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:149:5 + --> tests/ui/assigning_clones.rs:162:5 | LL | mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:170:5 + --> tests/ui/assigning_clones.rs:183:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:174:5 + --> tests/ui/assigning_clones.rs:187:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:178:5 + --> tests/ui/assigning_clones.rs:191:5 | LL | *mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:182:5 + --> tests/ui/assigning_clones.rs:195:5 | LL | mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)` -error: aborting due to 17 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index 75f7a20f961..a6f3b164c9b 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -11,8 +11,8 @@ use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::token::Star; use syn::{ - parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, - Signature, TraitItem, Type, + parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent, + PatType, Signature, TraitItem, Type, Visibility, }; #[proc_macro_attribute] @@ -101,9 +101,7 @@ pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream { let mut item = parse_macro_input!(item as ItemFn); let span = item.block.brace_token.span; - if item.sig.asyncness.is_some() { - item.sig.asyncness = None; - } + item.sig.asyncness = None; let crate_name = quote! { fake_crate }; let block = item.block; @@ -128,7 +126,7 @@ pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn fake_desugar_await(_args: TokenStream, input: TokenStream) -> TokenStream { - let mut async_fn = syn::parse_macro_input!(input as syn::ItemFn); + let mut async_fn = parse_macro_input!(input as syn::ItemFn); for stmt in &mut async_fn.block.stmts { if let syn::Stmt::Expr(syn::Expr::Match(syn::ExprMatch { expr: scrutinee, .. }), _) = stmt { @@ -145,3 +143,36 @@ pub fn fake_desugar_await(_args: TokenStream, input: TokenStream) -> TokenStream quote!(#async_fn).into() } + +#[proc_macro_attribute] +pub fn rewrite_struct(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut item_struct = parse_macro_input!(input as syn::ItemStruct); + // remove struct attributes including doc comments. + item_struct.attrs = vec![]; + if let Visibility::Public(token) = item_struct.vis { + // set vis to `pub(crate)` to trigger `missing_docs_in_private_items` lint. + let new_vis: Visibility = syn::parse_quote_spanned!(token.span() => pub(crate)); + item_struct.vis = new_vis; + } + if let syn::Fields::Named(fields) = &mut item_struct.fields { + for field in &mut fields.named { + // remove all attributes from fields as well. + field.attrs = vec![]; + } + } + + quote!(#item_struct).into() +} + +#[proc_macro_attribute] +pub fn with_empty_docs(_attr: TokenStream, input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + let attrs: Vec = vec![]; + let doc_comment = ""; + quote! { + #(#attrs)* + #[doc = #doc_comment] + #item + } + .into() +} diff --git a/tests/ui/await_holding_lock.rs b/tests/ui/await_holding_lock.rs index 27b57b64813..8e5510e6cd0 100644 --- a/tests/ui/await_holding_lock.rs +++ b/tests/ui/await_holding_lock.rs @@ -1,4 +1,5 @@ #![warn(clippy::await_holding_lock)] +#![allow(clippy::readonly_write_lock)] // When adding or modifying a test, please do the same for parking_lot::Mutex. mod std_mutex { diff --git a/tests/ui/await_holding_lock.stderr b/tests/ui/await_holding_lock.stderr index e58436345b5..0af48a36acc 100644 --- a/tests/ui/await_holding_lock.stderr +++ b/tests/ui/await_holding_lock.stderr @@ -1,12 +1,12 @@ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:9:13 + --> tests/ui/await_holding_lock.rs:10:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:11:15 + --> tests/ui/await_holding_lock.rs:12:15 | LL | baz().await | ^^^^^ @@ -14,40 +14,40 @@ LL | baz().await = help: to override `-D warnings` add `#[allow(clippy::await_holding_lock)]` error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:25:13 + --> tests/ui/await_holding_lock.rs:26:13 | LL | let guard = x.read().unwrap(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:27:15 + --> tests/ui/await_holding_lock.rs:28:15 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:31:13 + --> tests/ui/await_holding_lock.rs:32:13 | LL | let mut guard = x.write().unwrap(); | ^^^^^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:33:15 + --> tests/ui/await_holding_lock.rs:34:15 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:53:13 + --> tests/ui/await_holding_lock.rs:54:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:56:28 + --> tests/ui/await_holding_lock.rs:57:28 | LL | let second = baz().await; | ^^^^^ @@ -56,79 +56,79 @@ LL | let third = baz().await; | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:67:17 + --> tests/ui/await_holding_lock.rs:68:17 | LL | let guard = x.lock().unwrap(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:69:19 + --> tests/ui/await_holding_lock.rs:70:19 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:80:17 + --> tests/ui/await_holding_lock.rs:81:17 | LL | let guard = x.lock().unwrap(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:82:19 + --> tests/ui/await_holding_lock.rs:83:19 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:93:13 + --> tests/ui/await_holding_lock.rs:94:13 | LL | let guard = x.lock(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:95:15 + --> tests/ui/await_holding_lock.rs:96:15 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:109:13 + --> tests/ui/await_holding_lock.rs:110:13 | LL | let guard = x.read(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:111:15 + --> tests/ui/await_holding_lock.rs:112:15 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:115:13 + --> tests/ui/await_holding_lock.rs:116:13 | LL | let mut guard = x.write(); | ^^^^^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:117:15 + --> tests/ui/await_holding_lock.rs:118:15 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:137:13 + --> tests/ui/await_holding_lock.rs:138:13 | LL | let guard = x.lock(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:140:28 + --> tests/ui/await_holding_lock.rs:141:28 | LL | let second = baz().await; | ^^^^^ @@ -137,40 +137,40 @@ LL | let third = baz().await; | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:151:17 + --> tests/ui/await_holding_lock.rs:152:17 | LL | let guard = x.lock(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:153:19 + --> tests/ui/await_holding_lock.rs:154:19 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:164:17 + --> tests/ui/await_holding_lock.rs:165:17 | LL | let guard = x.lock(); | ^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:166:19 + --> tests/ui/await_holding_lock.rs:167:19 | LL | baz().await | ^^^^^ error: this `MutexGuard` is held across an `await` point - --> tests/ui/await_holding_lock.rs:185:9 + --> tests/ui/await_holding_lock.rs:186:9 | LL | let mut guard = x.lock().unwrap(); | ^^^^^^^^^ | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> tests/ui/await_holding_lock.rs:189:11 + --> tests/ui/await_holding_lock.rs:190:11 | LL | baz().await; | ^^^^^ diff --git a/tests/ui/bool_assert_comparison.fixed b/tests/ui/bool_assert_comparison.fixed index 63b8e27e1c6..b05166a055e 100644 --- a/tests/ui/bool_assert_comparison.fixed +++ b/tests/ui/bool_assert_comparison.fixed @@ -1,4 +1,4 @@ -#![allow(unused, clippy::assertions_on_constants)] +#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] use std::ops::Not; diff --git a/tests/ui/bool_assert_comparison.rs b/tests/ui/bool_assert_comparison.rs index 58f81fedb79..dc51fcf1d36 100644 --- a/tests/ui/bool_assert_comparison.rs +++ b/tests/ui/bool_assert_comparison.rs @@ -1,4 +1,4 @@ -#![allow(unused, clippy::assertions_on_constants)] +#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] use std::ops::Not; diff --git a/tests/ui/cast_lossless_bool.fixed b/tests/ui/cast_lossless_bool.fixed index a4ce1c6f928..51a38a60cf6 100644 --- a/tests/ui/cast_lossless_bool.fixed +++ b/tests/ui/cast_lossless_bool.fixed @@ -1,6 +1,8 @@ #![allow(dead_code)] #![warn(clippy::cast_lossless)] +type U8 = u8; + fn main() { // Test clippy::cast_lossless with casts to integer types let _ = u8::from(true); @@ -19,6 +21,8 @@ fn main() { // Test with an expression wrapped in parens let _ = u16::from(true | false); + + let _ = U8::from(true); } // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_bool.rs b/tests/ui/cast_lossless_bool.rs index e5b1c30c103..cb307bd68e4 100644 --- a/tests/ui/cast_lossless_bool.rs +++ b/tests/ui/cast_lossless_bool.rs @@ -1,6 +1,8 @@ #![allow(dead_code)] #![warn(clippy::cast_lossless)] +type U8 = u8; + fn main() { // Test clippy::cast_lossless with casts to integer types let _ = true as u8; @@ -19,6 +21,8 @@ fn main() { // Test with an expression wrapped in parens let _ = (true | false) as u16; + + let _ = true as U8; } // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_bool.stderr b/tests/ui/cast_lossless_bool.stderr index 792b30b7a38..b47b35461f6 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(_)` - --> tests/ui/cast_lossless_bool.rs:6:13 + --> tests/ui/cast_lossless_bool.rs:8:13 | LL | let _ = true as u8; | ^^^^^^^^^^ help: try: `u8::from(true)` @@ -8,82 +8,88 @@ LL | let _ = true as u8; = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` - --> tests/ui/cast_lossless_bool.rs:7:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:8:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:9:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:10:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:11:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:13:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:14:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:15:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:16:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:17:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:18:13 + --> tests/ui/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(_)` - --> tests/ui/cast_lossless_bool.rs:21:13 + --> tests/ui/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(_)` + --> tests/ui/cast_lossless_bool.rs:25:13 + | +LL | let _ = true as U8; + | ^^^^^^^^^^ help: try: `U8::from(true)` + error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` - --> tests/ui/cast_lossless_bool.rs:49:13 + --> tests/ui/cast_lossless_bool.rs:53:13 | LL | let _ = true as u8; | ^^^^^^^^^^ help: try: `u8::from(true)` -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index f4f2e4773a5..96a67b1945c 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -1,11 +1,16 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] +type F32 = f32; +type F64 = f64; + fn main() { // Test clippy::cast_lossless with casts to floating-point types let x0 = 1i8; let _ = f32::from(x0); let _ = f64::from(x0); + let _ = F32::from(x0); + let _ = F64::from(x0); let x1 = 1u8; let _ = f32::from(x1); let _ = f64::from(x1); diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index fdd88ed36fc..d37b2c1d920 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,11 +1,16 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] +type F32 = f32; +type F64 = f64; + fn main() { // Test clippy::cast_lossless with casts to floating-point types let x0 = 1i8; let _ = x0 as f32; let _ = x0 as f64; + let _ = x0 as F32; + let _ = x0 as F64; let x1 = 1u8; let _ = x1 as f32; let _ = x1 as f64; diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index e70f81eb91f..ad7de760adf 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,5 +1,5 @@ error: casting `i8` to `f32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:7:13 + --> tests/ui/cast_lossless_float.rs:10:13 | LL | let _ = x0 as f32; | ^^^^^^^^^ help: try: `f32::from(x0)` @@ -8,64 +8,76 @@ LL | let _ = x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` error: casting `i8` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:8:13 + --> tests/ui/cast_lossless_float.rs:11:13 | LL | let _ = x0 as f64; | ^^^^^^^^^ help: try: `f64::from(x0)` +error: casting `i8` to `F32` may become silently lossy if you later change the type + --> tests/ui/cast_lossless_float.rs:12:13 + | +LL | let _ = x0 as F32; + | ^^^^^^^^^ help: try: `F32::from(x0)` + +error: casting `i8` to `F64` may become silently lossy if you later change the type + --> tests/ui/cast_lossless_float.rs:13:13 + | +LL | let _ = x0 as F64; + | ^^^^^^^^^ help: try: `F64::from(x0)` + error: casting `u8` to `f32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:10:13 + --> tests/ui/cast_lossless_float.rs:15:13 | LL | let _ = x1 as f32; | ^^^^^^^^^ help: try: `f32::from(x1)` error: casting `u8` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:11:13 + --> tests/ui/cast_lossless_float.rs:16:13 | LL | let _ = x1 as f64; | ^^^^^^^^^ help: try: `f64::from(x1)` error: casting `i16` to `f32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:13:13 + --> tests/ui/cast_lossless_float.rs:18:13 | LL | let _ = x2 as f32; | ^^^^^^^^^ help: try: `f32::from(x2)` error: casting `i16` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:14:13 + --> tests/ui/cast_lossless_float.rs:19:13 | LL | let _ = x2 as f64; | ^^^^^^^^^ help: try: `f64::from(x2)` error: casting `u16` to `f32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:16:13 + --> tests/ui/cast_lossless_float.rs:21:13 | LL | let _ = x3 as f32; | ^^^^^^^^^ help: try: `f32::from(x3)` error: casting `u16` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:17:13 + --> tests/ui/cast_lossless_float.rs:22:13 | LL | let _ = x3 as f64; | ^^^^^^^^^ help: try: `f64::from(x3)` error: casting `i32` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:19:13 + --> tests/ui/cast_lossless_float.rs:24:13 | LL | let _ = x4 as f64; | ^^^^^^^^^ help: try: `f64::from(x4)` error: casting `u32` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:21:13 + --> tests/ui/cast_lossless_float.rs:26:13 | LL | let _ = x5 as f64; | ^^^^^^^^^ help: try: `f64::from(x5)` error: casting `f32` to `f64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_float.rs:24:13 + --> tests/ui/cast_lossless_float.rs:29:13 | LL | let _ = 1.0f32 as f64; | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index 5e7e545e764..291556a9774 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -1,6 +1,9 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] +type I64 = i64; +type U128 = u128; + fn main() { // Test clippy::cast_lossless with casts to integer types let _ = i16::from(1i8); @@ -24,6 +27,13 @@ fn main() { // Test with an expression wrapped in parens let _ = u16::from(1u8 + 1u8); + + let _ = I64::from(1i8); + + // Do not lint if destination type is u128 + // see https://github.com/rust-lang/rust-clippy/issues/12492 + let _ = 1u8 as u128; + let _ = 1u8 as U128; } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 0d69ddbd586..a917c7a371d 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,6 +1,9 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] +type I64 = i64; +type U128 = u128; + fn main() { // Test clippy::cast_lossless with casts to integer types let _ = 1i8 as i16; @@ -24,6 +27,13 @@ fn main() { // Test with an expression wrapped in parens let _ = (1u8 + 1u8) as u16; + + let _ = 1i8 as I64; + + // Do not lint if destination type is u128 + // see https://github.com/rust-lang/rust-clippy/issues/12492 + let _ = 1u8 as u128; + let _ = 1u8 as U128; } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index 43d4ce3ce91..aaece939285 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,5 +1,5 @@ error: casting `i8` to `i16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:6:13 + --> tests/ui/cast_lossless_integer.rs:9:13 | LL | let _ = 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` @@ -8,124 +8,130 @@ LL | let _ = 1i8 as i16; = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:7:13 + --> tests/ui/cast_lossless_integer.rs:10:13 | LL | let _ = 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting `i8` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:8:13 + --> tests/ui/cast_lossless_integer.rs:11:13 | LL | let _ = 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting `u8` to `i16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:9:13 + --> tests/ui/cast_lossless_integer.rs:12:13 | LL | let _ = 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting `u8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:10:13 + --> tests/ui/cast_lossless_integer.rs:13:13 | LL | let _ = 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting `u8` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:11:13 + --> tests/ui/cast_lossless_integer.rs:14:13 | LL | let _ = 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting `u8` to `u16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:12:13 + --> tests/ui/cast_lossless_integer.rs:15:13 | LL | let _ = 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting `u8` to `u32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:13:13 + --> tests/ui/cast_lossless_integer.rs:16:13 | LL | let _ = 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting `u8` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:14:13 + --> tests/ui/cast_lossless_integer.rs:17:13 | LL | let _ = 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting `i16` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:15:13 + --> tests/ui/cast_lossless_integer.rs:18:13 | LL | let _ = 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting `i16` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:16:13 + --> tests/ui/cast_lossless_integer.rs:19:13 | LL | let _ = 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting `u16` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:17:13 + --> tests/ui/cast_lossless_integer.rs:20:13 | LL | let _ = 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting `u16` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:18:13 + --> tests/ui/cast_lossless_integer.rs:21:13 | LL | let _ = 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting `u16` to `u32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:19:13 + --> tests/ui/cast_lossless_integer.rs:22:13 | LL | let _ = 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting `u16` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:20:13 + --> tests/ui/cast_lossless_integer.rs:23:13 | LL | let _ = 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting `i32` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:21:13 + --> tests/ui/cast_lossless_integer.rs:24:13 | LL | let _ = 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting `u32` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:22:13 + --> tests/ui/cast_lossless_integer.rs:25:13 | LL | let _ = 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting `u32` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:23:13 + --> tests/ui/cast_lossless_integer.rs:26:13 | LL | let _ = 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` error: casting `u8` to `u16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:26:13 + --> tests/ui/cast_lossless_integer.rs:29:13 | LL | let _ = (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` +error: casting `i8` to `I64` may become silently lossy if you later change the type + --> tests/ui/cast_lossless_integer.rs:31:13 + | +LL | let _ = 1i8 as I64; + | ^^^^^^^^^^ help: try: `I64::from(1i8)` + error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:60:13 + --> tests/ui/cast_lossless_integer.rs:70:13 | LL | let _ = sign_cast!(x, u8, i8) as i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))` error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:61:13 + --> tests/ui/cast_lossless_integer.rs:71:13 | LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)` -error: aborting due to 21 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/const_is_empty.rs b/tests/ui/const_is_empty.rs new file mode 100644 index 00000000000..ae37a82e4f9 --- /dev/null +++ b/tests/ui/const_is_empty.rs @@ -0,0 +1,174 @@ +#![feature(inline_const)] +#![warn(clippy::const_is_empty)] +#![allow(clippy::needless_late_init, unused_must_use)] + +fn test_literal() { + if "".is_empty() { + //~^ERROR: this expression always evaluates to true + } + if "foobar".is_empty() { + //~^ERROR: this expression always evaluates to false + } +} + +fn test_byte_literal() { + if b"".is_empty() { + //~^ERROR: this expression always evaluates to true + } + if b"foobar".is_empty() { + //~^ERROR: this expression always evaluates to false + } +} + +fn test_no_mut() { + let mut empty = ""; + if empty.is_empty() { + // No lint because it is mutable + } +} + +fn test_propagated() { + let empty = ""; + let non_empty = "foobar"; + let empty2 = empty; + let non_empty2 = non_empty; + if empty2.is_empty() { + //~^ERROR: this expression always evaluates to true + } + if non_empty2.is_empty() { + //~^ERROR: this expression always evaluates to false + } +} + +const EMPTY_STR: &str = ""; +const NON_EMPTY_STR: &str = "foo"; +const EMPTY_BSTR: &[u8] = b""; +const NON_EMPTY_BSTR: &[u8] = b"foo"; +const EMPTY_U8_SLICE: &[u8] = &[]; +const NON_EMPTY_U8_SLICE: &[u8] = &[1, 2]; +const EMPTY_SLICE: &[u32] = &[]; +const NON_EMPTY_SLICE: &[u32] = &[1, 2]; +const NON_EMPTY_SLICE_REPEAT: &[u32] = &[1; 2]; +const EMPTY_ARRAY: [u32; 0] = []; +const EMPTY_ARRAY_REPEAT: [u32; 0] = [1; 0]; +const NON_EMPTY_ARRAY: [u32; 2] = [1, 2]; +const NON_EMPTY_ARRAY_REPEAT: [u32; 2] = [1; 2]; +const EMPTY_REF_ARRAY: &[u32; 0] = &[]; +const NON_EMPTY_REF_ARRAY: &[u32; 3] = &[1, 2, 3]; + +fn test_from_const() { + let _ = EMPTY_STR.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = NON_EMPTY_STR.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = EMPTY_BSTR.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = NON_EMPTY_BSTR.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = EMPTY_ARRAY.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = EMPTY_ARRAY_REPEAT.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = EMPTY_U8_SLICE.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = NON_EMPTY_U8_SLICE.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = NON_EMPTY_ARRAY.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = EMPTY_REF_ARRAY.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = NON_EMPTY_REF_ARRAY.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = EMPTY_SLICE.is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = NON_EMPTY_SLICE.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); + //~^ ERROR: this expression always evaluates to false +} + +fn main() { + let value = "foobar"; + let _ = value.is_empty(); + //~^ ERROR: this expression always evaluates to false + let x = value; + let _ = x.is_empty(); + //~^ ERROR: this expression always evaluates to false + let _ = "".is_empty(); + //~^ ERROR: this expression always evaluates to true + let _ = b"".is_empty(); + //~^ ERROR: this expression always evaluates to true +} + +fn str_from_arg(var: &str) { + var.is_empty(); + // Do not lint, we know nothiny about var +} + +fn update_str() { + let mut value = "duck"; + value = "penguin"; + + let _ = value.is_empty(); + // Do not lint since value is mutable +} + +fn macros() { + // Content from Macro + let file = include_str!("const_is_empty.rs"); + let _ = file.is_empty(); + // No lint because initializer comes from a macro result + + let var = env!("PATH"); + let _ = var.is_empty(); + // No lint because initializer comes from a macro result +} + +fn conditional_value() { + let value; + + if true { + value = "hey"; + } else { + value = "hej"; + } + + let _ = value.is_empty(); + // Do not lint, current constant folding is too simple to detect this +} + +fn cfg_conditioned() { + #[cfg(test)] + let val = ""; + #[cfg(not(test))] + let val = "foo"; + + let _ = val.is_empty(); + // Do not lint, value depend on a #[cfg(…)] directive +} + +fn not_cfg_conditioned() { + let val = ""; + #[cfg(not(target_os = "inexistent"))] + let _ = val.is_empty(); + //~^ ERROR: this expression always evaluates to true +} + +const fn const_rand() -> &'static str { + "17" +} + +fn const_expressions() { + let _ = const { if true { "1" } else { "2" } }.is_empty(); + // Do not lint, we do not recurse into boolean expressions + + let _ = const_rand().is_empty(); + // Do not lint, we do not recurse into functions +} + +fn constant_from_external_crate() { + let _ = std::env::consts::EXE_EXTENSION.is_empty(); + // Do not lint, `exe_ext` comes from the `std` crate +} diff --git a/tests/ui/const_is_empty.stderr b/tests/ui/const_is_empty.stderr new file mode 100644 index 00000000000..0e09da77bb4 --- /dev/null +++ b/tests/ui/const_is_empty.stderr @@ -0,0 +1,161 @@ +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:6:8 + | +LL | if "".is_empty() { + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::const-is-empty` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::const_is_empty)]` + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:9:8 + | +LL | if "foobar".is_empty() { + | ^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:15:8 + | +LL | if b"".is_empty() { + | ^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:18:8 + | +LL | if b"foobar".is_empty() { + | ^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:35:8 + | +LL | if empty2.is_empty() { + | ^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:38:8 + | +LL | if non_empty2.is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:60:13 + | +LL | let _ = EMPTY_STR.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:62:13 + | +LL | let _ = NON_EMPTY_STR.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:64:13 + | +LL | let _ = EMPTY_BSTR.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:66:13 + | +LL | let _ = NON_EMPTY_BSTR.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:68:13 + | +LL | let _ = EMPTY_ARRAY.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:70:13 + | +LL | let _ = EMPTY_ARRAY_REPEAT.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:72:13 + | +LL | let _ = EMPTY_U8_SLICE.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:74:13 + | +LL | let _ = NON_EMPTY_U8_SLICE.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:76:13 + | +LL | let _ = NON_EMPTY_ARRAY.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:78:13 + | +LL | let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:80:13 + | +LL | let _ = EMPTY_REF_ARRAY.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:82:13 + | +LL | let _ = NON_EMPTY_REF_ARRAY.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:84:13 + | +LL | let _ = EMPTY_SLICE.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:86:13 + | +LL | let _ = NON_EMPTY_SLICE.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:88:13 + | +LL | let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:94:13 + | +LL | let _ = value.is_empty(); + | ^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to false + --> tests/ui/const_is_empty.rs:97:13 + | +LL | let _ = x.is_empty(); + | ^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:99:13 + | +LL | let _ = "".is_empty(); + | ^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:101:13 + | +LL | let _ = b"".is_empty(); + | ^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:155:13 + | +LL | let _ = val.is_empty(); + | ^^^^^^^^^^^^^^ + +error: aborting due to 26 previous errors + diff --git a/tests/ui/crashes/ice-12491.fixed b/tests/ui/crashes/ice-12491.fixed new file mode 100644 index 00000000000..4ea480b0663 --- /dev/null +++ b/tests/ui/crashes/ice-12491.fixed @@ -0,0 +1,7 @@ +#![warn(clippy::needless_return)] + +fn main() { + if (true) { + // anything一些中文 + } +} diff --git a/tests/ui/crashes/ice-12491.rs b/tests/ui/crashes/ice-12491.rs new file mode 100644 index 00000000000..60add6afa2c --- /dev/null +++ b/tests/ui/crashes/ice-12491.rs @@ -0,0 +1,8 @@ +#![warn(clippy::needless_return)] + +fn main() { + if (true) { + // anything一些中文 + return; + } +} diff --git a/tests/ui/crashes/ice-12491.stderr b/tests/ui/crashes/ice-12491.stderr new file mode 100644 index 00000000000..7cc418898e8 --- /dev/null +++ b/tests/ui/crashes/ice-12491.stderr @@ -0,0 +1,19 @@ +error: unneeded `return` statement + --> tests/ui/crashes/ice-12491.rs:5:24 + | +LL | // anything一些中文 + | ____________________________^ +LL | | return; + | |______________^ + | + = note: `-D clippy::needless-return` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_return)]` +help: remove `return` + | +LL - // anything一些中文 +LL - return; +LL + // anything一些中文 + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/dbg_macro/dbg_macro.fixed b/tests/ui/dbg_macro/dbg_macro.fixed new file mode 100644 index 00000000000..e3525191423 --- /dev/null +++ b/tests/ui/dbg_macro/dbg_macro.fixed @@ -0,0 +1,111 @@ +#![warn(clippy::dbg_macro)] +#![allow(clippy::unnecessary_operation, clippy::no_effect)] + +fn foo(n: u32) -> u32 { + if let Some(n) = n.checked_sub(4) { n } else { n } + //~^ ERROR: the `dbg!` macro is intended as a debugging tool +} +fn bar(_: ()) {} + +fn factorial(n: u32) -> u32 { + if n <= 1 { + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + 1 + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + } else { + n * factorial(n - 1) + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + } +} + +fn main() { + 42; + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + foo(3) + factorial(4); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + (1, 2, 3, 4, 5); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool +} + +fn issue9914() { + macro_rules! foo { + ($x:expr) => { + $x; + }; + } + macro_rules! foo2 { + ($x:expr) => { + $x; + }; + } + macro_rules! expand_to_dbg { + () => { + + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + }; + } + + + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + #[allow(clippy::let_unit_value)] + let _ = (); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + bar(()); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + foo!(()); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + foo2!(foo!(())); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + expand_to_dbg!(); +} + +mod issue7274 { + trait Thing<'b> { + fn foo(&self); + } + + macro_rules! define_thing { + ($thing:ident, $body:expr) => { + impl<'a> Thing<'a> for $thing { + fn foo<'b>(&self) { + $body + } + } + }; + } + + struct MyThing; + define_thing!(MyThing, { + 2; + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + }); +} + +#[test] +pub fn issue8481() { + 1; + //~^ ERROR: the `dbg!` macro is intended as a debugging tool +} + +#[cfg(test)] +fn foo2() { + 1; + //~^ ERROR: the `dbg!` macro is intended as a debugging tool +} + +#[cfg(test)] +mod mod1 { + fn func() { + 1; + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + } +} + +mod issue12131 { + fn dbg_in_print(s: &str) { + println!("dbg: {:?}", s); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + print!("{}", s); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + } +} diff --git a/tests/ui/dbg_macro/dbg_macro.rs b/tests/ui/dbg_macro/dbg_macro.rs index 3f4770c63d0..80606c2db05 100644 --- a/tests/ui/dbg_macro/dbg_macro.rs +++ b/tests/ui/dbg_macro/dbg_macro.rs @@ -1,9 +1,5 @@ -//@no-rustfix - #![warn(clippy::dbg_macro)] - -#[path = "auxiliary/submodule.rs"] -mod submodule; +#![allow(clippy::unnecessary_operation, clippy::no_effect)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } @@ -25,12 +21,8 @@ fn factorial(n: u32) -> u32 { fn main() { dbg!(42); //~^ ERROR: the `dbg!` macro is intended as a debugging tool - dbg!(dbg!(dbg!(42))); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool foo(3) + dbg!(factorial(4)); //~^ ERROR: the `dbg!` macro is intended as a debugging tool - dbg!(1, 2, dbg!(3, 4)); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool dbg!(1, 2, 3, 4, 5); //~^ ERROR: the `dbg!` macro is intended as a debugging tool } @@ -49,6 +41,7 @@ fn issue9914() { macro_rules! expand_to_dbg { () => { dbg!(); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool }; } @@ -107,3 +100,12 @@ mod mod1 { //~^ ERROR: the `dbg!` macro is intended as a debugging tool } } + +mod issue12131 { + fn dbg_in_print(s: &str) { + println!("dbg: {:?}", dbg!(s)); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + print!("{}", dbg!(s)); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + } +} diff --git a/tests/ui/dbg_macro/dbg_macro.stderr b/tests/ui/dbg_macro/dbg_macro.stderr index 5ad0bbfed94..86667701da0 100644 --- a/tests/ui/dbg_macro/dbg_macro.stderr +++ b/tests/ui/dbg_macro/dbg_macro.stderr @@ -1,30 +1,18 @@ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5 - | -LL | dbg!(); - | ^^^^^^^ - | - = note: `-D clippy::dbg-macro` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]` -help: remove the invocation before committing it to a version control system - | -LL - dbg!(); -LL + - | - -error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:9:22 + --> tests/ui/dbg_macro/dbg_macro.rs:5:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ | + = note: `-D clippy::dbg-macro` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]` help: remove the invocation before committing it to a version control system | LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:15:8 + --> tests/ui/dbg_macro/dbg_macro.rs:11:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -35,7 +23,7 @@ LL | if n <= 1 { | ~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:17:9 + --> tests/ui/dbg_macro/dbg_macro.rs:13:9 | LL | dbg!(1) | ^^^^^^^ @@ -46,7 +34,7 @@ LL | 1 | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:20:9 + --> tests/ui/dbg_macro/dbg_macro.rs:16:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +45,7 @@ LL | n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:26:5 + --> tests/ui/dbg_macro/dbg_macro.rs:22:5 | LL | dbg!(42); | ^^^^^^^^ @@ -68,18 +56,7 @@ LL | 42; | ~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:28:5 - | -LL | dbg!(dbg!(dbg!(42))); - | ^^^^^^^^^^^^^^^^^^^^ - | -help: remove the invocation before committing it to a version control system - | -LL | dbg!(dbg!(42)); - | ~~~~~~~~~~~~~~ - -error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:30:14 + --> tests/ui/dbg_macro/dbg_macro.rs:24:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -90,18 +67,7 @@ LL | foo(3) + factorial(4); | ~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:32:5 - | -LL | dbg!(1, 2, dbg!(3, 4)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: remove the invocation before committing it to a version control system - | -LL | (1, 2, dbg!(3, 4)); - | ~~~~~~~~~~~~~~~~~~ - -error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:34:5 + --> tests/ui/dbg_macro/dbg_macro.rs:26:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -112,7 +78,7 @@ LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:55:5 + --> tests/ui/dbg_macro/dbg_macro.rs:48:5 | LL | dbg!(); | ^^^^^^^ @@ -124,7 +90,7 @@ LL + | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:58:13 + --> tests/ui/dbg_macro/dbg_macro.rs:51:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -135,7 +101,7 @@ LL | let _ = (); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:60:9 + --> tests/ui/dbg_macro/dbg_macro.rs:53:9 | LL | bar(dbg!()); | ^^^^^^ @@ -146,7 +112,7 @@ LL | bar(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:62:10 + --> tests/ui/dbg_macro/dbg_macro.rs:55:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -157,7 +123,7 @@ LL | foo!(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:64:16 + --> tests/ui/dbg_macro/dbg_macro.rs:57:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -168,7 +134,23 @@ LL | foo2!(foo!(())); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:86:9 + --> tests/ui/dbg_macro/dbg_macro.rs:43:13 + | +LL | dbg!(); + | ^^^^^^^ +... +LL | expand_to_dbg!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `expand_to_dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove the invocation before committing it to a version control system + | +LL - dbg!(); +LL + + | + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro.rs:79:9 | LL | dbg!(2); | ^^^^^^^ @@ -179,7 +161,7 @@ LL | 2; | ~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:93:5 + --> tests/ui/dbg_macro/dbg_macro.rs:86:5 | LL | dbg!(1); | ^^^^^^^ @@ -190,7 +172,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:99:5 + --> tests/ui/dbg_macro/dbg_macro.rs:92:5 | LL | dbg!(1); | ^^^^^^^ @@ -201,7 +183,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:106:9 + --> tests/ui/dbg_macro/dbg_macro.rs:99:9 | LL | dbg!(1); | ^^^^^^^ @@ -211,5 +193,27 @@ help: remove the invocation before committing it to a version control system LL | 1; | ~ +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro.rs:106:31 + | +LL | println!("dbg: {:?}", dbg!(s)); + | ^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | println!("dbg: {:?}", s); + | ~ + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro.rs:108:22 + | +LL | print!("{}", dbg!(s)); + | ^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | print!("{}", s); + | ~ + error: aborting due to 19 previous errors diff --git a/tests/ui/dbg_macro/dbg_macro_unfixable.rs b/tests/ui/dbg_macro/dbg_macro_unfixable.rs new file mode 100644 index 00000000000..0e83766ccae --- /dev/null +++ b/tests/ui/dbg_macro/dbg_macro_unfixable.rs @@ -0,0 +1,12 @@ +//@no-rustfix +#![warn(clippy::dbg_macro)] + +#[path = "auxiliary/submodule.rs"] +mod submodule; + +fn main() { + dbg!(dbg!(dbg!(42))); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool + dbg!(1, 2, dbg!(3, 4)); + //~^ ERROR: the `dbg!` macro is intended as a debugging tool +} diff --git a/tests/ui/dbg_macro/dbg_macro_unfixable.stderr b/tests/ui/dbg_macro/dbg_macro_unfixable.stderr new file mode 100644 index 00000000000..d21595c2fcd --- /dev/null +++ b/tests/ui/dbg_macro/dbg_macro_unfixable.stderr @@ -0,0 +1,71 @@ +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5 + | +LL | dbg!(); + | ^^^^^^^ + | + = note: `-D clippy::dbg-macro` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]` +help: remove the invocation before committing it to a version control system + | +LL - dbg!(); +LL + + | + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:5 + | +LL | dbg!(dbg!(dbg!(42))); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | dbg!(dbg!(42)); + | ~~~~~~~~~~~~~~ + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:10 + | +LL | dbg!(dbg!(dbg!(42))); + | ^^^^^^^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | dbg!(dbg!(42)); + | ~~~~~~~~ + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:15 + | +LL | dbg!(dbg!(dbg!(42))); + | ^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | dbg!(dbg!(42)); + | ~~ + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:5 + | +LL | dbg!(1, 2, dbg!(3, 4)); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | (1, 2, dbg!(3, 4)); + | ~~~~~~~~~~~~~~~~~~ + +error: the `dbg!` macro is intended as a debugging tool + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:16 + | +LL | dbg!(1, 2, dbg!(3, 4)); + | ^^^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | +LL | dbg!(1, 2, (3, 4)); + | ~~~~~~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/doc/issue_10262.fixed b/tests/ui/doc/issue_10262.fixed new file mode 100644 index 00000000000..5d067736d55 --- /dev/null +++ b/tests/ui/doc/issue_10262.fixed @@ -0,0 +1,12 @@ +#![warn(clippy::doc_markdown)] + +// Should only warn for the first line! +/// `AviSynth` documentation: +//~^ ERROR: item in documentation is missing backticks +/// +/// > AvisynthPluginInit3 may be called more than once with different IScriptEnvironments. +/// +///
bla AvisynthPluginInit3 bla
+/// +/// bla AvisynthPluginInit3 bla +pub struct Foo; diff --git a/tests/ui/doc/issue_10262.rs b/tests/ui/doc/issue_10262.rs new file mode 100644 index 00000000000..e2cbd938d5d --- /dev/null +++ b/tests/ui/doc/issue_10262.rs @@ -0,0 +1,12 @@ +#![warn(clippy::doc_markdown)] + +// Should only warn for the first line! +/// AviSynth documentation: +//~^ ERROR: item in documentation is missing backticks +/// +/// > AvisynthPluginInit3 may be called more than once with different IScriptEnvironments. +/// +///
bla AvisynthPluginInit3 bla
+/// +/// bla AvisynthPluginInit3 bla +pub struct Foo; diff --git a/tests/ui/doc/issue_10262.stderr b/tests/ui/doc/issue_10262.stderr new file mode 100644 index 00000000000..f43d9551e94 --- /dev/null +++ b/tests/ui/doc/issue_10262.stderr @@ -0,0 +1,15 @@ +error: item in documentation is missing backticks + --> tests/ui/doc/issue_10262.rs:4:5 + | +LL | /// AviSynth documentation: + | ^^^^^^^^ + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]` +help: try + | +LL | /// `AviSynth` documentation: + | ~~~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs new file mode 100644 index 00000000000..0f036c684c1 --- /dev/null +++ b/tests/ui/duplicated_attributes.rs @@ -0,0 +1,17 @@ +#![warn(clippy::duplicated_attributes)] +#![cfg(any(unix, windows))] +#![allow(dead_code)] +#![allow(dead_code)] //~ ERROR: duplicated attribute +#![cfg(any(unix, windows))] +//~^ ERROR: duplicated attribute +//~| ERROR: duplicated attribute + +#[cfg(any(unix, windows, target_os = "linux"))] +#[allow(dead_code)] +#[allow(dead_code)] //~ ERROR: duplicated attribute +#[cfg(any(unix, windows, target_os = "linux"))] +//~^ ERROR: duplicated attribute +//~| ERROR: duplicated attribute +fn foo() {} + +fn main() {} diff --git a/tests/ui/duplicated_attributes.stderr b/tests/ui/duplicated_attributes.stderr new file mode 100644 index 00000000000..1c6578dbb43 --- /dev/null +++ b/tests/ui/duplicated_attributes.stderr @@ -0,0 +1,123 @@ +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:4:10 + | +LL | #![allow(dead_code)] + | ^^^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:3:10 + | +LL | #![allow(dead_code)] + | ^^^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:4:10 + | +LL | #![allow(dead_code)] + | ^^^^^^^^^ + = note: `-D clippy::duplicated-attributes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:5:12 + | +LL | #![cfg(any(unix, windows))] + | ^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:2:12 + | +LL | #![cfg(any(unix, windows))] + | ^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:5:12 + | +LL | #![cfg(any(unix, windows))] + | ^^^^ + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:5:18 + | +LL | #![cfg(any(unix, windows))] + | ^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:2:18 + | +LL | #![cfg(any(unix, windows))] + | ^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:5:18 + | +LL | #![cfg(any(unix, windows))] + | ^^^^^^^ + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:11:9 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:10:9 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:11:9 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^ + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:12:11 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:9:11 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:12:11 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^ + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:12:17 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:9:17 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:12:17 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^ + +error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:12:26 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^^^^^^^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:9:26 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^^^^^^^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:12:26 + | +LL | #[cfg(any(unix, windows, target_os = "linux"))] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index e7786f7dd27..b04c22fa2ae 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -1,7 +1,5 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - -#![warn(clippy::all)] #![warn(clippy::else_if_without_else)] +#![allow(clippy::collapsible_else_if)] fn bla1() -> bool { unimplemented!() @@ -12,6 +10,12 @@ fn bla2() -> bool { fn bla3() -> bool { unimplemented!() } +fn bla4() -> bool { + unimplemented!() +} +fn bla5() -> bool { + unimplemented!() +} fn main() { if bla1() { @@ -57,4 +61,62 @@ fn main() { //~^ ERROR: `if` expression with an `else if`, but without a final `else` println!("else if 2"); } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else if bla3() { + println!("else if 2"); + } else if bla4() { + println!("else if 3"); + } else if bla5() { + println!("else if 4"); + } else { + println!("else"); + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else if bla3() { + println!("else if 2"); + } else if bla4() { + println!("else if 3"); + } else if bla5() { + //~^ ERROR: `if` expression with an `else if`, but without a final `else` + println!("else if 4"); + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else { + if bla3() { + println!("else if 2"); + } else if bla4() { + println!("else if 3"); + } else if bla5() { + println!("else if 4"); + } else { + println!("else"); + } + } + + if bla1() { + println!("if"); + } else if bla2() { + println!("else if 1"); + } else { + if bla3() { + println!("else if 2"); + } else if bla4() { + println!("else if 3"); + } else if bla5() { + //~^ ERROR: `if` expression with an `else if`, but without a final `else` + println!("else if 4"); + } + } } diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 3bb840f39e7..bc717485229 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -1,5 +1,5 @@ error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:47:12 + --> tests/ui/else_if_without_else.rs:51:12 | LL | } else if bla2() { | ____________^ @@ -13,7 +13,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::else_if_without_else)]` error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:56:12 + --> tests/ui/else_if_without_else.rs:60:12 | LL | } else if bla3() { | ____________^ @@ -24,5 +24,29 @@ LL | | } | = help: add an `else` block here -error: aborting due to 2 previous errors +error: `if` expression with an `else if`, but without a final `else` + --> tests/ui/else_if_without_else.rs:87:12 + | +LL | } else if bla5() { + | ____________^ +LL | | +LL | | println!("else if 4"); +LL | | } + | |_____^ + | + = help: add an `else` block here + +error: `if` expression with an `else if`, but without a final `else` + --> tests/ui/else_if_without_else.rs:117:16 + | +LL | } else if bla5() { + | ________________^ +LL | | +LL | | println!("else if 4"); +LL | | } + | |_________^ + | + = help: add an `else` block here + +error: aborting due to 4 previous errors diff --git a/tests/ui/empty_docs.rs b/tests/ui/empty_docs.rs index 272fab7d5ca..00e64eebc5f 100644 --- a/tests/ui/empty_docs.rs +++ b/tests/ui/empty_docs.rs @@ -1,6 +1,9 @@ +//@aux-build:proc_macro_attr.rs + #![allow(unused)] #![warn(clippy::empty_docs)] #![allow(clippy::mixed_attributes_style)] +#![feature(extern_types)] mod outer { //! @@ -67,3 +70,17 @@ mod outer { y: i32, } } + +mod issue_12377 { + use proc_macro_attr::with_empty_docs; + + #[with_empty_docs] + extern "C" { + type Test; + } + + #[with_empty_docs] + struct Foo { + a: u8, + } +} diff --git a/tests/ui/empty_docs.stderr b/tests/ui/empty_docs.stderr index f12aead6aa7..28ebea22c5d 100644 --- a/tests/ui/empty_docs.stderr +++ b/tests/ui/empty_docs.stderr @@ -1,5 +1,5 @@ error: empty doc comment - --> tests/ui/empty_docs.rs:6:5 + --> tests/ui/empty_docs.rs:9:5 | LL | //! | ^^^ @@ -9,7 +9,7 @@ LL | //! = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]` error: empty doc comment - --> tests/ui/empty_docs.rs:14:5 + --> tests/ui/empty_docs.rs:17:5 | LL | /// | ^^^ @@ -17,7 +17,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:16:9 + --> tests/ui/empty_docs.rs:19:9 | LL | /// | ^^^ @@ -25,7 +25,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:27:5 + --> tests/ui/empty_docs.rs:30:5 | LL | #[doc = ""] | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:30:5 + --> tests/ui/empty_docs.rs:33:5 | LL | / #[doc = ""] LL | | #[doc = ""] @@ -42,7 +42,7 @@ LL | | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:37:5 + --> tests/ui/empty_docs.rs:40:5 | LL | /// | ^^^ @@ -50,7 +50,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:50:13 + --> tests/ui/empty_docs.rs:53:13 | LL | /*! */ | ^^^^^^ @@ -58,7 +58,7 @@ LL | /*! */ = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:58:13 + --> tests/ui/empty_docs.rs:61:13 | LL | /// | ^^^ @@ -66,7 +66,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:66:9 + --> tests/ui/empty_docs.rs:69:9 | LL | /// | ^^^ diff --git a/tests/ui/empty_line_after_doc_comments.rs b/tests/ui/empty_line_after_doc_comments.rs index e843770f578..dd78491749c 100644 --- a/tests/ui/empty_line_after_doc_comments.rs +++ b/tests/ui/empty_line_after_doc_comments.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macro_attr.rs #![warn(clippy::empty_line_after_doc_comments)] -#![allow(clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)] #![feature(custom_inner_attributes)] #![rustfmt::skip] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 269e66ea0a8..f147cf2cd5d 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macro_attr.rs #![warn(clippy::empty_line_after_outer_attr)] -#![allow(clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)] #![feature(custom_inner_attributes)] #![rustfmt::skip] diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed index 71ec13f4610..abdfae2a3e1 100644 --- a/tests/ui/entry.fixed +++ b/tests/ui/entry.fixed @@ -176,4 +176,14 @@ pub fn issue_11935() { } } +fn issue12489(map: &mut HashMap) -> Option<()> { + if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) { + let Some(1) = Some(2) else { + return None; + }; + e.insert(42); + } + Some(()) +} + fn main() {} diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 86092b7c055..7774f99a2a2 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -180,4 +180,14 @@ pub fn issue_11935() { } } +fn issue12489(map: &mut HashMap) -> Option<()> { + if !map.contains_key(&1) { + let Some(1) = Some(2) else { + return None; + }; + map.insert(1, 42); + } + Some(()) +} + fn main() {} diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index ef4c36bcf54..fb467676606 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -214,5 +214,26 @@ LL + v LL + }); | -error: aborting due to 10 previous errors +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry.rs:184:5 + | +LL | / if !map.contains_key(&1) { +LL | | let Some(1) = Some(2) else { +LL | | return None; +LL | | }; +LL | | map.insert(1, 42); +LL | | } + | |_____^ + | +help: try + | +LL ~ if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) { +LL + let Some(1) = Some(2) else { +LL + return None; +LL + }; +LL + e.insert(42); +LL + } + | + +error: aborting due to 11 previous errors diff --git a/tests/ui/integer_division_remainder_used.rs b/tests/ui/integer_division_remainder_used.rs new file mode 100644 index 00000000000..5d1b02095d1 --- /dev/null +++ b/tests/ui/integer_division_remainder_used.rs @@ -0,0 +1,41 @@ +#![warn(clippy::integer_division_remainder_used)] +#![allow(unused_variables)] +#![allow(clippy::op_ref)] + +struct CustomOps(pub i32); +impl std::ops::Div for CustomOps { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + Self(self.0 / rhs.0) + } +} +impl std::ops::Rem for CustomOps { + type Output = Self; + + fn rem(self, rhs: Self) -> Self::Output { + Self(self.0 % rhs.0) + } +} + +fn main() { + // should trigger + let a = 10; + let b = 5; + let c = a / b; + let d = a % b; + let e = &a / b; + let f = a % &b; + let g = &a / &b; + let h = &10 % b; + let i = a / &4; + + // should not trigger on custom Div and Rem + let w = CustomOps(3); + let x = CustomOps(4); + let y = w / x; + + let w = CustomOps(3); + let x = CustomOps(4); + let z = w % x; +} diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr new file mode 100644 index 00000000000..8adfda28893 --- /dev/null +++ b/tests/ui/integer_division_remainder_used.stderr @@ -0,0 +1,59 @@ +error: use of / has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:10:14 + | +LL | Self(self.0 / rhs.0) + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::integer-division-remainder-used` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::integer_division_remainder_used)]` + +error: use of % has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:17:14 + | +LL | Self(self.0 % rhs.0) + | ^^^^^^^^^^^^^^ + +error: use of / has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:25:13 + | +LL | let c = a / b; + | ^^^^^ + +error: use of % has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:26:13 + | +LL | let d = a % b; + | ^^^^^ + +error: use of / has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:27:13 + | +LL | let e = &a / b; + | ^^^^^^ + +error: use of % has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:28:13 + | +LL | let f = a % &b; + | ^^^^^^ + +error: use of / has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:29:13 + | +LL | let g = &a / &b; + | ^^^^^^^ + +error: use of % has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:30:13 + | +LL | let h = &10 % b; + | ^^^^^^^ + +error: use of / has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:31:13 + | +LL | let i = a / &4; + | ^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/iter_nth.fixed b/tests/ui/iter_nth.fixed new file mode 100644 index 00000000000..aff3731a883 --- /dev/null +++ b/tests/ui/iter_nth.fixed @@ -0,0 +1,60 @@ +//@aux-build:option_helpers.rs + +#![warn(clippy::iter_nth)] +#![allow(clippy::useless_vec)] + +#[macro_use] +extern crate option_helpers; + +use option_helpers::IteratorFalsePositives; +use std::collections::VecDeque; + +/// Struct to generate false positives for things with `.iter()`. +#[derive(Copy, Clone)] +struct HasIter; + +impl HasIter { + fn iter(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } + + fn iter_mut(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } +} + +/// Checks implementation of `ITER_NTH` lint. +fn iter_nth() { + let mut some_vec = vec![0, 1, 2, 3]; + let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); + let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect(); + + { + // Make sure we lint `.iter()` for relevant types. + let bad_vec = some_vec.get(3); + let bad_slice = &some_vec[..].get(3); + let bad_boxed_slice = boxed_slice.get(3); + let bad_vec_deque = some_vec_deque.get(3); + } + + { + // Make sure we lint `.iter_mut()` for relevant types. + let bad_vec = some_vec.get_mut(3); + } + { + let bad_slice = &some_vec[..].get_mut(3); + } + { + let bad_vec_deque = some_vec_deque.get_mut(3); + } + + let vec_ref = &Vec::::new(); + vec_ref.get(3); + + // Make sure we don't lint for non-relevant types. + let false_positive = HasIter; + let ok = false_positive.iter().nth(3); + let ok_mut = false_positive.iter_mut().nth(3); +} + +fn main() {} diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs index 7c567bb81d8..89d68044ddd 100644 --- a/tests/ui/iter_nth.rs +++ b/tests/ui/iter_nth.rs @@ -48,6 +48,9 @@ fn iter_nth() { let bad_vec_deque = some_vec_deque.iter_mut().nth(3); } + let vec_ref = &Vec::::new(); + vec_ref.iter().nth(3); + // Make sure we don't lint for non-relevant types. let false_positive = HasIter; let ok = false_positive.iter().nth(3); diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr index c5dd0c99727..178463f5347 100644 --- a/tests/ui/iter_nth.stderr +++ b/tests/ui/iter_nth.stderr @@ -4,9 +4,12 @@ error: called `.iter().nth()` on a `Vec` LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get()` is both faster and more readable = note: `-D clippy::iter-nth` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::iter_nth)]` +help: `get` is equivalent but more concise + | +LL | let bad_vec = some_vec.get(3); + | ~~~ error: called `.iter().nth()` on a slice --> tests/ui/iter_nth.rs:35:26 @@ -14,7 +17,10 @@ error: called `.iter().nth()` on a slice LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get()` is both faster and more readable +help: `get` is equivalent but more concise + | +LL | let bad_slice = &some_vec[..].get(3); + | ~~~ error: called `.iter().nth()` on a slice --> tests/ui/iter_nth.rs:36:31 @@ -22,7 +28,10 @@ error: called `.iter().nth()` on a slice LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get()` is both faster and more readable +help: `get` is equivalent but more concise + | +LL | let bad_boxed_slice = boxed_slice.get(3); + | ~~~ error: called `.iter().nth()` on a `VecDeque` --> tests/ui/iter_nth.rs:37:29 @@ -30,7 +39,10 @@ error: called `.iter().nth()` on a `VecDeque` LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get()` is both faster and more readable +help: `get` is equivalent but more concise + | +LL | let bad_vec_deque = some_vec_deque.get(3); + | ~~~ error: called `.iter_mut().nth()` on a `Vec` --> tests/ui/iter_nth.rs:42:23 @@ -38,7 +50,10 @@ error: called `.iter_mut().nth()` on a `Vec` LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get_mut()` is both faster and more readable +help: `get_mut` is equivalent but more concise + | +LL | let bad_vec = some_vec.get_mut(3); + | ~~~~~~~ error: called `.iter_mut().nth()` on a slice --> tests/ui/iter_nth.rs:45:26 @@ -46,7 +61,10 @@ error: called `.iter_mut().nth()` on a slice LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get_mut()` is both faster and more readable +help: `get_mut` is equivalent but more concise + | +LL | let bad_slice = &some_vec[..].get_mut(3); + | ~~~~~~~ error: called `.iter_mut().nth()` on a `VecDeque` --> tests/ui/iter_nth.rs:48:29 @@ -54,7 +72,21 @@ error: called `.iter_mut().nth()` on a `VecDeque` LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: calling `.get_mut()` is both faster and more readable +help: `get_mut` is equivalent but more concise + | +LL | let bad_vec_deque = some_vec_deque.get_mut(3); + | ~~~~~~~ -error: aborting due to 7 previous errors +error: called `.iter().nth()` on a `Vec` + --> tests/ui/iter_nth.rs:52:5 + | +LL | vec_ref.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: `get` is equivalent but more concise + | +LL | vec_ref.get(3); + | ~~~ + +error: aborting due to 8 previous errors diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index 745fc7e1a8b..c16d7a26616 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -1,5 +1,11 @@ #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] +#![allow( + dead_code, + unused, + clippy::needless_if, + clippy::len_without_is_empty, + clippy::const_is_empty +)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 048ad2f4fd3..5c49a5abf81 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,5 +1,11 @@ #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] +#![allow( + dead_code, + unused, + clippy::needless_if, + clippy::len_without_is_empty, + clippy::const_is_empty +)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index b1f04c94de6..dd07a85d62c 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,5 +1,5 @@ error: length comparison to zero - --> tests/ui/len_zero.rs:82:8 + --> tests/ui/len_zero.rs:88:8 | LL | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` @@ -8,13 +8,13 @@ LL | if x.len() == 0 { = help: to override `-D warnings` add `#[allow(clippy::len_zero)]` error: length comparison to zero - --> tests/ui/len_zero.rs:86:8 + --> tests/ui/len_zero.rs:92:8 | LL | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:95:20 + --> tests/ui/len_zero.rs:101:20 | LL | println!("{}", *s1 == ""); | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()` @@ -23,121 +23,121 @@ LL | println!("{}", *s1 == ""); = help: to override `-D warnings` add `#[allow(clippy::comparison_to_empty)]` error: comparison to empty slice - --> tests/ui/len_zero.rs:96:20 + --> tests/ui/len_zero.rs:102:20 | LL | println!("{}", **s2 == ""); | ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:97:20 + --> tests/ui/len_zero.rs:103:20 | LL | println!("{}", ***s3 == ""); | ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:98:20 + --> tests/ui/len_zero.rs:104:20 | LL | println!("{}", ****s4 == ""); | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:99:20 + --> tests/ui/len_zero.rs:105:20 | LL | println!("{}", *****s5 == ""); | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:100:20 + --> tests/ui/len_zero.rs:106:20 | LL | println!("{}", ******(s6) == ""); | ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:103:20 + --> tests/ui/len_zero.rs:109:20 | LL | println!("{}", &**d2s == ""); | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:118:8 + --> tests/ui/len_zero.rs:124:8 | LL | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:121:8 + --> tests/ui/len_zero.rs:127:8 | LL | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:124:8 + --> tests/ui/len_zero.rs:130:8 | LL | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:127:8 + --> tests/ui/len_zero.rs:133:8 | LL | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:130:8 + --> tests/ui/len_zero.rs:136:8 | LL | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:141:8 + --> tests/ui/len_zero.rs:147:8 | LL | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:144:8 + --> tests/ui/len_zero.rs:150:8 | LL | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:147:8 + --> tests/ui/len_zero.rs:153:8 | LL | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:150:8 + --> tests/ui/len_zero.rs:156:8 | LL | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:153:8 + --> tests/ui/len_zero.rs:159:8 | LL | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:167:8 + --> tests/ui/len_zero.rs:173:8 | LL | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:179:6 + --> tests/ui/len_zero.rs:185:6 | LL | (has_is_empty.len() > 0).then(|| println!("This can happen.")); | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:180:6 + --> tests/ui/len_zero.rs:186:6 | LL | (has_is_empty.len() == 0).then(|| println!("Or this!")); | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:184:8 + --> tests/ui/len_zero.rs:190:8 | LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()` diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index 9869d945299..a29d35880b8 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -57,6 +57,17 @@ fn early_return() -> u8 { foo } +fn allow_works() -> i32 { + #[allow(clippy::useless_let_if_seq)] + let x; + if true { + x = 1; + } else { + x = 2; + } + x +} + fn main() { early_return(); issue975(); diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 87ad20dc27e..41930108fb1 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -1,5 +1,5 @@ error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:66:5 + --> tests/ui/let_if_seq.rs:77:5 | LL | / let mut foo = 0; LL | | @@ -14,7 +14,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::useless_let_if_seq)]` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:73:5 + --> tests/ui/let_if_seq.rs:84:5 | LL | / let mut bar = 0; LL | | @@ -28,7 +28,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:83:5 + --> tests/ui/let_if_seq.rs:94:5 | LL | / let quz; LL | | @@ -40,7 +40,7 @@ LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:113:5 + --> tests/ui/let_if_seq.rs:124:5 | LL | / let mut baz = 0; LL | | diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 1fb252e3f97..2b36c3f3c2f 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -8,7 +8,8 @@ clippy::never_loop, clippy::needless_if, clippy::diverging_sub_expression, - clippy::single_match + clippy::single_match, + clippy::manual_unwrap_or_default )] #![warn(clippy::manual_let_else)] //@no-rustfix diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 7012c6b8891..55a410982ad 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:28:5 + --> tests/ui/manual_let_else.rs:29:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -8,7 +8,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:31:5 + --> tests/ui/manual_let_else.rs:32:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -26,7 +26,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:38:5 + --> tests/ui/manual_let_else.rs:39:5 | LL | / let v = if let Some(v) = g() { LL | | @@ -47,25 +47,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:50:9 + --> tests/ui/manual_let_else.rs:51:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:52:9 + --> tests/ui/manual_let_else.rs:53:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:57:5 + --> tests/ui/manual_let_else.rs:58:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:61:5 + --> tests/ui/manual_let_else.rs:62:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -83,7 +83,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:69:5 + --> tests/ui/manual_let_else.rs:70:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -101,7 +101,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:77:5 + --> tests/ui/manual_let_else.rs:78:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -121,7 +121,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:86:5 + --> tests/ui/manual_let_else.rs:87:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -141,7 +141,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:95:5 + --> tests/ui/manual_let_else.rs:96:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -168,7 +168,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:111:5 + --> tests/ui/manual_let_else.rs:112:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -190,7 +190,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:122:5 + --> tests/ui/manual_let_else.rs:123:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -217,7 +217,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:138:5 + --> tests/ui/manual_let_else.rs:139:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -239,7 +239,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:149:5 + --> tests/ui/manual_let_else.rs:150:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -257,7 +257,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:157:5 + --> tests/ui/manual_let_else.rs:158:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -278,7 +278,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:167:5 + --> tests/ui/manual_let_else.rs:168:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -299,7 +299,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:177:5 + --> tests/ui/manual_let_else.rs:178:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -328,7 +328,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:195:5 + --> tests/ui/manual_let_else.rs:196:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | @@ -346,7 +346,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:203:5 + --> tests/ui/manual_let_else.rs:204:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | @@ -364,7 +364,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:213:13 + --> tests/ui/manual_let_else.rs:214:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -375,19 +375,19 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:222:5 + --> tests/ui/manual_let_else.rs:223:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:226:5 + --> tests/ui/manual_let_else.rs:227:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:231:5 + --> tests/ui/manual_let_else.rs:232:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | @@ -405,19 +405,19 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:238:5 + --> tests/ui/manual_let_else.rs:239:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:242:5 + --> tests/ui/manual_let_else.rs:243:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:246:5 + --> tests/ui/manual_let_else.rs:247:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -435,7 +435,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:254:5 + --> tests/ui/manual_let_else.rs:255:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -453,7 +453,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:262:5 + --> tests/ui/manual_let_else.rs:263:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { LL | | @@ -471,7 +471,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:379:5 + --> tests/ui/manual_let_else.rs:380:5 | LL | / let _ = match ff { LL | | @@ -481,7 +481,7 @@ LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:456:9 + --> tests/ui/manual_let_else.rs:457:9 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index e359dfbb98c..5540029bf6b 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index 931814f08b7..cee641d9d65 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/tests/ui/manual_retain.stderr b/tests/ui/manual_retain.stderr index fdbbc53e4df..c25c804df75 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()` - --> tests/ui/manual_retain.rs:27:5 + --> tests/ui/manual_retain.rs:25:5 | LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` @@ -8,43 +8,43 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:28:5 + --> tests/ui/manual_retain.rs:26:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:29:5 + --> tests/ui/manual_retain.rs:27:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:33:5 + --> tests/ui/manual_retain.rs:31:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:34:5 + --> tests/ui/manual_retain.rs:32:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:64:5 + --> tests/ui/manual_retain.rs:62: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)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:65:5 + --> tests/ui/manual_retain.rs:63: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()` - --> tests/ui/manual_retain.rs:66:5 + --> tests/ui/manual_retain.rs:64:5 | LL | / btree_map = btree_map LL | | .into_iter() @@ -53,49 +53,49 @@ 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()` - --> tests/ui/manual_retain.rs:91:5 + --> tests/ui/manual_retain.rs:89: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()` - --> tests/ui/manual_retain.rs:92:5 + --> tests/ui/manual_retain.rs:90: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()` - --> tests/ui/manual_retain.rs:93:5 + --> tests/ui/manual_retain.rs:91: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()` - --> tests/ui/manual_retain.rs:97:5 + --> tests/ui/manual_retain.rs:95:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:98:5 + --> tests/ui/manual_retain.rs:96:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:128:5 + --> tests/ui/manual_retain.rs:126: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()` - --> tests/ui/manual_retain.rs:129:5 + --> tests/ui/manual_retain.rs:127: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()` - --> tests/ui/manual_retain.rs:130:5 + --> tests/ui/manual_retain.rs:128:5 | LL | / hash_map = hash_map LL | | .into_iter() @@ -104,133 +104,133 @@ 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()` - --> tests/ui/manual_retain.rs:154:5 + --> tests/ui/manual_retain.rs:152: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()` - --> tests/ui/manual_retain.rs:155:5 + --> tests/ui/manual_retain.rs:153: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()` - --> tests/ui/manual_retain.rs:156:5 + --> tests/ui/manual_retain.rs:154: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()` - --> tests/ui/manual_retain.rs:160:5 + --> tests/ui/manual_retain.rs:158:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:161:5 + --> tests/ui/manual_retain.rs:159:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:190:5 + --> tests/ui/manual_retain.rs:188: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()` - --> tests/ui/manual_retain.rs:202:5 + --> tests/ui/manual_retain.rs:200: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()` - --> tests/ui/manual_retain.rs:203:5 + --> tests/ui/manual_retain.rs:201: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()` - --> tests/ui/manual_retain.rs:204:5 + --> tests/ui/manual_retain.rs:202: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()` - --> tests/ui/manual_retain.rs:208:5 + --> tests/ui/manual_retain.rs:206:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:209:5 + --> tests/ui/manual_retain.rs:207:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:231:5 + --> tests/ui/manual_retain.rs:229: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()` - --> tests/ui/manual_retain.rs:232:5 + --> tests/ui/manual_retain.rs:230: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()` - --> tests/ui/manual_retain.rs:233:5 + --> tests/ui/manual_retain.rs:231: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)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:290:5 + --> tests/ui/manual_retain.rs:288:5 | LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:294:5 + --> tests/ui/manual_retain.rs:292:5 | LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:311:5 + --> tests/ui/manual_retain.rs:309:5 | LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:312:5 + --> tests/ui/manual_retain.rs:310:5 | LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:313:5 + --> tests/ui/manual_retain.rs:311:5 | LL | vec = vec.into_iter().filter(|&x| x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:316:5 + --> tests/ui/manual_retain.rs:314:5 | LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:317:5 + --> tests/ui/manual_retain.rs:315:5 | LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:318:5 + --> tests/ui/manual_retain.rs:316:5 | LL | vec = vec.into_iter().filter(|x| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index 737d4c90dca..dffd44b6a7c 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -1,5 +1,10 @@ #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] +#![allow( + unused_variables, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::manual_unwrap_or_default +)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index f59fb87529f..67427132c1a 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -1,5 +1,10 @@ #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] +#![allow( + unused_variables, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::manual_unwrap_or_default +)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.stderr b/tests/ui/manual_unwrap_or.stderr index 511b79881ac..33a099680ce 100644 --- a/tests/ui/manual_unwrap_or.stderr +++ b/tests/ui/manual_unwrap_or.stderr @@ -1,5 +1,5 @@ error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:6:5 + --> tests/ui/manual_unwrap_or.rs:11:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -11,7 +11,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or)]` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:12:5 + --> tests/ui/manual_unwrap_or.rs:17:5 | LL | / match Some(1) { LL | | None => 42, @@ -20,7 +20,7 @@ LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:18:5 + --> tests/ui/manual_unwrap_or.rs:23:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -29,7 +29,7 @@ LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(1 + 42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:25:5 + --> tests/ui/manual_unwrap_or.rs:30:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -50,7 +50,7 @@ LL ~ }); | error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:35:5 + --> tests/ui/manual_unwrap_or.rs:40:5 | LL | / match Some("Bob") { LL | | Some(i) => i, @@ -59,7 +59,7 @@ LL | | }; | |_____^ help: replace with: `Some("Bob").unwrap_or("Alice")` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:85:5 + --> tests/ui/manual_unwrap_or.rs:90:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -68,7 +68,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:92:5 + --> tests/ui/manual_unwrap_or.rs:97:5 | LL | / match a { LL | | Ok(i) => i, @@ -77,7 +77,7 @@ LL | | }; | |_____^ help: replace with: `a.unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:98:5 + --> tests/ui/manual_unwrap_or.rs:103:5 | LL | / match Ok(1) as Result { LL | | Ok(i) => i, @@ -86,7 +86,7 @@ LL | | }; | |_____^ help: replace with: `(Ok(1) as Result).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:111:5 + --> tests/ui/manual_unwrap_or.rs:116:5 | LL | / match s.method() { LL | | Some(i) => i, @@ -95,7 +95,7 @@ LL | | }; | |_____^ help: replace with: `s.method().unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:117:5 + --> tests/ui/manual_unwrap_or.rs:122:5 | LL | / match Ok::(1) { LL | | Err(_) => 42, @@ -104,7 +104,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:123:5 + --> tests/ui/manual_unwrap_or.rs:128:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -113,7 +113,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(1 + 42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:130:5 + --> tests/ui/manual_unwrap_or.rs:135:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -134,7 +134,7 @@ LL ~ }); | error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:140:5 + --> tests/ui/manual_unwrap_or.rs:145:5 | LL | / match Ok::<&str, &str>("Bob") { LL | | Ok(i) => i, @@ -143,7 +143,7 @@ LL | | }; | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:200:17 + --> tests/ui/manual_unwrap_or.rs:205:17 | LL | let _ = match some_macro!() { | _________________^ diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed new file mode 100644 index 00000000000..c8456805ee6 --- /dev/null +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -0,0 +1,19 @@ +#![warn(clippy::manual_unwrap_or_default)] +#![allow(clippy::unnecessary_literal_unwrap)] + +fn main() { + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); +} diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs new file mode 100644 index 00000000000..820717be53a --- /dev/null +++ b/tests/ui/manual_unwrap_or_default.rs @@ -0,0 +1,40 @@ +#![warn(clippy::manual_unwrap_or_default)] +#![allow(clippy::unnecessary_literal_unwrap)] + +fn main() { + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + None => Vec::default(), + }; + + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + _ => Vec::default(), + }; + + let x: Option = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + None => String::new(), + }; + + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + None => Vec::default(), + Some(v) => v, + }; + + let x: Option> = None; + if let Some(v) = x { + //~^ ERROR: if let can be simplified with `.unwrap_or_default()` + v + } else { + Vec::default() + }; +} diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr new file mode 100644 index 00000000000..f4eb6583588 --- /dev/null +++ b/tests/ui/manual_unwrap_or_default.stderr @@ -0,0 +1,56 @@ +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:6:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | None => Vec::default(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + | + = note: `-D clippy::manual-unwrap-or-default` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or_default)]` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:13:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | _ => Vec::default(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:20:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | None => String::new(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:27:5 + | +LL | / match x { +LL | | +LL | | None => Vec::default(), +LL | | Some(v) => v, +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: if let can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:34:5 + | +LL | / if let Some(v) = x { +LL | | +LL | | v +LL | | } else { +LL | | Vec::default() +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index 395eea69294..e58b6b2f19e 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -6,7 +6,8 @@ clippy::redundant_clone, clippy::redundant_closure, clippy::useless_asref, - clippy::useless_vec + clippy::useless_vec, + clippy::empty_loop )] fn main() { @@ -117,4 +118,17 @@ fn main() { let y = x.as_ref().map(|x| String::clone(x)); let x: Result = Ok(String::new()); let y = x.as_ref().map(|x| String::clone(x)); + + // Issue #12271 + { + // Don't lint these + let x: Option<&u8> = None; + let y = x.map(|x| String::clone(loop {})); + let x: Option<&u8> = None; + let y = x.map(|x| u8::clone(loop {})); + let x: Vec<&u8> = vec![]; + let y = x.into_iter().map(|x| String::clone(loop {})); + let x: Vec<&u8> = vec![]; + let y = x.into_iter().map(|x| u8::clone(loop {})); + } } diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 82a103edf5a..e642e4046f8 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -6,7 +6,8 @@ clippy::redundant_clone, clippy::redundant_closure, clippy::useless_asref, - clippy::useless_vec + clippy::useless_vec, + clippy::empty_loop )] fn main() { @@ -117,4 +118,17 @@ fn main() { let y = x.as_ref().map(|x| String::clone(x)); let x: Result = Ok(String::new()); let y = x.as_ref().map(|x| String::clone(x)); + + // Issue #12271 + { + // Don't lint these + let x: Option<&u8> = None; + let y = x.map(|x| String::clone(loop {})); + let x: Option<&u8> = None; + let y = x.map(|x| u8::clone(loop {})); + let x: Vec<&u8> = vec![]; + let y = x.into_iter().map(|x| String::clone(loop {})); + let x: Vec<&u8> = vec![]; + let y = x.into_iter().map(|x| u8::clone(loop {})); + } } diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 1a26a26a4ca..d9e025de4ab 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:13:22 + --> tests/ui/map_clone.rs:14:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()` @@ -8,85 +8,85 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = help: to override `-D warnings` add `#[allow(clippy::map_clone)]` error: you are using an explicit closure for cloning elements - --> tests/ui/map_clone.rs:14:26 + --> tests/ui/map_clone.rs:15:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:15:23 + --> tests/ui/map_clone.rs:16:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:17:26 + --> tests/ui/map_clone.rs:18:26 | LL | let _: Option = Some(&16).map(|b| *b); | ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:18:25 + --> tests/ui/map_clone.rs:19:25 | LL | let _: Option = Some(&1).map(|x| x.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()` error: you are needlessly cloning iterator elements - --> tests/ui/map_clone.rs:29:29 + --> tests/ui/map_clone.rs:30:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:68:13 + --> tests/ui/map_clone.rs:69:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:70:13 + --> tests/ui/map_clone.rs:71:13 | LL | let y = x.map(Clone::clone); | ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:73:13 + --> tests/ui/map_clone.rs:74:13 | LL | let y = x.map(String::clone); | ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:79:13 + --> tests/ui/map_clone.rs:80:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:82:13 + --> tests/ui/map_clone.rs:83:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:94:13 + --> tests/ui/map_clone.rs:95:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:97:13 + --> tests/ui/map_clone.rs:98:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:103:13 + --> tests/ui/map_clone.rs:104:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:106:13 + --> tests/ui/map_clone.rs:107:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` diff --git a/tests/ui/match_result_ok.fixed b/tests/ui/match_result_ok.fixed index 8d7cddc0ad7..76b26f5e438 100644 --- a/tests/ui/match_result_ok.fixed +++ b/tests/ui/match_result_ok.fixed @@ -1,6 +1,6 @@ #![warn(clippy::match_result_ok)] #![allow(dead_code)] -#![allow(clippy::boxed_local, clippy::uninlined_format_args)] +#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)] // Checking `if` cases diff --git a/tests/ui/match_result_ok.rs b/tests/ui/match_result_ok.rs index 9a18b813aca..d6f2475ba79 100644 --- a/tests/ui/match_result_ok.rs +++ b/tests/ui/match_result_ok.rs @@ -1,6 +1,6 @@ #![warn(clippy::match_result_ok)] #![allow(dead_code)] -#![allow(clippy::boxed_local, clippy::uninlined_format_args)] +#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)] // Checking `if` cases diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index 9bfad3b96cf..9c936d7fa23 100644 --- a/tests/ui/missing_doc.rs +++ b/tests/ui/missing_doc.rs @@ -1,5 +1,6 @@ //@needs-asm-support //@aux-build: proc_macros.rs +//@aux-build: proc_macro_attr.rs #![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the @@ -8,6 +9,8 @@ //! Some garbage docs for the crate here #![doc = "More garbage"] +#[macro_use] +extern crate proc_macro_attr; extern crate proc_macros; use proc_macros::with_span; @@ -112,3 +115,12 @@ with_span!(span pub enum FooPm3 { A, B(u32), C { field: u32 }}); with_span!(span pub fn foo_pm() {}); with_span!(span pub static FOO_PM: u32 = 0;); with_span!(span pub const FOO2_PM: u32 = 0;); + +// issue #12197 +// Undocumented field originated inside of spanned proc-macro attribute +/// Some dox for struct. +#[rewrite_struct] +pub struct Test { + /// Dox + a: u8, +} diff --git a/tests/ui/missing_doc.stderr b/tests/ui/missing_doc.stderr index 7e66e2097e9..ef0f96a5b71 100644 --- a/tests/ui/missing_doc.stderr +++ b/tests/ui/missing_doc.stderr @@ -1,5 +1,5 @@ error: missing documentation for a type alias - --> tests/ui/missing_doc.rs:16:1 + --> tests/ui/missing_doc.rs:19:1 | LL | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,19 +8,19 @@ LL | type Typedef = String; = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]` error: missing documentation for a module - --> tests/ui/missing_doc.rs:19:1 + --> tests/ui/missing_doc.rs:22:1 | LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:25:1 + --> tests/ui/missing_doc.rs:28:1 | LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> tests/ui/missing_doc.rs:39:1 + --> tests/ui/missing_doc.rs:42:1 | LL | / enum Baz { LL | | BazA { a: isize, b: isize }, @@ -29,43 +29,43 @@ LL | | } | |_^ error: missing documentation for a variant - --> tests/ui/missing_doc.rs:40:5 + --> tests/ui/missing_doc.rs:43:5 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc.rs:40:12 + --> tests/ui/missing_doc.rs:43:12 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc.rs:40:22 + --> tests/ui/missing_doc.rs:43:22 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a variant - --> tests/ui/missing_doc.rs:41:5 + --> tests/ui/missing_doc.rs:44:5 | LL | BarB, | ^^^^ error: missing documentation for a constant - --> tests/ui/missing_doc.rs:65:1 + --> tests/ui/missing_doc.rs:68:1 | LL | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> tests/ui/missing_doc.rs:74:1 + --> tests/ui/missing_doc.rs:77:1 | LL | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> tests/ui/missing_doc.rs:83:1 + --> tests/ui/missing_doc.rs:86:1 | LL | / mod internal_impl { LL | | /// dox @@ -77,13 +77,13 @@ LL | | } | |_^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:88:5 + --> tests/ui/missing_doc.rs:91:5 | LL | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:94:9 + --> tests/ui/missing_doc.rs:97:9 | LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs index ad93e3019fa..4f89aa8a5e5 100644 --- a/tests/ui/mixed_attributes_style.rs +++ b/tests/ui/mixed_attributes_style.rs @@ -1,4 +1,5 @@ #![warn(clippy::mixed_attributes_style)] +#![allow(clippy::duplicated_attributes)] #[allow(unused)] //~ ERROR: item has both inner and outer attributes fn foo1() { diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr index d1d5cd3f47f..ed798073cb7 100644 --- a/tests/ui/mixed_attributes_style.stderr +++ b/tests/ui/mixed_attributes_style.stderr @@ -1,5 +1,5 @@ error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:3:1 + --> tests/ui/mixed_attributes_style.rs:4:1 | LL | / #[allow(unused)] LL | | fn foo1() { @@ -10,7 +10,7 @@ LL | | #![allow(unused)] = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]` error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:17:1 + --> tests/ui/mixed_attributes_style.rs:18:1 | LL | / /// linux LL | | @@ -19,7 +19,7 @@ LL | | //! windows | |_______________^ error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:32:1 + --> tests/ui/mixed_attributes_style.rs:33:1 | LL | / #[allow(unused)] LL | | mod bar { diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 288b003405d..4c45bc98026 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,5 +1,4 @@ //@aux-build:proc_macros.rs -//@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::mut_mut)] #![allow(unused)] @@ -82,3 +81,8 @@ mod issue9035 { fn bar(_: &mut impl Display) {} } + +fn allow_works() { + #[allow(clippy::mut_mut)] + let _ = &mut &mut 1; +} diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 73f2410a252..42853fdc008 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -1,5 +1,5 @@ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:16:11 + --> tests/ui/mut_mut.rs:15:11 | LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]` error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:33:17 + --> tests/ui/mut_mut.rs:32:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:48:25 + --> tests/ui/mut_mut.rs:47:25 | LL | let mut z = inline!(&mut $(&mut 3u32)); | ^ @@ -22,37 +22,37 @@ LL | let mut z = inline!(&mut $(&mut 3u32)); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: this expression mutably borrows a mutable reference. Consider reborrowing - --> tests/ui/mut_mut.rs:35:21 + --> tests/ui/mut_mut.rs:34:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:39:32 + --> tests/ui/mut_mut.rs:38:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:39:16 + --> tests/ui/mut_mut.rs:38:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:44:37 + --> tests/ui/mut_mut.rs:43:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:44:16 + --> tests/ui/mut_mut.rs:43:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:44:21 + --> tests/ui/mut_mut.rs:43:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/tests/ui/needless_bitwise_bool.fixed b/tests/ui/needless_bitwise_bool.fixed index 201f8a4c19d..a8176618c1f 100644 --- a/tests/ui/needless_bitwise_bool.fixed +++ b/tests/ui/needless_bitwise_bool.fixed @@ -1,4 +1,5 @@ #![warn(clippy::needless_bitwise_bool)] +#![allow(clippy::const_is_empty)] fn returns_bool() -> bool { true diff --git a/tests/ui/needless_bitwise_bool.rs b/tests/ui/needless_bitwise_bool.rs index b0e5014b74b..f190eb2b76e 100644 --- a/tests/ui/needless_bitwise_bool.rs +++ b/tests/ui/needless_bitwise_bool.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_bitwise_bool)] +#![allow(clippy::const_is_empty)] fn returns_bool() -> bool { true diff --git a/tests/ui/needless_bitwise_bool.stderr b/tests/ui/needless_bitwise_bool.stderr index f29d4492540..9f14646c3e5 100644 --- a/tests/ui/needless_bitwise_bool.stderr +++ b/tests/ui/needless_bitwise_bool.stderr @@ -1,5 +1,5 @@ error: use of bitwise operator instead of lazy operator between booleans - --> tests/ui/needless_bitwise_bool.rs:22:8 + --> tests/ui/needless_bitwise_bool.rs:23:8 | LL | if y & !x { | ^^^^^^ help: try: `y && !x` diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index f9eb39d4938..2575f2449e1 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -316,4 +316,11 @@ fn test_match_as_stmt() { }; } +fn allow_works() -> i32 { + #[allow(clippy::needless_return, clippy::match_single_binding)] + match () { + () => return 42, + } +} + fn main() {} diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 4dd2e22ea9f..04f21834d88 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -326,4 +326,11 @@ fn test_match_as_stmt() { }; } +fn allow_works() -> i32 { + #[allow(clippy::needless_return, clippy::match_single_binding)] + match () { + () => return 42, + } +} + fn main() {} diff --git a/tests/ui/no_effect_replace.rs b/tests/ui/no_effect_replace.rs index 2a940d87fb9..e4fd5caae2a 100644 --- a/tests/ui/no_effect_replace.rs +++ b/tests/ui/no_effect_replace.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::no_effect_replace)] fn main() { diff --git a/tests/ui/no_effect_replace.stderr b/tests/ui/no_effect_replace.stderr index ad2dcd2cc9b..ded86c5c5b8 100644 --- a/tests/ui/no_effect_replace.stderr +++ b/tests/ui/no_effect_replace.stderr @@ -1,5 +1,5 @@ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:6:13 + --> tests/ui/no_effect_replace.rs:4:13 | LL | let _ = "12345".replace('1', "1"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,43 +8,43 @@ LL | let _ = "12345".replace('1', "1"); = help: to override `-D warnings` add `#[allow(clippy::no_effect_replace)]` error: replacing text with itself - --> tests/ui/no_effect_replace.rs:9:13 + --> tests/ui/no_effect_replace.rs:7:13 | LL | let _ = "12345".replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:11:13 + --> tests/ui/no_effect_replace.rs:9:13 | LL | let _ = String::new().replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:14:13 + --> tests/ui/no_effect_replace.rs:12:13 | LL | let _ = "12345".replacen('1', "1", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:16:13 + --> tests/ui/no_effect_replace.rs:14:13 | LL | let _ = "12345".replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:18:13 + --> tests/ui/no_effect_replace.rs:16:13 | LL | let _ = String::new().replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:25:13 + --> tests/ui/no_effect_replace.rs:23:13 | LL | let _ = "hello".replace(&x.f(), &x.f()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:29:13 + --> tests/ui/no_effect_replace.rs:27:13 | LL | let _ = "hello".replace(&y(), &y()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index d443334bb05..eeab801b7da 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -3,7 +3,8 @@ clippy::ref_option_ref, clippy::equatable_if_let, clippy::let_unit_value, - clippy::redundant_locals + clippy::redundant_locals, + clippy::manual_unwrap_or_default )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 317c35bf842..3e5b96d7c31 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -3,7 +3,8 @@ clippy::ref_option_ref, clippy::equatable_if_let, clippy::let_unit_value, - clippy::redundant_locals + clippy::redundant_locals, + clippy::manual_unwrap_or_default )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index a794dca762f..f5359a0c34f 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -1,5 +1,5 @@ error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:10:5 + --> tests/ui/option_if_let_else.rs:11:5 | LL | / if let Some(x) = string { LL | | (true, x) @@ -12,19 +12,19 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:28:13 + --> tests/ui/option_if_let_else.rs:29:13 | LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:29:13 + --> tests/ui/option_if_let_else.rs:30:13 | LL | let _ = if let Some(s) = &num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:30:13 + --> tests/ui/option_if_let_else.rs:31:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ @@ -44,13 +44,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:36:13 + --> tests/ui/option_if_let_else.rs:37:13 | LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:37:13 + --> tests/ui/option_if_let_else.rs:38:13 | LL | let _ = if let Some(mut s) = num { | _____________^ @@ -70,7 +70,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:43:13 + --> tests/ui/option_if_let_else.rs:44:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ @@ -90,7 +90,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:52:5 + --> tests/ui/option_if_let_else.rs:53:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -109,7 +109,7 @@ LL + }) | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:65:13 + --> tests/ui/option_if_let_else.rs:66:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:74:13 + --> tests/ui/option_if_let_else.rs:75:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -144,7 +144,7 @@ LL ~ }, |x| x * x * x * x); | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:107:13 + --> tests/ui/option_if_let_else.rs:108:13 | LL | / if let Some(idx) = s.find('.') { LL | | vec![s[..idx].to_string(), s[idx..].to_string()] @@ -154,7 +154,7 @@ LL | | } | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:118:5 + --> tests/ui/option_if_let_else.rs:119:5 | LL | / if let Ok(binding) = variable { LL | | println!("Ok {binding}"); @@ -177,13 +177,13 @@ LL + }) | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:142:13 + --> tests/ui/option_if_let_else.rs:143:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:152:13 + --> tests/ui/option_if_let_else.rs:153:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -205,13 +205,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:180:13 + --> tests/ui/option_if_let_else.rs:181:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:184:13 + --> tests/ui/option_if_let_else.rs:185:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -231,7 +231,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:223:13 + --> tests/ui/option_if_let_else.rs:224:13 | LL | let _ = match s { | _____________^ @@ -241,7 +241,7 @@ LL | | }; | |_____^ help: try: `s.map_or(1, |string| string.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:227:13 + --> tests/ui/option_if_let_else.rs:228:13 | LL | let _ = match Some(10) { | _____________^ @@ -251,7 +251,7 @@ LL | | }; | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:233:13 + --> tests/ui/option_if_let_else.rs:234:13 | LL | let _ = match res { | _____________^ @@ -261,7 +261,7 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:237:13 + --> tests/ui/option_if_let_else.rs:238:13 | LL | let _ = match res { | _____________^ @@ -271,13 +271,13 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:241:13 + --> tests/ui/option_if_let_else.rs:242:13 | LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:258:17 + --> tests/ui/option_if_let_else.rs:259:17 | LL | let _ = match initial { | _________________^ @@ -287,7 +287,7 @@ LL | | }; | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:265:17 + --> tests/ui/option_if_let_else.rs:266:17 | LL | let _ = match initial { | _________________^ @@ -297,7 +297,7 @@ LL | | }; | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:288:24 + --> tests/ui/option_if_let_else.rs:289:24 | LL | let mut _hashmap = if let Some(hm) = &opt { | ________________________^ @@ -308,7 +308,7 @@ LL | | }; | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:294:19 + --> tests/ui/option_if_let_else.rs:295:19 | LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 2f6e4d76145..42f03aae7bb 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,7 +1,5 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![deny(clippy::option_option)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::manual_unwrap_or_default)] const C: Option> = None; //~^ ERROR: consider using `Option` instead of `Option>` or a custom enum if diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 76cb9ae944c..0cd048e400e 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,77 +1,77 @@ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:6:10 + --> tests/ui/option_option.rs:4:10 | LL | const C: Option> = None; | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui/option_option.rs:3:9 + --> tests/ui/option_option.rs:1:9 | LL | #![deny(clippy::option_option)] | ^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:8:11 + --> tests/ui/option_option.rs:6:11 | LL | static S: Option> = None; | ^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:11:13 + --> tests/ui/option_option.rs:9:13 | LL | fn input(_: Option>) {} | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:14:16 + --> tests/ui/option_option.rs:12:16 | LL | fn output() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:19:27 + --> tests/ui/option_option.rs:17:27 | LL | fn output_nested() -> Vec>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:25:30 + --> tests/ui/option_option.rs:23:30 | LL | fn output_nested_nested() -> Option>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:31:8 + --> tests/ui/option_option.rs:29:8 | LL | x: Option>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:36:23 + --> tests/ui/option_option.rs:34:23 | LL | fn struct_fn() -> Option> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:43:22 + --> tests/ui/option_option.rs:41:22 | LL | fn trait_fn() -> Option>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:48:11 + --> tests/ui/option_option.rs:46:11 | LL | Tuple(Option>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:50:17 + --> tests/ui/option_option.rs:48:17 | LL | Struct { x: Option> }, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option` instead of `Option>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:92:14 + --> tests/ui/option_option.rs:90:14 | LL | foo: Option>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/read_zero_byte_vec.rs b/tests/ui/read_zero_byte_vec.rs index fd5a88a37a6..68acf433469 100644 --- a/tests/ui/read_zero_byte_vec.rs +++ b/tests/ui/read_zero_byte_vec.rs @@ -112,4 +112,10 @@ async fn test_tokio(r: &mut R) { //~^ ERROR: reading zero byte data to `Vec` } +fn allow_works(mut f: F) { + let mut data = Vec::with_capacity(100); + #[allow(clippy::read_zero_byte_vec)] + f.read(&mut data).unwrap(); +} + fn main() {} diff --git a/tests/ui/redundant_as_str.fixed b/tests/ui/redundant_as_str.fixed index 4185b402226..708a1cc9150 100644 --- a/tests/ui/redundant_as_str.fixed +++ b/tests/ui/redundant_as_str.fixed @@ -1,4 +1,5 @@ #![warn(clippy::redundant_as_str)] +#![allow(clippy::const_is_empty)] fn main() { let string = "Hello, world!".to_owned(); diff --git a/tests/ui/redundant_as_str.rs b/tests/ui/redundant_as_str.rs index 7a74d8a55de..257af591cef 100644 --- a/tests/ui/redundant_as_str.rs +++ b/tests/ui/redundant_as_str.rs @@ -1,4 +1,5 @@ #![warn(clippy::redundant_as_str)] +#![allow(clippy::const_is_empty)] fn main() { let string = "Hello, world!".to_owned(); diff --git a/tests/ui/redundant_as_str.stderr b/tests/ui/redundant_as_str.stderr index f086de5fede..f5379d701db 100644 --- a/tests/ui/redundant_as_str.stderr +++ b/tests/ui/redundant_as_str.stderr @@ -1,5 +1,5 @@ error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too - --> tests/ui/redundant_as_str.rs:7:29 + --> tests/ui/redundant_as_str.rs:8:29 | LL | let _redundant = string.as_str().as_bytes(); | ^^^^^^^^^^^^^^^^^ help: try: `as_bytes` @@ -8,7 +8,7 @@ LL | let _redundant = string.as_str().as_bytes(); = help: to override `-D warnings` add `#[allow(clippy::redundant_as_str)]` error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too - --> tests/ui/redundant_as_str.rs:8:29 + --> tests/ui/redundant_as_str.rs:9:29 | LL | let _redundant = string.as_str().is_empty(); | ^^^^^^^^^^^^^^^^^ help: try: `is_empty` diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index f4ff0f0b88b..24d0f797542 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -2,6 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. +#![allow(clippy::duplicated_attributes)] #![allow(clippy::almost_complete_range)] #![allow(clippy::disallowed_names)] #![allow(clippy::blocks_in_conditions)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 0df1098f5fb..be8da2fa1a3 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -2,6 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. +#![allow(clippy::duplicated_attributes)] #![allow(clippy::almost_complete_range)] #![allow(clippy::disallowed_names)] #![allow(clippy::blocks_in_conditions)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index e6659b109e5..777ac20153d 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> tests/ui/rename.rs:55:9 + --> tests/ui/rename.rs:56:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -8,343 +8,343 @@ LL | #![warn(clippy::almost_complete_letter_range)] = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> tests/ui/rename.rs:56:9 + --> tests/ui/rename.rs:57:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:57:9 + --> tests/ui/rename.rs:58:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:58:9 + --> tests/ui/rename.rs:59:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:59:9 + --> tests/ui/rename.rs:60:9 | LL | #![warn(clippy::blocks_in_if_conditions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> tests/ui/rename.rs:60:9 + --> tests/ui/rename.rs:61:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> tests/ui/rename.rs:61:9 + --> tests/ui/rename.rs:62:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> tests/ui/rename.rs:62:9 + --> tests/ui/rename.rs:63:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> tests/ui/rename.rs:63:9 + --> tests/ui/rename.rs:64:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> tests/ui/rename.rs:64:9 + --> tests/ui/rename.rs:65:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> tests/ui/rename.rs:65:9 + --> tests/ui/rename.rs:66:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> tests/ui/rename.rs:66:9 + --> tests/ui/rename.rs:67:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> tests/ui/rename.rs:67:9 + --> tests/ui/rename.rs:68:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> tests/ui/rename.rs:68:9 + --> tests/ui/rename.rs:69:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl` - --> tests/ui/rename.rs:69:9 + --> tests/ui/rename.rs:70:9 | LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl` - --> tests/ui/rename.rs:70:9 + --> tests/ui/rename.rs:71:9 | LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> tests/ui/rename.rs:71:9 + --> tests/ui/rename.rs:72:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> tests/ui/rename.rs:72:9 + --> tests/ui/rename.rs:73:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> tests/ui/rename.rs:73:9 + --> tests/ui/rename.rs:74:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> tests/ui/rename.rs:74:9 + --> tests/ui/rename.rs:75:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:75:9 + --> tests/ui/rename.rs:76:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:76:9 + --> tests/ui/rename.rs:77:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:77:9 + --> tests/ui/rename.rs:78:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:78:9 + --> tests/ui/rename.rs:79:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> tests/ui/rename.rs:79:9 + --> tests/ui/rename.rs:80:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:80:9 + --> tests/ui/rename.rs:81:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:81:9 + --> tests/ui/rename.rs:82:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:82:9 + --> tests/ui/rename.rs:83:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> tests/ui/rename.rs:83:9 + --> tests/ui/rename.rs:84:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> tests/ui/rename.rs:84:9 + --> tests/ui/rename.rs:85:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> tests/ui/rename.rs:85:9 + --> tests/ui/rename.rs:86:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` - --> tests/ui/rename.rs:86:9 + --> tests/ui/rename.rs:87:9 | LL | #![warn(clippy::unwrap_or_else_default)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> tests/ui/rename.rs:87:9 + --> tests/ui/rename.rs:88:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting` - --> tests/ui/rename.rs:88:9 + --> tests/ui/rename.rs:89:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> tests/ui/rename.rs:89:9 + --> tests/ui/rename.rs:90:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> tests/ui/rename.rs:90:9 + --> tests/ui/rename.rs:91:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> tests/ui/rename.rs:91:9 + --> tests/ui/rename.rs:92:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> tests/ui/rename.rs:92:9 + --> tests/ui/rename.rs:93:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> tests/ui/rename.rs:93:9 + --> tests/ui/rename.rs:94:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` - --> tests/ui/rename.rs:94:9 + --> tests/ui/rename.rs:95:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:95:9 + --> tests/ui/rename.rs:96:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:96:9 + --> tests/ui/rename.rs:97:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:97:9 + --> tests/ui/rename.rs:98:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> tests/ui/rename.rs:98:9 + --> tests/ui/rename.rs:99:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> tests/ui/rename.rs:99:9 + --> tests/ui/rename.rs:100:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> tests/ui/rename.rs:100:9 + --> tests/ui/rename.rs:101:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> tests/ui/rename.rs:101:9 + --> tests/ui/rename.rs:102:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> tests/ui/rename.rs:102:9 + --> tests/ui/rename.rs:103:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> tests/ui/rename.rs:103:9 + --> tests/ui/rename.rs:104:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> tests/ui/rename.rs:104:9 + --> tests/ui/rename.rs:105:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:105:9 + --> tests/ui/rename.rs:106:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:106:9 + --> tests/ui/rename.rs:107:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:107:9 + --> tests/ui/rename.rs:108:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> tests/ui/rename.rs:108:9 + --> tests/ui/rename.rs:109:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:109:9 + --> tests/ui/rename.rs:110:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:110:9 + --> tests/ui/rename.rs:111:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:111:9 + --> tests/ui/rename.rs:112:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:112:9 + --> tests/ui/rename.rs:113:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 6df64eb4053..acd70416d8b 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -1,12 +1,11 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::single_match)] #![allow( unused, clippy::uninlined_format_args, clippy::needless_if, clippy::redundant_guards, - clippy::redundant_pattern_matching + clippy::redundant_pattern_matching, + clippy::manual_unwrap_or_default )] fn dummy() {} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 4f005f4e04f..bde78199810 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,12 +1,11 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::single_match)] #![allow( unused, clippy::uninlined_format_args, clippy::needless_if, clippy::redundant_guards, - clippy::redundant_pattern_matching + clippy::redundant_pattern_matching, + clippy::manual_unwrap_or_default )] fn dummy() {} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 651d0b4911d..a249c120ee4 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:16:5 + --> tests/ui/single_match.rs:15:5 | LL | / match x { LL | | Some(y) => { @@ -19,7 +19,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:24:5 + --> tests/ui/single_match.rs:23:5 | LL | / match x { LL | | // Note the missing block braces. @@ -31,7 +31,7 @@ LL | | } | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:33:5 + --> tests/ui/single_match.rs:32:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:62:5 + --> tests/ui/single_match.rs:61:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:67:5 + --> tests/ui/single_match.rs:66:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:74:5 + --> tests/ui/single_match.rs:73:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -67,7 +67,7 @@ LL | | }; | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:95:5 + --> tests/ui/single_match.rs:94:5 | LL | / match x { LL | | "test" => println!(), @@ -76,7 +76,7 @@ LL | | } | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:108:5 + --> tests/ui/single_match.rs:107:5 | LL | / match x { LL | | Foo::A => println!(), @@ -85,7 +85,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:114:5 + --> tests/ui/single_match.rs:113:5 | LL | / match x { LL | | FOO_C => println!(), @@ -94,7 +94,7 @@ LL | | } | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:119:5 + --> tests/ui/single_match.rs:118:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -103,7 +103,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:125:5 + --> tests/ui/single_match.rs:124:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -112,7 +112,7 @@ LL | | } | |_____^ help: try: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:142:5 + --> tests/ui/single_match.rs:141:5 | LL | / match x { LL | | Bar::A => println!(), @@ -121,7 +121,7 @@ LL | | } | |_____^ help: try: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:150:5 + --> tests/ui/single_match.rs:149:5 | LL | / match x { LL | | None => println!(), @@ -130,7 +130,7 @@ LL | | }; | |_____^ help: try: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:172:5 + --> tests/ui/single_match.rs:171:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -139,7 +139,7 @@ LL | | } | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:178:5 + --> tests/ui/single_match.rs:177:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -148,7 +148,7 @@ LL | | } | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:184:5 + --> tests/ui/single_match.rs:183:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -157,7 +157,7 @@ LL | | } | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:256:5 + --> tests/ui/single_match.rs:255:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -177,7 +177,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:264:5 + --> tests/ui/single_match.rs:263:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed index 2970f5485fa..e840adf0fa3 100644 --- a/tests/ui/single_match_else.fixed +++ b/tests/ui/single_match_else.fixed @@ -1,5 +1,4 @@ //@aux-build: proc_macros.rs -//@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 26974b2a48a..430c4da20f1 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,5 +1,4 @@ //@aux-build: proc_macros.rs -//@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 48c74c0caea..f8f88379d6d 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:18:13 + --> tests/ui/single_match_else.rs:17:13 | LL | let _ = match ExprNode::Butterflies { | _____________^ @@ -22,7 +22,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:83:5 + --> tests/ui/single_match_else.rs:82:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -42,7 +42,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:92:5 + --> tests/ui/single_match_else.rs:91:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -62,7 +62,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:102:5 + --> tests/ui/single_match_else.rs:101:5 | LL | / match Result::::Ok(1) { LL | | Ok(a) => println!("${:?}", a), @@ -82,7 +82,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:111:5 + --> tests/ui/single_match_else.rs:110:5 | LL | / match Cow::from("moo") { LL | | Cow::Owned(a) => println!("${:?}", a), @@ -102,7 +102,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:121:5 + --> tests/ui/single_match_else.rs:120:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -125,7 +125,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:132:5 + --> tests/ui/single_match_else.rs:131:5 | LL | / match bar { LL | | Some(v) => { @@ -149,7 +149,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:144:5 + --> tests/ui/single_match_else.rs:143:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -173,7 +173,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:156:5 + --> tests/ui/single_match_else.rs:155:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/tests/ui/std_instead_of_core.fixed b/tests/ui/std_instead_of_core.fixed index 0a734a65d29..ec4ae2ea13c 100644 --- a/tests/ui/std_instead_of_core.fixed +++ b/tests/ui/std_instead_of_core.fixed @@ -17,7 +17,7 @@ fn std_instead_of_core() { use ::core::hash::Hash; //~^ ERROR: used import from `std` instead of `core` // Don't lint on `env` macro - use core::env; + use std::env; // Multiple imports use core::fmt::{Debug, Result}; diff --git a/tests/ui/std_instead_of_core.stderr b/tests/ui/std_instead_of_core.stderr index ee42b474a32..8f920511cc5 100644 --- a/tests/ui/std_instead_of_core.stderr +++ b/tests/ui/std_instead_of_core.stderr @@ -13,12 +13,6 @@ error: used import from `std` instead of `core` LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` -error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:20:9 - | -LL | use std::env; - | ^^^ help: consider importing the item from `core`: `core` - error: used import from `std` instead of `core` --> tests/ui/std_instead_of_core.rs:23:9 | @@ -85,5 +79,5 @@ LL | use alloc::slice::from_ref; = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]` -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index 35275e81ded..70b390b00e2 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -1,7 +1,11 @@ //@no-rustfix #![warn(clippy::unconditional_recursion)] -#![allow(clippy::partialeq_ne_impl, clippy::default_constructed_unit_structs)] +#![allow( + clippy::partialeq_ne_impl, + clippy::default_constructed_unit_structs, + clippy::only_used_in_recursion +)] enum Foo { A, @@ -350,4 +354,48 @@ mod issue12154 { } } +// From::from -> Into::into -> From::from +struct BadFromTy1<'a>(&'a ()); +struct BadIntoTy1<'b>(&'b ()); +impl<'a> From> for BadIntoTy1<'static> { + fn from(f: BadFromTy1<'a>) -> Self { + f.into() + } +} + +// Using UFCS syntax +struct BadFromTy2<'a>(&'a ()); +struct BadIntoTy2<'b>(&'b ()); +impl<'a> From> for BadIntoTy2<'static> { + fn from(f: BadFromTy2<'a>) -> Self { + Into::into(f) + } +} + +// Different Into impl (>), so no infinite recursion +struct BadFromTy3; +impl From for i32 { + fn from(f: BadFromTy3) -> Self { + Into::into(1i16) + } +} + +// A conditional return that ends the recursion +struct BadFromTy4; +impl From for i32 { + fn from(f: BadFromTy4) -> Self { + if true { + return 42; + } + f.into() + } +} + +// Types differ in refs, don't lint +impl From<&BadFromTy4> for i32 { + fn from(f: &BadFromTy4) -> Self { + BadFromTy4.into() + } +} + fn main() {} diff --git a/tests/ui/unconditional_recursion.stderr b/tests/ui/unconditional_recursion.stderr index 3fd6c91000e..03c27bd8ed8 100644 --- a/tests/ui/unconditional_recursion.stderr +++ b/tests/ui/unconditional_recursion.stderr @@ -1,5 +1,5 @@ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:42:5 + --> tests/ui/unconditional_recursion.rs:46:5 | LL | fn ne(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -12,7 +12,7 @@ LL | self.ne(other) = help: to override `-D warnings` add `#[allow(unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:46:5 + --> tests/ui/unconditional_recursion.rs:50:5 | LL | fn eq(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -23,7 +23,7 @@ LL | self.eq(other) = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:211:5 + --> tests/ui/unconditional_recursion.rs:215:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -34,7 +34,7 @@ LL | self.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:221:5 + --> tests/ui/unconditional_recursion.rs:225:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -45,7 +45,7 @@ LL | x.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:232:5 + --> tests/ui/unconditional_recursion.rs:236:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -56,7 +56,7 @@ LL | (self as &Self).to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:12:5 + --> tests/ui/unconditional_recursion.rs:16:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -65,7 +65,7 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:14:9 + --> tests/ui/unconditional_recursion.rs:18:9 | LL | self != other | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | self != other = help: to override `-D warnings` add `#[allow(clippy::unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:16:5 + --> tests/ui/unconditional_recursion.rs:20:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -82,13 +82,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:18:9 + --> tests/ui/unconditional_recursion.rs:22:9 | LL | self == other | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:28:5 + --> tests/ui/unconditional_recursion.rs:32:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | self != &Foo2::B // no error here @@ -96,13 +96,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:29:9 + --> tests/ui/unconditional_recursion.rs:33:9 | LL | self != &Foo2::B // no error here | ^^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:31:5 + --> tests/ui/unconditional_recursion.rs:35:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | self == &Foo2::B // no error here @@ -110,13 +110,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:32:9 + --> tests/ui/unconditional_recursion.rs:36:9 | LL | self == &Foo2::B // no error here | ^^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:42:5 + --> tests/ui/unconditional_recursion.rs:46:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -125,27 +125,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:44:9 + --> tests/ui/unconditional_recursion.rs:48:9 | LL | self.ne(other) | ^^^^^^^^^^^^^^ -error: parameter is only used in recursion - --> tests/ui/unconditional_recursion.rs:42:18 - | -LL | fn ne(&self, other: &Self) -> bool { - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_other` - | -note: parameter used here - --> tests/ui/unconditional_recursion.rs:44:17 - | -LL | self.ne(other) - | ^^^^^ - = note: `-D clippy::only-used-in-recursion` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::only_used_in_recursion)]` - error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:46:5 + --> tests/ui/unconditional_recursion.rs:50:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -154,25 +140,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:48:9 + --> tests/ui/unconditional_recursion.rs:52:9 | LL | self.eq(other) | ^^^^^^^^^^^^^^ -error: parameter is only used in recursion - --> tests/ui/unconditional_recursion.rs:46:18 - | -LL | fn eq(&self, other: &Self) -> bool { - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_other` - | -note: parameter used here - --> tests/ui/unconditional_recursion.rs:48:17 - | -LL | self.eq(other) - | ^^^^^ - error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:90:5 + --> tests/ui/unconditional_recursion.rs:94:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -181,13 +155,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:92:9 + --> tests/ui/unconditional_recursion.rs:96:9 | LL | other != self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:94:5 + --> tests/ui/unconditional_recursion.rs:98:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -196,13 +170,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:96:9 + --> tests/ui/unconditional_recursion.rs:100:9 | LL | other == self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:104:5 + --> tests/ui/unconditional_recursion.rs:108:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | @@ -211,13 +185,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:106:9 + --> tests/ui/unconditional_recursion.rs:110:9 | LL | other != other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:106:9 + --> tests/ui/unconditional_recursion.rs:110:9 | LL | other != other | ^^^^^^^^^^^^^^ @@ -225,7 +199,7 @@ LL | other != other = note: `#[deny(clippy::eq_op)]` on by default error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:108:5 + --> tests/ui/unconditional_recursion.rs:112:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -234,19 +208,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:110:9 + --> tests/ui/unconditional_recursion.rs:114:9 | LL | other == other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:110:9 + --> tests/ui/unconditional_recursion.rs:114:9 | LL | other == other | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:117:5 + --> tests/ui/unconditional_recursion.rs:121:5 | LL | / fn ne(&self, _other: &Self) -> bool { LL | | @@ -255,19 +229,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:119:9 + --> tests/ui/unconditional_recursion.rs:123:9 | LL | self != self | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:119:9 + --> tests/ui/unconditional_recursion.rs:123:9 | LL | self != self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:121:5 + --> tests/ui/unconditional_recursion.rs:125:5 | LL | / fn eq(&self, _other: &Self) -> bool { LL | | @@ -276,19 +250,19 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:123:9 + --> tests/ui/unconditional_recursion.rs:127:9 | LL | self == self | ^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:123:9 + --> tests/ui/unconditional_recursion.rs:127:9 | LL | self == self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:149:13 + --> tests/ui/unconditional_recursion.rs:153:13 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -300,7 +274,7 @@ LL | impl_partial_eq!(S5); | -------------------- in this macro invocation | note: recursive call site - --> tests/ui/unconditional_recursion.rs:151:17 + --> tests/ui/unconditional_recursion.rs:155:17 | LL | self == other | ^^^^^^^^^^^^^ @@ -310,7 +284,7 @@ LL | impl_partial_eq!(S5); = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:178:5 + --> tests/ui/unconditional_recursion.rs:182:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -321,13 +295,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:182:9 + --> tests/ui/unconditional_recursion.rs:186:9 | LL | mine == theirs | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:247:5 + --> tests/ui/unconditional_recursion.rs:251:5 | LL | / fn new() -> Self { LL | | @@ -336,13 +310,13 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:249:9 + --> tests/ui/unconditional_recursion.rs:253:9 | LL | Self::default() | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:286:5 + --> tests/ui/unconditional_recursion.rs:290:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -353,10 +327,38 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:290:9 + --> tests/ui/unconditional_recursion.rs:294:9 | LL | mine.eq(theirs) | ^^^^^^^^^^^^^^^ +error: function cannot return without recursing + --> tests/ui/unconditional_recursion.rs:361:5 + | +LL | / fn from(f: BadFromTy1<'a>) -> Self { +LL | | f.into() +LL | | } + | |_____^ + | +note: recursive call site + --> tests/ui/unconditional_recursion.rs:362:9 + | +LL | f.into() + | ^^^^^^^^ + +error: function cannot return without recursing + --> tests/ui/unconditional_recursion.rs:370:5 + | +LL | / fn from(f: BadFromTy2<'a>) -> Self { +LL | | Into::into(f) +LL | | } + | |_____^ + | +note: recursive call site + --> tests/ui/unconditional_recursion.rs:371:9 + | +LL | Into::into(f) + | ^^^^^^^^^^^^^ + error: aborting due to 27 previous errors diff --git a/tests/ui/unused_enumerate_index.fixed b/tests/ui/unused_enumerate_index.fixed index d079807ab58..cffd02b0acc 100644 --- a/tests/ui/unused_enumerate_index.fixed +++ b/tests/ui/unused_enumerate_index.fixed @@ -1,8 +1,12 @@ -#![allow(unused)] +#![allow(unused, clippy::map_identity)] #![warn(clippy::unused_enumerate_index)] use std::iter::Enumerate; +fn get_enumerate() -> Enumerate> { + vec![1].into_iter().enumerate() +} + fn main() { let v = [1, 2, 3]; for x in v.iter() { @@ -55,4 +59,48 @@ fn main() { for x in dummy { println!("{x}"); } + + let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}")); + + let p = vec![1, 2, 3].into_iter(); + p.map(|x| println!("{x}")); + + // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we + // have no control. + let p = get_enumerate(); + p.map(|(_, x)| println!("{x}")); + + // This shouldn't trigger the lint. The `enumerate` call is in a different context. + macro_rules! mac { + () => { + [1].iter().enumerate() + }; + } + _ = mac!().map(|(_, v)| v); + + macro_rules! mac2 { + () => { + [1].iter() + }; + } + _ = mac2!().map(|_v| {}); + + // This shouldn't trigger the lint because of the `allow`. + #[allow(clippy::unused_enumerate_index)] + let v = [1].iter().enumerate(); + v.map(|(_, _x)| {}); + + // This should keep the explicit type of `x`. + let v = [1, 2, 3].iter().copied(); + let x = v.map(|x: i32| x).sum::(); + assert_eq!(x, 6); + + // This should keep the explicit type of `x`. + let v = [1, 2, 3].iter().copied(); + let x = v.map(|x: i32| x).sum::(); + assert_eq!(x, 6); + + let v = [1, 2, 3].iter().copied(); + let x = v.map(|x| x).sum::(); + assert_eq!(x, 6); } diff --git a/tests/ui/unused_enumerate_index.rs b/tests/ui/unused_enumerate_index.rs index 2d524da7632..f2b5f8b9124 100644 --- a/tests/ui/unused_enumerate_index.rs +++ b/tests/ui/unused_enumerate_index.rs @@ -1,8 +1,12 @@ -#![allow(unused)] +#![allow(unused, clippy::map_identity)] #![warn(clippy::unused_enumerate_index)] use std::iter::Enumerate; +fn get_enumerate() -> Enumerate> { + vec![1].into_iter().enumerate() +} + fn main() { let v = [1, 2, 3]; for (_, x) in v.iter().enumerate() { @@ -55,4 +59,48 @@ fn main() { for (_, x) in dummy.enumerate() { println!("{x}"); } + + let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}")); + + let p = vec![1, 2, 3].into_iter().enumerate(); + p.map(|(_, x)| println!("{x}")); + + // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we + // have no control. + let p = get_enumerate(); + p.map(|(_, x)| println!("{x}")); + + // This shouldn't trigger the lint. The `enumerate` call is in a different context. + macro_rules! mac { + () => { + [1].iter().enumerate() + }; + } + _ = mac!().map(|(_, v)| v); + + macro_rules! mac2 { + () => { + [1].iter() + }; + } + _ = mac2!().enumerate().map(|(_, _v)| {}); + + // This shouldn't trigger the lint because of the `allow`. + #[allow(clippy::unused_enumerate_index)] + let v = [1].iter().enumerate(); + v.map(|(_, _x)| {}); + + // This should keep the explicit type of `x`. + let v = [1, 2, 3].iter().copied().enumerate(); + let x = v.map(|(_, x): (usize, i32)| x).sum::(); + assert_eq!(x, 6); + + // This should keep the explicit type of `x`. + let v = [1, 2, 3].iter().copied().enumerate(); + let x = v.map(|(_, x): (_, i32)| x).sum::(); + assert_eq!(x, 6); + + let v = [1, 2, 3].iter().copied().enumerate(); + let x = v.map(|(_, x)| x).sum::(); + assert_eq!(x, 6); } diff --git a/tests/ui/unused_enumerate_index.stderr b/tests/ui/unused_enumerate_index.stderr index 7bd7d29117e..6ec07dcbff0 100644 --- a/tests/ui/unused_enumerate_index.stderr +++ b/tests/ui/unused_enumerate_index.stderr @@ -1,5 +1,5 @@ error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:8:19 + --> tests/ui/unused_enumerate_index.rs:12:19 | LL | for (_, x) in v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | for x in v.iter() { | ~ ~~~~~~~~ error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:55:19 + --> tests/ui/unused_enumerate_index.rs:59:19 | LL | for (_, x) in dummy.enumerate() { | ^^^^^^^^^^^^^^^^^ @@ -22,5 +22,77 @@ help: remove the `.enumerate()` call LL | for x in dummy { | ~ ~~~~~ -error: aborting due to 2 previous errors +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:63:39 + | +LL | let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}")); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL - let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}")); +LL + let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}")); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:65:39 + | +LL | let p = vec![1, 2, 3].into_iter().enumerate(); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL ~ let p = vec![1, 2, 3].into_iter(); +LL ~ p.map(|x| println!("{x}")); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:86:17 + | +LL | _ = mac2!().enumerate().map(|(_, _v)| {}); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL - _ = mac2!().enumerate().map(|(_, _v)| {}); +LL + _ = mac2!().map(|_v| {}); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:94:39 + | +LL | let v = [1, 2, 3].iter().copied().enumerate(); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL ~ let v = [1, 2, 3].iter().copied(); +LL ~ let x = v.map(|x: i32| x).sum::(); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:99:39 + | +LL | let v = [1, 2, 3].iter().copied().enumerate(); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL ~ let v = [1, 2, 3].iter().copied(); +LL ~ let x = v.map(|x: i32| x).sum::(); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:103:39 + | +LL | let v = [1, 2, 3].iter().copied().enumerate(); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL ~ let v = [1, 2, 3].iter().copied(); +LL ~ let x = v.map(|x| x).sum::(); + | + +error: aborting due to 8 previous errors diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 7e5a10c911b..f5b200d5ffe 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -271,5 +271,10 @@ pub fn wildcards(rdr: &mut dyn std::io::Read) { } } } +fn allow_works(mut f: F) { + let mut data = Vec::with_capacity(100); + #[allow(clippy::unused_io_amount)] + f.read(&mut data).unwrap(); +} fn main() {} diff --git a/tests/ui/unused_peekable.rs b/tests/ui/unused_peekable.rs index 131b51e01b6..5865bba4350 100644 --- a/tests/ui/unused_peekable.rs +++ b/tests/ui/unused_peekable.rs @@ -174,3 +174,9 @@ fn valid() { let mut peekable = std::iter::empty::().peekable(); takes_dyn(&mut peekable); } + +fn allow_works() { + #[allow(clippy::unused_peekable)] + let iter = [1, 2, 3].iter().peekable(); + iter; +} diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 787dd3ec7e6..6ea7857a238 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -6,7 +6,8 @@ clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into, - clippy::self_named_constructors + clippy::self_named_constructors, + clippy::needless_lifetimes )] #[macro_use] @@ -53,6 +54,7 @@ mod better { } mod lifetimes { + #[derive(Clone, Copy)] struct Foo<'a> { foo_str: &'a str, } @@ -68,11 +70,19 @@ mod lifetimes { Foo { foo_str: "foo" } } - // FIXME: the lint does not handle lifetimed struct - // `Self` should be applicable here - fn clone(&self) -> Foo<'a> { + fn clone(&self) -> Self { Foo { foo_str: self.foo_str } } + + // Cannot replace with `Self` because the lifetime is not `'a`. + fn eq<'b>(&self, other: Foo<'b>) -> bool { + let x: Foo<'_> = other; + self.foo_str == other.foo_str + } + + fn f(&self) -> Foo<'_> { + *self + } } } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 39e182faea6..338cc00e45a 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -6,7 +6,8 @@ clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into, - clippy::self_named_constructors + clippy::self_named_constructors, + clippy::needless_lifetimes )] #[macro_use] @@ -53,6 +54,7 @@ mod better { } mod lifetimes { + #[derive(Clone, Copy)] struct Foo<'a> { foo_str: &'a str, } @@ -68,11 +70,19 @@ mod lifetimes { Foo { foo_str: "foo" } } - // FIXME: the lint does not handle lifetimed struct - // `Self` should be applicable here fn clone(&self) -> Foo<'a> { Foo { foo_str: self.foo_str } } + + // Cannot replace with `Self` because the lifetime is not `'a`. + fn eq<'b>(&self, other: Foo<'b>) -> bool { + let x: Foo<'_> = other; + self.foo_str == other.foo_str + } + + fn f(&self) -> Foo<'_> { + *self + } } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 8d045f05ed2..d7aa8410a47 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> tests/ui/use_self.rs:21:21 + --> tests/ui/use_self.rs:22:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -8,250 +8,256 @@ LL | fn new() -> Foo { = help: to override `-D warnings` add `#[allow(clippy::use_self)]` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:22:13 + --> tests/ui/use_self.rs:23:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:24:22 + --> tests/ui/use_self.rs:25:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:25:13 + --> tests/ui/use_self.rs:26:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:30:25 + --> tests/ui/use_self.rs:31:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:31:13 + --> tests/ui/use_self.rs:32:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:96:24 + --> tests/ui/use_self.rs:73:28 + | +LL | fn clone(&self) -> Foo<'a> { + | ^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> tests/ui/use_self.rs:106:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:96:55 + --> tests/ui/use_self.rs:106:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:111:13 + --> tests/ui/use_self.rs:121:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:146:29 + --> tests/ui/use_self.rs:156:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:147:21 + --> tests/ui/use_self.rs:157:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:158:21 + --> tests/ui/use_self.rs:168:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:159:13 + --> tests/ui/use_self.rs:169:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:176:21 + --> tests/ui/use_self.rs:186:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:177:21 + --> tests/ui/use_self.rs:187:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:178:21 + --> tests/ui/use_self.rs:188:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:220:13 + --> tests/ui/use_self.rs:230:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:221:13 + --> tests/ui/use_self.rs:231:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:223:13 + --> tests/ui/use_self.rs:233:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:242:13 + --> tests/ui/use_self.rs:252:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:256:25 + --> tests/ui/use_self.rs:266:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:257:13 + --> tests/ui/use_self.rs:267:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:261:16 + --> tests/ui/use_self.rs:271:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:261:22 + --> tests/ui/use_self.rs:271:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:284:29 + --> tests/ui/use_self.rs:294:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:285:13 + --> tests/ui/use_self.rs:295:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:457:13 + --> tests/ui/use_self.rs:467:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:494:13 + --> tests/ui/use_self.rs:504:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:531:17 + --> tests/ui/use_self.rs:541:17 | LL | Foo::Bar => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:532:17 + --> tests/ui/use_self.rs:542:17 | LL | Foo::Baz => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:538:20 + --> tests/ui/use_self.rs:548:20 | LL | if let Foo::Bar = self { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:562:17 + --> tests/ui/use_self.rs:572:17 | LL | Something::Num(n) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:563:17 + --> tests/ui/use_self.rs:573:17 | LL | Something::TupleNums(n, _m) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:564:17 + --> tests/ui/use_self.rs:574:17 | LL | Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:570:17 + --> tests/ui/use_self.rs:580:17 | LL | crate::issue8845::Something::Num(n) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:571:17 + --> tests/ui/use_self.rs:581:17 | LL | crate::issue8845::Something::TupleNums(n, _m) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:572:17 + --> tests/ui/use_self.rs:582:17 | LL | crate::issue8845::Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:588:17 + --> tests/ui/use_self.rs:598:17 | LL | let Foo(x) = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:593:17 + --> tests/ui/use_self.rs:603:17 | LL | let crate::issue8845::Foo(x) = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:600:17 + --> tests/ui/use_self.rs:610:17 | LL | let Bar { x, .. } = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:605:17 + --> tests/ui/use_self.rs:615:17 | LL | let crate::issue8845::Bar { x, .. } = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:644:17 + --> tests/ui/use_self.rs:654:17 | LL | E::A => {}, | ^ help: use the applicable keyword: `Self` -error: aborting due to 42 previous errors +error: aborting due to 43 previous errors diff --git a/tests/ui/zero_repeat_side_effects.fixed b/tests/ui/zero_repeat_side_effects.fixed new file mode 100644 index 00000000000..6f132521926 --- /dev/null +++ b/tests/ui/zero_repeat_side_effects.fixed @@ -0,0 +1,60 @@ +#![warn(clippy::zero_repeat_side_effects)] +#![allow(clippy::unnecessary_operation)] +#![allow(clippy::useless_vec)] +#![allow(clippy::needless_late_init)] + +fn f() -> i32 { + println!("side effect"); + 10 +} + +fn main() { + const N: usize = 0; + const M: usize = 1; + + // should trigger + + // on arrays + f(); let a: [i32; 0] = []; + f(); let a: [i32; 0] = []; + let mut b; + f(); b = [] as [i32; 0]; + f(); b = [] as [i32; 0]; + + // on vecs + // vecs dont support infering value of consts + f(); let c: std::vec::Vec = vec![]; + let d; + f(); d = vec![] as std::vec::Vec; + + // for macros + println!("side effect"); let e: [(); 0] = []; + + // for nested calls + { f() }; let g: [i32; 0] = []; + + // as function param + drop({ f(); vec![] as std::vec::Vec }); + + // when singled out/not part of assignment/local + { f(); vec![] as std::vec::Vec }; + { f(); [] as [i32; 0] }; + { f(); [] as [i32; 0] }; + + // should not trigger + + // on arrays with > 0 repeat + let a = [f(); 1]; + let a = [f(); M]; + let mut b; + b = [f(); 1]; + b = [f(); M]; + + // on vecs with > 0 repeat + let c = vec![f(); 1]; + let d; + d = vec![f(); 1]; + + // as function param + drop(vec![f(); 1]); +} diff --git a/tests/ui/zero_repeat_side_effects.rs b/tests/ui/zero_repeat_side_effects.rs new file mode 100644 index 00000000000..9d9c367375a --- /dev/null +++ b/tests/ui/zero_repeat_side_effects.rs @@ -0,0 +1,60 @@ +#![warn(clippy::zero_repeat_side_effects)] +#![allow(clippy::unnecessary_operation)] +#![allow(clippy::useless_vec)] +#![allow(clippy::needless_late_init)] + +fn f() -> i32 { + println!("side effect"); + 10 +} + +fn main() { + const N: usize = 0; + const M: usize = 1; + + // should trigger + + // on arrays + let a = [f(); 0]; + let a = [f(); N]; + let mut b; + b = [f(); 0]; + b = [f(); N]; + + // on vecs + // vecs dont support infering value of consts + let c = vec![f(); 0]; + let d; + d = vec![f(); 0]; + + // for macros + let e = [println!("side effect"); 0]; + + // for nested calls + let g = [{ f() }; 0]; + + // as function param + drop(vec![f(); 0]); + + // when singled out/not part of assignment/local + vec![f(); 0]; + [f(); 0]; + [f(); N]; + + // should not trigger + + // on arrays with > 0 repeat + let a = [f(); 1]; + let a = [f(); M]; + let mut b; + b = [f(); 1]; + b = [f(); M]; + + // on vecs with > 0 repeat + let c = vec![f(); 1]; + let d; + d = vec![f(); 1]; + + // as function param + drop(vec![f(); 1]); +} diff --git a/tests/ui/zero_repeat_side_effects.stderr b/tests/ui/zero_repeat_side_effects.stderr new file mode 100644 index 00000000000..afdc6054253 --- /dev/null +++ b/tests/ui/zero_repeat_side_effects.stderr @@ -0,0 +1,77 @@ +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:18:5 + | +LL | let a = [f(); 0]; + | ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];` + | + = note: `-D clippy::zero-repeat-side-effects` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:19:5 + | +LL | let a = [f(); N]; + | ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:21:5 + | +LL | b = [f(); 0]; + | ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:22:5 + | +LL | b = [f(); N]; + | ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:26:5 + | +LL | let c = vec![f(); 0]; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec = vec![];` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:28:5 + | +LL | d = vec![f(); 0]; + | ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:31:5 + | +LL | let e = [println!("side effect"); 0]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:34:5 + | +LL | let g = [{ f() }; 0]; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:37:10 + | +LL | drop(vec![f(); 0]); + | ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec }` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:40:5 + | +LL | vec![f(); 0]; + | ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec }` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:41:5 + | +LL | [f(); 0]; + | ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }` + +error: function or method calls as the initial value in zero-sized array initializers may cause side effects + --> tests/ui/zero_repeat_side_effects.rs:42:5 + | +LL | [f(); N]; + | ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }` + +error: aborting due to 12 previous errors + diff --git a/triagebot.toml b/triagebot.toml index 1a81394af10..d455d967e30 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -19,7 +19,7 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" -users_on_vacation = ["xFrednet"] +users_on_vacation = [] [assign.owners] "/.github" = ["@flip1995"] From 0c392d918aae3dc8a2eedc9a26b1ca9d7ed2ea1d Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:34:24 -0500 Subject: [PATCH 15/79] new lint `legacy_numeric_constants` --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 1 + clippy_config/src/conf.rs | 2 +- clippy_config/src/msrvs.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 4 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/legacy_numeric_constants.rs | 290 ++++++++++++++++++ clippy_lints/src/lib.rs | 2 + clippy_utils/src/check_proc_macro.rs | 12 +- .../ui-toml/absolute_paths/absolute_paths.rs | 2 +- tests/ui/checked_conversions.fixed | 1 + tests/ui/checked_conversions.rs | 1 + tests/ui/checked_conversions.stderr | 34 +- tests/ui/legacy_numeric_constants.fixed | 118 +++++++ tests/ui/legacy_numeric_constants.rs | 118 +++++++ tests/ui/legacy_numeric_constants.stderr | 184 +++++++++++ .../ui/legacy_numeric_constants_unfixable.rs | 79 +++++ .../legacy_numeric_constants_unfixable.stderr | 83 +++++ tests/ui/manual_saturating_arithmetic.fixed | 2 +- tests/ui/manual_saturating_arithmetic.rs | 2 +- tests/ui/suspicious_arithmetic_impl.rs | 1 + tests/ui/suspicious_arithmetic_impl.stderr | 18 +- 22 files changed, 921 insertions(+), 37 deletions(-) create mode 100644 clippy_lints/src/legacy_numeric_constants.rs create mode 100644 tests/ui/legacy_numeric_constants.fixed create mode 100644 tests/ui/legacy_numeric_constants.rs create mode 100644 tests/ui/legacy_numeric_constants.stderr create mode 100644 tests/ui/legacy_numeric_constants_unfixable.rs create mode 100644 tests/ui/legacy_numeric_constants_unfixable.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 76ef84a48b8..c2260d7fc39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5379,6 +5379,7 @@ Released 2018-09-13 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays [`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value +[`legacy_numeric_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero [`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index a9234899746..4a2727c5197 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -616,6 +616,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) * [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) * [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) +* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants) * [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) * [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) * [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 3218fe7f456..3b5de2c16ff 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -262,7 +262,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index bf4da5f14fe..32107ded305 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -36,7 +36,7 @@ msrv_aliases! { 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN } 1,46,0 { CONST_IF_MATCH } 1,45,0 { STR_STRIP_PREFIX } - 1,43,0 { LOG2_10, LOG10_2 } + 1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS } 1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS } 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 2c0a3d48296..32e45bd0a79 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -41,7 +41,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b }) }, BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right) - .unwrap_or(u64::max_value()) + .unwrap_or(u64::MAX) .min(apply_reductions(cx, nbits, left, signed)), BinOpKind::Shr => apply_reductions(cx, nbits, left, signed) .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).unwrap_or_default())), @@ -56,7 +56,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b } else { None }; - apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value())) + apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX)) }, ExprKind::MethodCall(method, _, [lo, hi], _) => { if method.ident.as_str() == "clamp" { diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index c8e148598a2..b8607d8f475 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -254,6 +254,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::large_include_file::LARGE_INCLUDE_FILE_INFO, crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO, crate::large_stack_frames::LARGE_STACK_FRAMES_INFO, + crate::legacy_numeric_constants::LEGACY_NUMERIC_CONSTANTS_INFO, crate::len_zero::COMPARISON_TO_EMPTY_INFO, crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO, crate::len_zero::LEN_ZERO_INFO, diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs new file mode 100644 index 00000000000..a325b4d5493 --- /dev/null +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -0,0 +1,290 @@ +use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS}; +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::{get_parent_expr, is_from_proc_macro}; +use hir::def_id::DefId; +use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_hir as hir; +use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::impl_lint_pass; +use rustc_span::symbol::kw; +use rustc_span::{sym, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `::max_value()`, `std::::MAX`, + /// `std::::EPSILON`, etc. + /// + /// ### Why is this bad? + /// All of these have been superceded by the associated constants on their respective types, + /// such as `i128::MAX`. These legacy items may be deprecated in a future version of rust. + /// + /// ### Example + /// ```rust + /// let eps = std::f32::EPSILON; + /// ``` + /// Use instead: + /// ```rust + /// let eps = f32::EPSILON; + /// ``` + #[clippy::version = "1.72.0"] + pub LEGACY_NUMERIC_CONSTANTS, + style, + "checks for usage of legacy std numeric constants and methods" +} +pub struct LegacyNumericConstants { + msrv: Msrv, +} + +impl LegacyNumericConstants { + #[must_use] + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(LegacyNumericConstants => [LEGACY_NUMERIC_CONSTANTS]); + +impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + let Self { msrv } = self; + + if !msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) || in_external_macro(cx.sess(), item.span) { + return; + } + + // Integer modules are "TBD" deprecated, and the contents are too, + // so lint on the `use` statement directly. + if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind + && let Some(def_id) = path.res[0].opt_def_id() + { + let module = if is_integer_module(cx, def_id) { + true + } else if is_numeric_const(cx, def_id) { + false + } else { + return; + }; + + span_lint_and_then( + cx, + LEGACY_NUMERIC_CONSTANTS, + path.span, + if module { + "importing legacy numeric constants" + } else { + "importing a legacy numeric constant" + }, + |diag| { + if item.ident.name == kw::Underscore { + diag.help("remove this import"); + return; + } + + let def_path = cx.get_def_path(def_id); + + if module && let [.., module_name] = &*def_path { + if kind == UseKind::Glob { + diag.help(format!("remove this import and use associated constants `{module_name}::` from the primitive type instead")); + } else { + diag.help("remove this import").note(format!( + "then `{module_name}::` will resolve to the respective associated constant" + )); + } + } else if let [.., module_name, name] = &*def_path { + diag.help( + format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead") + ); + } + }, + ); + } + } + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + let Self { msrv } = self; + + if !msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) || in_external_macro(cx.sess(), expr.span) { + return; + } + let ExprKind::Path(qpath) = expr.kind else { + return; + }; + + // `std::::` check + let (span, sugg, msg) = if let QPath::Resolved(None, path) = qpath + && let Some(def_id) = path.res.opt_def_id() + && is_numeric_const(cx, def_id) + && let def_path = cx.get_def_path(def_id) + && let [.., mod_name, name] = &*def_path + // Skip linting if this usage looks identical to the associated constant, + // since this would only require removing a `use` import (which is already linted). + && !is_numeric_const_path_canonical(path, [*mod_name, *name]) + { + ( + expr.span, + format!("{mod_name}::{name}"), + "usage of a legacy numeric constant", + ) + // `::xxx_value` check + } else if let QPath::TypeRelative(_, last_segment) = qpath + && let Some(def_id) = cx.qpath_res(&qpath, expr.hir_id).opt_def_id() + && is_integer_method(cx, def_id) + && let Some(par_expr) = get_parent_expr(cx, expr) + && let ExprKind::Call(_, _) = par_expr.kind + { + let name = last_segment.ident.name.as_str(); + + ( + last_segment.ident.span.with_hi(par_expr.span.hi()), + name[..=2].to_ascii_uppercase(), + "usage of a legacy numeric method", + ) + } else { + return; + }; + + if is_from_proc_macro(cx, expr) { + return; + } + + span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| { + diag.span_suggestion_with_style( + span, + "use the associated constant instead", + sugg, + Applicability::MaybeIncorrect, + SuggestionStyle::ShowAlways, + ); + }); + } + + extract_msrv_attr!(LateContext); +} + +fn is_integer_module(cx: &LateContext<'_>, did: DefId) -> bool { + [ + sym::isize_legacy_mod, + sym::i128_legacy_mod, + sym::i64_legacy_mod, + sym::i32_legacy_mod, + sym::i16_legacy_mod, + sym::i8_legacy_mod, + sym::usize_legacy_mod, + sym::u128_legacy_mod, + sym::u64_legacy_mod, + sym::u32_legacy_mod, + sym::u16_legacy_mod, + sym::u8_legacy_mod, + ] + .iter() + .any(|&name| cx.tcx.is_diagnostic_item(name, did)) +} + +fn is_numeric_const(cx: &LateContext<'_>, did: DefId) -> bool { + [ + sym::isize_legacy_const_max, + sym::isize_legacy_const_min, + sym::i128_legacy_const_max, + sym::i128_legacy_const_min, + sym::i16_legacy_const_max, + sym::i16_legacy_const_min, + sym::i32_legacy_const_max, + sym::i32_legacy_const_min, + sym::i64_legacy_const_max, + sym::i64_legacy_const_min, + sym::i8_legacy_const_max, + sym::i8_legacy_const_min, + sym::usize_legacy_const_max, + sym::usize_legacy_const_min, + sym::u128_legacy_const_max, + sym::u128_legacy_const_min, + sym::u16_legacy_const_max, + sym::u16_legacy_const_min, + sym::u32_legacy_const_max, + sym::u32_legacy_const_min, + sym::u64_legacy_const_max, + sym::u64_legacy_const_min, + sym::u8_legacy_const_max, + sym::u8_legacy_const_min, + sym::f32_legacy_const_digits, + sym::f32_legacy_const_epsilon, + sym::f32_legacy_const_infinity, + sym::f32_legacy_const_mantissa_dig, + sym::f32_legacy_const_max, + sym::f32_legacy_const_max_10_exp, + sym::f32_legacy_const_max_exp, + sym::f32_legacy_const_min, + sym::f32_legacy_const_min_10_exp, + sym::f32_legacy_const_min_exp, + sym::f32_legacy_const_min_positive, + sym::f32_legacy_const_nan, + sym::f32_legacy_const_neg_infinity, + sym::f32_legacy_const_radix, + sym::f64_legacy_const_digits, + sym::f64_legacy_const_epsilon, + sym::f64_legacy_const_infinity, + sym::f64_legacy_const_mantissa_dig, + sym::f64_legacy_const_max, + sym::f64_legacy_const_max_10_exp, + sym::f64_legacy_const_max_exp, + sym::f64_legacy_const_min, + sym::f64_legacy_const_min_10_exp, + sym::f64_legacy_const_min_exp, + sym::f64_legacy_const_min_positive, + sym::f64_legacy_const_nan, + sym::f64_legacy_const_neg_infinity, + sym::f64_legacy_const_radix, + ] + .iter() + .any(|&name| cx.tcx.is_diagnostic_item(name, did)) +} + +// Whether path expression looks like `i32::MAX` +fn is_numeric_const_path_canonical(expr_path: &hir::Path<'_>, [mod_name, name]: [Symbol; 2]) -> bool { + let [ + hir::PathSegment { + ident: one, args: None, .. + }, + hir::PathSegment { + ident: two, args: None, .. + }, + ] = expr_path.segments + else { + return false; + }; + + one.name == mod_name && two.name == name +} + +fn is_integer_method(cx: &LateContext<'_>, did: DefId) -> bool { + [ + sym::isize_legacy_fn_max_value, + sym::isize_legacy_fn_min_value, + sym::i128_legacy_fn_max_value, + sym::i128_legacy_fn_min_value, + sym::i16_legacy_fn_max_value, + sym::i16_legacy_fn_min_value, + sym::i32_legacy_fn_max_value, + sym::i32_legacy_fn_min_value, + sym::i64_legacy_fn_max_value, + sym::i64_legacy_fn_min_value, + sym::i8_legacy_fn_max_value, + sym::i8_legacy_fn_min_value, + sym::usize_legacy_fn_max_value, + sym::usize_legacy_fn_min_value, + sym::u128_legacy_fn_max_value, + sym::u128_legacy_fn_min_value, + sym::u16_legacy_fn_max_value, + sym::u16_legacy_fn_min_value, + sym::u32_legacy_fn_max_value, + sym::u32_legacy_fn_min_value, + sym::u64_legacy_fn_max_value, + sym::u64_legacy_fn_min_value, + sym::u8_legacy_fn_max_value, + sym::u8_legacy_fn_min_value, + ] + .iter() + .any(|&name| cx.tcx.is_diagnostic_item(name, did)) +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 57fac351042..21010c0f416 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -186,6 +186,7 @@ mod large_futures; mod large_include_file; mod large_stack_arrays; mod large_stack_frames; +mod legacy_numeric_constants; mod len_zero; mod let_if_seq; mod let_underscore; @@ -1080,6 +1081,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { allow_one_hash_in_raw_strings, }) }); + store.register_late_pass(move |_| Box::new(legacy_numeric_constants::LegacyNumericConstants::new(msrv()))); store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); store.register_early_pass(|| Box::new(visibility::Visibility)); store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() })); diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index d751aeaf902..42267310513 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -24,7 +24,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::symbol::Ident; +use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; @@ -99,9 +99,13 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { let start = if ty.is_some() { Pat::Str("<") } else { - path.segments - .first() - .map_or(Pat::Str(""), |seg| Pat::Sym(seg.ident.name)) + path.segments.first().map_or(Pat::Str(""), |seg| { + if seg.ident.name == kw::PathRoot { + Pat::Str("::") + } else { + Pat::Sym(seg.ident.name) + } + }) }; let end = path.segments.last().map_or(Pat::Str(""), |seg| { if seg.args.is_some() { diff --git a/tests/ui-toml/absolute_paths/absolute_paths.rs b/tests/ui-toml/absolute_paths/absolute_paths.rs index 0e6a54452ee..a828701bcee 100644 --- a/tests/ui-toml/absolute_paths/absolute_paths.rs +++ b/tests/ui-toml/absolute_paths/absolute_paths.rs @@ -3,7 +3,7 @@ //@revisions: allow_crates disallow_crates //@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates //@[disallow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/disallow_crates -#![allow(clippy::no_effect, unused)] +#![allow(clippy::no_effect, clippy::legacy_numeric_constants, unused)] #![warn(clippy::absolute_paths)] #![feature(decl_macro)] diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index 0e05a27429b..1e8da331614 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -1,5 +1,6 @@ #![allow( clippy::cast_lossless, + clippy::legacy_numeric_constants, unused, // Int::max_value will be deprecated in the future deprecated, diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index ac782699265..67a9adc049e 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -1,5 +1,6 @@ #![allow( clippy::cast_lossless, + clippy::legacy_numeric_constants, unused, // Int::max_value will be deprecated in the future deprecated, diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index 223e379cce9..453cd7fcf01 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -1,5 +1,5 @@ error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:14:13 + --> tests/ui/checked_conversions.rs:15:13 | LL | let _ = value <= (u32::max_value() as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` @@ -8,97 +8,97 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0; = help: to override `-D warnings` add `#[allow(clippy::checked_conversions)]` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:15:13 + --> tests/ui/checked_conversions.rs:16:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:19:13 + --> tests/ui/checked_conversions.rs:20: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 - --> tests/ui/checked_conversions.rs:20:13 + --> tests/ui/checked_conversions.rs:21:13 | LL | let _ = value <= i64::from(u16::MAX) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:24:13 + --> tests/ui/checked_conversions.rs:25: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 - --> tests/ui/checked_conversions.rs:25:13 + --> tests/ui/checked_conversions.rs:26:13 | LL | let _ = value <= (u8::MAX as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:31:13 + --> tests/ui/checked_conversions.rs:32: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 - --> tests/ui/checked_conversions.rs:32:13 + --> tests/ui/checked_conversions.rs:33: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 - --> tests/ui/checked_conversions.rs:36:13 + --> tests/ui/checked_conversions.rs:37: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 - --> tests/ui/checked_conversions.rs:37:13 + --> tests/ui/checked_conversions.rs:38: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 - --> tests/ui/checked_conversions.rs:43:13 + --> tests/ui/checked_conversions.rs:44:13 | LL | let _ = value <= i32::max_value() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:44:13 + --> tests/ui/checked_conversions.rs:45:13 | LL | let _ = value <= i32::MAX as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:48:13 + --> tests/ui/checked_conversions.rs:49: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 - --> tests/ui/checked_conversions.rs:49:13 + --> tests/ui/checked_conversions.rs:50: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 - --> tests/ui/checked_conversions.rs:53:13 + --> tests/ui/checked_conversions.rs:54: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 - --> tests/ui/checked_conversions.rs:54:13 + --> tests/ui/checked_conversions.rs:55: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 - --> tests/ui/checked_conversions.rs:87:13 + --> tests/ui/checked_conversions.rs:88:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed new file mode 100644 index 00000000000..31a6c1b3944 --- /dev/null +++ b/tests/ui/legacy_numeric_constants.fixed @@ -0,0 +1,118 @@ +//@aux-build:proc_macros.rs +#![allow(clippy::no_effect, deprecated, unused)] +#![allow(clippy::legacy_numeric_constants)] // For imports. +#![feature(lint_reasons)] + +#[macro_use] +extern crate proc_macros; + +pub mod a { + pub use std::u128; +} + +macro_rules! b { + () => { + mod b { + #[warn(clippy::legacy_numeric_constants)] + fn b() { + let x = u64::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + } + } + }; +} + +use std::u32::MAX; +use std::u8::MIN; +use std::{f64, u32}; + +#[warn(clippy::legacy_numeric_constants)] +fn main() { + f32::EPSILON; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u8::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + usize::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + i32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u8::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u8::MIN; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u8::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + ::std::primitive::u8::MIN; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + std::primitive::i32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u128::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + u128::MAX; + f32::EPSILON; + ::std::primitive::u8::MIN; + std::f32::consts::E; + f64::consts::E; + u8::MIN; + std::f32::consts::E; + f64::consts::E; + b!(); + + [(0, "", i128::MAX)]; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead +} + +#[warn(clippy::legacy_numeric_constants)] +fn ext() { + external! { + ::std::primitive::u8::MIN; + ::std::u8::MIN; + ::std::primitive::u8::min_value(); + use std::u64; + use std::u8::MIN; + } +} + +#[allow(clippy::legacy_numeric_constants)] +fn allow() { + ::std::primitive::u8::MIN; + ::std::u8::MIN; + ::std::primitive::u8::min_value(); + use std::u64; + use std::u8::MIN; +} + +#[warn(clippy::legacy_numeric_constants)] +#[clippy::msrv = "1.42.0"] +fn msrv_too_low() { + std::u32::MAX; +} + +#[warn(clippy::legacy_numeric_constants)] +#[clippy::msrv = "1.43.0"] +fn msrv_juust_right() { + u32::MAX; + //~^ ERROR: usage of a legacy numeric constant +} diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs new file mode 100644 index 00000000000..e4dd3d5896f --- /dev/null +++ b/tests/ui/legacy_numeric_constants.rs @@ -0,0 +1,118 @@ +//@aux-build:proc_macros.rs +#![allow(clippy::no_effect, deprecated, unused)] +#![allow(clippy::legacy_numeric_constants)] // For imports. +#![feature(lint_reasons)] + +#[macro_use] +extern crate proc_macros; + +pub mod a { + pub use std::u128; +} + +macro_rules! b { + () => { + mod b { + #[warn(clippy::legacy_numeric_constants)] + fn b() { + let x = std::u64::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + } + } + }; +} + +use std::u32::MAX; +use std::u8::MIN; +use std::{f64, u32}; + +#[warn(clippy::legacy_numeric_constants)] +fn main() { + std::f32::EPSILON; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + std::u8::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + std::usize::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + std::u32::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + core::u32::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + i32::max_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u8::max_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + u8::min_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + ::std::u8::MIN; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + ::std::primitive::u8::min_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + std::primitive::i32::max_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + self::a::u128::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + u128::MAX; + f32::EPSILON; + ::std::primitive::u8::MIN; + std::f32::consts::E; + f64::consts::E; + u8::MIN; + std::f32::consts::E; + f64::consts::E; + b!(); + + [(0, "", std::i128::MAX)]; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead +} + +#[warn(clippy::legacy_numeric_constants)] +fn ext() { + external! { + ::std::primitive::u8::MIN; + ::std::u8::MIN; + ::std::primitive::u8::min_value(); + use std::u64; + use std::u8::MIN; + } +} + +#[allow(clippy::legacy_numeric_constants)] +fn allow() { + ::std::primitive::u8::MIN; + ::std::u8::MIN; + ::std::primitive::u8::min_value(); + use std::u64; + use std::u8::MIN; +} + +#[warn(clippy::legacy_numeric_constants)] +#[clippy::msrv = "1.42.0"] +fn msrv_too_low() { + std::u32::MAX; +} + +#[warn(clippy::legacy_numeric_constants)] +#[clippy::msrv = "1.43.0"] +fn msrv_juust_right() { + std::u32::MAX; + //~^ ERROR: usage of a legacy numeric constant +} diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr new file mode 100644 index 00000000000..af9b003ed54 --- /dev/null +++ b/tests/ui/legacy_numeric_constants.stderr @@ -0,0 +1,184 @@ +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:32:5 + | +LL | std::f32::EPSILON; + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::legacy-numeric-constants` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]` +help: use the associated constant instead + | +LL | f32::EPSILON; + | ~~~~~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:35:5 + | +LL | std::u8::MIN; + | ^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u8::MIN; + | ~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:38:5 + | +LL | std::usize::MIN; + | ^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | usize::MIN; + | ~~~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:41:5 + | +LL | std::u32::MAX; + | ^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u32::MAX; + | ~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:44:5 + | +LL | core::u32::MAX; + | ^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u32::MAX; + | ~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:47:5 + | +LL | MAX; + | ^^^ + | +help: use the associated constant instead + | +LL | u32::MAX; + | ~~~~~~~~ + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:50:10 + | +LL | i32::max_value(); + | ^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | i32::MAX; + | ~~~ + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:53:9 + | +LL | u8::max_value(); + | ^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u8::MAX; + | ~~~ + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:56:9 + | +LL | u8::min_value(); + | ^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u8::MIN; + | ~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:59:5 + | +LL | ::std::u8::MIN; + | ^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u8::MIN; + | ~~~~~~~ + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:62:27 + | +LL | ::std::primitive::u8::min_value(); + | ^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | ::std::primitive::u8::MIN; + | ~~~ + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:65:26 + | +LL | std::primitive::i32::max_value(); + | ^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | std::primitive::i32::MAX; + | ~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:68:5 + | +LL | self::a::u128::MAX; + | ^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u128::MAX; + | ~~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:18:25 + | +LL | let x = std::u64::MAX; + | ^^^^^^^^^^^^^ +... +LL | b!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the associated constant instead + | +LL | let x = u64::MAX; + | ~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:82:14 + | +LL | [(0, "", std::i128::MAX)]; + | ^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | [(0, "", i128::MAX)]; + | ~~~~~~~~~ + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:116:5 + | +LL | std::u32::MAX; + | ^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL | u32::MAX; + | ~~~~~~~~ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/legacy_numeric_constants_unfixable.rs b/tests/ui/legacy_numeric_constants_unfixable.rs new file mode 100644 index 00000000000..228ebdd6a6c --- /dev/null +++ b/tests/ui/legacy_numeric_constants_unfixable.rs @@ -0,0 +1,79 @@ +//@no-rustfix +//@aux-build:proc_macros.rs +#![allow(clippy::no_effect, deprecated, unused)] +#![warn(clippy::legacy_numeric_constants)] +#![feature(lint_reasons)] + +#[macro_use] +extern crate proc_macros; + +use std::u128 as _; +//~^ ERROR: importing legacy numeric constants +//~| HELP: remove this import +pub mod a { + pub use std::{mem, u128}; + //~^ ERROR: importing legacy numeric constants + //~| HELP: remove this import +} + +macro_rules! b { + () => { + mod b { + use std::u32; + //~^ ERROR: importing legacy numeric constants + //~| HELP: remove this import + } + }; +} + +fn main() { + use std::u32::MAX; + //~^ ERROR: importing a legacy numeric constant + //~| HELP: remove this import and use the associated constant `u32::MAX` + use std::u8::MIN; + //~^ ERROR: importing a legacy numeric constant + //~| HELP: remove this import and use the associated constant `u8::MIN` + f64::MAX; + use std::u32; + //~^ ERROR: importing legacy numeric constants + //~| HELP: remove this import + u32::MAX; + use std::f32::MIN_POSITIVE; + //~^ ERROR: importing a legacy numeric constant + //~| HELP: remove this import and use the associated constant `f32::MIN_POSITIVE` + use std::f64; + use std::i16::*; + //~^ ERROR: importing legacy numeric constants + //~| HELP: remove this import and use associated constants `i16::` + u128::MAX; + f32::EPSILON; + f64::EPSILON; + ::std::primitive::u8::MIN; + std::f32::consts::E; + f64::consts::E; + u8::MIN; + std::f32::consts::E; + f64::consts::E; + b!(); +} + +fn ext() { + external! { + ::std::primitive::u8::MIN; + ::std::u8::MIN; + ::std::primitive::u8::min_value(); + use std::u64; + use std::u8::MIN; + } +} + +#[clippy::msrv = "1.42.0"] +fn msrv_too_low() { + use std::u32::MAX; +} + +#[clippy::msrv = "1.43.0"] +fn msrv_juust_right() { + use std::u32::MAX; + //~^ ERROR: importing a legacy numeric constant +} diff --git a/tests/ui/legacy_numeric_constants_unfixable.stderr b/tests/ui/legacy_numeric_constants_unfixable.stderr new file mode 100644 index 00000000000..96e6c9ef975 --- /dev/null +++ b/tests/ui/legacy_numeric_constants_unfixable.stderr @@ -0,0 +1,83 @@ +error: importing legacy numeric constants + --> tests/ui/legacy_numeric_constants_unfixable.rs:10:5 + | +LL | use std::u128 as _; + | ^^^^^^^^^ + | + = help: remove this import + = note: `-D clippy::legacy-numeric-constants` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]` + +error: importing legacy numeric constants + --> tests/ui/legacy_numeric_constants_unfixable.rs:14:24 + | +LL | pub use std::{mem, u128}; + | ^^^^ + | + = help: remove this import + = note: then `u128::` will resolve to the respective associated constant + +error: importing a legacy numeric constant + --> tests/ui/legacy_numeric_constants_unfixable.rs:30:9 + | +LL | use std::u32::MAX; + | ^^^^^^^^^^^^^ + | + = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead + +error: importing a legacy numeric constant + --> tests/ui/legacy_numeric_constants_unfixable.rs:33:9 + | +LL | use std::u8::MIN; + | ^^^^^^^^^^^^ + | + = help: remove this import and use the associated constant `u8::MIN` from the primitive type instead + +error: importing legacy numeric constants + --> tests/ui/legacy_numeric_constants_unfixable.rs:37:9 + | +LL | use std::u32; + | ^^^^^^^^ + | + = help: remove this import + = note: then `u32::` will resolve to the respective associated constant + +error: importing a legacy numeric constant + --> tests/ui/legacy_numeric_constants_unfixable.rs:41:9 + | +LL | use std::f32::MIN_POSITIVE; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: remove this import and use the associated constant `f32::MIN_POSITIVE` from the primitive type instead + +error: importing legacy numeric constants + --> tests/ui/legacy_numeric_constants_unfixable.rs:45:9 + | +LL | use std::i16::*; + | ^^^^^^^^ + | + = help: remove this import and use associated constants `i16::` from the primitive type instead + +error: importing legacy numeric constants + --> tests/ui/legacy_numeric_constants_unfixable.rs:22:17 + | +LL | use std::u32; + | ^^^^^^^^ +... +LL | b!(); + | ---- in this macro invocation + | + = help: remove this import + = note: then `u32::` will resolve to the respective associated constant + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: importing a legacy numeric constant + --> tests/ui/legacy_numeric_constants_unfixable.rs:77:9 + | +LL | use std::u32::MAX; + | ^^^^^^^^^^^^^ + | + = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead + +error: aborting due to 9 previous errors + diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed index 8218f10881a..41a32df32ee 100644 --- a/tests/ui/manual_saturating_arithmetic.fixed +++ b/tests/ui/manual_saturating_arithmetic.fixed @@ -1,4 +1,4 @@ -#![allow(unused_imports)] +#![allow(clippy::legacy_numeric_constants, unused_imports)] use std::{i128, i32, u128, u32}; diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs index 60022b54b02..3a6b32d8069 100644 --- a/tests/ui/manual_saturating_arithmetic.rs +++ b/tests/ui/manual_saturating_arithmetic.rs @@ -1,4 +1,4 @@ -#![allow(unused_imports)] +#![allow(clippy::legacy_numeric_constants, unused_imports)] use std::{i128, i32, u128, u32}; diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 1bd4cd5fb50..07280351e76 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,3 +1,4 @@ +#![allow(clippy::legacy_numeric_constants)] #![warn(clippy::suspicious_arithmetic_impl)] use std::ops::{ Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, DivAssign, Mul, MulAssign, Rem, Shl, Shr, Sub, diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 193cd64149b..1bfca49a635 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,5 +1,5 @@ error: suspicious use of `-` in `Add` impl - --> tests/ui/suspicious_arithmetic_impl.rs:13:20 + --> tests/ui/suspicious_arithmetic_impl.rs:14:20 | LL | Foo(self.0 - other.0) | ^ @@ -8,7 +8,7 @@ LL | Foo(self.0 - other.0) = help: to override `-D warnings` add `#[allow(clippy::suspicious_arithmetic_impl)]` error: suspicious use of `-` in `AddAssign` impl - --> tests/ui/suspicious_arithmetic_impl.rs:21:23 + --> tests/ui/suspicious_arithmetic_impl.rs:22:23 | LL | *self = *self - other; | ^ @@ -17,43 +17,43 @@ LL | *self = *self - other; = help: to override `-D warnings` add `#[allow(clippy::suspicious_op_assign_impl)]` error: suspicious use of `/` in `MulAssign` impl - --> tests/ui/suspicious_arithmetic_impl.rs:36:16 + --> tests/ui/suspicious_arithmetic_impl.rs:37:16 | LL | self.0 /= other.0; | ^^ error: suspicious use of `/` in `Rem` impl - --> tests/ui/suspicious_arithmetic_impl.rs:75:20 + --> tests/ui/suspicious_arithmetic_impl.rs:76:20 | LL | Foo(self.0 / other.0) | ^ error: suspicious use of `|` in `BitAnd` impl - --> tests/ui/suspicious_arithmetic_impl.rs:84:20 + --> tests/ui/suspicious_arithmetic_impl.rs:85:20 | LL | Foo(self.0 | other.0) | ^ error: suspicious use of `^` in `BitOr` impl - --> tests/ui/suspicious_arithmetic_impl.rs:93:20 + --> tests/ui/suspicious_arithmetic_impl.rs:94:20 | LL | Foo(self.0 ^ other.0) | ^ error: suspicious use of `&` in `BitXor` impl - --> tests/ui/suspicious_arithmetic_impl.rs:102:20 + --> tests/ui/suspicious_arithmetic_impl.rs:103:20 | LL | Foo(self.0 & other.0) | ^ error: suspicious use of `>>` in `Shl` impl - --> tests/ui/suspicious_arithmetic_impl.rs:111:20 + --> tests/ui/suspicious_arithmetic_impl.rs:112:20 | LL | Foo(self.0 >> other.0) | ^^ error: suspicious use of `<<` in `Shr` impl - --> tests/ui/suspicious_arithmetic_impl.rs:120:20 + --> tests/ui/suspicious_arithmetic_impl.rs:121:20 | LL | Foo(self.0 << other.0) | ^^ From 75390b9f7f2e25f0c3f831a63035bab7cfd98685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 15 Mar 2024 03:21:55 +0100 Subject: [PATCH 16/79] Rename AstConv to HIR ty lowering This includes updating astconv-related items and a few local variables. --- clippy_lints/src/implicit_hasher.rs | 4 ++-- clippy_lints/src/implied_bounds_in_impls.rs | 4 ++-- clippy_lints/src/types/redundant_allocation.rs | 4 ++-- clippy_lints/src/types/vec_box.rs | 6 +++--- clippy_lints/src/unconditional_recursion.rs | 4 ++-- clippy_lints/src/uninhabited_references.rs | 4 ++-- clippy_lints/src/use_self.rs | 4 ++-- clippy_lints/src/zero_sized_map_values.rs | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index a79bf66ae01..8acb138332c 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -5,7 +5,7 @@ use rustc_errors::Diag; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor}; use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{Ty, TypeckResults}; @@ -227,7 +227,7 @@ impl<'tcx> ImplicitHasherType<'tcx> { .collect(); let params_len = params.len(); - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let ty = lower_ty(cx.tcx, hir_ty); if is_type_diagnostic_item(cx, ty, sym::HashMap) && params_len == 2 { Some(ImplicitHasherType::HashMap( diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 74582f7f1de..9f4d7b51271 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -6,7 +6,7 @@ use rustc_hir::{ GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, TypeBinding, WherePredicate, }; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, ClauseKind, Generics, Ty, TyCtxt}; use rustc_session::declare_lint_pass; @@ -146,7 +146,7 @@ fn try_resolve_type<'tcx>( index: usize, ) -> Option> { match args.get(index - 1) { - Some(GenericArg::Type(ty)) => Some(hir_ty_to_ty(tcx, ty)), + Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty)), Some(_) => None, None => Some(tcx.type_of(generics.params[index].def_id).skip_binder()), } diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index a0d609501a0..9729c971672 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -4,7 +4,7 @@ use clippy_utils::{path_def_id, qpath_generic_tys}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, QPath, TyKind}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::LateContext; use rustc_middle::ty::TypeVisitableExt; use rustc_span::symbol::sym; @@ -59,7 +59,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: // Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let ty = lower_ty(cx.tcx, hir_ty); if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) { return false; } diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs index 7926738d68f..29996a6f783 100644 --- a/clippy_lints/src/types/vec_box.rs +++ b/clippy_lints/src/types/vec_box.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg, LangItem, QPath, TyKind}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::TypeVisitableExt; @@ -35,7 +35,7 @@ pub(super) fn check<'tcx>( && let Some(GenericArg::Type(boxed_ty)) = last.args.first() // extract allocator from the Box for later && let boxed_alloc_ty = last.args.get(1) - && let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty) + && let ty_ty = lower_ty(cx.tcx, boxed_ty) && !ty_ty.has_escaping_bound_vars() && ty_ty.is_sized(cx.tcx, cx.param_env) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) @@ -55,7 +55,7 @@ pub(super) fn check<'tcx>( } }, (Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) => - hir_ty_to_ty(cx.tcx, l) == hir_ty_to_ty(cx.tcx, r), + lower_ty(cx.tcx, l) == lower_ty(cx.tcx, r), _ => false } { diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index d638af2b78b..8764e3006c6 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_body, walk_expr, FnKind, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath, TyKind}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; @@ -74,7 +74,7 @@ fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Op match qpath { QPath::Resolved(_, path) => path.res.opt_def_id(), QPath::TypeRelative(_, _) => { - let ty = hir_ty_to_ty(tcx, &hir_ty); + let ty = lower_ty(tcx, &hir_ty); match ty.kind() { ty::Alias(ty::Projection, proj) => { diff --git a/clippy_lints/src/uninhabited_references.rs b/clippy_lints/src/uninhabited_references.rs index 6732a43a19e..88039372ebd 100644 --- a/clippy_lints/src/uninhabited_references.rs +++ b/clippy_lints/src/uninhabited_references.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind, UnOp}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; @@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences { } if let FnRetTy::Return(hir_ty) = fndecl.output && let TyKind::Ref(_, mut_ty) = hir_ty.kind - && hir_ty_to_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env) + && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env) { span_lint( cx, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b28037db112..dfa816963bc 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -11,7 +11,7 @@ use rustc_hir::{ self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, }; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty as MiddleTy; use rustc_session::impl_lint_pass; @@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let ty = if in_body > 0 { cx.typeck_results().node_type(hir_ty.hir_id) } else { - hir_ty_to_ty(cx.tcx, hir_ty) + lower_ty(cx.tcx, hir_ty) } && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() && same_type_and_consts(ty, impl_ty) diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index 4aaf3b0a0b6..d1f7c6417c7 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; use rustc_hir::{self as hir, HirId, ItemKind, Node}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{Adt, Ty, TypeVisitableExt}; @@ -91,5 +91,5 @@ fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'t None } }) - .unwrap_or_else(|| hir_ty_to_ty(cx.tcx, hir_ty)) + .unwrap_or_else(|| lower_ty(cx.tcx, hir_ty)) } From b7026f87f52f75ebcb7c0de0c1bf56b714d4b73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 11 Feb 2024 09:22:52 +0100 Subject: [PATCH 17/79] Update (doc) comments Several (doc) comments were super outdated or didn't provide enough context. Some doc comments shoved everything in a single paragraph without respecting the fact that the first paragraph should be a single sentence because rustdoc treats these as item descriptions / synopses on module pages. --- book/src/development/type_checking.md | 10 +++++----- clippy_lints/src/types/redundant_allocation.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- tests/ui/crashes/ice-6179.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 136b3fd0270..e6da4322a17 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -118,10 +118,10 @@ Here the HIR sees the types without "thinking" about them, it knows that the fun an `u32`. As far as `hir::Ty` is concerned those might be different types. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc... -To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or +To get from a `hir::Ty` to a `ty::Ty`, you can use the [`lower_ty`][lower_ty] function outside of bodies or the [`TypeckResults::node_type()`][node_type] method inside of bodies. -> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs. +> **Warning**: Don't use `lower_ty` inside of bodies, because this can cause ICEs. ## Creating Types programmatically @@ -162,6 +162,6 @@ in this chapter: [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_type_ir/ty_kind/enum.TyKind.html [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html -[middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html -[hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html -[hir_ty_to_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir_analysis/fn.hir_ty_to_ty.html +[middle_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html +[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Ty.html +[lower_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/fn.lower_ty.html diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index 9729c971672..37437cbfbec 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -56,7 +56,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: }; let inner_span = match qpath_generic_tys(inner_qpath).next() { Some(hir_ty) => { - // Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use + // Reallocation of a fat pointer causes it to become thin. `lower_ty` is safe to use // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. let ty = lower_ty(cx.tcx, hir_ty); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index dfa816963bc..a6b411d6c0f 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -193,7 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) { - // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies + // `lower_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`. // However the `node_type()` method can *only* be called in bodies. if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() { diff --git a/tests/ui/crashes/ice-6179.rs b/tests/ui/crashes/ice-6179.rs index fffc0f7d0d4..91160eef03d 100644 --- a/tests/ui/crashes/ice-6179.rs +++ b/tests/ui/crashes/ice-6179.rs @@ -1,5 +1,5 @@ //! This is a minimal reproducer for the ICE in https://github.com/rust-lang/rust-clippy/pull/6179. -//! The ICE is mainly caused by using `hir_ty_to_ty`. See the discussion in the PR for details. +//! The ICE is mainly caused by using `lower_ty`. See the discussion in the PR for details. #![warn(clippy::use_self)] #![allow(dead_code, clippy::let_with_type_underscore)] From 7c9fe30ce4313cc9e77030ca1e66a7c88a8ffd02 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 22 Mar 2024 00:33:31 +0100 Subject: [PATCH 18/79] Do not warn on .map(_::clone) for Arc, Rc, and their weak variants Those constructions are idiomatic, and using `Arc::clone(x)` and `Rc::clone(x)` is often the recommended way of cloning a `Arc` or a `Rc`. --- clippy_lints/src/methods/map_clone.rs | 5 +++++ tests/ui/map_clone.fixed | 24 ++++++++++++++++++++++++ tests/ui/map_clone.rs | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index c3c7a3a0033..749a31c8a91 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -124,6 +124,11 @@ fn handle_path( && let ty::Ref(_, ty, Mutability::Not) = ty.kind() && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind() && lst.iter().all(|l| l.as_type() == Some(*ty)) + && !matches!( + ty.ty_adt_def() + .and_then(|adt_def| cx.tcx.get_diagnostic_name(adt_def.did())), + Some(sym::Arc | sym::ArcWeak | sym::Rc | sym::RcWeak) + ) { lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs())); } diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index e58b6b2f19e..f9f8dc1a512 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -131,4 +131,28 @@ fn main() { let x: Vec<&u8> = vec![]; let y = x.into_iter().map(|x| u8::clone(loop {})); } + + // Issue #12528 + { + // Don't lint these + use std::rc::{Rc, Weak as RcWeak}; + use std::sync::{Arc, Weak as ArcWeak}; + struct Foo; + + let x = Arc::new(Foo); + let y = Some(&x); + let _z = y.map(Arc::clone); + + let x = Rc::new(Foo); + let y = Some(&x); + let _z = y.map(Rc::clone); + + let x = Arc::downgrade(&Arc::new(Foo)); + let y = Some(&x); + let _z = y.map(ArcWeak::clone); + + let x = Rc::downgrade(&Rc::new(Foo)); + let y = Some(&x); + let _z = y.map(RcWeak::clone); + } } diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index e642e4046f8..a5c19ce0631 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -131,4 +131,28 @@ fn main() { let x: Vec<&u8> = vec![]; let y = x.into_iter().map(|x| u8::clone(loop {})); } + + // Issue #12528 + { + // Don't lint these + use std::rc::{Rc, Weak as RcWeak}; + use std::sync::{Arc, Weak as ArcWeak}; + struct Foo; + + let x = Arc::new(Foo); + let y = Some(&x); + let _z = y.map(Arc::clone); + + let x = Rc::new(Foo); + let y = Some(&x); + let _z = y.map(Rc::clone); + + let x = Arc::downgrade(&Arc::new(Foo)); + let y = Some(&x); + let _z = y.map(ArcWeak::clone); + + let x = Rc::downgrade(&Rc::new(Foo)); + let y = Some(&x); + let _z = y.map(RcWeak::clone); + } } From b392e4782541195a0d3c6b367297fb98e4eddc50 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 22 Mar 2024 13:44:28 +0000 Subject: [PATCH 19/79] Remove unused dep `tester` --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2b37b54c004..43f20ecedc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ anstream = "0.6.0" [dev-dependencies] ui_test = "0.22.2" -tester = "0.9" regex = "1.5.5" toml = "0.7.3" walkdir = "2.3" From 2ffd1336c720190fe26cf27324c111c41bfa9a8a Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 22 Mar 2024 12:21:35 +0100 Subject: [PATCH 20/79] Add necessary parentheses to `manual_unwrap_or_default` lint output --- clippy_lints/src/manual_unwrap_or_default.rs | 5 +++-- tests/ui/manual_unwrap_or_default.fixed | 9 +++++++++ tests/ui/manual_unwrap_or_default.rs | 12 ++++++++++++ tests/ui/manual_unwrap_or_default.stderr | 12 +++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs index ddaf97c463a..fc6b0d6f9f6 100644 --- a/clippy_lints/src/manual_unwrap_or_default.rs +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -1,3 +1,4 @@ +use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath}; @@ -124,7 +125,7 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { // We now check the `None` arm is calling a method equivalent to `Default::default`. && let body_none = body_none.peel_blocks() && is_default_equivalent(cx, body_none) - && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span) + && let Some(receiver) = Sugg::hir_opt(cx, match_expr).map(Sugg::maybe_par) { span_lint_and_sugg( cx, @@ -132,7 +133,7 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { expr.span, "match can be simplified with `.unwrap_or_default()`", "replace it with", - format!("{match_expr_snippet}.unwrap_or_default()"), + format!("{receiver}.unwrap_or_default()"), Applicability::MachineApplicable, ); } diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed index c8456805ee6..b24967242eb 100644 --- a/tests/ui/manual_unwrap_or_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -17,3 +17,12 @@ fn main() { let x: Option> = None; x.unwrap_or_default(); } + +// Issue #12531 +unsafe fn no_deref_ptr(a: Option, b: *const Option) -> i32 { + match a { + // `*b` being correct depends on `a == Some(_)` + Some(_) => (*b).unwrap_or_default(), + _ => 0, + } +} diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index 820717be53a..ed5e54b4e14 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -38,3 +38,15 @@ fn main() { Vec::default() }; } + +// Issue #12531 +unsafe fn no_deref_ptr(a: Option, b: *const Option) -> i32 { + match a { + // `*b` being correct depends on `a == Some(_)` + Some(_) => match *b { + Some(v) => v, + _ => 0, + }, + _ => 0, + } +} diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr index f4eb6583588..d89212e6045 100644 --- a/tests/ui/manual_unwrap_or_default.stderr +++ b/tests/ui/manual_unwrap_or_default.stderr @@ -52,5 +52,15 @@ LL | | Vec::default() LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` -error: aborting due to 5 previous errors +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/manual_unwrap_or_default.rs:46:20 + | +LL | Some(_) => match *b { + | ____________________^ +LL | | Some(v) => v, +LL | | _ => 0, +LL | | }, + | |_________^ help: replace it with: `(*b).unwrap_or_default()` + +error: aborting due to 6 previous errors From 0b810866ef8ffe4125f9c7aebb7d8b3792d2b7f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Mar 2024 16:50:21 -0400 Subject: [PATCH 21/79] Eagerly convert some ctors to use their specialized ctors --- clippy_lints/src/methods/unnecessary_to_owned.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index c234e4f9b11..6e525b5ff93 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -336,12 +336,9 @@ fn check_other_call_arg<'tcx>( && let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) { Some((n_refs, receiver_ty)) } else if trait_predicate.def_id() != deref_trait_id { - Some((1, Ty::new_ref(cx.tcx, + Some((1, Ty::new_imm_ref(cx.tcx, cx.tcx.lifetimes.re_erased, - ty::TypeAndMut { - ty: receiver_ty, - mutbl: Mutability::Not, - }, + receiver_ty, ))) } else { None From c92b350581583c251dcd447f92fc20d362d34834 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Mar 2024 17:11:06 -0400 Subject: [PATCH 22/79] Programmatically convert some of the pat ctors --- .../src/casts/cast_slice_different_sizes.rs | 2 +- clippy_lints/src/casts/ptr_as_ptr.rs | 4 ++-- clippy_lints/src/casts/ref_as_ptr.rs | 2 +- clippy_lints/src/from_raw_with_void_ptr.rs | 2 +- clippy_lints/src/functions/must_use.rs | 2 +- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../src/matches/significant_drop_in_scrutinee.rs | 2 +- clippy_lints/src/methods/zst_offset.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/non_send_fields_in_send_ty.rs | 4 ++-- clippy_lints/src/significant_drop_tightening.rs | 2 +- clippy_lints/src/size_of_in_element_count.rs | 2 +- .../src/transmute/transmute_ptr_to_ptr.rs | 2 +- .../src/transmute/transmute_undefined_repr.rs | 16 ++++++++-------- clippy_lints/src/transmute/useless_transmute.rs | 2 +- clippy_lints/src/transmute/wrong_transmute.rs | 2 +- clippy_utils/src/consts.rs | 2 +- clippy_utils/src/lib.rs | 4 ++-- clippy_utils/src/ty.rs | 2 +- 19 files changed, 29 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index a31943f0021..76d5c329179 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -87,7 +87,7 @@ fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// the type is one of those slices fn get_raw_slice_ty_mut(ty: Ty<'_>) -> Option> { match ty.kind() { - ty::RawPtr(TypeAndMut { ty: slice_ty, mutbl }) => match slice_ty.kind() { + ty::RawPtr(slice_ty, mutbl) => match slice_ty.kind() { ty::Slice(ty) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }), _ => None, }, diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 35e36e9ef3f..5182c6179e6 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -33,8 +33,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind && let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr)) - && let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind() - && let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind() + && let ty::RawPtr(_, from_mutbl) = cast_from.kind() + && let ty::RawPtr(to_pointee_ty, to_mutbl) = cast_to.kind() && matches!((from_mutbl, to_mutbl), (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut)) // The `U` in `pointer::cast` have to be `Sized` diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs index 9d5a486336d..a999b4e4388 100644 --- a/clippy_lints/src/casts/ref_as_ptr.rs +++ b/clippy_lints/src/casts/ref_as_ptr.rs @@ -21,7 +21,7 @@ pub(super) fn check<'tcx>( ); if matches!(cast_from.kind(), ty::Ref(..)) - && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind() + && let ty::RawPtr(_, to_mutbl) = cast_to.kind() && let Some(use_cx) = expr_use_ctxt(cx, expr) // TODO: only block the lint if `cast_expr` is a temporary && !matches!(use_cx.node, ExprUseNode::Local(_) | ExprUseNode::ConstStatic(_)) diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs index c8d10dc4b92..1c91a377b1a 100644 --- a/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/clippy_lints/src/from_raw_with_void_ptr.rs @@ -44,7 +44,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr { && seg.ident.name == sym!(from_raw) && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id)) && let arg_kind = cx.typeck_results().expr_ty(arg).kind() - && let RawPtr(TypeAndMut { ty, .. }) = arg_kind + && let ty::RawPtr(ty, _) = arg_kind && is_c_void(cx, *ty) { let msg = format!("creating a `{type_str}` from a void raw pointer"); diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 3aaf63ce340..d752d010f9f 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -207,7 +207,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) }, ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)), ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, tys), - ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { + ty::RawPtr(ty, mutbl) | ty::Ref(_, ty, mutbl) => { mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys) }, // calling something constitutes a side effect, so return true on all callables diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index f2aa7b597a7..2d757883f26 100644 --- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -75,7 +75,7 @@ fn check_raw_ptr<'tcx>( } fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option { - if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_))) = ( + if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_, _))) = ( &arg.pat.kind, cx.maybe_typeck_results() .map(|typeck_results| typeck_results.pat_ty(arg.pat).kind()), diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index b770ad0ddb5..10c3203725a 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { false }, rustc_middle::ty::Array(ty, _) - | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. }) + | rustc_middle::ty::RawPtr(ty, _) | rustc_middle::ty::Ref(_, ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(cx, *ty), _ => false, diff --git a/clippy_lints/src/methods/zst_offset.rs b/clippy_lints/src/methods/zst_offset.rs index 0b829d99aef..d33021c2a7b 100644 --- a/clippy_lints/src/methods/zst_offset.rs +++ b/clippy_lints/src/methods/zst_offset.rs @@ -6,7 +6,7 @@ use rustc_middle::ty; use super::ZST_OFFSET; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { - if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind() + if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind() && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)) && layout.is_zst() { diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 4ae4fc9b096..61243c83731 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -127,7 +127,7 @@ fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> { IntTy::I128 => None, } }, - ty::RawPtr(_) => Some("AtomicPtr"), + ty::RawPtr(_, _) => Some("AtomicPtr"), _ => None, } } diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs index 793a3a9545c..408216229a4 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -219,7 +219,7 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } }, // Raw pointers are `!Send` but allowed by the heuristic - ty::RawPtr(_) => true, + ty::RawPtr(_, _) => true, _ => false, } } @@ -229,7 +229,7 @@ fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> b for ty_node in target_ty.walk() { if let GenericArgKind::Type(inner_ty) = ty_node.unpack() { match inner_ty.kind() { - ty::RawPtr(_) => { + ty::RawPtr(_, _) => { return true; }, ty::Adt(adt_def, _) => { diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index f8726aa173a..57470f950da 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -199,7 +199,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { false }, rustc_middle::ty::Array(ty, _) - | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. }) + | rustc_middle::ty::RawPtr(ty, _) | rustc_middle::ty::Ref(_, ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty), _ => false, diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index 756e47cbdf0..c26ce1272ff 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -107,7 +107,7 @@ fn get_pointee_ty_and_count_expr<'tcx>( && METHODS.iter().any(|m| *m == method_ident) // Get the pointee type - && let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) = + && let ty::RawPtr(pointee_ty, _) = cx.typeck_results().expr_ty(ptr_self).kind() { return Some((*pointee_ty, count)); diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 4ae4359eea0..84fa201639a 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -16,7 +16,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(_), ty::RawPtr(to_ty)) => { + (ty::RawPtr(_, _), ty::RawPtr(to_ty)) => { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index a6f03c85b4f..44b5f460737 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -45,8 +45,8 @@ pub(super) fn check<'tcx>( // ptr <-> ptr (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty)) - if matches!(from_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_)) - && matches!(to_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_)) => + if matches!(from_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_, _)) + && matches!(to_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_, _)) => { from_ty = from_sub_ty; to_ty = to_sub_ty; @@ -196,21 +196,21 @@ fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: T let (from_fat_ptr, to_fat_ptr) = loop { break match (from_ty.kind(), to_ty.kind()) { ( - &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), - &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), + &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(from_sub_ty, _)), + &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(to_sub_ty, _)), ) => { - from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); + from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_, _)); from_ty = from_sub_ty; - to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); + to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_, _)); to_ty = to_sub_ty; continue; }, - (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _) + (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => { (true, false) }, - (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))) + (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _))) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => { (false, true) diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs index 088c8fda87a..f3d3516755c 100644 --- a/clippy_lints/src/transmute/useless_transmute.rs +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -53,7 +53,7 @@ pub(super) fn check<'tcx>( } true }, - (ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => { + (ty::Int(_) | ty::Uint(_), ty::RawPtr(_, _)) => { span_lint_and_then( cx, USELESS_TRANSMUTE, diff --git a/clippy_lints/src/transmute/wrong_transmute.rs b/clippy_lints/src/transmute/wrong_transmute.rs index d1965565b92..ed815884a76 100644 --- a/clippy_lints/src/transmute/wrong_transmute.rs +++ b/clippy_lints/src/transmute/wrong_transmute.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Ty}; /// Returns `true` if it's triggered, otherwise returns `false`. pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_)) => { + (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_, _)) => { span_lint( cx, WRONG_TRANSMUTE, diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 046087d3298..6b86630339f 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -819,7 +819,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( int.try_into().expect("invalid f64 bit representation"), ))), - ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), + ty::RawPtr(_, _) => Some(Constant::RawPtr(int.assert_bits(int.size()))), _ => None, }, (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 11b56ed47de..e90317f5524 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1040,7 +1040,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { .get(child_id) .map_or(&[][..], |x| &**x) { - if let rustc_ty::RawPtr(TypeAndMut { mutbl: mutability, .. }) | rustc_ty::Ref(_, _, mutability) = + if let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) = *adjust.last().map_or(target, |a| a.target).kind() { return CaptureKind::Ref(mutability); @@ -3235,7 +3235,7 @@ fn get_path_to_ty<'tcx>(tcx: TyCtxt<'tcx>, from: LocalDefId, ty: Ty<'tcx>, args: rustc_ty::Array(..) | rustc_ty::Dynamic(..) | rustc_ty::Never - | rustc_ty::RawPtr(_) + | rustc_ty::RawPtr(_, _) | rustc_ty::Ref(..) | rustc_ty::Slice(_) | rustc_ty::Tuple(_) => format!("<{}>", EarlyBinder::bind(ty).instantiate(tcx, args)), diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 801452e444c..97ce755adbb 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -321,7 +321,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use), ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use), - ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => { + ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) From f9ad628acd819bb38de972edc777246311f021f7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Mar 2024 17:42:46 -0400 Subject: [PATCH 23/79] And the tools too --- clippy_lints/src/casts/as_ptr_cast_mut.rs | 11 +++-------- clippy_lints/src/casts/cast_ptr_alignment.rs | 10 +++++----- .../src/casts/cast_slice_from_raw_parts.rs | 4 ++-- clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- clippy_lints/src/casts/ptr_cast_constness.rs | 12 +++--------- clippy_lints/src/casts/ref_as_ptr.rs | 2 +- clippy_lints/src/from_raw_with_void_ptr.rs | 4 ++-- clippy_lints/src/loops/explicit_iter_loop.rs | 6 +++--- clippy_lints/src/mut_reference.rs | 4 +--- .../src/significant_drop_tightening.rs | 2 +- clippy_lints/src/size_of_in_element_count.rs | 2 +- .../src/transmute/crosspointer_transmute.rs | 6 +++--- .../src/transmute/transmute_ptr_to_ptr.rs | 4 ++-- .../src/transmute/transmute_ptr_to_ref.rs | 4 ++-- .../src/transmute/transmute_ref_to_ref.rs | 18 +++++------------- .../src/transmute/transmute_undefined_repr.rs | 2 +- .../src/transmute/useless_transmute.rs | 13 ++++--------- clippy_utils/src/lib.rs | 2 +- 18 files changed, 41 insertions(+), 67 deletions(-) diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs index 8bfb7383f14..a667ea04af0 100644 --- a/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -4,18 +4,13 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; -use rustc_middle::ty::{self, Ty, TypeAndMut}; +use rustc_middle::ty::{self, Ty}; use super::AS_PTR_CAST_MUT; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) { - if let ty::RawPtr(TypeAndMut { - mutbl: Mutability::Mut, - ty: ptrty, - }) = cast_to.kind() - && let ty::RawPtr(TypeAndMut { - mutbl: Mutability::Not, .. - }) = cx.typeck_results().node_type(cast_expr.hir_id).kind() + if let ty::RawPtr(ptrty, Mutability::Mut) = cast_to.kind() + && let ty::RawPtr(_, Mutability::Not) = cx.typeck_results().node_type(cast_expr.hir_id).kind() && let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind && method_name.ident.name == rustc_span::sym::as_ptr && let Some(as_ptr_did) = cx diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs index f12f03fbe79..4d1a0f678f4 100644 --- a/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -33,13 +33,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { } fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) { - if let ty::RawPtr(from_ptr_ty) = &cast_from.kind() - && let ty::RawPtr(to_ptr_ty) = &cast_to.kind() - && let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty) - && let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty) + if let ty::RawPtr(from_ptr_ty, _) = *cast_from.kind() + && let ty::RawPtr(to_ptr_ty, _) = *cast_to.kind() + && let Ok(from_layout) = cx.layout_of(from_ptr_ty) + && let Ok(to_layout) = cx.layout_of(to_ptr_ty) && from_layout.align.abi < to_layout.align.abi // with c_void, we inherently need to trust the user - && !is_c_void(cx, from_ptr_ty.ty) + && !is_c_void(cx, from_ptr_ty) // when casting from a ZST, we don't know enough to properly lint && !from_layout.is_zst() && !is_used_as_unaligned(cx, expr) 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 3db1e3e6d97..48629b6c5cc 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -25,8 +25,8 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option { pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) { if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) - && let ty::RawPtr(ptrty) = cast_to.kind() - && let ty::Slice(_) = ptrty.ty.kind() + && let ty::RawPtr(ptrty, _) = cast_to.kind() + && let ty::Slice(_) = ptrty.kind() && let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind && let ExprKind::Path(ref qpath) = fun.kind && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 5182c6179e6..5a121e6a7eb 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability, QPath, TyKind}; use rustc_hir_pretty::qpath_to_string; use rustc_lint::LateContext; -use rustc_middle::ty::{self, TypeAndMut}; +use rustc_middle::ty; use rustc_span::sym; use super::PTR_AS_PTR; diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index ff069860a11..e88146331ca 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -4,7 +4,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty, TypeAndMut}; +use rustc_middle::ty::{self, Ty}; use super::PTR_CAST_CONSTNESS; @@ -17,14 +17,8 @@ pub(super) fn check<'tcx>( msrv: &Msrv, ) { if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) - && let ty::RawPtr(TypeAndMut { - mutbl: from_mutbl, - ty: from_ty, - }) = cast_from.kind() - && let ty::RawPtr(TypeAndMut { - mutbl: to_mutbl, - ty: to_ty, - }) = cast_to.kind() + && let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind() + && let ty::RawPtr(to_ty, to_mutbl) = cast_to.kind() && matches!( (from_mutbl, to_mutbl), (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not) diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs index a999b4e4388..662737a14a4 100644 --- a/clippy_lints/src/casts/ref_as_ptr.rs +++ b/clippy_lints/src/casts/ref_as_ptr.rs @@ -5,7 +5,7 @@ use clippy_utils::{expr_use_ctxt, is_no_std_crate, ExprUseNode}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, Ty, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, TypeAndMut}; +use rustc_middle::ty; use super::REF_AS_PTR; diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs index 1c91a377b1a..286ba2306c9 100644 --- a/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/clippy_lints/src/from_raw_with_void_ptr.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{RawPtr, TypeAndMut}; +use rustc_middle::ty::{RawPtr}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -44,7 +44,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr { && seg.ident.name == sym!(from_raw) && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id)) && let arg_kind = cx.typeck_results().expr_ty(arg).kind() - && let ty::RawPtr(ty, _) = arg_kind + && let RawPtr(ty, _) = arg_kind && is_c_void(cx, *ty) { let msg = format!("creating a `{type_str}` from a void raw pointer"); diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 814ccaa36f5..eea5f2a94ea 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -10,7 +10,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut}; +use rustc_middle::ty::{self, EarlyBinder, Ty}; use rustc_span::sym; pub(super) fn check( @@ -160,7 +160,7 @@ fn is_ref_iterable<'tcx>( let self_ty = if mutbl.is_mut() { self_ty } else { - Ty::new_ref(cx.tcx, region, TypeAndMut { ty, mutbl }) + Ty::new_ref(cx.tcx, region, ty, mutbl) }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = @@ -175,7 +175,7 @@ fn is_ref_iterable<'tcx>( && !self_ty.is_ref() { // Attempt to borrow - let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, TypeAndMut { ty: self_ty, mutbl }); + let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl); if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index f905a4e5b64..14a1e6be738 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -84,9 +84,7 @@ fn check_arguments<'tcx>( for (argument, parameter) in iter::zip(arguments, parameters) { match parameter.kind() { ty::Ref(_, _, Mutability::Not) - | ty::RawPtr(ty::TypeAndMut { - mutbl: Mutability::Not, .. - }) => { + | ty::RawPtr(_, Mutability::Not) => { if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind { span_lint( cx, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index 57470f950da..d3540bc8e1c 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{self as hir}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{GenericArgKind, Ty, TypeAndMut}; +use rustc_middle::ty::{GenericArgKind, Ty}; use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, DUMMY_SP}; diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index c26ce1272ff..01f0e3cfadb 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, Ty, TypeAndMut}; +use rustc_middle::ty::{self, Ty}; use rustc_session::declare_lint_pass; use rustc_span::sym; diff --git a/clippy_lints/src/transmute/crosspointer_transmute.rs b/clippy_lints/src/transmute/crosspointer_transmute.rs index c4b9d82fc73..102aee1cb95 100644 --- a/clippy_lints/src/transmute/crosspointer_transmute.rs +++ b/clippy_lints/src/transmute/crosspointer_transmute.rs @@ -7,8 +7,8 @@ use rustc_middle::ty::{self, Ty}; /// Checks for `crosspointer_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { - match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => { + match (*from_ty.kind(), *to_ty.kind()) { + (ty::RawPtr(from_ptr_ty, _), _) if from_ptr_ty == to_ty => { span_lint( cx, CROSSPOINTER_TRANSMUTE, @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty ); true }, - (_, ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => { + (_, ty::RawPtr(to_ptr_ty, _)) if to_ptr_ty == from_ty => { span_lint( cx, CROSSPOINTER_TRANSMUTE, diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 84fa201639a..1476ea8e7a4 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -16,7 +16,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(_, _), ty::RawPtr(to_ty)) => { + (ty::RawPtr(_, _), ty::RawPtr(to_ty, to_mutbl)) => { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( "transmute from a pointer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let sugg = arg.as_ty(Ty::new_ptr(cx.tcx, *to_ty)); + let sugg = arg.as_ty(Ty::new_ptr(cx.tcx, *to_ty, *to_mutbl)); diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); } }, diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 4ab3afbe714..cf78709583c 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -20,7 +20,7 @@ pub(super) fn check<'tcx>( msrv: &Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(from_ptr_ty), ty::Ref(_, to_ref_ty, mutbl)) => { + (ty::RawPtr(from_ptr_ty, _), ty::Ref(_, to_ref_ty, mutbl)) => { span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( } else { sugg::make_unop(deref, arg.as_ty(format!("{cast} {ty_snip}"))).to_string() } - } else if from_ptr_ty.ty == *to_ref_ty { + } else if *from_ptr_ty == *to_ref_ty { if from_ptr_ty.has_erased_regions() { if msrv.meets(msrvs::POINTER_CAST) { format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par()) diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 6c885ebdea1..73321c56f3f 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>( ) -> bool { let mut triggered = false; - if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) { + if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (*from_ty.kind(), *to_ty.kind()) { if let ty::Slice(slice_ty) = *ty_from.kind() && ty_to.is_str() && let ty::Uint(ty::UintTy::U8) = slice_ty.kind() @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( { let Some(top_crate) = std_or_core(cx) else { return true }; - let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" }; + let postfix = if from_mutbl == Mutability::Mut { "_mut" } else { "" }; let snippet = snippet(cx, arg.span, ".."); @@ -53,18 +53,10 @@ pub(super) fn check<'tcx>( "transmute from a reference to a reference", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let ty_from_and_mut = ty::TypeAndMut { - ty: *ty_from, - mutbl: *from_mutbl, - }; - let ty_to_and_mut = ty::TypeAndMut { - ty: *ty_to, - mutbl: *to_mutbl, - }; let sugg_paren = arg - .as_ty(Ty::new_ptr(cx.tcx, ty_from_and_mut)) - .as_ty(Ty::new_ptr(cx.tcx, ty_to_and_mut)); - let sugg = if *to_mutbl == Mutability::Mut { + .as_ty(Ty::new_ptr(cx.tcx, ty_from, from_mutbl)) + .as_ty(Ty::new_ptr(cx.tcx, ty_to, to_mutbl)); + let sugg = if to_mutbl == Mutability::Mut { sugg_paren.mut_addr_deref() } else { sugg_paren.addr_deref() diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 44b5f460737..33c4031fa87 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_c_void; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::{self, GenericArgsRef, IntTy, Ty, TypeAndMut, UintTy}; +use rustc_middle::ty::{self, GenericArgsRef, IntTy, Ty, UintTy}; #[expect(clippy::too_many_lines)] pub(super) fn check<'tcx>( diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs index f3d3516755c..70628f3d4f4 100644 --- a/clippy_lints/src/transmute/useless_transmute.rs +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -15,7 +15,7 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, ) -> bool { - match (&from_ty.kind(), &to_ty.kind()) { + match (*from_ty.kind(), *to_ty.kind()) { _ if from_ty == to_ty && !from_ty.has_erased_regions() => { span_lint( cx, @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( ); true }, - (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => { + (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty, ptr_mutbl)) => { // No way to give the correct suggestion here. Avoid linting for now. if !rty.has_erased_regions() { span_lint_and_then( @@ -35,15 +35,10 @@ pub(super) fn check<'tcx>( "transmute from a reference to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let rty_and_mut = ty::TypeAndMut { - ty: *rty, - mutbl: *rty_mutbl, - }; - - let sugg = if *ptr_ty == rty_and_mut { + let sugg = if ptr_ty == rty && rty_mutbl == ptr_mutbl { arg.as_ty(to_ty) } else { - arg.as_ty(Ty::new_ptr(cx.tcx, rty_and_mut)).as_ty(to_ty) + arg.as_ty(Ty::new_ptr(cx.tcx, rty, rty_mutbl)).as_ty(to_ty) }; diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index e90317f5524..a526ba97af6 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -112,7 +112,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, ParamEnv, - ParamEnvAnd, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UintTy, UpvarCapture, + ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; From 6b04fc24fc4ade1a03b9c47596fb3ec14a3349c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Mar 2024 15:49:17 -0400 Subject: [PATCH 24/79] Fix clippy --- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f0f2c7d6658..c554edc8fce 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty, + self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt, }; use rustc_session::declare_lint_pass; @@ -502,7 +502,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), - polarity: ImplPolarity::Positive, + polarity: ty::PredicatePolarity::Positive, }) .to_predicate(tcx) }), diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 40be71a0e5d..eccfc31fdd3 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -9,7 +9,7 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPat use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ - self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, ImplPolarity, List, Region, RegionKind, + self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults, }; use rustc_session::declare_lint_pass; @@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait( cx.param_env, Binder::bind_with_vars(callee_ty_adjusted, List::empty()), - ImplPolarity::Positive, + ty::PredicatePolarity::Positive, ) && path_to_local(callee).map_or(false, |l| { local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr) }) { diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index c234e4f9b11..abf717126fb 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -18,7 +18,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::{ - self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ImplPolarity, ParamTy, ProjectionPredicate, + self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty, }; use rustc_span::{sym, Symbol}; @@ -669,7 +669,7 @@ fn check_borrow_predicate<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { && let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow) && cx.tcx.predicates_of(method_def_id).predicates.iter().any(|(pred, _)| { if let ClauseKind::Trait(trait_pred) = pred.kind().skip_binder() - && trait_pred.polarity == ImplPolarity::Positive + && trait_pred.polarity == ty::PredicatePolarity::Positive && trait_pred.trait_ref.def_id == borrow_id { true From a24d12b7aa0d5e4d94b5d4f8467d21986d906de3 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 18 Mar 2024 21:28:43 +0000 Subject: [PATCH 25/79] Enable unused_qualifications lint --- clippy_config/src/lib.rs | 8 ++- clippy_dev/src/lib.rs | 9 ++- clippy_dev/src/update_lints.rs | 4 +- clippy_lints/src/assigning_clones.rs | 11 +-- clippy_lints/src/booleans.rs | 4 +- clippy_lints/src/box_default.rs | 2 +- clippy_lints/src/collection_is_never_read.rs | 2 +- .../src/default_constructed_unit_structs.rs | 2 +- .../src/default_instead_of_iter_empty.rs | 2 +- clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eta_reduction.rs | 4 +- clippy_lints/src/floating_point_arithmetic.rs | 6 +- clippy_lints/src/functions/result.rs | 4 +- clippy_lints/src/implied_bounds_in_impls.rs | 2 +- clippy_lints/src/instant_subtraction.rs | 4 +- .../src/invalid_upcast_comparisons.rs | 2 +- clippy_lints/src/len_zero.rs | 4 +- clippy_lints/src/lib.rs | 13 ++-- clippy_lints/src/literal_representation.rs | 8 +-- clippy_lints/src/loops/mut_range_bound.rs | 4 +- clippy_lints/src/loops/needless_range_loop.rs | 2 +- clippy_lints/src/loops/never_loop.rs | 9 +-- clippy_lints/src/loops/single_element_loop.rs | 4 +- clippy_lints/src/manual_bits.rs | 2 +- clippy_lints/src/methods/clear_with_drain.rs | 3 +- clippy_lints/src/methods/filter_map.rs | 51 ++++++------- clippy_lints/src/methods/iter_filter.rs | 14 ++-- .../src/methods/iter_overeager_cloned.rs | 2 +- clippy_lints/src/methods/map_clone.rs | 2 +- clippy_lints/src/methods/mod.rs | 18 ++--- clippy_lints/src/methods/needless_collect.rs | 2 +- clippy_lints/src/methods/search_is_some.rs | 2 +- clippy_lints/src/methods/utils.rs | 11 ++- clippy_lints/src/missing_fields_in_debug.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 4 +- .../src/needless_borrows_for_generic_args.rs | 6 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/non_copy_const.rs | 4 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/question_mark.rs | 8 +-- clippy_lints/src/redundant_closure_call.rs | 34 ++++----- .../src/redundant_type_annotations.rs | 2 +- ...ead_local_initializer_can_be_made_const.rs | 4 +- .../src/undocumented_unsafe_blocks.rs | 18 ++--- clippy_lints/src/unit_types/unit_arg.rs | 4 +- .../src/unnecessary_map_on_constructor.rs | 2 +- clippy_lints/src/unnested_or_patterns.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 24 +++---- clippy_lints/src/unwrap_in_result.rs | 2 +- clippy_lints/src/use_self.rs | 4 +- clippy_lints/src/utils/author.rs | 4 +- .../utils/internal_lints/collapsible_calls.rs | 3 +- .../internal_lints/metadata_collector.rs | 10 +-- .../internal_lints/unnecessary_def_path.rs | 5 +- clippy_utils/src/ast_utils.rs | 20 +++--- clippy_utils/src/consts.rs | 12 ++-- clippy_utils/src/higher.rs | 54 +++++++------- clippy_utils/src/lib.rs | 56 ++++++++------- clippy_utils/src/macros.rs | 2 +- clippy_utils/src/mir/mod.rs | 2 +- clippy_utils/src/sugg.rs | 72 +++++++++---------- clippy_utils/src/ty.rs | 24 +++---- clippy_utils/src/usage.rs | 18 ++--- clippy_utils/src/visitors.rs | 28 ++++---- lintcheck/src/main.rs | 41 ++++++----- 67 files changed, 349 insertions(+), 349 deletions(-) diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 01e2aa6e0a6..ff7fa7241cb 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -1,6 +1,12 @@ #![feature(rustc_private, let_chains)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![warn(rust_2018_idioms, unused_lifetimes)] +#![warn( + trivial_casts, + trivial_numeric_casts, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications +)] #![allow( clippy::must_use_candidate, clippy::missing_panics_doc, diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index c4ae4f0e2bd..bb62e902cd5 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -2,8 +2,13 @@ #![feature(let_chains)] #![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -// warn on lints, that are included in `rust-lang/rust`s bootstrap -#![warn(rust_2018_idioms, unused_lifetimes)] +#![warn( + trivial_casts, + trivial_numeric_casts, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications +)] // The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate. #[allow(unused_extern_crates)] diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 76ae26dddf4..625b1339591 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -992,7 +992,7 @@ fn replace_region_in_text<'a>( } fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { - match fs::OpenOptions::new().create_new(true).write(true).open(new_name) { + match OpenOptions::new().create_new(true).write(true).open(new_name) { Ok(file) => drop(file), Err(e) if matches!(e.kind(), io::ErrorKind::AlreadyExists | io::ErrorKind::NotFound) => return false, Err(e) => panic_file(e, new_name, "create"), @@ -1016,7 +1016,7 @@ fn panic_file(error: io::Error, name: &Path, action: &str) -> ! { } fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option) { - let mut file = fs::OpenOptions::new() + let mut file = OpenOptions::new() .write(true) .read(true) .open(path) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 88d9f762a87..e3ec8039841 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -65,7 +65,7 @@ impl AssigningClones { impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); impl<'tcx> LateLintPass<'tcx> for AssigningClones { - fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx Expr<'_>) { // Do not fire the lint in macros let expn_data = assign_expr.span().ctxt().outer_expn_data(); match expn_data.kind { @@ -205,12 +205,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC implemented_fns.contains_key(&provided_fn.def_id) } -fn suggest<'tcx>( - cx: &LateContext<'tcx>, - assign_expr: &hir::Expr<'tcx>, - lhs: &hir::Expr<'tcx>, - call: &CallCandidate<'tcx>, -) { +fn suggest<'tcx>(cx: &LateContext<'tcx>, assign_expr: &Expr<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) { span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| { let mut applicability = Applicability::MachineApplicable; @@ -263,7 +258,7 @@ impl<'tcx> CallCandidate<'tcx> { fn suggested_replacement( &self, cx: &LateContext<'tcx>, - lhs: &hir::Expr<'tcx>, + lhs: &Expr<'tcx>, applicability: &mut Applicability, ) -> String { match self.target { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index a474356608f..6edfebb5534 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -392,13 +392,13 @@ fn simple_negate(b: Bool) -> Bool { t @ Term(_) => Not(Box::new(t)), And(mut v) => { for el in &mut v { - *el = simple_negate(::std::mem::replace(el, True)); + *el = simple_negate(std::mem::replace(el, True)); } Or(v) }, Or(mut v) => { for el in &mut v { - *el = simple_negate(::std::mem::replace(el, True)); + *el = simple_negate(std::mem::replace(el, True)); } And(v) }, diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index 779ae03c464..e83f5c2a74c 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -127,7 +127,7 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) struct InferVisitor(bool); impl<'tcx> Visitor<'tcx> for InferVisitor { - fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) { + fn visit_ty(&mut self, t: &Ty<'_>) { self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..)); if !self.0 { walk_ty(self, t); diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index d820413e111..83660bf2691 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { } } -fn match_acceptable_type(cx: &LateContext<'_>, local: &Local<'_>, collections: &[rustc_span::Symbol]) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, local: &Local<'_>, collections: &[Symbol]) -> bool { let ty = cx.typeck_results().pat_ty(local.pat); collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) // String type is a lang item but not a diagnostic item for now so we need a separate check diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index 71e1a25c2bc..13778175496 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -56,7 +56,7 @@ fn is_alias(ty: hir::Ty<'_>) -> bool { impl LateLintPass<'_> for DefaultConstructedUnitStructs { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind + if let ExprKind::Call(fn_expr, &[]) = expr.kind // make sure we have a call to `Default::default` && let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind // make sure this isn't a type alias: diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index e617c19eff0..61f68fdb66c 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { fn make_sugg( cx: &LateContext<'_>, - ty_path: &rustc_hir::QPath<'_>, + ty_path: &QPath<'_>, ctxt: SyntaxContext, applicability: &mut Applicability, path: &str, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index b0f46f5c646..80327586fed 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool { fn contains_trait_object(ty: Ty<'_>) -> bool { match ty.kind() { ty::Ref(_, ty, _) => contains_trait_object(*ty), - ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object), + Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object), ty::Dynamic(..) => true, _ => false, } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index ad589dad350..386d4c3c317 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} + fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} } impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 40be71a0e5d..18d54bd94cc 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -3,7 +3,7 @@ use clippy_utils::higher::VecArgs; use clippy_utils::source::snippet_opt; use clippy_utils::ty::type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; -use clippy_utils::{get_path_from_caller_to_method_type, higher, is_adjusted, path_to_local, path_to_local_id}; +use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety}; use rustc_infer::infer::TyCtxtInferExt; @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { if body.value.span.from_expansion() { if body.params.is_empty() { - if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, body.value) { + if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) { // replace `|| vec![]` with `Vec::new` span_lint_and_sugg( cx, diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index c8b87e510ed..46d47e217b0 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -552,9 +552,9 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) - /// Returns true iff expr is some zero literal fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match constant_simple(cx, cx.typeck_results(), expr) { - Some(Constant::Int(i)) => i == 0, - Some(Constant::F32(f)) => f == 0.0, - Some(Constant::F64(f)) => f == 0.0, + Some(Int(i)) => i == 0, + Some(F32(f)) => f == 0.0, + Some(F64(f)) => f == 0.0, _ => false, } } diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs index 37fbf2c7d59..93f088d3e33 100644 --- a/clippy_lints/src/functions/result.rs +++ b/clippy_lints/src/functions/result.rs @@ -2,7 +2,7 @@ use rustc_errors::Diag; use rustc_hir as hir; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Adt, Ty}; +use rustc_middle::ty::{Adt, Ty}; use rustc_span::{sym, Span}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; @@ -25,7 +25,7 @@ fn result_err_ty<'tcx>( .tcx .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output()) && is_type_diagnostic_item(cx, ty, sym::Result) - && let ty::Adt(_, args) = ty.kind() + && let Adt(_, args) = ty.kind() { let err_ty = args.type_at(1); Some((hir_ty, err_ty)) diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 74582f7f1de..79078055cc3 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -56,7 +56,7 @@ fn emit_lint( index: usize, // The bindings that were implied, used for suggestion purposes since removing a bound with associated types // means we might need to then move it to a different bound - implied_bindings: &[rustc_hir::TypeBinding<'_>], + implied_bindings: &[TypeBinding<'_>], bound: &ImplTraitBound<'_>, ) { let implied_by = snippet(cx, bound.span, ".."); diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 17b6256f982..10b00f632bb 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -1,5 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::{self, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::ty; @@ -149,7 +149,7 @@ fn print_unchecked_duration_subtraction_sugg( let left_expr = snippet_with_context(cx, left_expr.span, ctxt, "", &mut applicability).0; let right_expr = snippet_with_context(cx, right_expr.span, ctxt, "", &mut applicability).0; - diagnostics::span_lint_and_sugg( + span_lint_and_sugg( cx, UNCHECKED_DURATION_SUBTRACTION, expr.span, diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs index 8bcd9b532bd..7dcb80ac274 100644 --- a/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/clippy_lints/src/invalid_upcast_comparisons.rs @@ -88,7 +88,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa fn upcast_comparison_bounds_err<'tcx>( cx: &LateContext<'tcx>, span: Span, - rel: comparisons::Rel, + rel: Rel, lhs_bounds: Option<(FullInt, FullInt)>, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 27d85cde532..174b775f88b 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -256,7 +256,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items .items() .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty)) .any(|i| { - i.kind == ty::AssocKind::Fn + i.kind == AssocKind::Fn && i.fn_has_self_parameter && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1 }); @@ -594,7 +594,7 @@ fn is_empty_array(expr: &Expr<'_>) -> bool { fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { - if item.kind == ty::AssocKind::Fn { + if item.kind == AssocKind::Fn { let sig = cx.tcx.fn_sig(item.def_id).skip_binder(); let ty = sig.skip_binder(); ty.inputs().len() == 1 diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 57fac351042..169e51e2cb9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -16,11 +16,14 @@ rustc::diagnostic_outside_of_impl, rustc::untranslatable_diagnostic )] -#![warn(trivial_casts, trivial_numeric_casts)] -// warn on lints, that are included in `rust-lang/rust`s bootstrap -#![warn(rust_2018_idioms, unused_lifetimes)] -// warn on rustc internal lints -#![warn(rustc::internal)] +#![warn( + trivial_casts, + trivial_numeric_casts, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications, + rustc::internal +)] // Disable this rustc lint for now, as it was also done in rustc #![allow(rustc::potential_query_instability)] diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index f33151cf4c5..2348dd18220 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -158,7 +158,7 @@ enum WarningType { } impl WarningType { - fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: rustc_span::Span) { + fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: Span) { match self { Self::MistypedLiteralSuffix => span_lint_and_sugg( cx, @@ -302,11 +302,7 @@ impl LiteralDigitGrouping { } // Returns `false` if the check fails - fn check_for_mistyped_suffix( - cx: &EarlyContext<'_>, - span: rustc_span::Span, - num_lit: &mut NumericLiteral<'_>, - ) -> bool { + fn check_for_mistyped_suffix(cx: &EarlyContext<'_>, span: Span, num_lit: &mut NumericLiteral<'_>) -> bool { if num_lit.suffix.is_some() { return true; } diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index c4e60e98ad4..94330001e4f 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -109,7 +109,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { } } - fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} + fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} } impl MutatePairDelegate<'_, '_> { @@ -141,7 +141,7 @@ impl BreakAfterExprVisitor { } } -impl<'tcx> intravisit::Visitor<'tcx> for BreakAfterExprVisitor { +impl<'tcx> Visitor<'tcx> for BreakAfterExprVisitor { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { if self.past_candidate { return; diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index cf34c904dfe..04340d33330 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -357,7 +357,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); for (ty, expr) in iter::zip( self.cx.tcx.fn_sig(def_id).instantiate_identity().inputs().skip_binder(), - std::iter::once(receiver).chain(args.iter()), + iter::once(receiver).chain(args.iter()), ) { self.prefer_mutable = false; if let ty::Ref(_, _, mutbl) = *ty.kind() { diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 8aae7be4593..313a5bfefbc 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -159,12 +159,9 @@ fn never_loop_expr<'tcx>( | ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id), ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id), ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id), - ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all( - cx, - std::iter::once(receiver).chain(es.iter()), - local_labels, - main_loop_id, - ), + ExprKind::MethodCall(_, receiver, es, _) => { + never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id) + }, ExprKind::Struct(_, fields, base) => { let fields = never_loop_expr_all(cx, fields.iter().map(|f| f.expr), local_labels, main_loop_id); if let Some(base) = base { diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index 4773a1454b7..a1ff787ebb5 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>( }, [], _, - ) if method.ident.name == rustc_span::sym::iter => (arg, "&"), + ) if method.ident.name == sym::iter => (arg, "&"), ExprKind::MethodCall( method, Expr { @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>( }, [], _, - ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""), + ) if method.ident.name == sym::into_iter => (arg, ""), // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise. ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""), _ => return, diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index aa02e4e7a43..24fc2b4faea 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -139,7 +139,7 @@ fn is_ty_conversion(expr: &Expr<'_>) -> bool { if let ExprKind::Cast(..) = expr.kind { true } else if let ExprKind::MethodCall(path, _, [], _) = expr.kind - && path.ident.name == rustc_span::sym::try_into + && path.ident.name == sym::try_into { // This is only called for `usize` which implements `TryInto`. Therefore, // we don't have to check here if `self` implements the `TryInto` trait. diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index 67ad58d5a8c..506ec6ba1c9 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_range_full; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_hir::{Expr, ExprKind, LangItem, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; @@ -28,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span } } -fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, types: &[rustc_span::Symbol]) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, expr: &Expr<'_>, types: &[rustc_span::Symbol]) -> bool { let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty)) // String type is a lang item but not a diagnostic item for now so we need a separate check diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 9b656531957..83dcc90637e 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -16,20 +16,18 @@ use std::borrow::Cow; use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP}; -fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { +fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool { match &expr.kind { - hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, - hir::ExprKind::Path(QPath::Resolved(_, segments)) => { - segments.segments.last().unwrap().ident.name == method_name - }, - hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, - hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, + ExprKind::Path(QPath::Resolved(_, segments)) => segments.segments.last().unwrap().ident.name == method_name, + ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, + ExprKind::Closure(&Closure { body, .. }) => { let body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(body.value); match closure_expr.kind { - hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { + ExprKind::MethodCall(PathSegment { ident, .. }, receiver, ..) => { if ident.name == method_name - && let hir::ExprKind::Path(path) = &receiver.kind + && let ExprKind::Path(path) = &receiver.kind && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) && !body.params.is_empty() { @@ -45,10 +43,10 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> } } -fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool { +fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool { is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some)) } -fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool { +fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool { is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_ok)) } @@ -267,10 +265,10 @@ impl<'tcx> OffendingFilterExpr<'tcx> { /// is `filter(|x| x.is_some()).map(|x| x.unwrap())` fn is_filter_some_map_unwrap( cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - filter_recv: &hir::Expr<'_>, - filter_arg: &hir::Expr<'_>, - map_arg: &hir::Expr<'_>, + expr: &Expr<'_>, + filter_recv: &Expr<'_>, + filter_arg: &Expr<'_>, + map_arg: &Expr<'_>, ) -> bool { let iterator = is_trait_method(cx, expr, sym::Iterator); let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::Option); @@ -279,12 +277,7 @@ fn is_filter_some_map_unwrap( } /// is `filter(|x| x.is_ok()).map(|x| x.unwrap())` -fn is_filter_ok_map_unwrap( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - filter_arg: &hir::Expr<'_>, - map_arg: &hir::Expr<'_>, -) -> bool { +fn is_filter_ok_map_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool { // result has no filter, so we only check for iterators let iterator = is_trait_method(cx, expr, sym::Iterator); iterator && is_ok_filter_map(cx, filter_arg, map_arg) @@ -294,12 +287,12 @@ fn is_filter_ok_map_unwrap( #[allow(clippy::too_many_arguments)] pub(super) fn check( cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - filter_recv: &hir::Expr<'_>, - filter_arg: &hir::Expr<'_>, + expr: &Expr<'_>, + filter_recv: &Expr<'_>, + filter_arg: &Expr<'_>, filter_span: Span, - map_recv: &hir::Expr<'_>, - map_arg: &hir::Expr<'_>, + map_recv: &Expr<'_>, + map_arg: &Expr<'_>, map_span: Span, is_find: bool, ) { @@ -405,9 +398,9 @@ pub(super) fn check( fn is_find_or_filter<'a>( cx: &LateContext<'a>, - map_recv: &hir::Expr<'_>, - filter_arg: &hir::Expr<'_>, - map_arg: &hir::Expr<'_>, + map_recv: &Expr<'_>, + filter_arg: &Expr<'_>, + map_arg: &Expr<'_>, ) -> Option<(Ident, CheckResult<'a>)> { if is_trait_method(cx, map_recv, sym::Iterator) // filter(|x| ...is_some())... diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs index 9f84321ced4..12647ea1ffc 100644 --- a/clippy_lints/src/methods/iter_filter.rs +++ b/clippy_lints/src/methods/iter_filter.rs @@ -55,7 +55,7 @@ fn is_method( } } match expr.kind { - hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => { + ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => { // compare the identifier of the receiver to the parameter // we are in a filter => closure has a single parameter and a single, non-block // expression, this means that the parameter shadows all outside variables with @@ -73,7 +73,7 @@ fn is_method( // This is used to check for complete paths via `|a| std::option::Option::is_some(a)` // this then unwraps to a path with `QPath::TypeRelative` // we pass the params as they've been passed to the current call through the closure - hir::ExprKind::Call(expr, [param]) => { + ExprKind::Call(expr, [param]) => { // this will hit the `QPath::TypeRelative` case and check that the method name is correct if is_method(cx, expr, type_symbol, method_name, params) // we then check that this is indeed passing the parameter of the closure @@ -85,7 +85,7 @@ fn is_method( } false }, - hir::ExprKind::Path(QPath::TypeRelative(ty, mname)) => { + ExprKind::Path(QPath::TypeRelative(ty, mname)) => { let ty = cx.typeck_results().node_type(ty.hir_id); if let Some(did) = cx.tcx.get_diagnostic_item(type_symbol) && ty.ty_adt_def() == cx.tcx.type_of(did).skip_binder().ty_adt_def() @@ -94,7 +94,7 @@ fn is_method( } false }, - hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(body.value); let params = body.params.iter().map(|param| param.pat).collect::>(); @@ -107,8 +107,8 @@ fn is_method( fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { if let Some(expr) = get_parent_expr(cx, expr) && is_trait_method(cx, expr, sym::Iterator) - && let hir::ExprKind::MethodCall(path, _, _, _) = expr.kind - && path.ident.name == rustc_span::sym::map + && let ExprKind::MethodCall(path, _, _, _) = expr.kind + && path.ident.name == sym::map { return true; } @@ -148,7 +148,7 @@ fn expression_type( { return None; } - if let hir::ExprKind::MethodCall(_, receiver, _, _) = expr.kind + if let ExprKind::MethodCall(_, receiver, _, _) = expr.kind && let receiver_ty = cx.typeck_results().expr_ty(receiver) && let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty) { diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs index b2fe129cd95..4729481320e 100644 --- a/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>( } if let Op::NeedlessMove(expr) = op { - let rustc_hir::ExprKind::Closure(closure) = expr.kind else { + let ExprKind::Closure(closure) = expr.kind else { return; }; let body @ Body { params: [p], .. } = cx.tcx.hir().body(closure.body) else { diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index c3c7a3a0033..fc271690d2f 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -50,7 +50,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ let closure_body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(closure_body.value); match closure_body.params[0].pat.kind { - hir::PatKind::Ref(inner, hir::Mutability::Not) => { + hir::PatKind::Ref(inner, Mutability::Not) => { if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind { if ident_eq(name, closure_expr) { lint_explicit_closure(cx, e.span, recv.span, true, msrv); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e3137a868a0..df5dad0423c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4240,8 +4240,8 @@ impl_lint_pass!(Methods => [ /// Extracts a method call name, args, and `Span` of the method name. pub fn method_call<'tcx>( - recv: &'tcx hir::Expr<'tcx>, -) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span, Span)> { + recv: &'tcx Expr<'tcx>, +) -> Option<(&'tcx str, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> { if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind { if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() { let name = path.ident.name.as_str(); @@ -4252,7 +4252,7 @@ pub fn method_call<'tcx>( } impl<'tcx> LateLintPass<'tcx> for Methods { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } @@ -4260,12 +4260,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods { self.check_methods(cx, expr); match expr.kind { - hir::ExprKind::Call(func, args) => { + ExprKind::Call(func, args) => { from_iter_instead_of_collect::check(cx, expr, args, func); unnecessary_fallible_conversions::check_function(cx, expr, func); manual_c_str_literals::check(cx, expr, func, args, &self.msrv); }, - hir::ExprKind::MethodCall(method_call, receiver, args, _) => { + ExprKind::MethodCall(method_call, receiver, args, _) => { let method_span = method_call.ident.span; or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); @@ -4277,7 +4277,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { 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); }, - hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { + ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { expr, chain: lhs, @@ -4999,9 +4999,9 @@ fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, /// Used for `lint_binary_expr_with_method_call`. #[derive(Copy, Clone)] struct BinaryExprInfo<'a> { - expr: &'a hir::Expr<'a>, - chain: &'a hir::Expr<'a>, - other: &'a hir::Expr<'a>, + expr: &'a Expr<'a>, + chain: &'a Expr<'a>, + other: &'a Expr<'a>, eq: bool, } diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 78540353005..747da125b68 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -107,7 +107,7 @@ pub(super) fn check<'tcx>( span.push_span_label(iter_call.span, "the iterator could be used here instead"); span_lint_hir_and_then( cx, - super::NEEDLESS_COLLECT, + NEEDLESS_COLLECT, collect_expr.hir_id, span, NEEDLESS_COLLECT_MSG, diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs index ef1baa6c988..0c3b881b086 100644 --- a/clippy_lints/src/methods/search_is_some.rs +++ b/clippy_lints/src/methods/search_is_some.rs @@ -39,7 +39,7 @@ pub(super) fn check<'tcx>( && let closure_body = cx.tcx.hir().body(body) && let Some(closure_arg) = closure_body.params.first() { - if let hir::PatKind::Ref(..) = closure_arg.pat.kind { + if let PatKind::Ref(..) = closure_arg.pat.kind { Some(search_snippet.replacen('&', "", 1)) } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind { // `find()` provides a reference to the item, but `any` does not, diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 3a0305b4d55..ef00c812d51 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -3,7 +3,6 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{get_parent_expr, path_to_local_id, usage}; use rustc_ast::ast; use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat}; use rustc_lint::LateContext; @@ -13,9 +12,9 @@ use rustc_span::symbol::sym; pub(super) fn derefs_to_slice<'tcx>( cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'tcx>, + expr: &'tcx Expr<'tcx>, ty: Ty<'tcx>, -) -> Option<&'tcx hir::Expr<'tcx>> { +) -> Option<&'tcx Expr<'tcx>> { fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { match ty.kind() { ty::Slice(_) => true, @@ -27,7 +26,7 @@ pub(super) fn derefs_to_slice<'tcx>( } } - if let hir::ExprKind::MethodCall(path, self_arg, ..) = &expr.kind { + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind { if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) { Some(self_arg) } else { @@ -51,10 +50,10 @@ pub(super) fn derefs_to_slice<'tcx>( pub(super) fn get_hint_if_single_char_arg( cx: &LateContext<'_>, - arg: &hir::Expr<'_>, + arg: &Expr<'_>, applicability: &mut Applicability, ) -> Option { - if let hir::ExprKind::Lit(lit) = &arg.kind + if let ExprKind::Lit(lit) = &arg.kind && let ast::LitKind::Str(r, style) = lit.node && let string = r.as_str() && string.chars().count() == 1 diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index 3bf9f75e226..a64faa124f0 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -198,7 +198,7 @@ fn check_struct<'tcx>( } impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::Item<'tcx>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { // is this an `impl Debug for X` block? if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index f905a4e5b64..7447a2287d3 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { let method_type = cx.tcx.type_of(def_id).instantiate(cx.tcx, args); check_arguments( cx, - std::iter::once(receiver).chain(arguments.iter()).collect(), + iter::once(receiver).chain(arguments.iter()).collect(), method_type, path.ident.as_str(), "method", diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 4ae4fc9b096..b882e00dbdf 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -92,8 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for Mutex { behavior and not the internal type, consider using `Mutex<()>`" ); match *mutex_param.kind() { - ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::Int(t) if t != ty::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index a32bca3d038..c555fc8675c 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -381,7 +381,7 @@ fn replace_types<'tcx>( fn_sig: FnSig<'tcx>, arg_index: usize, projection_predicates: &[ProjectionPredicate<'tcx>], - args: &mut [ty::GenericArg<'tcx>], + args: &mut [GenericArg<'tcx>], ) -> bool { let mut replaced = BitSet::new_empty(args.len()); @@ -399,7 +399,7 @@ fn replace_types<'tcx>( return false; } - args[param_ty.index as usize] = ty::GenericArg::from(new_ty); + args[param_ty.index as usize] = GenericArg::from(new_ty); // The `replaced.insert(...)` check provides some protection against infinite loops. if replaced.insert(param_ty.index) { @@ -414,7 +414,7 @@ fn replace_types<'tcx>( )); if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) - && args[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty) + && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) { deque.push_back((*term_param_ty, projected_ty)); } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 43810ec0ec7..f915145e794 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { } } - fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(def_id) = path_to_local(expr) { // FIXME(rust/#120456) - is `swap_remove` correct? self.underscore_bindings.swap_remove(&def_id); diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 6cb84bb78b6..73fc34c2450 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -285,7 +285,7 @@ impl NonCopyConst { let def_id = body_id.hir_id.owner.to_def_id(); let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id); let instance = ty::Instance::new(def_id, args); - let cid = rustc_middle::mir::interpret::GlobalId { + let cid = GlobalId { instance, promoted: None, }; @@ -534,7 +534,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } } -fn ignored_macro(cx: &LateContext<'_>, it: &rustc_hir::Item<'_>) -> bool { +fn ignored_macro(cx: &LateContext<'_>, it: &Item<'_>) -> bool { macro_backtrace(it.span).any(|macro_call| { matches!( cx.tcx.get_diagnostic_name(macro_call.def_id), diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2587b3881bb..6f20b5ec150 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -628,7 +628,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: } }, ExprKind::MethodCall(name, self_arg, expr_args, _) => { - let i = std::iter::once(self_arg) + let i = iter::once(self_arg) .chain(expr_args.iter()) .position(|arg| arg.hir_id == child_id) .unwrap_or(0); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 831c291ed7c..09bbcdb9c79 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -306,9 +306,9 @@ impl QuestionMark { } } -fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool { +fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool { if let Some(expr) = bl.expr - && let rustc_hir::ExprKind::Call(callee, _) = expr.kind + && let ExprKind::Call(callee, _) = expr.kind { is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput) } else { @@ -337,7 +337,7 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { } } - fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if is_try_block(cx, block) { *self .try_block_depth_stack @@ -354,7 +354,7 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { self.try_block_depth_stack.pop(); } - fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if is_try_block(cx, block) { *self .try_block_depth_stack diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 435899ddaa7..2863eb190d3 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -56,7 +56,7 @@ impl ReturnVisitor { impl<'tcx> Visitor<'tcx> for ReturnVisitor { fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind { + if let ExprKind::Ret(_) | ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind { self.found_return = true; } else { hir_visit::walk_expr(self, ex); @@ -68,7 +68,7 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor { /// Returns true for `async || whatever_expression`, but false for `|| async { whatever_expression /// }`. fn is_async_closure(body: &hir::Body<'_>) -> bool { - if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind + if let ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind // checks whether it is `async || whatever_expression` && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) = innermost_closure_generated_by_desugar.kind @@ -99,7 +99,7 @@ fn find_innermost_closure<'tcx>( )> { let mut data = None; - while let hir::ExprKind::Closure(closure) = expr.kind + while let ExprKind::Closure(closure) = expr.kind && let body = cx.tcx.hir().body(closure.body) && { let mut visitor = ReturnVisitor::new(); @@ -137,7 +137,7 @@ fn get_parent_call_exprs<'tcx>( ) -> (&'tcx hir::Expr<'tcx>, usize) { let mut depth = 1; while let Some(parent) = get_parent_expr(cx, expr) - && let hir::ExprKind::Call(recv, _) = parent.kind + && let ExprKind::Call(recv, _) = parent.kind && expr.span == recv.span { expr = parent; @@ -152,13 +152,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { return; } - if let hir::ExprKind::Call(recv, _) = expr.kind + if let ExprKind::Call(recv, _) = expr.kind // don't lint if the receiver is a call, too. // we do this in order to prevent linting multiple times; consider: // `(|| || 1)()()` // ^^ we only want to lint for this call (but we walk up the calls to consider both calls). // without this check, we'd end up linting twice. - && !matches!(recv.kind, hir::ExprKind::Call(..)) + && !matches!(recv.kind, ExprKind::Call(..)) // Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is // the same as the one the call is in. // For instance, let's assume `x!()` returns a closure: @@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability); if coroutine_kind.is_async() - && let hir::ExprKind::Closure(closure) = body.kind + && let ExprKind::Closure(closure) = body.kind { // Like `async fn`, async closures are wrapped in an additional block // to move all of the closure's arguments into the future. @@ -202,7 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { }; // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) { + if !matches!(body_expr.kind, ExprKind::Block(_, _)) { hint = hint.blockify(); } @@ -210,7 +210,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } let is_in_fn_call_arg = if let Node::Expr(expr) = cx.tcx.parent_hir_node(expr.hir_id) { - matches!(expr.kind, hir::ExprKind::Call(_, _)) + matches!(expr.kind, ExprKind::Call(_, _)) } else { false }; @@ -238,12 +238,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { path: &'tcx hir::Path<'tcx>, count: usize, } - impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> { + impl<'a, 'tcx> Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Call(closure, _) = expr.kind - && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind + if let ExprKind::Call(closure, _) = expr.kind + && let ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind && self.path.segments[0].ident == path.segments[0].ident && self.path.res == path.res { @@ -263,13 +263,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { for w in block.stmts.windows(2) { if let hir::StmtKind::Let(local) = w[0].kind - && let Option::Some(t) = local.init - && let hir::ExprKind::Closure { .. } = t.kind + && let Some(t) = local.init + && let ExprKind::Closure { .. } = t.kind && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind && let hir::StmtKind::Semi(second) = w[1].kind - && let hir::ExprKind::Assign(_, call, _) = second.kind - && let hir::ExprKind::Call(closure, _) = call.kind - && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind + && let ExprKind::Assign(_, call, _) = second.kind + && let ExprKind::Call(closure, _) = call.kind + && let ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind && ident == path.segments[0].ident && count_closure_usage(cx, block, path) == 1 { diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index 079e6500e3c..c28468e52a2 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -59,7 +59,7 @@ fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, f fn func_hir_id_to_func_ty<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::hir_id::HirId) -> Option> { if let Some((defkind, func_defid)) = cx.typeck_results().type_dependent_def(hir_id) - && defkind == hir::def::DefKind::AssocFn + && defkind == DefKind::AssocFn && let Some(init_ty) = cx.tcx.type_of(func_defid).no_bound_vars() { Some(init_ty) diff --git a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs index f8bdb866ca3..c1e24674e3e 100644 --- a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs +++ b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs @@ -59,7 +59,7 @@ impl_lint_pass!(ThreadLocalInitializerCanBeMadeConst => [THREAD_LOCAL_INITIALIZE #[inline] fn is_thread_local_initializer( cx: &LateContext<'_>, - fn_kind: rustc_hir::intravisit::FnKind<'_>, + fn_kind: intravisit::FnKind<'_>, span: rustc_span::Span, ) -> Option { let macro_def_id = span.source_callee()?.macro_def_id?; @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst { fn check_fn( &mut self, cx: &LateContext<'tcx>, - fn_kind: rustc_hir::intravisit::FnKind<'tcx>, + fn_kind: intravisit::FnKind<'tcx>, _: &'tcx rustc_hir::FnDecl<'tcx>, body: &'tcx rustc_hir::Body<'tcx>, span: rustc_span::Span, diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 0efa65b28e2..1dedb4510bd 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (hir::ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => { + (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (hir::ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => { + (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); @@ -236,9 +236,9 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { ); } }, - (hir::ItemKind::Impl(_), _) => {}, + (ItemKind::Impl(_), _) => {}, // const and static items only need a safety comment if their body is an unsafe block, lint otherwise - (&hir::ItemKind::Const(.., body) | &hir::ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => { + (&ItemKind::Const(.., body) | &ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) { let body = cx.tcx.hir().body(body); if !matches!( @@ -338,13 +338,13 @@ fn block_parents_have_safety_comment( accept_comment_above_statement: bool, accept_comment_above_attributes: bool, cx: &LateContext<'_>, - id: hir::HirId, + id: HirId, ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { - kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + kind: ItemKind::Const(..) | ItemKind::Static(..), span, owner_id, .. @@ -365,7 +365,7 @@ fn block_parents_have_safety_comment( }) | Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { - kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + kind: ItemKind::Const(..) | ItemKind::Static(..), span, owner_id, .. @@ -605,11 +605,11 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option { Node::Expr(e) => span = e.span, Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (), Node::Item(hir::Item { - kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + kind: ItemKind::Const(..) | ItemKind::Static(..), .. }) => maybe_global_var = true, Node::Item(hir::Item { - kind: hir::ItemKind::Mod(_), + kind: ItemKind::Mod(_), span: item_span, .. }) => { diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index eba7fa7b993..7fd17e332e4 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind}; use rustc_lint::LateContext; use super::{utils, UNIT_ARG}; @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if is_questionmark_desugar_marked_call(expr) { return; } - if let hir::Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id) + if let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id) && is_questionmark_desugar_marked_call(parent_expr) { return; diff --git a/clippy_lints/src/unnecessary_map_on_constructor.rs b/clippy_lints/src/unnecessary_map_on_constructor.rs index 2b0d2d61d20..252e5e4dd7c 100644 --- a/clippy_lints/src/unnecessary_map_on_constructor.rs +++ b/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { hir::QPath::LangItem(..) => return, }; match constructor_symbol { - sym::Some | sym::Ok if path.ident.name == rustc_span::sym::map => (), + sym::Some | sym::Ok if path.ident.name == sym::map => (), sym::Err if path.ident.name == sym::map_err => (), _ => return, } diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 7246214f9bf..8094fee8477 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -215,7 +215,7 @@ macro_rules! always_pat { /// in `alternatives[focus_idx + 1..]`. fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: usize) -> bool { // Extract the kind; we'll need to make some changes in it. - let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, PatKind::Wild); + let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, Wild); // We'll focus on `alternatives[focus_idx]`, // so we're draining from `alternatives[focus_idx + 1..]`. let start = focus_idx + 1; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 17a5c881c3b..9d735b19c64 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { if let Some(exp) = block.expr && matches!( exp.kind, - hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, hir::MatchSource::Normal) + ExprKind::If(_, _, _) | ExprKind::Match(_, _, hir::MatchSource::Normal) ) { check_expr(cx, exp); @@ -130,7 +130,7 @@ fn non_consuming_ok_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool { fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { match expr.kind { - hir::ExprKind::If(cond, _, _) + ExprKind::If(cond, _, _) if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind && is_ok_wild_or_dotdot_pattern(cx, pat) && let Some(op) = should_lint(cx, init) => @@ -140,7 +140,7 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { // we will capture only the case where the match is Ok( ) or Err( ) // prefer to match the minimum possible, and expand later if needed // to avoid false positives on something as used as this - hir::ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { + ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { if non_consuming_ok_arm(cx, arm1) && non_consuming_err_arm(cx, arm2) { emit_lint(cx, expr.span, expr.hir_id, op, &[arm1.pat.span]); } @@ -148,7 +148,7 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { emit_lint(cx, expr.span, expr.hir_id, op, &[arm2.pat.span]); } }, - hir::ExprKind::Match(_, _, hir::MatchSource::Normal) => {}, + ExprKind::Match(_, _, hir::MatchSource::Normal) => {}, _ if let Some(op) = should_lint(cx, expr) => { emit_lint(cx, expr.span, expr.hir_id, op, &[]); }, @@ -201,7 +201,7 @@ fn is_unreachable_or_panic(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { } fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind { + while let ExprKind::MethodCall(path, receiver, ..) = expr.kind { if matches!( path.ident.as_str(), "unwrap" | "expect" | "unwrap_or" | "unwrap_or_else" | "ok" | "is_ok" | "is_err" | "or_else" | "or" @@ -215,10 +215,10 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { } fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - while let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind + while let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind && matches!( func.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) + ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) ) { expr = arg_0; @@ -227,7 +227,7 @@ fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { } fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - while let hir::ExprKind::Match(res, _, _) = expr.kind { + while let ExprKind::Match(res, _, _) = expr.kind { expr = res; } expr @@ -236,11 +236,11 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> { - if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { - if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { + if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { + if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { if matches!( func.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) + ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) ) { return arg_0; } @@ -251,7 +251,7 @@ fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> { /// Check whether the current expr is a function call for an IO operation fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option { - let hir::ExprKind::MethodCall(path, ..) = call.kind else { + let ExprKind::MethodCall(path, ..) = call.kind else { return None; }; diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs index a615ef11691..aca500590ce 100644 --- a/clippy_lints/src/unwrap_in_result.rs +++ b/clippy_lints/src/unwrap_in_result.rs @@ -59,7 +59,7 @@ declare_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]); impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind + if let ImplItemKind::Fn(ref _signature, _) = impl_item.kind // first check if it's a method or function // checking if its return type is `result` or `option` && (is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b28037db112..10a69364dae 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx>) { if !hir_ty.span.from_expansion() && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { @@ -286,7 +286,7 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { walk_inf(self, inf); } - fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) { + fn visit_ty(&mut self, hir_ty: &Ty<'_>) { self.types_to_skip.push(hir_ty.hir_id); walk_ty(self, hir_ty); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 187bfda129c..538a748089e 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -747,7 +747,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } } -fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool { +fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { let attrs = cx.tcx.hir().attrs(hir_id); get_attr(cx.sess(), attrs, "author").count() > 0 } @@ -764,7 +764,7 @@ fn path_to_string(path: &QPath<'_>) -> Result { } }, QPath::TypeRelative(ty, segment) => match &ty.kind { - hir::TyKind::Path(inner_path) => { + TyKind::Path(inner_path) => { inner(s, inner_path)?; *s += ", "; write!(s, "{:?}", segment.ident.as_str()).unwrap(); diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs index 7c70d3f45db..f7529682675 100644 --- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs +++ b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq}; use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_hir::{Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -72,7 +71,7 @@ declare_clippy_lint! { declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]); impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) { return; } diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 1ebe1d6a2c4..d6a541a1eff 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -153,7 +153,7 @@ impl MetadataCollector { lints: BinaryHeap::::default(), applicability_info: FxHashMap::::default(), config: get_configuration_metadata(), - clippy_project_root: std::env::current_dir() + clippy_project_root: env::current_dir() .expect("failed to get current dir") .ancestors() .nth(1) @@ -243,7 +243,7 @@ Please use that command to update the file and do not edit it by hand. .unwrap(); // Write configuration links to CHANGELOG.md - let changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap(); + let changelog = fs::read_to_string(CHANGELOG_PATH).unwrap(); let mut changelog_file = File::create(CHANGELOG_PATH).unwrap(); let position = changelog .find("") @@ -912,7 +912,7 @@ impl<'a, 'hir> LintResolver<'a, 'hir> { } } -impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> { +impl<'a, 'hir> Visitor<'hir> for LintResolver<'a, 'hir> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { @@ -963,7 +963,7 @@ impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> { } } -impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { +impl<'a, 'hir> Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { @@ -1042,7 +1042,7 @@ impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> { } } -impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { +impl<'a, 'hir> Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index f4e277fd0c4..5fb643854dc 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -4,7 +4,6 @@ use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_ use rustc_ast::ast::LitKind; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::Applicability; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, Local, Mutability, Node}; @@ -49,7 +48,7 @@ pub struct UnnecessaryDefPath { } impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if is_lint_allowed(cx, UNNECESSARY_DEF_PATH, expr.hir_id) { return; } @@ -213,7 +212,7 @@ impl UnnecessaryDefPath { } } -fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option> { +fn path_to_matched_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option> { match peel_hir_expr_refs(expr).0.kind { ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 3874c1169e4..93b0913a6b7 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -97,8 +97,8 @@ pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { match (l, r) { - (GenericArgs::AngleBracketed(l), GenericArgs::AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg), - (GenericArgs::Parenthesized(l), GenericArgs::Parenthesized(r)) => { + (AngleBracketed(l), AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg), + (Parenthesized(l), Parenthesized(r)) => { over(&l.inputs, &r.inputs, |l, r| eq_ty(l, r)) && eq_fn_ret_ty(&l.output, &r.output) }, _ => false, @@ -304,25 +304,25 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), ( - Static(box ast::StaticItem { + Static(box StaticItem { ty: lt, mutability: lm, expr: le, }), - Static(box ast::StaticItem { + Static(box StaticItem { ty: rt, mutability: rm, expr: re, }), ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), ( - Const(box ast::ConstItem { + Const(box ConstItem { defaultness: ld, generics: lg, ty: lt, expr: le, }), - Const(box ast::ConstItem { + Const(box ConstItem { defaultness: rd, generics: rg, ty: rt, @@ -493,13 +493,13 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { ( - Const(box ast::ConstItem { + Const(box ConstItem { defaultness: ld, generics: lg, ty: lt, expr: le, }), - Const(box ast::ConstItem { + Const(box ConstItem { defaultness: rd, generics: rg, ty: rt, @@ -523,14 +523,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, ( - Type(box ast::TyAlias { + Type(box TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }), - Type(box ast::TyAlias { + Type(box TyAlias { defaultness: rd, generics: rg, bounds: rb, diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 046087d3298..cd22174f5c2 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -24,7 +24,7 @@ use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] pub enum Constant<'tcx> { - Adt(rustc_middle::mir::Const<'tcx>), + Adt(mir::Const<'tcx>), /// A `String` (e.g., "abc"). Str(String), /// A binary string (e.g., `b"abc"`). @@ -207,7 +207,7 @@ impl<'tcx> Constant<'tcx> { .zip(r) .zip(tys) .map(|((li, ri), cmp_type)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.map_or(true, |o| o != Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), _ => None, }, @@ -217,7 +217,7 @@ impl<'tcx> Constant<'tcx> { }; iter::zip(l, r) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.map_or(true, |o| o != Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))) }, (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => { @@ -361,7 +361,7 @@ pub enum FullInt { impl PartialEq for FullInt { #[must_use] fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal + self.cmp(other) == Equal } } @@ -579,7 +579,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it. fn fetch_path_and_apply(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option where - F: FnOnce(&mut Self, rustc_middle::mir::Const<'tcx>) -> Option, + F: FnOnce(&mut Self, mir::Const<'tcx>) -> Option, { let res = self.typeck_results.qpath_res(qpath, id); match res { @@ -612,7 +612,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() - .map(|val| rustc_middle::mir::Const::from_value(val, ty))?; + .map(|val| mir::Const::from_value(val, ty))?; f(self, result) }, _ => None, diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index ba682813dad..9f69941cfc7 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -16,11 +16,11 @@ use rustc_span::{sym, symbol, Span}; /// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`. pub struct ForLoop<'tcx> { /// `for` loop item - pub pat: &'tcx hir::Pat<'tcx>, + pub pat: &'tcx Pat<'tcx>, /// `IntoIterator` argument - pub arg: &'tcx hir::Expr<'tcx>, + pub arg: &'tcx Expr<'tcx>, /// `for` loop body - pub body: &'tcx hir::Expr<'tcx>, + pub body: &'tcx Expr<'tcx>, /// Compare this against `hir::Destination.target` pub loop_id: HirId, /// entire `for` loop span @@ -30,13 +30,13 @@ pub struct ForLoop<'tcx> { impl<'tcx> ForLoop<'tcx> { /// Parses a desugared `for` loop pub fn hir(expr: &Expr<'tcx>) -> Option { - if let hir::ExprKind::DropTemps(e) = expr.kind - && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind - && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind - && let hir::ExprKind::Loop(block, ..) = arm.body.kind + if let ExprKind::DropTemps(e) = expr.kind + && let ExprKind::Match(iterexpr, [arm], MatchSource::ForLoopDesugar) = e.kind + && let ExprKind::Call(_, [arg]) = iterexpr.kind + && let ExprKind::Loop(block, ..) = arm.body.kind && let [stmt] = block.stmts && let hir::StmtKind::Expr(e) = stmt.kind - && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind + && let ExprKind::Match(_, [_, some_arm], _) = e.kind && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind { return Some(Self { @@ -209,28 +209,28 @@ impl<'hir> IfOrIfLet<'hir> { #[derive(Debug, Copy, Clone)] pub struct Range<'a> { /// The lower bound of the range, or `None` for ranges such as `..X`. - pub start: Option<&'a hir::Expr<'a>>, + pub start: Option<&'a Expr<'a>>, /// The upper bound of the range, or `None` for ranges such as `X..`. - pub end: Option<&'a hir::Expr<'a>>, + pub end: Option<&'a Expr<'a>>, /// Whether the interval is open or closed. pub limits: ast::RangeLimits, } impl<'a> Range<'a> { /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. - pub fn hir(expr: &'a hir::Expr<'_>) -> Option> { + pub fn hir(expr: &'a Expr<'_>) -> Option> { /// Finds the field named `name` in the field. Always return `Some` for /// convenience. - fn get_field<'c>(name: &str, fields: &'c [hir::ExprField<'_>]) -> Option<&'c hir::Expr<'c>> { + fn get_field<'c>(name: &str, fields: &'c [hir::ExprField<'_>]) -> Option<&'c Expr<'c>> { let expr = &fields.iter().find(|field| field.ident.name.as_str() == name)?.expr; Some(expr) } match expr.kind { - hir::ExprKind::Call(path, args) + ExprKind::Call(path, args) if matches!( path.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..)) + ExprKind::Path(QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..)) ) => { Some(Range { @@ -239,28 +239,28 @@ impl<'a> Range<'a> { limits: ast::RangeLimits::Closed, }) }, - hir::ExprKind::Struct(path, fields, None) => match &path { - hir::QPath::LangItem(hir::LangItem::RangeFull, ..) => Some(Range { + ExprKind::Struct(path, fields, None) => match &path { + QPath::LangItem(hir::LangItem::RangeFull, ..) => Some(Range { start: None, end: None, limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::RangeFrom, ..) => Some(Range { + QPath::LangItem(hir::LangItem::RangeFrom, ..) => Some(Range { start: Some(get_field("start", fields)?), end: None, limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::Range, ..) => Some(Range { + QPath::LangItem(hir::LangItem::Range, ..) => Some(Range { start: Some(get_field("start", fields)?), end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::RangeToInclusive, ..) => Some(Range { + QPath::LangItem(hir::LangItem::RangeToInclusive, ..) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, }), - hir::QPath::LangItem(hir::LangItem::RangeTo, ..) => Some(Range { + QPath::LangItem(hir::LangItem::RangeTo, ..) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, @@ -275,17 +275,17 @@ impl<'a> Range<'a> { /// Represents the pre-expansion arguments of a `vec!` invocation. pub enum VecArgs<'a> { /// `vec![elem; len]` - Repeat(&'a hir::Expr<'a>, &'a hir::Expr<'a>), + Repeat(&'a Expr<'a>, &'a Expr<'a>), /// `vec![a, b, c]` - Vec(&'a [hir::Expr<'a>]), + Vec(&'a [Expr<'a>]), } impl<'a> VecArgs<'a> { /// Returns the arguments of the `vec!` macro if this expression was expanded /// from `vec!`. - pub fn hir(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option> { - if let hir::ExprKind::Call(fun, args) = expr.kind - && let hir::ExprKind::Path(ref qpath) = fun.kind + pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option> { + if let ExprKind::Call(fun, args) = expr.kind + && let ExprKind::Path(ref qpath) = fun.kind && is_expn_of(fun.span, "vec").is_some() && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() { @@ -294,8 +294,8 @@ impl<'a> VecArgs<'a> { Some(VecArgs::Repeat(&args[0], &args[1])) } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { // `vec![a, b, c]` case - if let hir::ExprKind::Call(_, [arg]) = &args[0].kind - && let hir::ExprKind::Array(args) = arg.kind + if let ExprKind::Call(_, [arg]) = &args[0].kind + && let ExprKind::Array(args) = arg.kind { Some(VecArgs::Vec(args)) } else { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d040fb28c63..a6faac62f1c 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -16,12 +16,14 @@ rustc::diagnostic_outside_of_impl, rustc::untranslatable_diagnostic )] -// warn on the same lints as `clippy_lints` -#![warn(trivial_casts, trivial_numeric_casts)] -// warn on lints, that are included in `rust-lang/rust`s bootstrap -#![warn(rust_2018_idioms, unused_lifetimes)] -// warn on rustc internal lints -#![warn(rustc::internal)] +#![warn( + trivial_casts, + trivial_numeric_casts, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications, + rustc::internal +)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) @@ -349,7 +351,7 @@ pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool /// refers to an item of the trait `Default`, which is associated with the /// `diag_item` of `sym::Default`. pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool { - if let hir::ExprKind::Path(ref qpath) = expr.kind { + if let ExprKind::Path(ref qpath) = expr.kind { cx.qpath_res(qpath, expr.hir_id) .opt_def_id() .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item)) @@ -723,8 +725,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); let parent_impl = cx.tcx.hir().get_parent_item(hir_id); if parent_impl != hir::CRATE_OWNER_ID - && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_impl.def_id) - && let hir::ItemKind::Impl(impl_) = &item.kind + && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_impl.def_id) + && let ItemKind::Impl(impl_) = &item.kind { return impl_.of_trait.as_ref(); } @@ -830,7 +832,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath< /// Returns true if the expr is equal to `Default::default` when evaluated. pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool { - if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind + if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() && (is_diag_trait_item(cx, repl_def_id, sym::Default) || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath)) @@ -1295,7 +1297,7 @@ pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext< /// Returns `true` if `expr` contains a return expression pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool { for_each_expr(expr, |e| { - if matches!(e.kind, hir::ExprKind::Ret(..)) { + if matches!(e.kind, ExprKind::Ret(..)) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) @@ -1311,7 +1313,7 @@ pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'t /// This retrieves the parent for the given `HirId` if it's an expression. This is useful for /// constraint lints -pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> { +pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { match cx.tcx.parent_hir_node(hir_id) { Node::Expr(parent) => Some(parent), _ => None, @@ -1635,13 +1637,13 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { } /// Convenience function to get the return type of a function. -pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId) -> Ty<'tcx> { +pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId) -> Ty<'tcx> { let ret_ty = cx.tcx.fn_sig(fn_def_id).instantiate_identity().output(); cx.tcx.instantiate_bound_regions_with_erased(ret_ty) } /// Convenience function to get the nth argument type of a function. -pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId, nth: usize) -> Ty<'tcx> { +pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) -> Ty<'tcx> { let arg = cx.tcx.fn_sig(fn_def_id).instantiate_identity().input(nth); cx.tcx.instantiate_bound_regions_with_erased(arg) } @@ -1652,8 +1654,8 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_ if let ExprKind::Path(ref qp) = fun.kind { let res = cx.qpath_res(qp, fun.hir_id); return match res { - def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, - def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), + Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, + Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), _ => false, }; } @@ -1667,7 +1669,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool { matches!( cx.qpath_res(qpath, id), - def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _) + Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _) ) } @@ -1823,26 +1825,26 @@ pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> { pat } -pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 { +pub fn int_bits(tcx: TyCtxt<'_>, ity: IntTy) -> u64 { Integer::from_int_ty(&tcx, ity).size().bits() } #[expect(clippy::cast_possible_wrap)] /// Turn a constant int byte representation into an i128 -pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 { +pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } #[expect(clippy::cast_sign_loss)] /// clip unused bytes -pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 { +pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); ((u as u128) << amt) >> amt } /// clip unused bytes -pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 { +pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 { let bits = Integer::from_uint_ty(&tcx, ity).size().bits(); let amt = 128 - bits; (u << amt) >> amt @@ -2007,7 +2009,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { ExprKind::Call(path, _) => { if let ExprKind::Path(ref qpath) = path.kind - && let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) + && let Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) { Some(did) } else { @@ -2218,7 +2220,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { /// ``` pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool { if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) { - matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) + matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) } else { false } @@ -2254,7 +2256,7 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { pub fn fn_def_id_with_node_args<'tcx>( cx: &LateContext<'tcx>, expr: &Expr<'_>, -) -> Option<(DefId, rustc_ty::GenericArgsRef<'tcx>)> { +) -> Option<(DefId, GenericArgsRef<'tcx>)> { let typeck = cx.typeck_results(); match &expr.kind { ExprKind::MethodCall(..) => Some(( @@ -2500,7 +2502,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym /// Checks if the function containing the given `HirId` is a `#[test]` function /// /// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function -pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { +pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { with_test_item_names(tcx, tcx.parent_module(id), |names| { tcx.hir() .parent_iter(id) @@ -2523,7 +2525,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { /// /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent /// use [`is_in_cfg_test`] -pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { +pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir().attrs(id).iter().any(|attr| { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() @@ -2538,7 +2540,7 @@ pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { } /// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied -pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { +pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir() .parent_id_iter(id) .any(|parent_id| is_cfg_test(tcx, parent_id)) diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index c475e7b7c43..f166087dc3c 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -429,7 +429,7 @@ pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) pub fn find_format_arg_expr<'hir, 'ast>( start: &'hir Expr<'hir>, target: &'ast FormatArgument, -) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> { +) -> Result<&'hir Expr<'hir>, &'ast rustc_ast::Expr> { let SpanData { lo, hi, diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index 9dbb4c68d13..e4966690d8c 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -111,7 +111,7 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool { } /// Convenience wrapper around `visit_local_usage`. -pub fn used_exactly_once(mir: &Body<'_>, local: rustc_middle::mir::Local) -> Option { +pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option { visit_local_usage( &[local], mir, diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 5090d0bd98b..18949faf022 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -41,7 +41,7 @@ pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); pub const EMPTY: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("")); impl Display for Sugg<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) => s.fmt(f), Sugg::BinOp(op, ref lhs, ref rhs) => binop_to_string(op, lhs, rhs).fmt(f), @@ -124,48 +124,48 @@ impl<'a> Sugg<'a> { } match expr.kind { - hir::ExprKind::AddrOf(..) - | hir::ExprKind::If(..) - | hir::ExprKind::Let(..) - | hir::ExprKind::Closure { .. } - | hir::ExprKind::Unary(..) - | hir::ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)), - hir::ExprKind::Continue(..) - | hir::ExprKind::Yield(..) - | hir::ExprKind::Array(..) - | hir::ExprKind::Block(..) - | hir::ExprKind::Break(..) - | hir::ExprKind::Call(..) - | hir::ExprKind::Field(..) - | hir::ExprKind::Index(..) - | hir::ExprKind::InlineAsm(..) - | hir::ExprKind::OffsetOf(..) - | hir::ExprKind::ConstBlock(..) - | hir::ExprKind::Lit(..) - | hir::ExprKind::Loop(..) - | hir::ExprKind::MethodCall(..) - | hir::ExprKind::Path(..) - | hir::ExprKind::Repeat(..) - | hir::ExprKind::Ret(..) - | hir::ExprKind::Become(..) - | hir::ExprKind::Struct(..) - | hir::ExprKind::Tup(..) - | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), - hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet), - hir::ExprKind::Assign(lhs, rhs, _) => { + ExprKind::AddrOf(..) + | ExprKind::If(..) + | ExprKind::Let(..) + | ExprKind::Closure { .. } + | ExprKind::Unary(..) + | ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)), + ExprKind::Continue(..) + | ExprKind::Yield(..) + | ExprKind::Array(..) + | ExprKind::Block(..) + | ExprKind::Break(..) + | ExprKind::Call(..) + | ExprKind::Field(..) + | ExprKind::Index(..) + | ExprKind::InlineAsm(..) + | ExprKind::OffsetOf(..) + | ExprKind::ConstBlock(..) + | ExprKind::Lit(..) + | ExprKind::Loop(..) + | ExprKind::MethodCall(..) + | ExprKind::Path(..) + | ExprKind::Repeat(..) + | ExprKind::Ret(..) + | ExprKind::Become(..) + | ExprKind::Struct(..) + | ExprKind::Tup(..) + | ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), + ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet), + ExprKind::Assign(lhs, rhs, _) => { Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) }, - hir::ExprKind::AssignOp(op, lhs, rhs) => { + ExprKind::AssignOp(op, lhs, rhs) => { Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span)) }, - hir::ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( + ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( AssocOp::from_ast_binop(op.node), get_snippet(lhs.span), get_snippet(rhs.span), ), - hir::ExprKind::Cast(lhs, ty) | + ExprKind::Cast(lhs, ty) | //FIXME(chenyukang), remove this after type ascription is removed from AST - hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)), + ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)), } } @@ -508,7 +508,7 @@ impl ParenHelper { } impl Display for ParenHelper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { if self.paren { write!(f, "({})", self.wrapped) } else { @@ -801,7 +801,7 @@ pub struct DerefClosure { /// /// note: this only works on single line immutable closures with exactly one input parameter. pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option { - if let hir::ExprKind::Closure(&Closure { + if let ExprKind::Closure(&Closure { fn_decl, def_id, body, .. }) = closure.kind { diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 6e011a28bb7..a2595580eaf 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -91,7 +91,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return true; } - if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() { + if let ty::Alias(ty::Opaque, AliasTy { def_id, .. }) = *inner_ty.kind() { if !seen.insert(def_id) { return false; } @@ -301,7 +301,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( cause: ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), + predicate: Binder::dummy(trait_ref).to_predicate(tcx), }; infcx .evaluate_obligation(&obligation) @@ -327,7 +327,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { is_must_use_ty(cx, *ty) }, ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), - ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { + ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { @@ -356,13 +356,13 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // not succeed /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. -pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { +pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { is_normalizable_helper(cx, param_env, ty, &mut FxHashMap::default()) } fn is_normalizable_helper<'tcx>( cx: &LateContext<'tcx>, - param_env: ty::ParamEnv<'tcx>, + param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, cache: &mut FxHashMap, bool>, ) -> bool { @@ -372,7 +372,7 @@ fn is_normalizable_helper<'tcx>( // prevent recursive loops, false-negative is better than endless loop leading to stack overflow cache.insert(ty, false); let infcx = cx.tcx.infer_ctxt().build(); - let cause = rustc_middle::traits::ObligationCause::dummy(); + let cause = ObligationCause::dummy(); let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() { match ty.kind() { ty::Adt(def, args) => def.variants().iter().all(|variant| { @@ -446,7 +446,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb /// Checks if the type is equal to a lang item. /// /// Returns `false` if the `LangItem` is not defined. -pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool { +pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: LangItem) -> bool { match ty.kind() { ty::Adt(adt, _) => cx.tcx.lang_items().get(lang_item) == Some(adt.did()), _ => false, @@ -726,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).instantiate(cx.tcx, subs), Some(id))), - ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => sig_from_bounds( + ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) => sig_from_bounds( cx, ty, cx.tcx.item_bounds(def_id).iter_instantiated(cx.tcx, args), @@ -899,7 +899,7 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { if let ty::Adt(adt, _) = ty.kind() && let &[krate, .., name] = &*cx.get_def_path(adt.did()) && let sym::libc | sym::core | sym::std = krate - && name == rustc_span::sym::c_void + && name == sym::c_void { true } else { @@ -1134,7 +1134,7 @@ pub fn make_projection<'tcx>( #[cfg(debug_assertions)] assert_generic_args_match(tcx, assoc_item.def_id, args); - Some(ty::AliasTy::new(tcx, assoc_item.def_id, args)) + Some(AliasTy::new(tcx, assoc_item.def_id, args)) } helper( tcx, @@ -1251,7 +1251,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( ); return None; } - let cause = rustc_middle::traits::ObligationCause::dummy(); + let cause = ObligationCause::dummy(); match tcx .infer_ctxt() .build() @@ -1269,7 +1269,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( } pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - let cause = rustc_middle::traits::ObligationCause::dummy(); + let cause = ObligationCause::dummy(); match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) { Ok(ty) => ty.value, Err(_) => ty, diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index ec131c7f6a3..a145920aa85 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -83,15 +83,15 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { self.update(cmt); } - fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} + fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} } pub struct ParamBindingIdCollector { - pub binding_hir_ids: Vec, + pub binding_hir_ids: Vec, } impl<'tcx> ParamBindingIdCollector { - fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec { - let mut hir_ids: Vec = Vec::new(); + fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec { + let mut hir_ids: Vec = Vec::new(); for param in body.params { let mut finder = ParamBindingIdCollector { binding_hir_ids: Vec::new(), @@ -104,7 +104,7 @@ impl<'tcx> ParamBindingIdCollector { hir_ids } } -impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector { +impl<'tcx> Visitor<'tcx> for ParamBindingIdCollector { fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind { self.binding_hir_ids.push(hir_id); @@ -115,7 +115,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector { pub struct BindingUsageFinder<'a, 'tcx> { cx: &'a LateContext<'tcx>, - binding_ids: Vec, + binding_ids: Vec, usage_found: bool, } impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> { @@ -129,16 +129,16 @@ impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> { finder.usage_found } } -impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { if !self.usage_found { intravisit::walk_expr(self, expr); } } - fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) { if let Res::Local(id) = path.res { if self.binding_ids.contains(&id) { self.usage_found = true; diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index ebc38e531fe..a4c06c0e637 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -180,9 +180,9 @@ pub fn for_each_expr_with_closures<'tcx, B, C: Continue>( } /// returns `true` if expr contains match expr desugared from try -fn contains_try(expr: &hir::Expr<'_>) -> bool { +fn contains_try(expr: &Expr<'_>) -> bool { for_each_expr(expr, |e| { - if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) { + if matches!(e.kind, ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) @@ -191,9 +191,9 @@ fn contains_try(expr: &hir::Expr<'_>) -> bool { .is_some() } -pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool +pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir Expr<'hir>, callback: F) -> bool where - F: FnMut(&'hir hir::Expr<'hir>) -> bool, + F: FnMut(&'hir Expr<'hir>) -> bool, { struct RetFinder { in_stmt: bool, @@ -236,37 +236,37 @@ where } } - impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder { - fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) { + impl<'hir, F: FnMut(&'hir Expr<'hir>) -> bool> Visitor<'hir> for RetFinder { + fn visit_stmt(&mut self, stmt: &'hir Stmt<'_>) { intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt); } - fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) { + fn visit_expr(&mut self, expr: &'hir Expr<'_>) { if self.failed { return; } if self.in_stmt { match expr.kind { - hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr), - _ => intravisit::walk_expr(self, expr), + ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr), + _ => walk_expr(self, expr), } } else { match expr.kind { - hir::ExprKind::If(cond, then, else_opt) => { + ExprKind::If(cond, then, else_opt) => { self.inside_stmt(true).visit_expr(cond); self.visit_expr(then); if let Some(el) = else_opt { self.visit_expr(el); } }, - hir::ExprKind::Match(cond, arms, _) => { + ExprKind::Match(cond, arms, _) => { self.inside_stmt(true).visit_expr(cond); for arm in arms { self.visit_expr(arm.body); } }, - hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr), - hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr), + ExprKind::Block(..) => walk_expr(self, expr), + ExprKind::Ret(Some(expr)) => self.visit_expr(expr), _ => self.failed |= !(self.cb)(expr), } } @@ -316,7 +316,7 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> is_const: bool, } impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { - type NestedFilter = rustc_hir::intravisit::nested_filter::None; + type NestedFilter = intravisit::nested_filter::None; fn visit_expr(&mut self, e: &'tcx Expr<'_>) { if !self.is_const { diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 66442998161..4251151c454 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -5,6 +5,13 @@ // When a new lint is introduced, we can search the results for new warnings and check for false // positives. +#![warn( + trivial_casts, + trivial_numeric_casts, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications +)] #![allow(clippy::collapsible_else_if)] mod config; @@ -189,13 +196,13 @@ impl CrateSource { // don't download/extract if we already have done so if !krate_file_path.is_file() { // create a file path to download and write the crate data into - let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap(); + let mut krate_dest = fs::File::create(&krate_file_path).unwrap(); let mut krate_req = get(&url).unwrap().into_reader(); // copy the crate into the file - std::io::copy(&mut krate_req, &mut krate_dest).unwrap(); + io::copy(&mut krate_req, &mut krate_dest).unwrap(); // unzip the tarball - let ungz_tar = flate2::read::GzDecoder::new(std::fs::File::open(&krate_file_path).unwrap()); + let ungz_tar = flate2::read::GzDecoder::new(fs::File::open(&krate_file_path).unwrap()); // extract the tar archive let mut archive = tar::Archive::new(ungz_tar); archive.unpack(&extract_dir).expect("Failed to extract!"); @@ -257,7 +264,7 @@ impl CrateSource { }, CrateSource::Path { name, path, options } => { fn is_cache_dir(entry: &DirEntry) -> bool { - std::fs::read(entry.path().join("CACHEDIR.TAG")) + fs::read(entry.path().join("CACHEDIR.TAG")) .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) .unwrap_or(false) } @@ -268,7 +275,7 @@ impl CrateSource { let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name); if dest_crate_root.exists() { println!("Deleting existing directory at {dest_crate_root:?}"); - std::fs::remove_dir_all(&dest_crate_root).unwrap(); + fs::remove_dir_all(&dest_crate_root).unwrap(); } println!("Copying {path:?} to {dest_crate_root:?}"); @@ -281,9 +288,9 @@ impl CrateSource { let metadata = entry_path.symlink_metadata().unwrap(); if metadata.is_dir() { - std::fs::create_dir(dest_path).unwrap(); + fs::create_dir(dest_path).unwrap(); } else if metadata.is_file() { - std::fs::copy(entry_path, dest_path).unwrap(); + fs::copy(entry_path, dest_path).unwrap(); } } @@ -330,7 +337,7 @@ impl Crate { ); } - let cargo_clippy_path = std::fs::canonicalize(cargo_clippy_path).unwrap(); + let cargo_clippy_path = fs::canonicalize(cargo_clippy_path).unwrap(); let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir"); @@ -353,7 +360,7 @@ impl Crate { clippy_args.push("--cap-lints=warn"); } else { clippy_args.push("--cap-lints=allow"); - clippy_args.extend(lint_filter.iter().map(std::string::String::as_str)); + clippy_args.extend(lint_filter.iter().map(String::as_str)); } if let Some(server) = server { @@ -454,7 +461,7 @@ fn build_clippy() { /// Read a `lintcheck_crates.toml` file fn read_crates(toml_path: &Path) -> (Vec, RecursiveOptions) { let toml_content: String = - std::fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display())); + fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display())); let crate_list: SourceList = toml::from_str(&toml_content).unwrap_or_else(|e| panic!("Failed to parse {}: \n{e}", toml_path.display())); // parse the hashmap of the toml file into a list of crates @@ -549,7 +556,7 @@ fn main() { } // assert that we launch lintcheck from the repo root (via cargo lintcheck) - if std::fs::metadata("lintcheck/Cargo.toml").is_err() { + if fs::metadata("lintcheck/Cargo.toml").is_err() { eprintln!("lintcheck needs to be run from clippy's repo root!\nUse `cargo lintcheck` alternatively."); std::process::exit(3); } @@ -570,7 +577,7 @@ fn main() { cargo_clippy_path.display() ); - let clippy_ver = std::process::Command::new(&cargo_clippy_path) + let clippy_ver = Command::new(&cargo_clippy_path) .arg("--version") .output() .map(|o| String::from_utf8_lossy(&o.stdout).into_owned()) @@ -699,7 +706,7 @@ fn main() { /// read the previous stats from the lintcheck-log file fn read_stats_from_file(file_path: &Path) -> HashMap { - let file_content: String = match std::fs::read_to_string(file_path).ok() { + let file_content: String = match fs::read_to_string(file_path).ok() { Some(content) => content, None => { return HashMap::new(); @@ -779,17 +786,17 @@ fn print_stats(old_stats: HashMap, new_stats: HashMap<&String, us /// /// This function panics if creating one of the dirs fails. fn create_dirs(krate_download_dir: &Path, extract_dir: &Path) { - std::fs::create_dir("target/lintcheck/").unwrap_or_else(|err| { + fs::create_dir("target/lintcheck/").unwrap_or_else(|err| { assert_eq!( err.kind(), ErrorKind::AlreadyExists, "cannot create lintcheck target dir" ); }); - std::fs::create_dir(krate_download_dir).unwrap_or_else(|err| { + fs::create_dir(krate_download_dir).unwrap_or_else(|err| { assert_eq!(err.kind(), ErrorKind::AlreadyExists, "cannot create crate download dir"); }); - std::fs::create_dir(extract_dir).unwrap_or_else(|err| { + fs::create_dir(extract_dir).unwrap_or_else(|err| { assert_eq!( err.kind(), ErrorKind::AlreadyExists, @@ -816,7 +823,7 @@ fn lintcheck_test() { "--crates-toml", "lintcheck/test_sources.toml", ]; - let status = std::process::Command::new(env::var("CARGO").unwrap_or("cargo".into())) + let status = Command::new(env::var("CARGO").unwrap_or("cargo".into())) .args(args) .current_dir("..") // repo root .status(); From bd9efd5265115956d9a0eec09c34f95898643603 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Mar 2024 17:50:31 +0100 Subject: [PATCH 26/79] Rename `hir::Local` into `hir::LetStmt` --- clippy_lints/src/box_default.rs | 4 ++-- clippy_lints/src/collection_is_never_read.rs | 6 +++--- clippy_lints/src/let_underscore.rs | 4 ++-- clippy_lints/src/let_with_type_underscore.rs | 4 ++-- clippy_lints/src/loops/utils.rs | 4 ++-- clippy_lints/src/loops/while_let_loop.rs | 4 ++-- clippy_lints/src/loops/while_let_on_iterator.rs | 4 ++-- clippy_lints/src/manual_hash_one.rs | 4 ++-- .../src/matches/infallible_destructuring_match.rs | 4 ++-- clippy_lints/src/matches/mod.rs | 4 ++-- clippy_lints/src/methods/needless_collect.rs | 4 ++-- clippy_lints/src/methods/str_splitn.rs | 4 ++-- clippy_lints/src/mixed_read_write_in_expression.rs | 4 ++-- clippy_lints/src/mut_key.rs | 2 +- clippy_lints/src/needless_late_init.rs | 10 +++++----- clippy_lints/src/question_mark.rs | 4 ++-- clippy_lints/src/read_zero_byte_vec.rs | 4 ++-- clippy_lints/src/redundant_locals.rs | 4 ++-- clippy_lints/src/redundant_type_annotations.rs | 2 +- clippy_lints/src/reserve_after_initialization.rs | 4 ++-- clippy_lints/src/types/mod.rs | 4 ++-- clippy_lints/src/undocumented_unsafe_blocks.rs | 8 ++++---- clippy_lints/src/unit_types/let_unit_value.rs | 4 ++-- clippy_lints/src/unit_types/mod.rs | 4 ++-- clippy_lints/src/unused_peekable.rs | 4 ++-- clippy_lints/src/vec.rs | 6 +++--- clippy_lints/src/vec_init_then_push.rs | 4 ++-- clippy_utils/src/lib.rs | 14 +++++++------- 28 files changed, 66 insertions(+), 66 deletions(-) diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index 66206d1a059..a950de4bd22 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -6,7 +6,7 @@ use clippy_utils::{is_default_equivalent, path_def_id}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_ty, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, Ty, TyKind}; +use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -139,7 +139,7 @@ impl<'tcx> Visitor<'tcx> for InferVisitor { fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match cx.tcx.parent_hir_node(expr.hir_id) { - Node::Local(Local { ty: Some(ty), .. }) => { + Node::Local(LetStmt { ty: Some(ty), .. }) => { let mut v = InferVisitor::default(); v.visit_ty(ty); !v.0 diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index d820413e111..e921b9b46a6 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::for_each_expr_with_closures; use clippy_utils::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; -use rustc_hir::{Block, ExprKind, HirId, LangItem, Local, Node, PatKind}; +use rustc_hir::{Block, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -58,7 +58,7 @@ static COLLECTIONS: [Symbol; 9] = [ ]; impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { // Look for local variables whose type is a container. Search surrounding bock for read access. if match_acceptable_type(cx, local, &COLLECTIONS) && let PatKind::Binding(_, local_id, _, _) = local.pat.kind @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { } } -fn match_acceptable_type(cx: &LateContext<'_>, local: &Local<'_>, collections: &[rustc_span::Symbol]) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[rustc_span::Symbol]) -> bool { let ty = cx.typeck_results().pat_ty(local.pat); collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) // String type is a lang item but not a diagnostic item for now so we need a separate check diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 0ea53c39280..619e933b4ff 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths}; -use rustc_hir::{Local, LocalSource, PatKind}; +use rustc_hir::{LetStmt, LocalSource, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{GenericArgKind, IsSuggestable}; @@ -138,7 +138,7 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [ ]; impl<'tcx> LateLintPass<'tcx> for LetUnderscore { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) { if matches!(local.source, LocalSource::Normal) && !in_external_macro(cx.tcx.sess, local.span) && let PatKind::Wild = local.pat.kind diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 5f3f9b43f45..593b29154b4 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; -use rustc_hir::{Local, TyKind}; +use rustc_hir::{LetStmt, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; @@ -26,7 +26,7 @@ declare_clippy_lint! { declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); impl LateLintPass<'_> for UnderscoreTyped { - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &LetStmt<'_>) { if !in_external_macro(cx.tcx.sess, local.span) && let Some(ty) = local.ty // Ensure that it has a type defined && let TyKind::Infer = &ty.kind // that type is '_' diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs index 8bca33754e8..7b45cc95431 100644 --- a/clippy_lints/src/loops/utils.rs +++ b/clippy_lints/src/loops/utils.rs @@ -3,7 +3,7 @@ use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_loc use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_local, Visitor}; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, PatKind}; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; @@ -141,7 +141,7 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn visit_local(&mut self, l: &'tcx Local<'_>) { + fn visit_local(&mut self, l: &'tcx LetStmt<'_>) { // Look for declarations of the variable if l.pat.hir_id == self.var_id && let PatKind::Binding(.., ident, _) = l.pat.kind diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index 93774b89768..bd04827a1f0 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -5,13 +5,13 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::any_temporaries_need_ordered_drop; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, Local, MatchSource, Pat, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, StmtKind}; use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { ([stmt, stmts @ ..], expr) => { - if let StmtKind::Let(&Local { + if let StmtKind::Let(&LetStmt { init: Some(e), els: None, .. diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index d070ee74985..194dd4752f9 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -6,7 +6,7 @@ use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutabl use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp}; +use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, LetStmt, Mutability, PatKind, UnOp}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::ty::adjustment::Adjust; @@ -286,7 +286,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: & self.cx.tcx.hir() } - fn visit_local(&mut self, l: &'tcx Local<'_>) { + fn visit_local(&mut self, l: &'tcx LetStmt<'_>) { if !self.after_loop { l.pat.each_binding_or_first(&mut |_, id, _, _| { if id == self.local_id { diff --git a/clippy_lints/src/manual_hash_one.rs b/clippy_lints/src/manual_hash_one.rs index 5cbab0ec977..f8f33cfc82e 100644 --- a/clippy_lints/src/manual_hash_one.rs +++ b/clippy_lints/src/manual_hash_one.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_opt; use clippy_utils::visitors::{is_local_used, local_used_once}; use clippy_utils::{is_trait_method, path_to_local_id}; use rustc_errors::Applicability; -use rustc_hir::{BindingAnnotation, ExprKind, Local, Node, PatKind, StmtKind}; +use rustc_hir::{BindingAnnotation, ExprKind, LetStmt, Node, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -60,7 +60,7 @@ impl ManualHashOne { impl_lint_pass!(ManualHashOne => [MANUAL_HASH_ONE]); impl LateLintPass<'_> for ManualHashOne { - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &LetStmt<'_>) { // `let mut hasher = seg.build_hasher();` if let PatKind::Binding(BindingAnnotation::MUT, hasher, _, None) = local.pat.kind && let Some(init) = local.init diff --git a/clippy_lints/src/matches/infallible_destructuring_match.rs b/clippy_lints/src/matches/infallible_destructuring_match.rs index c8a48246e67..0f242e0b9e1 100644 --- a/clippy_lints/src/matches/infallible_destructuring_match.rs +++ b/clippy_lints/src/matches/infallible_destructuring_match.rs @@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs}; use rustc_errors::Applicability; -use rustc_hir::{ByRef, ExprKind, Local, MatchSource, PatKind, QPath}; +use rustc_hir::{ByRef, ExprKind, LetStmt, MatchSource, PatKind, QPath}; use rustc_lint::LateContext; use super::INFALLIBLE_DESTRUCTURING_MATCH; -pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool { +pub(crate) fn check(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool { if !local.span.from_expansion() && let Some(expr) = local.init && let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 50494f4819f..580d4a64296 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -27,7 +27,7 @@ mod wild_in_or_pats; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_opt, walk_span_to_context}; use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text}; -use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat}; +use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat}; use rustc_lexer::TokenKind; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -1124,7 +1124,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { } } - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { self.infallible_destructuring_match_linted |= local.els.is_none() && infallible_destructuring_match::check(cx, local); } diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 78540353005..378644c53c0 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{ - BindingAnnotation, Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind, + BindingAnnotation, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, PatKind, Stmt, StmtKind, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -424,7 +424,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> match stmt.kind { StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some((expr, None)), StmtKind::Item(..) => None, - StmtKind::Let(Local { init, pat, .. }) => { + StmtKind::Let(LetStmt { init, pat, .. }) => { if let PatKind::Binding(_, hir_id, ..) = pat.kind { init.map(|init_expr| (init_expr, Some(hir_id))) } else { diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 55cd1a38ec9..94e263cf3d1 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -8,7 +8,7 @@ use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths} use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{ - BindingAnnotation, Expr, ExprKind, HirId, LangItem, Local, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind, + BindingAnnotation, Expr, ExprKind, HirId, LangItem, LetStmt, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind, }; use rustc_lint::LateContext; use rustc_middle::ty; @@ -198,7 +198,7 @@ fn indirect_usage<'tcx>( binding: HirId, ctxt: SyntaxContext, ) -> Option> { - if let StmtKind::Let(&Local { + if let StmtKind::Let(&LetStmt { pat: Pat { kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None), .. diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 12c7c18afde..656fb907fcd 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Local, Node, Stmt, StmtKind}; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { StmtKind::Let(local) => { - if let Local { init: Some(e), .. } = local { + if let LetStmt { init: Some(e), .. } = local { DivergenceVisitor { cx }.visit_expr(e); } }, diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index c32025fcbb6..79f0a398d55 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::LetStmt<'_>) { if let hir::PatKind::Wild = local.pat.kind { return; } diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs index 4cda4b171e3..810799acb2e 100644 --- a/clippy_lints/src/needless_late_init.rs +++ b/clippy_lints/src/needless_late_init.rs @@ -6,7 +6,7 @@ use clippy_utils::visitors::{for_each_expr, for_each_expr_with_closures, is_loca use core::ops::ControlFlow; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::{ - BindingAnnotation, Block, Expr, ExprKind, HirId, Local, LocalSource, MatchSource, Node, Pat, PatKind, Stmt, + BindingAnnotation, Block, Expr, ExprKind, HirId, LetStmt, LocalSource, MatchSource, Node, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; @@ -237,7 +237,7 @@ fn first_usage<'tcx>( }) } -fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &Local<'_>) -> Option { +fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option { let span = local.span.with_hi(match local.ty { // let : ; // ~~~~~~~~~~~~~~~ @@ -252,7 +252,7 @@ fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &Local<'_>) -> O fn check<'tcx>( cx: &LateContext<'tcx>, - local: &'tcx Local<'tcx>, + local: &'tcx LetStmt<'tcx>, local_stmt: &'tcx Stmt<'tcx>, block: &'tcx Block<'tcx>, binding_id: HirId, @@ -363,9 +363,9 @@ fn check<'tcx>( } impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { let mut parents = cx.tcx.hir().parent_iter(local.hir_id); - if let Local { + if let LetStmt { init: None, pat: &Pat { diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 831c291ed7c..f1db571e113 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -14,7 +14,7 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - BindingAnnotation, Block, ByRef, Expr, ExprKind, Local, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, + BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -109,7 +109,7 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir } fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if let StmtKind::Let(Local { + if let StmtKind::Let(LetStmt { pat, init: Some(init_expr), els: Some(els), diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index 0ebdb031d5a..7f4735c6a88 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -3,7 +3,7 @@ use clippy_utils::get_enclosing_block; use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; use clippy_utils::source::snippet; -use hir::{Expr, ExprKind, HirId, Local, PatKind, PathSegment, QPath, StmtKind}; +use hir::{Expr, ExprKind, HirId, LetStmt, PatKind, PathSegment, QPath, StmtKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { } if let StmtKind::Let(local) = stmt.kind - && let Local { + && let LetStmt { pat, init: Some(init), .. } = local && let PatKind::Binding(_, id, ident, _) = pat.kind diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs index 6528a7b369f..0f579f779df 100644 --- a/clippy_lints/src/redundant_locals.rs +++ b/clippy_lints/src/redundant_locals.rs @@ -3,7 +3,7 @@ use clippy_utils::is_from_proc_macro; use clippy_utils::ty::needs_ordered_drop; use rustc_ast::Mutability; use rustc_hir::def::Res; -use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, Local, Node, Pat, PatKind, QPath}; +use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, LetStmt, Node, Pat, PatKind, QPath}; use rustc_hir_typeck::expr_use_visitor::PlaceBase; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -47,7 +47,7 @@ declare_clippy_lint! { declare_lint_pass!(RedundantLocals => [REDUNDANT_LOCALS]); impl<'tcx> LateLintPass<'tcx> for RedundantLocals { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if !local.span.is_desugaring(DesugaringKind::Async) // the pattern is a single by-value binding && let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index 079e6500e3c..96f6f0ec36f 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -131,7 +131,7 @@ fn extract_primty(ty_kind: &hir::TyKind<'_>) -> Option { } impl LateLintPass<'_> for RedundantTypeAnnotations { - fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) { + fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::LetStmt<'tcx>) { if !is_lint_allowed(cx, REDUNDANT_TYPE_ANNOTATIONS, local.hir_id) // type annotation part && !local.span.from_expansion() diff --git a/clippy_lints/src/reserve_after_initialization.rs b/clippy_lints/src/reserve_after_initialization.rs index ca7a0c7c87b..c227b5b22f4 100644 --- a/clippy_lints/src/reserve_after_initialization.rs +++ b/clippy_lints/src/reserve_after_initialization.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use clippy_utils::{is_from_proc_macro, path_to_local_id}; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Local, PatKind, QPath, Stmt, StmtKind}; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; @@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for ReserveAfterInitialization { self.searcher = None; } - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if let Some(init_expr) = local.init && let PatKind::Binding(BindingAnnotation::MUT, id, _, None) = local.pat.kind && !in_external_macro(cx.sess(), local.span) diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 2ad15ac8312..0802cb2b7c7 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -12,7 +12,7 @@ mod vec_box; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem, + Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MutTy, QPath, TraitItem, TraitItemKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; @@ -425,7 +425,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) { if let Some(ty) = local.ty { self.check_ty( cx, diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 0efa65b28e2..fe3888d09c9 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -158,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &hir::Stmt<'tcx>) { - let (hir::StmtKind::Let(&hir::Local { init: Some(expr), .. }) + let (hir::StmtKind::Let(&hir::LetStmt { init: Some(expr), .. }) | hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr)) = stmt.kind else { @@ -342,7 +342,7 @@ fn block_parents_have_safety_comment( ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { - Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id), + Node::Local(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, @@ -358,12 +358,12 @@ fn block_parents_have_safety_comment( }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Let(hir::Local { span, hir_id, .. }) + hir::StmtKind::Let(hir::LetStmt { span, hir_id, .. }) | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. }) - | Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id), + | Node::Local(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 9406d160769..c11acab98c0 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -4,14 +4,14 @@ use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, Local, MatchSource, Node, PatKind, QPath, TyKind}; +use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, LetStmt, MatchSource, Node, PatKind, QPath, TyKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::{in_external_macro, is_from_async_await}; use rustc_middle::ty; use super::LET_UNIT_VALUE; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { // skip `let () = { ... }` if let PatKind::Tuple(fields, ..) = local.pat.kind && fields.is_empty() diff --git a/clippy_lints/src/unit_types/mod.rs b/clippy_lints/src/unit_types/mod.rs index 0abd48e6423..e016bd3434b 100644 --- a/clippy_lints/src/unit_types/mod.rs +++ b/clippy_lints/src/unit_types/mod.rs @@ -3,7 +3,7 @@ mod unit_arg; mod unit_cmp; mod utils; -use rustc_hir::{Expr, Local}; +use rustc_hir::{Expr, LetStmt}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -99,7 +99,7 @@ declare_clippy_lint! { declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]); impl<'tcx> LateLintPass<'tcx> for UnitTypes { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { let_unit_value::check(cx, local); } diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index 3f4ab3e31cf..e152a0e8343 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable}; use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators}; use rustc_ast::Mutability; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, HirId, LetStmt, Node, PatKind, PathSegment, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_session::declare_lint_pass; @@ -190,7 +190,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { }, } }, - Node::Local(Local { init: Some(init), .. }) => { + Node::Local(LetStmt { init: Some(init), .. }) => { if arg_is_mut_peekable(self.cx, init) { self.found_peek_call = true; } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 7cfcf3fe946..fba96b630a0 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -9,7 +9,7 @@ use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{get_parent_expr, higher, is_trait_method}; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Local, Mutability, Node, Pat, PatKind}; +use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf; @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { match cx.tcx.parent_hir_node(expr.hir_id) { // search for `let foo = vec![_]` expressions where all uses of `foo` // adjust to slices or call a method that exist on slices (e.g. len) - Node::Local(Local { + Node::Local(LetStmt { ty: None, pat: Pat { @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } }, // if the local pattern has a specified type, do not lint. - Node::Local(Local { ty: Some(_), .. }) if higher::VecArgs::hir(cx, expr).is_some() => { + Node::Local(LetStmt { ty: Some(_), .. }) if higher::VecArgs::hir(cx, expr).is_some() => { self.span_to_lint_map.insert(callsite, None); }, // search for `for _ in vec![...]` diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs index ac3b2bdaf65..b58a4fb8474 100644 --- a/clippy_lints/src/vec_init_then_push.rs +++ b/clippy_lints/src/vec_init_then_push.rs @@ -7,7 +7,7 @@ use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - BindingAnnotation, Block, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, Stmt, StmtKind, UnOp, + BindingAnnotation, Block, Expr, ExprKind, HirId, LetStmt, Mutability, PatKind, QPath, Stmt, StmtKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { self.searcher = None; } - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if let Some(init_expr) = local.init && let PatKind::Binding(BindingAnnotation::MUT, id, name, None) = local.pat.kind && !in_external_macro(cx.sess(), local.span) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 11b56ed47de..0709d56c231 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -99,7 +99,7 @@ use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, - ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, + ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, }; use rustc_lexer::{tokenize, TokenKind}; @@ -1462,7 +1462,7 @@ pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { let mut child_id = expr.hir_id; for (parent_id, node) in tcx.hir().parent_iter(child_id) { - if let Node::Local(Local { + if let Node::Local(LetStmt { init: Some(init), els: Some(els), .. @@ -1482,7 +1482,7 @@ pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { let mut child_id = expr.hir_id; for (parent_id, node) in tcx.hir().parent_iter(child_id) { - if let Node::Local(Local { els: Some(els), .. }) = node + if let Node::Local(LetStmt { els: Some(els), .. }) = node && els.hir_id == child_id { return true; @@ -2158,7 +2158,7 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { Node::Stmt(Stmt { kind: StmtKind::Expr(_) | StmtKind::Semi(_) - | StmtKind::Let(Local { + | StmtKind::Let(LetStmt { pat: Pat { kind: PatKind::Wild, .. @@ -2639,7 +2639,7 @@ pub struct ExprUseCtxt<'tcx> { /// The node which consumes a value. pub enum ExprUseNode<'tcx> { /// Assignment to, or initializer for, a local - Local(&'tcx Local<'tcx>), + Local(&'tcx LetStmt<'tcx>), /// Initializer for a const or static item. ConstStatic(OwnerId), /// Implicit or explicit return from a function. @@ -2671,7 +2671,7 @@ impl<'tcx> ExprUseNode<'tcx> { /// Gets the needed type as it's defined without any type inference. pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option> { match *self { - Self::Local(Local { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), + Self::Local(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), Self::ConstStatic(id) => Some(DefinedTy::Mir( cx.param_env .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), @@ -3158,7 +3158,7 @@ pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option< } } - fn visit_local(&mut self, l: &'tcx Local<'_>) { + fn visit_local(&mut self, l: &'tcx LetStmt<'_>) { if let Some(e) = l.init { self.visit_expr(e); } From 43a61e9aca89e9d872e00222e92318d5043ca87c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Mar 2024 18:06:20 +0100 Subject: [PATCH 27/79] Rename `hir::Node::Local` into `hir::Node::LetStmt` --- clippy_lints/src/assigning_clones.rs | 2 +- clippy_lints/src/box_default.rs | 2 +- clippy_lints/src/casts/ref_as_ptr.rs | 2 +- clippy_lints/src/casts/unnecessary_cast.rs | 4 ++-- clippy_lints/src/ignored_unit_patterns.rs | 2 +- clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/manual_rem_euclid.rs | 2 +- .../src/matches/match_single_binding.rs | 2 +- clippy_lints/src/matches/needless_match.rs | 2 +- clippy_lints/src/methods/clone_on_copy.rs | 2 +- .../iter_on_single_or_empty_collections.rs | 2 +- clippy_lints/src/methods/needless_collect.rs | 2 +- .../src/methods/readonly_write_lock.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 2 +- clippy_lints/src/methods/unnecessary_fold.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/tuple_array_conversions.rs | 4 ++-- clippy_lints/src/undocumented_unsafe_blocks.rs | 6 +++--- clippy_lints/src/unit_types/let_unit_value.rs | 2 +- clippy_lints/src/unused_peekable.rs | 2 +- .../utils/internal_lints/metadata_collector.rs | 2 +- .../internal_lints/unnecessary_def_path.rs | 2 +- clippy_lints/src/vec.rs | 4 ++-- clippy_lints/src/zero_repeat_side_effects.rs | 2 +- clippy_utils/src/lib.rs | 18 +++++++++--------- clippy_utils/src/ty/type_certainty/mod.rs | 2 +- 27 files changed, 40 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 88d9f762a87..8e27b3ccefd 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -163,7 +163,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. - if let Some(Node::Local(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p)) + if let Some(Node::LetStmt(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p)) && local.init.is_none() { return false; diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index a950de4bd22..8683cb86e8a 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -139,7 +139,7 @@ impl<'tcx> Visitor<'tcx> for InferVisitor { fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match cx.tcx.parent_hir_node(expr.hir_id) { - Node::Local(LetStmt { ty: Some(ty), .. }) => { + Node::LetStmt(LetStmt { ty: Some(ty), .. }) => { let mut v = InferVisitor::default(); v.visit_ty(ty); !v.0 diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs index 9d5a486336d..0d7eae182c4 100644 --- a/clippy_lints/src/casts/ref_as_ptr.rs +++ b/clippy_lints/src/casts/ref_as_ptr.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind() && let Some(use_cx) = expr_use_ctxt(cx, expr) // TODO: only block the lint if `cast_expr` is a temporary - && !matches!(use_cx.node, ExprUseNode::Local(_) | ExprUseNode::ConstStatic(_)) + && !matches!(use_cx.node, ExprUseNode::LetStmt(_) | ExprUseNode::ConstStatic(_)) { let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; let fn_name = match to_mutbl { diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 08341ff32f3..148d52cb5dd 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -66,7 +66,7 @@ pub(super) fn check<'tcx>( && let QPath::Resolved(None, Path { res, .. }) = qpath && let Res::Local(hir_id) = res && let parent = cx.tcx.parent_hir_node(*hir_id) - && let Node::Local(local) = parent + && let Node::LetStmt(local) = parent { if let Some(ty) = local.ty && let TyKind::Path(qpath) = ty.kind @@ -275,7 +275,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx } // Local usage } else if let Res::Local(hir_id) = res - && let Node::Local(l) = cx.tcx.parent_hir_node(hir_id) + && let Node::LetStmt(l) = cx.tcx.parent_hir_node(hir_id) { if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) diff --git a/clippy_lints/src/ignored_unit_patterns.rs b/clippy_lints/src/ignored_unit_patterns.rs index 80a537b9f94..a32201d8079 100644 --- a/clippy_lints/src/ignored_unit_patterns.rs +++ b/clippy_lints/src/ignored_unit_patterns.rs @@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns { // Ignore function parameters return; }, - Node::Local(local) if local.ty.is_some() => { + Node::LetStmt(local) if local.ty.is_some() => { // Ignore let bindings with explicit type return; }, diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 0f35514b8ad..670a78d58c3 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( if let Node::Pat(pat) = node && let PatKind::Binding(bind_ann, ..) = pat.kind && !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)) - && let Node::Local(parent_let_expr) = cx.tcx.parent_hir_node(hir_id) + && let Node::LetStmt(parent_let_expr) = cx.tcx.parent_hir_node(hir_id) && let Some(init) = parent_let_expr.init { match init.kind { diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 0bde62bd554..ab9bca170cf 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { // Apply only to params or locals with annotated types match cx.tcx.parent_hir_node(hir_id) { Node::Param(..) => (), - Node::Local(local) => { + Node::LetStmt(local) => { let Some(ty) = local.ty else { return }; if matches!(ty.kind, TyKind::Infer) { return; diff --git a/clippy_lints/src/matches/match_single_binding.rs b/clippy_lints/src/matches/match_single_binding.rs index 61977045fd4..864923b2773 100644 --- a/clippy_lints/src/matches/match_single_binding.rs +++ b/clippy_lints/src/matches/match_single_binding.rs @@ -148,7 +148,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option { if let Node::Expr(parent_arm_expr) = cx.tcx.parent_hir_node(ex.hir_id) { return match cx.tcx.parent_hir_node(parent_arm_expr.hir_id) { - Node::Local(parent_let_expr) => Some(AssignmentExpr::Local { + Node::LetStmt(parent_let_expr) => Some(AssignmentExpr::Local { span: parent_let_expr.span, pat_span: parent_let_expr.pat.span(), }), diff --git a/clippy_lints/src/matches/needless_match.rs b/clippy_lints/src/matches/needless_match.rs index 3d3f29e5fc6..cee77f62b61 100644 --- a/clippy_lints/src/matches/needless_match.rs +++ b/clippy_lints/src/matches/needless_match.rs @@ -125,7 +125,7 @@ fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> { fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>) -> bool { match cx.tcx.parent_hir_node(p_expr.hir_id) { // Compare match_expr ty with local in `let local = match match_expr {..}` - Node::Local(local) => { + Node::LetStmt(local) => { let results = cx.typeck_results(); return same_type_and_consts(results.node_type(local.hir_id), results.expr_ty(expr)); }, diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index fb5c0c544a9..d4a5de3d1de 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -69,7 +69,7 @@ pub(super) fn check( _ => false, }, // local binding capturing a reference - Node::Local(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => { + Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => { return; }, _ => false, diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 4c7c56e7174..19b7e97339d 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -50,7 +50,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re | ExprKind::Break(_, _) => true, _ => false, }, - Some((Node::Stmt(_) | Node::Local(_), _)) => false, + Some((Node::Stmt(_) | Node::LetStmt(_), _)) => false, _ => true, }; diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 378644c53c0..9e2fd92255e 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -85,7 +85,7 @@ pub(super) fn check<'tcx>( ); } }, - Node::Local(l) => { + Node::LetStmt(l) => { if let PatKind::Binding(BindingAnnotation::NONE | BindingAnnotation::MUT, id, _, None) = l.pat.kind && let ty = cx.typeck_results().expr_ty(collect_expr) && [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList] diff --git a/clippy_lints/src/methods/readonly_write_lock.rs b/clippy_lints/src/methods/readonly_write_lock.rs index 6c6846c4b47..9b0180d9369 100644 --- a/clippy_lints/src/methods/readonly_write_lock.rs +++ b/clippy_lints/src/methods/readonly_write_lock.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, receiver && let Node::Expr(unwrap_call_expr) = cx.tcx.parent_hir_node(expr.hir_id) && is_unwrap_call(cx, unwrap_call_expr) && let parent = cx.tcx.parent_hir_node(unwrap_call_expr.hir_id) - && let Node::Local(local) = parent + && let Node::LetStmt(local) = parent && let Some(mir) = enclosing_mir(cx.tcx, expr.hir_id) && let Some((local, _)) = mir .local_decls diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 94e263cf3d1..946cdb49d27 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -128,7 +128,7 @@ fn check_manual_split_once_indirect( ) -> Option<()> { let ctxt = expr.span.ctxt(); let mut parents = cx.tcx.hir().parent_iter(expr.hir_id); - if let (_, Node::Local(local)) = parents.next()? + if let (_, Node::LetStmt(local)) = parents.next()? && let PatKind::Binding(BindingAnnotation::MUT, iter_binding_id, iter_ident, None) = local.pat.kind && let (iter_stmt_id, Node::Stmt(_)) = parents.next()? && let (_, Node::Block(enclosing_block)) = parents.next()? diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index 988f3e86fcf..ccc8d17970e 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -20,7 +20,7 @@ fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { // some common cases where turbofish isn't needed: // - assigned to a local variable with a type annotation - if let hir::Node::Local(local) = parent + if let hir::Node::LetStmt(local) = parent && local.ty.is_some() { return false; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2587b3881bb..896c99a7104 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -604,7 +604,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: match get_expr_use_or_unification_node(self.cx.tcx, e) { Some((Node::Stmt(_), _)) => (), - Some((Node::Local(l), _)) => { + Some((Node::LetStmt(l), _)) => { // Only trace simple bindings. e.g `let x = y;` if let PatKind::Binding(BindingAnnotation::NONE, id, _, None) = l.pat.kind { self.bindings.insert(id, args_idx); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index df7bd4c8d1d..d98b37bda35 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -241,7 +241,7 @@ fn find_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<' ExprKind::Match(e, _, _) | ExprKind::Let(&LetExpr { init: e, .. }) => Some(e), _ => None, }, - Node::Local(local) => local.init, + Node::LetStmt(local) => local.init, _ => None, }; return init; diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 0d84a9ab395..564b065d0ba 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -159,7 +159,7 @@ fn all_bindings_are_for_conv<'tcx>( .iter() .map(|node| match node { Node::Pat(pat) => kind.eq(&pat.kind).then_some(pat.hir_id), - Node::Local(l) => Some(l.hir_id), + Node::LetStmt(l) => Some(l.hir_id), _ => None, }) .all_equal() @@ -170,7 +170,7 @@ fn all_bindings_are_for_conv<'tcx>( && local_parents.first().is_some_and(|node| { let Some(ty) = match node { Node::Pat(pat) => Some(pat.hir_id), - Node::Local(l) => Some(l.hir_id), + Node::LetStmt(l) => Some(l.hir_id), _ => None, } .map(|hir_id| cx.typeck_results().node_type(hir_id)) else { diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index fe3888d09c9..5fe4b74b3a7 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -342,7 +342,7 @@ fn block_parents_have_safety_comment( ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { - Node::Local(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), + Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, @@ -363,7 +363,7 @@ fn block_parents_have_safety_comment( | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. }) - | Node::Local(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), + | Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, @@ -603,7 +603,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option { for (_, node) in map.parent_iter(body.hir_id) { match node { Node::Expr(e) => span = e.span, - Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (), + Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::LetStmt(_) => (), Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), .. diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index c11acab98c0..ffb909d7907 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -102,7 +102,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) - return false; } while let Some(id) = locals_to_check.pop() { - if let Node::Local(l) = cx.tcx.parent_hir_node(id) { + if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) { if !l.ty.map_or(true, |ty| matches!(ty.kind, TyKind::Infer)) { return false; } diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index e152a0e8343..e6f799335d7 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -190,7 +190,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { }, } }, - Node::Local(LetStmt { init: Some(init), .. }) => { + Node::LetStmt(LetStmt { init: Some(init), .. }) => { if arg_is_mut_peekable(self.cx, init) { self.found_peek_call = true; } diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 1ebe1d6a2c4..c56c8ddc7a9 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -1006,7 +1006,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) - fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> { match cx.tcx.parent_hir_node(hir_id) { - hir::Node::Local(local) => Some(local), + hir::Node::LetStmt(local) => Some(local), hir::Node::Pat(pattern) => get_parent_local_hir_id(cx, pattern.hir_id), _ => None, } diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index f4e277fd0c4..304a1379374 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -217,7 +217,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { - if let Node::Local(Local { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) { + if let Node::LetStmt(Local { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) { path_to_matched_type(cx, init) } else { None diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index fba96b630a0..27ead55bf39 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { match cx.tcx.parent_hir_node(expr.hir_id) { // search for `let foo = vec![_]` expressions where all uses of `foo` // adjust to slices or call a method that exist on slices (e.g. len) - Node::Local(LetStmt { + Node::LetStmt(LetStmt { ty: None, pat: Pat { @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } }, // if the local pattern has a specified type, do not lint. - Node::Local(LetStmt { ty: Some(_), .. }) if higher::VecArgs::hir(cx, expr).is_some() => { + Node::LetStmt(LetStmt { ty: Some(_), .. }) if higher::VecArgs::hir(cx, expr).is_some() => { self.span_to_lint_map.insert(callsite, None); }, // search for `for _ in vec![...]` diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs index 852d04cd21b..143fecdd237 100644 --- a/clippy_lints/src/zero_repeat_side_effects.rs +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -78,7 +78,7 @@ fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr: let parent_hir_node = cx.tcx.parent_hir_node(expr.hir_id); let return_type = cx.typeck_results().expr_ty(expr); - if let Node::Local(l) = parent_hir_node { + if let Node::LetStmt(l) = parent_hir_node { array_span_lint( cx, l.span, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 0709d56c231..d7886e723e8 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -184,7 +184,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { if let Node::Pat(pat) = cx.tcx.hir_node(hir_id) && matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)) - && let Node::Local(local) = cx.tcx.parent_hir_node(hir_id) + && let Node::LetStmt(local) = cx.tcx.parent_hir_node(hir_id) { return local.init; } @@ -1079,7 +1079,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { }, _ => break, }, - Node::Local(l) => match pat_capture_kind(cx, l.pat) { + Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) { CaptureKind::Value => break, capture @ CaptureKind::Ref(_) => return capture, }, @@ -1357,7 +1357,7 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>( ExprKind::Closure { .. } | ExprKind::Loop(..) => return Some(e), _ => (), }, - Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (), + Node::Stmt(_) | Node::Block(_) | Node::LetStmt(_) | Node::Arm(_) => (), _ => break, } } @@ -1462,7 +1462,7 @@ pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { let mut child_id = expr.hir_id; for (parent_id, node) in tcx.hir().parent_iter(child_id) { - if let Node::Local(LetStmt { + if let Node::LetStmt(LetStmt { init: Some(init), els: Some(els), .. @@ -1482,7 +1482,7 @@ pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { let mut child_id = expr.hir_id; for (parent_id, node) in tcx.hir().parent_iter(child_id) { - if let Node::Local(LetStmt { els: Some(els), .. }) = node + if let Node::LetStmt(LetStmt { els: Some(els), .. }) = node && els.hir_id == child_id { return true; @@ -2639,7 +2639,7 @@ pub struct ExprUseCtxt<'tcx> { /// The node which consumes a value. pub enum ExprUseNode<'tcx> { /// Assignment to, or initializer for, a local - Local(&'tcx LetStmt<'tcx>), + LetStmt(&'tcx LetStmt<'tcx>), /// Initializer for a const or static item. ConstStatic(OwnerId), /// Implicit or explicit return from a function. @@ -2671,7 +2671,7 @@ impl<'tcx> ExprUseNode<'tcx> { /// Gets the needed type as it's defined without any type inference. pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option> { match *self { - Self::Local(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), + Self::LetStmt(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), Self::ConstStatic(id) => Some(DefinedTy::Mir( cx.param_env .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), @@ -2731,7 +2731,7 @@ impl<'tcx> ExprUseNode<'tcx> { let sig = cx.tcx.fn_sig(id).skip_binder(); Some(DefinedTy::Mir(cx.tcx.param_env(id).and(sig.input(i)))) }, - Self::Local(_) | Self::FieldAccess(..) | Self::Callee | Self::Expr | Self::Other => None, + Self::LetStmt(_) | Self::FieldAccess(..) | Self::Callee | Self::Expr | Self::Other => None, } } } @@ -2770,7 +2770,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Optio .continue_value() .map(|(use_node, child_id)| { let node = match use_node { - Node::Local(l) => ExprUseNode::Local(l), + Node::LetStmt(l) => ExprUseNode::LetStmt(l), Node::ExprField(field) => ExprUseNode::Field(field), Node::Item(&Item { diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs index 7913926928f..762830ffd78 100644 --- a/clippy_utils/src/ty/type_certainty/mod.rs +++ b/clippy_utils/src/ty/type_certainty/mod.rs @@ -242,7 +242,7 @@ fn path_segment_certainty( Node::Param(..) => Certainty::Certain(None), // A local's type is certain if its type annotation is certain or it has an initializer whose // type is certain. - Node::Local(local) => { + Node::LetStmt(local) => { let lhs = local.ty.map_or(Certainty::Uncertain, |ty| type_certainty(cx, ty)); let rhs = local .init From 2d499d8f4aa5c7a4739898057dafc4dbf67ea3c7 Mon Sep 17 00:00:00 2001 From: Jeremy S Date: Fri, 22 Mar 2024 22:19:31 +0000 Subject: [PATCH 28/79] Fix typo in exhaustive_items.rs --- clippy_lints/src/exhaustive_items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index 3a621d967f4..9ffda645742 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Warns on any exported `structs`s that are not tagged `#[non_exhaustive]` + /// Warns on any exported `struct`s that are not tagged `#[non_exhaustive]` /// /// ### Why is this bad? /// Exhaustive structs are typically fine, but a project which does From 6b12829943aa617b17965b1c25d898d09406eab6 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Mar 2024 01:27:14 +0100 Subject: [PATCH 29/79] Move `is_parent_stmt` to `clippy_utils` --- clippy_lints/src/needless_bool.rs | 12 +++--------- clippy_utils/src/lib.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 166a7f71d69..081d14c043c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,11 +6,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{ - higher, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq, + higher, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, span_extract_comment, + SpanlessEq, }; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -135,13 +136,6 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool { false } -fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool { - matches!( - cx.tcx.parent_hir_node(id), - Node::Stmt(..) | Node::Block(Block { stmts: &[], .. }) - ) -} - impl<'tcx> LateLintPass<'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use self::Expression::{Bool, RetBool}; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index a6faac62f1c..5babc024a6e 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -3335,3 +3335,12 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St repeat(String::from("super")).take(go_up_by).chain(path).join("::") } } + +/// Returns true if the specified `HirId` is the top-level expression of a statement or the only +/// expression in a block. +pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool { + matches!( + cx.tcx.parent_hir_node(id), + Node::Stmt(..) | Node::Block(Block { stmts: &[], .. }) + ) +} From c137c78ba2718134ad7937ee4ad5034c296b70df Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Mar 2024 01:32:25 +0100 Subject: [PATCH 30/79] `manual_assert`: do not add extra semicolon --- clippy_lints/src/manual_assert.rs | 5 +++-- tests/ui/manual_assert.edition2018.fixed | 8 ++++++++ tests/ui/manual_assert.edition2018.stderr | 11 ++++++++++- tests/ui/manual_assert.edition2021.fixed | 8 ++++++++ tests/ui/manual_assert.edition2021.stderr | 11 ++++++++++- tests/ui/manual_assert.rs | 10 ++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/manual_assert.rs b/clippy_lints/src/manual_assert.rs index 4f6a2cf017c..76edbe8b755 100644 --- a/clippy_lints/src/manual_assert.rs +++ b/clippy_lints/src/manual_assert.rs @@ -1,7 +1,7 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call; -use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg}; +use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -63,7 +63,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert { _ => (cond, "!"), }; let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); - let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});"); + let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" }; + let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}"); // we show to the user the suggestion without the comments, but when applying the fix, include the // comments in the block span_lint_and_then( diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed index 75beedfa450..75835780801 100644 --- a/tests/ui/manual_assert.edition2018.fixed +++ b/tests/ui/manual_assert.edition2018.fixed @@ -66,3 +66,11 @@ fn issue7730(a: u8) { // comment after `panic!` assert!(!(a > 2), "panic with comment"); } + +fn issue12505() { + struct Foo(T); + + impl Foo { + const BAR: () = assert!(!(N == 0), ); + } +} diff --git a/tests/ui/manual_assert.edition2018.stderr b/tests/ui/manual_assert.edition2018.stderr index 57015933d40..1eebe1bfe17 100644 --- a/tests/ui/manual_assert.edition2018.stderr +++ b/tests/ui/manual_assert.edition2018.stderr @@ -82,5 +82,14 @@ help: try instead LL | assert!(!(a > 2), "panic with comment"); | -error: aborting due to 9 previous errors +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:91:25 + | +LL | const BAR: () = if N == 0 { + | _________________________^ +LL | | panic!() +LL | | }; + | |_________^ help: try instead: `assert!(!(N == 0), )` + +error: aborting due to 10 previous errors diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed index 75beedfa450..75835780801 100644 --- a/tests/ui/manual_assert.edition2021.fixed +++ b/tests/ui/manual_assert.edition2021.fixed @@ -66,3 +66,11 @@ fn issue7730(a: u8) { // comment after `panic!` assert!(!(a > 2), "panic with comment"); } + +fn issue12505() { + struct Foo(T); + + impl Foo { + const BAR: () = assert!(!(N == 0), ); + } +} diff --git a/tests/ui/manual_assert.edition2021.stderr b/tests/ui/manual_assert.edition2021.stderr index 57015933d40..1eebe1bfe17 100644 --- a/tests/ui/manual_assert.edition2021.stderr +++ b/tests/ui/manual_assert.edition2021.stderr @@ -82,5 +82,14 @@ help: try instead LL | assert!(!(a > 2), "panic with comment"); | -error: aborting due to 9 previous errors +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:91:25 + | +LL | const BAR: () = if N == 0 { + | _________________________^ +LL | | panic!() +LL | | }; + | |_________^ help: try instead: `assert!(!(N == 0), )` + +error: aborting due to 10 previous errors diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index 5979496ca83..363bafdf05d 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -83,3 +83,13 @@ fn issue7730(a: u8) { panic!("panic with comment") // comment after `panic!` } } + +fn issue12505() { + struct Foo(T); + + impl Foo { + const BAR: () = if N == 0 { + panic!() + }; + } +} From e9f25b3b096a8dba595fee21ba42e255563a55b5 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Thu, 14 Mar 2024 17:06:18 +0800 Subject: [PATCH 31/79] add test cases for #12435 don't lint [`mixed_attributes_style`] when mixing docs and other attrs add test files for issue #12436 move [`mixed_attributes_style`] to `LateLintPass` to enable global `allow` stop [`mixed_attributes_style`] from linting on different attributes add `@compile-flags` to [`mixed_attributes_style`]'s test; turns out not linting in test mod is not a FN. Apply suggestions from code review Co-authored-by: Timo <30553356+y21@users.noreply.github.com> move [`mixed_attributes_style`] to late pass and stop it from linting on different kind of attributes --- .../src/attrs/mixed_attributes_style.rs | 85 +++++++++++++++---- clippy_lints/src/attrs/mod.rs | 18 +++- tests/ui/mixed_attributes_style.rs | 60 +++++++++++++ tests/ui/mixed_attributes_style.stderr | 41 ++++++++- .../auxiliary/submodule.rs | 9 ++ .../ui/mixed_attributes_style/global_allow.rs | 7 ++ .../mixed_attributes_style/mod_declaration.rs | 3 + .../mod_declaration.stderr | 14 +++ 8 files changed, 214 insertions(+), 23 deletions(-) create mode 100644 tests/ui/mixed_attributes_style/auxiliary/submodule.rs create mode 100644 tests/ui/mixed_attributes_style/global_allow.rs create mode 100644 tests/ui/mixed_attributes_style/mod_declaration.rs create mode 100644 tests/ui/mixed_attributes_style/mod_declaration.stderr diff --git a/clippy_lints/src/attrs/mixed_attributes_style.rs b/clippy_lints/src/attrs/mixed_attributes_style.rs index c2e21cfd330..75a3d7a9ac3 100644 --- a/clippy_lints/src/attrs/mixed_attributes_style.rs +++ b/clippy_lints/src/attrs/mixed_attributes_style.rs @@ -1,30 +1,85 @@ use super::MIXED_ATTRIBUTES_STYLE; use clippy_utils::diagnostics::span_lint; -use rustc_ast::AttrStyle; -use rustc_lint::EarlyContext; +use rustc_ast::{AttrKind, AttrStyle, Attribute}; +use rustc_data_structures::fx::FxHashSet; +use rustc_lint::{LateContext, LintContext}; +use rustc_span::source_map::SourceMap; +use rustc_span::{SourceFile, Span, Symbol}; +use std::sync::Arc; -pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { - let mut has_outer = false; - let mut has_inner = false; +#[derive(Hash, PartialEq, Eq)] +enum SimpleAttrKind { + Doc, + /// A normal attribute, with its name symbols. + Normal(Vec), +} - for attr in &item.attrs { - if attr.span.from_expansion() { +impl From<&AttrKind> for SimpleAttrKind { + fn from(value: &AttrKind) -> Self { + match value { + AttrKind::Normal(attr) => { + let path_symbols = attr + .item + .path + .segments + .iter() + .map(|seg| seg.ident.name) + .collect::>(); + Self::Normal(path_symbols) + }, + AttrKind::DocComment(..) => Self::Doc, + } + } +} + +pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) { + let mut inner_attr_kind: FxHashSet = FxHashSet::default(); + let mut outer_attr_kind: FxHashSet = FxHashSet::default(); + + let source_map = cx.sess().source_map(); + let item_src = source_map.lookup_source_file(item_span.lo()); + + for attr in attrs { + if attr.span.from_expansion() || !attr_in_same_src_as_item(source_map, &item_src, attr.span) { continue; } + + let kind: SimpleAttrKind = (&attr.kind).into(); match attr.style { - AttrStyle::Inner => has_inner = true, - AttrStyle::Outer => has_outer = true, - } + AttrStyle::Inner => { + if outer_attr_kind.contains(&kind) { + lint_mixed_attrs(cx, attrs); + return; + } + inner_attr_kind.insert(kind); + }, + AttrStyle::Outer => { + if inner_attr_kind.contains(&kind) { + lint_mixed_attrs(cx, attrs); + return; + } + outer_attr_kind.insert(kind); + }, + }; } - if !has_outer || !has_inner { +} + +fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) { + let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion()); + let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) { + first.span.with_hi(last.span.hi()) + } else { return; - } - let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion()); - let span = attrs_iter.next().unwrap().span; + }; span_lint( cx, MIXED_ATTRIBUTES_STYLE, - span.with_hi(attrs_iter.last().unwrap().span.hi()), + span, "item has both inner and outer attributes", ); } + +fn attr_in_same_src_as_item(source_map: &SourceMap, item_src: &Arc, attr_span: Span) -> bool { + let attr_src = source_map.lookup_source_file(attr_span.lo()); + Arc::ptr_eq(item_src, &attr_src) +} diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 675c428948f..6f4575f1b9a 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -465,10 +465,20 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks that an item has only one kind of attributes. + /// Checks for items that have the same kind of attributes with mixed styles (inner/outer). /// /// ### Why is this bad? - /// Having both kinds of attributes makes it more complicated to read code. + /// Having both style of said attributes makes it more complicated to read code. + /// + /// ### Known problems + /// This lint currently has false-negatives when mixing same attributes + /// but they have different path symbols, for example: + /// ```ignore + /// #[custom_attribute] + /// pub fn foo() { + /// #![my_crate::custom_attribute] + /// } + /// ``` /// /// ### Example /// ```no_run @@ -523,6 +533,7 @@ declare_lint_pass!(Attributes => [ USELESS_ATTRIBUTE, BLANKET_CLIPPY_RESTRICTION_LINTS, SHOULD_PANIC_WITHOUT_EXPECT, + MIXED_ATTRIBUTES_STYLE, ]); impl<'tcx> LateLintPass<'tcx> for Attributes { @@ -566,6 +577,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs), _ => {}, } + mixed_attributes_style::check(cx, item.span, attrs); } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { @@ -594,7 +606,6 @@ impl_lint_pass!(EarlyAttributes => [ MAYBE_MISUSED_CFG, DEPRECATED_CLIPPY_CFG_ATTR, UNNECESSARY_CLIPPY_CFG, - MIXED_ATTRIBUTES_STYLE, DUPLICATED_ATTRIBUTES, ]); @@ -605,7 +616,6 @@ impl EarlyLintPass for EarlyAttributes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { empty_line_after::check(cx, item); - mixed_attributes_style::check(cx, item); duplicated_attributes::check(cx, &item.attrs); } diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs index 4f89aa8a5e5..1a646c26522 100644 --- a/tests/ui/mixed_attributes_style.rs +++ b/tests/ui/mixed_attributes_style.rs @@ -1,6 +1,12 @@ +//@aux-build:proc_macro_attr.rs +//@compile-flags: --test --cfg dummy_cfg +#![feature(custom_inner_attributes)] #![warn(clippy::mixed_attributes_style)] #![allow(clippy::duplicated_attributes)] +#[macro_use] +extern crate proc_macro_attr; + #[allow(unused)] //~ ERROR: item has both inner and outer attributes fn foo1() { #![allow(unused)] @@ -38,3 +44,57 @@ mod bar { fn main() { // test code goes here } + +// issue #12435 +#[cfg(test)] +mod tests { + //! Module doc, don't lint +} +#[allow(unused)] +mod baz { + //! Module doc, don't lint + const FOO: u8 = 0; +} +/// Module doc, don't lint +mod quz { + #![allow(unused)] +} + +mod issue_12530 { + // don't lint different attributes entirely + #[cfg(test)] + mod tests { + #![allow(clippy::unreadable_literal)] + + #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + mod inner_mod { + #![allow(dead_code)] + } + } + #[cfg(dummy_cfg)] + mod another_mod { + #![allow(clippy::question_mark)] + } + /// Nested mod + mod nested_mod { + #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + mod inner_mod { + #![allow(dead_code)] + } + } + /// Nested mod //~ ERROR: item has both inner and outer attributes + #[allow(unused)] + mod nest_mod_2 { + #![allow(unused)] + + #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes + mod inner_mod { + #![allow(dead_code)] + } + } + // Different path symbols - Known FN + #[dummy] + fn use_dummy() { + #![proc_macro_attr::dummy] + } +} diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr index ed798073cb7..a1d3fc430f6 100644 --- a/tests/ui/mixed_attributes_style.stderr +++ b/tests/ui/mixed_attributes_style.stderr @@ -1,5 +1,5 @@ error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:4:1 + --> tests/ui/mixed_attributes_style.rs:10:1 | LL | / #[allow(unused)] LL | | fn foo1() { @@ -10,7 +10,7 @@ LL | | #![allow(unused)] = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]` error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:18:1 + --> tests/ui/mixed_attributes_style.rs:24:1 | LL | / /// linux LL | | @@ -19,12 +19,45 @@ LL | | //! windows | |_______________^ error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:33:1 + --> tests/ui/mixed_attributes_style.rs:39:1 | LL | / #[allow(unused)] LL | | mod bar { LL | | #![allow(unused)] | |_____________________^ -error: aborting due to 3 previous errors +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:69:9 + | +LL | / #[allow(dead_code)] +LL | | mod inner_mod { +LL | | #![allow(dead_code)] + | |________________________________^ + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:80:9 + | +LL | / #[allow(dead_code)] +LL | | mod inner_mod { +LL | | #![allow(dead_code)] + | |________________________________^ + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:85:5 + | +LL | / /// Nested mod +LL | | #[allow(unused)] +LL | | mod nest_mod_2 { +LL | | #![allow(unused)] + | |_________________________^ + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:90:9 + | +LL | / #[allow(dead_code)] +LL | | mod inner_mod { +LL | | #![allow(dead_code)] + | |________________________________^ + +error: aborting due to 7 previous errors diff --git a/tests/ui/mixed_attributes_style/auxiliary/submodule.rs b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs new file mode 100644 index 00000000000..df44b07a694 --- /dev/null +++ b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs @@ -0,0 +1,9 @@ +//! Module level doc + +#![allow(dead_code)] + +#[allow(unused)] +//~^ ERROR: item has both inner and outer attributes +mod foo { + #![allow(dead_code)] +} diff --git a/tests/ui/mixed_attributes_style/global_allow.rs b/tests/ui/mixed_attributes_style/global_allow.rs new file mode 100644 index 00000000000..153262e6557 --- /dev/null +++ b/tests/ui/mixed_attributes_style/global_allow.rs @@ -0,0 +1,7 @@ +// issue 12436 +#![allow(clippy::mixed_attributes_style)] + +#[path = "auxiliary/submodule.rs"] +mod submodule; + +fn main() {} diff --git a/tests/ui/mixed_attributes_style/mod_declaration.rs b/tests/ui/mixed_attributes_style/mod_declaration.rs new file mode 100644 index 00000000000..b0f1f0bda9e --- /dev/null +++ b/tests/ui/mixed_attributes_style/mod_declaration.rs @@ -0,0 +1,3 @@ +#[path = "auxiliary/submodule.rs"] // don't lint. +/// This doc comment should not lint, it could be used to add context to the original module doc +mod submodule; diff --git a/tests/ui/mixed_attributes_style/mod_declaration.stderr b/tests/ui/mixed_attributes_style/mod_declaration.stderr new file mode 100644 index 00000000000..968c537c7e4 --- /dev/null +++ b/tests/ui/mixed_attributes_style/mod_declaration.stderr @@ -0,0 +1,14 @@ +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style/auxiliary/submodule.rs:5:1 + | +LL | / #[allow(unused)] +LL | | +LL | | mod foo { +LL | | #![allow(dead_code)] + | |________________________^ + | + = note: `-D clippy::mixed-attributes-style` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]` + +error: aborting due to 1 previous error + From 02fc25635e88b670f0b4bfe5afdcf4ab2771d3e0 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Mar 2024 00:23:59 +0100 Subject: [PATCH 32/79] Add `should_call_clone_as_function()` utility function --- clippy_lints/src/methods/map_clone.rs | 8 ++------ clippy_utils/src/ty.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 0ba8cbbe699..9d020092ccb 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; +use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function}; use clippy_utils::{is_diag_trait_item, match_def_path, paths, peel_blocks}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -124,11 +124,7 @@ fn handle_path( && let ty::Ref(_, ty, Mutability::Not) = ty.kind() && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind() && lst.iter().all(|l| l.as_type() == Some(*ty)) - && !matches!( - ty.ty_adt_def() - .and_then(|adt_def| cx.tcx.get_diagnostic_name(adt_def.did())), - Some(sym::Arc | sym::ArcWeak | sym::Rc | sym::RcWeak) - ) + && !should_call_clone_as_function(cx, *ty) { lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs())); } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index a2595580eaf..3924eb5a81c 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -159,6 +159,16 @@ pub fn get_type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option, ty: Ty<'_>) -> bool { + matches!( + get_type_diagnostic_name(cx, ty), + Some(sym::Arc | sym::ArcWeak | sym::Rc | sym::RcWeak) + ) +} + /// Returns true if ty has `iter` or `iter_mut` methods pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option { // FIXME: instead of this hard-coded list, we should check if `::iter` From fed2f28223c43e56da6a31e6eb8c3fd5d84606d2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Mar 2024 00:24:30 +0100 Subject: [PATCH 33/79] Do not rewrite `.as_ref().map(Arc::clone)` and similar --- clippy_lints/src/methods/useless_asref.rs | 4 ++- tests/ui/useless_asref.fixed | 18 ++++++++++++ tests/ui/useless_asref.rs | 18 ++++++++++++ tests/ui/useless_asref.stderr | 36 +++++++++++------------ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index b8baad18cc8..474103fccd2 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::walk_ptrs_ty_depth; +use clippy_utils::ty::{should_call_clone_as_function, walk_ptrs_ty_depth}; use clippy_utils::{ get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, paths, peel_blocks, strip_pat_refs, }; @@ -93,6 +93,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, // And that it only has one argument. && let [arg] = args && is_calling_clone(cx, arg) + // And that we are not recommending recv.clone() over Arc::clone() or similar + && !should_call_clone_as_function(cx, rcv_ty) { lint_as_ref_clone(cx, expr.span.with_hi(parent.span.hi()), recvr, call_name); } diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index c98f2928e03..ddbb9255b46 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -8,6 +8,8 @@ )] use std::fmt::Debug; +use std::rc::{Rc, Weak as RcWeak}; +use std::sync::{Arc, Weak as ArcWeak}; struct FakeAsRef; @@ -180,6 +182,22 @@ mod issue12135 { } } +fn issue_12528() { + struct Foo; + + let opt = Some(Arc::new(Foo)); + let _ = opt.as_ref().map(Arc::clone); + + let opt = Some(Rc::new(Foo)); + let _ = opt.as_ref().map(Rc::clone); + + let opt = Some(Arc::downgrade(&Arc::new(Foo))); + let _ = opt.as_ref().map(ArcWeak::clone); + + let opt = Some(Rc::downgrade(&Rc::new(Foo))); + let _ = opt.as_ref().map(RcWeak::clone); +} + fn main() { not_ok(); ok(); diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index f9d603f116d..b0405e930a2 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -8,6 +8,8 @@ )] use std::fmt::Debug; +use std::rc::{Rc, Weak as RcWeak}; +use std::sync::{Arc, Weak as ArcWeak}; struct FakeAsRef; @@ -180,6 +182,22 @@ mod issue12135 { } } +fn issue_12528() { + struct Foo; + + let opt = Some(Arc::new(Foo)); + let _ = opt.as_ref().map(Arc::clone); + + let opt = Some(Rc::new(Foo)); + let _ = opt.as_ref().map(Rc::clone); + + let opt = Some(Arc::downgrade(&Arc::new(Foo))); + let _ = opt.as_ref().map(ArcWeak::clone); + + let opt = Some(Rc::downgrade(&Rc::new(Foo))); + let _ = opt.as_ref().map(RcWeak::clone); +} + fn main() { not_ok(); ok(); diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index c7d622ec2dc..5f495c39670 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,5 +1,5 @@ error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:48:18 + --> tests/ui/useless_asref.rs:50:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try: `rstr` @@ -11,103 +11,103 @@ LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:50:20 + --> tests/ui/useless_asref.rs:52:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try: `rslice` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:54:21 + --> tests/ui/useless_asref.rs:56:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:56:20 + --> tests/ui/useless_asref.rs:58:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:63:20 + --> tests/ui/useless_asref.rs:65:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:65:18 + --> tests/ui/useless_asref.rs:67:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:70:21 + --> tests/ui/useless_asref.rs:72:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:72:20 + --> tests/ui/useless_asref.rs:74:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:76:16 + --> tests/ui/useless_asref.rs:78:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:126:13 + --> tests/ui/useless_asref.rs:128:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try: `mrt` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:128:12 + --> tests/ui/useless_asref.rs:130:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try: `mrt` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:139:13 + --> tests/ui/useless_asref.rs:141:13 | LL | let z = x.as_ref().map(String::clone); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:141:13 + --> tests/ui/useless_asref.rs:143:13 | LL | let z = x.as_ref().map(|z| z.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:143:13 + --> tests/ui/useless_asref.rs:145:13 | LL | let z = x.as_ref().map(|z| String::clone(z)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:167:9 + --> tests/ui/useless_asref.rs:169:9 | LL | x.field.as_ref().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:169:9 + --> tests/ui/useless_asref.rs:171:9 | LL | x.field.as_ref().map(Clone::clone); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:171:9 + --> tests/ui/useless_asref.rs:173:9 | LL | x.field.as_ref().map(|v| Clone::clone(v)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:176:9 + --> tests/ui/useless_asref.rs:178:9 | LL | Some(1).as_ref().map(|&x| x.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(1).clone()` From 4d623015e0c993aea542834b44fc4dd18b62483e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 Mar 2024 12:21:20 +0100 Subject: [PATCH 34/79] rename MIR int2ptr casts to match library name --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index dadb0d662ce..0c4260037f2 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -112,7 +112,7 @@ fn check_rvalue<'tcx>( Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::Cast( - CastKind::PointerFromExposedAddress + CastKind::PointerWithExposedProvenance | CastKind::IntToInt | CastKind::FloatToInt | CastKind::IntToFloat From 5919b26d33aac5da7e78468c4412814869b0b12f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 Mar 2024 10:12:25 +0100 Subject: [PATCH 35/79] move assert_unsafe_preconditions to its own file These macros and functions are not intrinsics, after all. --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index dadb0d662ce..cabebf89bec 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -174,7 +174,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbCheck(_), _) + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks, _) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); From 8e0496170d7f655f1e14887e22e12f7795bdb394 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 19 Feb 2024 14:53:53 +0100 Subject: [PATCH 36/79] Add ui test for `missing_transmute_annotations` --- tests/ui/author/issue_3849.rs | 2 +- tests/ui/auxiliary/macro_rules.rs | 7 ++ tests/ui/blocks_in_conditions.fixed | 7 +- tests/ui/blocks_in_conditions.rs | 7 +- tests/ui/blocks_in_conditions.stderr | 8 +- tests/ui/crashes/ice-1782.rs | 2 +- tests/ui/eager_transmute.fixed | 2 +- tests/ui/eager_transmute.rs | 2 +- .../ui/missing_const_for_fn/could_be_const.rs | 2 +- tests/ui/missing_transmute_annotations.fixed | 79 +++++++++++++++++ tests/ui/missing_transmute_annotations.rs | 79 +++++++++++++++++ tests/ui/missing_transmute_annotations.stderr | 64 ++++++++++++++ tests/ui/ptr_cast_constness.fixed | 7 +- tests/ui/ptr_cast_constness.rs | 7 +- tests/ui/ptr_cast_constness.stderr | 14 +-- tests/ui/transmute.rs | 7 +- tests/ui/transmute.stderr | 72 ++++++++-------- tests/ui/transmute_collection.rs | 1 + tests/ui/transmute_collection.stderr | 36 ++++---- tests/ui/transmute_float_to_int.fixed | 1 + tests/ui/transmute_float_to_int.rs | 1 + tests/ui/transmute_float_to_int.stderr | 12 +-- tests/ui/transmute_int_to_char.fixed | 1 + tests/ui/transmute_int_to_char.rs | 1 + tests/ui/transmute_int_to_char.stderr | 4 +- tests/ui/transmute_int_to_char_no_std.fixed | 1 + tests/ui/transmute_int_to_char_no_std.rs | 1 + tests/ui/transmute_int_to_char_no_std.stderr | 4 +- tests/ui/transmute_int_to_non_zero.fixed | 1 + tests/ui/transmute_int_to_non_zero.rs | 1 + tests/ui/transmute_int_to_non_zero.stderr | 20 ++--- tests/ui/transmute_null_to_fn.rs | 2 +- tests/ui/transmute_ptr_to_ptr.fixed | 2 +- tests/ui/transmute_ptr_to_ptr.rs | 2 +- tests/ui/transmute_ptr_to_ref.fixed | 6 +- tests/ui/transmute_ptr_to_ref.rs | 6 +- tests/ui/transmute_ptr_to_ref.stderr | 44 +++++----- tests/ui/transmute_ref_to_ref.rs | 2 +- tests/ui/transmute_ref_to_ref_no_std.rs | 2 +- tests/ui/transmute_undefined_repr.rs | 7 +- tests/ui/transmute_undefined_repr.stderr | 24 +++--- .../transmutes_expressible_as_ptr_casts.fixed | 2 +- .../ui/transmutes_expressible_as_ptr_casts.rs | 2 +- tests/ui/transmuting_null.rs | 2 +- tests/ui/uninhabited_references.rs | 1 + tests/ui/uninhabited_references.stderr | 8 +- tests/ui/use_self.fixed | 4 +- tests/ui/use_self.rs | 4 +- tests/ui/use_self.stderr | 86 +++++++++---------- 49 files changed, 470 insertions(+), 189 deletions(-) create mode 100644 tests/ui/missing_transmute_annotations.fixed create mode 100644 tests/ui/missing_transmute_annotations.rs create mode 100644 tests/ui/missing_transmute_annotations.stderr diff --git a/tests/ui/author/issue_3849.rs b/tests/ui/author/issue_3849.rs index bae4570e539..5f65746d71f 100644 --- a/tests/ui/author/issue_3849.rs +++ b/tests/ui/author/issue_3849.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(clippy::zero_ptr)] #![allow(clippy::transmute_ptr_to_ref)] -#![allow(clippy::transmuting_null)] +#![allow(clippy::transmuting_null, clippy::missing_transmute_annotations)] pub const ZPTR: *const usize = 0 as *const _; diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index 6b164967a28..9efbb390849 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -50,3 +50,10 @@ macro_rules! macro_with_panic { panic!() }; } + +#[macro_export] +macro_rules! bad_transmute { + ($e:expr) => { + std::mem::transmute($e) + }; +} diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index caf29e23d54..a2da5f9c5fb 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -1,7 +1,12 @@ //@aux-build:proc_macro_attr.rs #![warn(clippy::blocks_in_conditions)] -#![allow(unused, clippy::let_and_return, clippy::needless_if)] +#![allow( + unused, + clippy::let_and_return, + clippy::needless_if, + clippy::missing_transmute_annotations +)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs index e72daaa910d..608ca4cf267 100644 --- a/tests/ui/blocks_in_conditions.rs +++ b/tests/ui/blocks_in_conditions.rs @@ -1,7 +1,12 @@ //@aux-build:proc_macro_attr.rs #![warn(clippy::blocks_in_conditions)] -#![allow(unused, clippy::let_and_return, clippy::needless_if)] +#![allow( + unused, + clippy::let_and_return, + clippy::needless_if, + clippy::missing_transmute_annotations +)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_conditions.stderr b/tests/ui/blocks_in_conditions.stderr index 3641e71aae8..a55e1efb575 100644 --- a/tests/ui/blocks_in_conditions.stderr +++ b/tests/ui/blocks_in_conditions.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> tests/ui/blocks_in_conditions.rs:25:5 + --> tests/ui/blocks_in_conditions.rs:30:5 | LL | / if { LL | | @@ -20,13 +20,13 @@ LL ~ }; if res { | error: omit braces around single expression condition - --> tests/ui/blocks_in_conditions.rs:37:8 + --> tests/ui/blocks_in_conditions.rs:42:8 | LL | if { true } { 6 } else { 10 } | ^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> tests/ui/blocks_in_conditions.rs:43:8 + --> tests/ui/blocks_in_conditions.rs:48:8 | LL | if true && x == 3 { 6 } else { 10 } | ^^^^^^^^^^^^^^ help: try: `x == 3` @@ -35,7 +35,7 @@ LL | if true && x == 3 { 6 } else { 10 } = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> tests/ui/blocks_in_conditions.rs:70:5 + --> tests/ui/blocks_in_conditions.rs:75:5 | LL | / match { LL | | diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index 19ab03418ee..73de5721cbc 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/tests/ui/crashes/ice-1782.rs @@ -1,5 +1,5 @@ #![allow(dead_code, unused_variables)] -#![allow(clippy::unnecessary_cast)] +#![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` /// diff --git a/tests/ui/eager_transmute.fixed b/tests/ui/eager_transmute.fixed index bece09bba1a..c29e7dd9ab3 100644 --- a/tests/ui/eager_transmute.fixed +++ b/tests/ui/eager_transmute.fixed @@ -1,6 +1,6 @@ #![feature(rustc_attrs)] #![warn(clippy::eager_transmute)] -#![allow(clippy::transmute_int_to_non_zero)] +#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)] use std::num::NonZeroU8; diff --git a/tests/ui/eager_transmute.rs b/tests/ui/eager_transmute.rs index a82bd578f76..491a9485c93 100644 --- a/tests/ui/eager_transmute.rs +++ b/tests/ui/eager_transmute.rs @@ -1,6 +1,6 @@ #![feature(rustc_attrs)] #![warn(clippy::eager_transmute)] -#![allow(clippy::transmute_int_to_non_zero)] +#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)] use std::num::NonZeroU8; 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 6985c2d0c19..12a8320c8f3 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,5 +1,5 @@ #![warn(clippy::missing_const_for_fn)] -#![allow(incomplete_features, clippy::let_and_return)] +#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed new file mode 100644 index 00000000000..cf6117b171b --- /dev/null +++ b/tests/ui/missing_transmute_annotations.fixed @@ -0,0 +1,79 @@ +//@aux-build:macro_rules.rs + +#![warn(clippy::missing_transmute_annotations)] + +#[macro_use] +extern crate macro_rules; + +macro_rules! local_bad_transmute { + ($e:expr) => { + std::mem::transmute::<[u16; 2], i32>($e) + }; +} + +fn bar(x: i32) -> i32 { + x +} + +unsafe fn foo1() -> i32 { + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo2() -> i32 { + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo3() -> i32 { + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo4() -> i32 { + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo5() -> i32 { + let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])); + //~^ ERROR: transmute used without annotations + bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo6() -> i32 { + local_bad_transmute!([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo7() -> i32 { + // Should not warn. + bad_transmute!([1u16, 2u16]) +} + +#[repr(i32)] +enum Foo { + A = 0, +} + +unsafe fn foo8() -> Foo { + std::mem::transmute::(0i32) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo9() -> i32 { + std::mem::transmute::(Foo::A) + //~^ ERROR: transmute used without annotations +} + +fn main() { + unsafe { + // Should not warn. + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + let x: i32 = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]); + let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); + let x: i32 = std::mem::transmute([1u16, 2u16]); + } +} diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs new file mode 100644 index 00000000000..53fd7a84939 --- /dev/null +++ b/tests/ui/missing_transmute_annotations.rs @@ -0,0 +1,79 @@ +//@aux-build:macro_rules.rs + +#![warn(clippy::missing_transmute_annotations)] + +#[macro_use] +extern crate macro_rules; + +macro_rules! local_bad_transmute { + ($e:expr) => { + std::mem::transmute($e) + }; +} + +fn bar(x: i32) -> i32 { + x +} + +unsafe fn foo1() -> i32 { + std::mem::transmute([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo2() -> i32 { + std::mem::transmute::<_, _>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo3() -> i32 { + std::mem::transmute::<_, i32>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo4() -> i32 { + std::mem::transmute::<[u16; 2], _>([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo5() -> i32 { + let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); + //~^ ERROR: transmute used without annotations + bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo6() -> i32 { + local_bad_transmute!([1u16, 2u16]) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo7() -> i32 { + // Should not warn. + bad_transmute!([1u16, 2u16]) +} + +#[repr(i32)] +enum Foo { + A = 0, +} + +unsafe fn foo8() -> Foo { + std::mem::transmute(0i32) + //~^ ERROR: transmute used without annotations +} + +unsafe fn foo9() -> i32 { + std::mem::transmute(Foo::A) + //~^ ERROR: transmute used without annotations +} + +fn main() { + unsafe { + // Should not warn. + std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + let x: i32 = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]); + let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); + let x: i32 = std::mem::transmute([1u16, 2u16]); + } +} diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr new file mode 100644 index 00000000000..9f2e8e8c9e7 --- /dev/null +++ b/tests/ui/missing_transmute_annotations.stderr @@ -0,0 +1,64 @@ +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:19:15 + | +LL | std::mem::transmute([1u16, 2u16]) + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + | + = note: `-D clippy::missing-transmute-annotations` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:24:15 + | +LL | std::mem::transmute::<_, _>([1u16, 2u16]) + | ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:29:15 + | +LL | std::mem::transmute::<_, i32>([1u16, 2u16]) + | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:34:15 + | +LL | std::mem::transmute::<[u16; 2], _>([1u16, 2u16]) + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:39:32 + | +LL | let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:41:19 + | +LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])) + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:10:19 + | +LL | std::mem::transmute($e) + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` +... +LL | local_bad_transmute!([1u16, 2u16]) + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:61:15 + | +LL | std::mem::transmute(0i32) + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:66:15 + | +LL | std::mem::transmute(Foo::A) + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index c410a660dc4..33c0725faad 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -1,7 +1,12 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] -#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] +#![allow( + clippy::transmute_ptr_to_ref, + clippy::unnecessary_cast, + unused, + clippy::missing_transmute_annotations +)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 6025b857b8f..24d959856db 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -1,7 +1,12 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] -#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] +#![allow( + clippy::transmute_ptr_to_ref, + clippy::unnecessary_cast, + unused, + clippy::missing_transmute_annotations +)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 8e2bec527ff..322c3585e62 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -1,5 +1,5 @@ error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:10:41 + --> tests/ui/ptr_cast_constness.rs:15:41 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` @@ -8,37 +8,37 @@ LL | let _: &mut T = std::mem::transmute(p as *mut T); = help: to override `-D warnings` add `#[allow(clippy::ptr_cast_constness)]` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:11:19 + --> tests/ui/ptr_cast_constness.rs:16:19 | LL | let _ = &mut *(p as *mut T); | ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:26:17 + --> tests/ui/ptr_cast_constness.rs:31:17 | LL | let _ = *ptr_ptr as *mut u32; | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:29:13 + --> tests/ui/ptr_cast_constness.rs:34:13 | LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:30:13 + --> tests/ui/ptr_cast_constness.rs:35:13 | LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:59:13 + --> tests/ui/ptr_cast_constness.rs:64:13 | LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:60:13 + --> tests/ui/ptr_cast_constness.rs:65:13 | LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 1796ccaf28e..be6e071767d 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,4 +1,9 @@ -#![allow(dead_code, clippy::borrow_as_ptr, clippy::needless_lifetimes)] +#![allow( + dead_code, + clippy::borrow_as_ptr, + clippy::needless_lifetimes, + clippy::missing_transmute_annotations +)] //@no-rustfix extern crate core; diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 3ed6cb2b3f9..375e8f19dd6 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:24:23 + --> tests/ui/transmute.rs:29:23 | LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` @@ -8,61 +8,61 @@ LL | let _: *const T = core::intrinsics::transmute(t); = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:28:21 + --> tests/ui/transmute.rs:33:21 | LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:31:23 + --> tests/ui/transmute.rs:36:23 | LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:38:27 + --> tests/ui/transmute.rs:43:27 | LL | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:41:27 + --> tests/ui/transmute.rs:46:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:44:27 + --> tests/ui/transmute.rs:49:27 | LL | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:47:27 + --> tests/ui/transmute.rs:52:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:50:27 + --> tests/ui/transmute.rs:55:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:53:31 + --> tests/ui/transmute.rs:58:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:58:31 + --> tests/ui/transmute.rs:63:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:90:24 + --> tests/ui/transmute.rs:95:24 | LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,25 +71,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:94:24 + --> tests/ui/transmute.rs:99:24 | LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> tests/ui/transmute.rs:97:31 + --> tests/ui/transmute.rs:102:31 | LL | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> tests/ui/transmute.rs:100:29 + --> tests/ui/transmute.rs:105:29 | LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u8` to a `bool` - --> tests/ui/transmute.rs:107:28 + --> tests/ui/transmute.rs:112:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -98,7 +98,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]` error: transmute from a `u32` to a `f32` - --> tests/ui/transmute.rs:115:31 + --> tests/ui/transmute.rs:120:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -107,25 +107,25 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]` error: transmute from a `i32` to a `f32` - --> tests/ui/transmute.rs:118:31 + --> tests/ui/transmute.rs:123:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `u64` to a `f64` - --> tests/ui/transmute.rs:120:31 + --> tests/ui/transmute.rs:125:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` error: transmute from a `i64` to a `f64` - --> tests/ui/transmute.rs:122:31 + --> tests/ui/transmute.rs:127:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:143:30 + --> tests/ui/transmute.rs:148:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -134,85 +134,85 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:146:30 + --> tests/ui/transmute.rs:151:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:148:31 + --> tests/ui/transmute.rs:153:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:150:30 + --> tests/ui/transmute.rs:155:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:152:30 + --> tests/ui/transmute.rs:157:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:154:31 + --> tests/ui/transmute.rs:159:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> tests/ui/transmute.rs:156:30 + --> tests/ui/transmute.rs:161:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> tests/ui/transmute.rs:158:30 + --> tests/ui/transmute.rs:163:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:164:30 + --> tests/ui/transmute.rs:169:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:166:30 + --> tests/ui/transmute.rs:171:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:168:31 + --> tests/ui/transmute.rs:173:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:170:30 + --> tests/ui/transmute.rs:175:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:172:30 + --> tests/ui/transmute.rs:177:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:174:31 + --> tests/ui/transmute.rs:179:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:185:28 + --> tests/ui/transmute.rs:190:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -221,13 +221,13 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> tests/ui/transmute.rs:188:32 + --> tests/ui/transmute.rs:193:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:190:30 + --> tests/ui/transmute.rs:195:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` diff --git a/tests/ui/transmute_collection.rs b/tests/ui/transmute_collection.rs index 8bf45457335..e30b34a5d7d 100644 --- a/tests/ui/transmute_collection.rs +++ b/tests/ui/transmute_collection.rs @@ -1,4 +1,5 @@ #![warn(clippy::unsound_collection_transmute)] +#![allow(clippy::missing_transmute_annotations)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; use std::mem::{transmute, MaybeUninit}; diff --git a/tests/ui/transmute_collection.stderr b/tests/ui/transmute_collection.stderr index f71fba6315c..06db9321064 100644 --- a/tests/ui/transmute_collection.stderr +++ b/tests/ui/transmute_collection.stderr @@ -1,5 +1,5 @@ error: transmute from `std::vec::Vec` to `std::vec::Vec` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:9:17 + --> tests/ui/transmute_collection.rs:10:17 | LL | let _ = transmute::<_, Vec>(vec![0u8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,103 +8,103 @@ LL | let _ = transmute::<_, Vec>(vec![0u8]); = help: to override `-D warnings` add `#[allow(clippy::unsound_collection_transmute)]` error: transmute from `std::vec::Vec` to `std::vec::Vec<[u8; 4]>` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:13:17 + --> tests/ui/transmute_collection.rs:14:17 | LL | let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::VecDeque` to `std::collections::VecDeque` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:17:17 + --> tests/ui/transmute_collection.rs:18:17 | LL | let _ = transmute::<_, VecDeque>(VecDeque::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collections::VecDeque` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:20:17 + --> tests/ui/transmute_collection.rs:21:17 | LL | let _ = transmute::<_, VecDeque>(VecDeque::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BinaryHeap` to `std::collections::BinaryHeap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:24:17 + --> tests/ui/transmute_collection.rs:25:17 | LL | let _ = transmute::<_, BinaryHeap>(BinaryHeap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collections::BinaryHeap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:27:17 + --> tests/ui/transmute_collection.rs:28:17 | LL | let _ = transmute::<_, BinaryHeap>(BinaryHeap::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeSet` to `std::collections::BTreeSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:31:17 + --> tests/ui/transmute_collection.rs:32:17 | LL | let _ = transmute::<_, BTreeSet>(BTreeSet::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collections::BTreeSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:34:17 + --> tests/ui/transmute_collection.rs:35:17 | LL | let _ = transmute::<_, BTreeSet>(BTreeSet::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashSet` to `std::collections::HashSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:38:17 + --> tests/ui/transmute_collection.rs:39:17 | LL | let _ = transmute::<_, HashSet>(HashSet::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collections::HashSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:41:17 + --> tests/ui/transmute_collection.rs:42:17 | LL | let _ = transmute::<_, HashSet>(HashSet::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:45:17 + --> tests/ui/transmute_collection.rs:46:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:47:17 + --> tests/ui/transmute_collection.rs:48:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:50:17 + --> tests/ui/transmute_collection.rs:51:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:52:17 + --> tests/ui/transmute_collection.rs:53:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::<[u8; 4], u32>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:56:17 + --> tests/ui/transmute_collection.rs:57:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:58:17 + --> tests/ui/transmute_collection.rs:59:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:61:17 + --> tests/ui/transmute_collection.rs:62:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:63:17 + --> tests/ui/transmute_collection.rs:64:17 | LL | let _ = transmute::<_, HashMap>(HashMap::<[u8; 4], u32>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmute_float_to_int.fixed b/tests/ui/transmute_float_to_int.fixed index cef0bcfa623..82d5f7fdca1 100644 --- a/tests/ui/transmute_float_to_int.fixed +++ b/tests/ui/transmute_float_to_int.fixed @@ -1,4 +1,5 @@ #![warn(clippy::transmute_float_to_int)] +#![allow(clippy::missing_transmute_annotations)] fn float_to_int() { let _: u32 = unsafe { 1f32.to_bits() }; diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 3d95bec2a20..9f056330adf 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -1,4 +1,5 @@ #![warn(clippy::transmute_float_to_int)] +#![allow(clippy::missing_transmute_annotations)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index e89258d9102..ac3aae5f8b7 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -1,5 +1,5 @@ error: transmute from a `f32` to a `u32` - --> tests/ui/transmute_float_to_int.rs:4:27 + --> tests/ui/transmute_float_to_int.rs:5:27 | LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()` @@ -8,31 +8,31 @@ LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_float_to_int)]` error: transmute from a `f32` to a `i32` - --> tests/ui/transmute_float_to_int.rs:7:27 + --> tests/ui/transmute_float_to_int.rs:8:27 | LL | let _: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:9:27 + --> tests/ui/transmute_float_to_int.rs:10:27 | LL | let _: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f64` to a `i64` - --> tests/ui/transmute_float_to_int.rs:11:27 + --> tests/ui/transmute_float_to_int.rs:12:27 | LL | let _: i64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:13:27 + --> tests/ui/transmute_float_to_int.rs:14:27 | LL | let _: u64 = unsafe { std::mem::transmute(1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:15:27 + --> tests/ui/transmute_float_to_int.rs:16:27 | LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` diff --git a/tests/ui/transmute_int_to_char.fixed b/tests/ui/transmute_int_to_char.fixed index 17080118175..d3277d1b8c7 100644 --- a/tests/ui/transmute_int_to_char.fixed +++ b/tests/ui/transmute_int_to_char.fixed @@ -1,4 +1,5 @@ #![warn(clippy::transmute_int_to_char)] +#![allow(clippy::missing_transmute_annotations)] fn int_to_char() { let _: char = unsafe { std::char::from_u32(0_u32).unwrap() }; diff --git a/tests/ui/transmute_int_to_char.rs b/tests/ui/transmute_int_to_char.rs index 5846a97e88a..d21c4fd6fea 100644 --- a/tests/ui/transmute_int_to_char.rs +++ b/tests/ui/transmute_int_to_char.rs @@ -1,4 +1,5 @@ #![warn(clippy::transmute_int_to_char)] +#![allow(clippy::missing_transmute_annotations)] fn int_to_char() { let _: char = unsafe { std::mem::transmute(0_u32) }; diff --git a/tests/ui/transmute_int_to_char.stderr b/tests/ui/transmute_int_to_char.stderr index 8444afbd21e..e3a3620f28b 100644 --- a/tests/ui/transmute_int_to_char.stderr +++ b/tests/ui/transmute_int_to_char.stderr @@ -1,5 +1,5 @@ error: transmute from a `u32` to a `char` - --> tests/ui/transmute_int_to_char.rs:4:28 + --> tests/ui/transmute_int_to_char.rs:5:28 | LL | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` @@ -8,7 +8,7 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]` error: transmute from a `i32` to a `char` - --> tests/ui/transmute_int_to_char.rs:7:28 + --> tests/ui/transmute_int_to_char.rs:8:28 | LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` diff --git a/tests/ui/transmute_int_to_char_no_std.fixed b/tests/ui/transmute_int_to_char_no_std.fixed index 9ae4e11fb56..32a57645b46 100644 --- a/tests/ui/transmute_int_to_char_no_std.fixed +++ b/tests/ui/transmute_int_to_char_no_std.fixed @@ -1,6 +1,7 @@ #![no_std] #![feature(lang_items)] #![warn(clippy::transmute_int_to_char)] +#![allow(clippy::missing_transmute_annotations)] use core::panic::PanicInfo; diff --git a/tests/ui/transmute_int_to_char_no_std.rs b/tests/ui/transmute_int_to_char_no_std.rs index 9a2afd5bd2f..942794c32f8 100644 --- a/tests/ui/transmute_int_to_char_no_std.rs +++ b/tests/ui/transmute_int_to_char_no_std.rs @@ -1,6 +1,7 @@ #![no_std] #![feature(lang_items)] #![warn(clippy::transmute_int_to_char)] +#![allow(clippy::missing_transmute_annotations)] use core::panic::PanicInfo; diff --git a/tests/ui/transmute_int_to_char_no_std.stderr b/tests/ui/transmute_int_to_char_no_std.stderr index d2c3842b684..d94580a84d7 100644 --- a/tests/ui/transmute_int_to_char_no_std.stderr +++ b/tests/ui/transmute_int_to_char_no_std.stderr @@ -1,5 +1,5 @@ error: transmute from a `u32` to a `char` - --> tests/ui/transmute_int_to_char_no_std.rs:16:28 + --> tests/ui/transmute_int_to_char_no_std.rs:17:28 | LL | let _: char = unsafe { core::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_u32).unwrap()` @@ -8,7 +8,7 @@ LL | let _: char = unsafe { core::mem::transmute(0_u32) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]` error: transmute from a `i32` to a `char` - --> tests/ui/transmute_int_to_char_no_std.rs:19:28 + --> tests/ui/transmute_int_to_char_no_std.rs:20:28 | LL | let _: char = unsafe { core::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_i32 as u32).unwrap()` diff --git a/tests/ui/transmute_int_to_non_zero.fixed b/tests/ui/transmute_int_to_non_zero.fixed index 866c0bbf127..fe8db3dcb0c 100644 --- a/tests/ui/transmute_int_to_non_zero.fixed +++ b/tests/ui/transmute_int_to_non_zero.fixed @@ -1,4 +1,5 @@ #![warn(clippy::transmute_int_to_non_zero)] +#![allow(clippy::missing_transmute_annotations)] use core::num::*; diff --git a/tests/ui/transmute_int_to_non_zero.rs b/tests/ui/transmute_int_to_non_zero.rs index 803c4945c75..a79ed5279b1 100644 --- a/tests/ui/transmute_int_to_non_zero.rs +++ b/tests/ui/transmute_int_to_non_zero.rs @@ -1,4 +1,5 @@ #![warn(clippy::transmute_int_to_non_zero)] +#![allow(clippy::missing_transmute_annotations)] use core::num::*; diff --git a/tests/ui/transmute_int_to_non_zero.stderr b/tests/ui/transmute_int_to_non_zero.stderr index dd37bd21055..bb0b0d0ff4f 100644 --- a/tests/ui/transmute_int_to_non_zero.stderr +++ b/tests/ui/transmute_int_to_non_zero.stderr @@ -1,5 +1,5 @@ error: transmute from a `u8` to a `NonZeroU8` - --> tests/ui/transmute_int_to_non_zero.rs:18:33 + --> tests/ui/transmute_int_to_non_zero.rs:19:33 | LL | let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU8::new_unchecked(int_u8)` @@ -8,55 +8,55 @@ LL | let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_non_zero)]` error: transmute from a `u16` to a `NonZeroU16` - --> tests/ui/transmute_int_to_non_zero.rs:21:34 + --> tests/ui/transmute_int_to_non_zero.rs:22:34 | LL | let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU16::new_unchecked(int_u16)` error: transmute from a `u32` to a `NonZeroU32` - --> tests/ui/transmute_int_to_non_zero.rs:23:34 + --> tests/ui/transmute_int_to_non_zero.rs:24:34 | LL | let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU32::new_unchecked(int_u32)` error: transmute from a `u64` to a `NonZeroU64` - --> tests/ui/transmute_int_to_non_zero.rs:25:34 + --> tests/ui/transmute_int_to_non_zero.rs:26:34 | LL | let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU64::new_unchecked(int_u64)` error: transmute from a `u128` to a `NonZeroU128` - --> tests/ui/transmute_int_to_non_zero.rs:27:35 + --> tests/ui/transmute_int_to_non_zero.rs:28:35 | LL | let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU128::new_unchecked(int_u128)` error: transmute from a `i8` to a `NonZeroI8` - --> tests/ui/transmute_int_to_non_zero.rs:30:33 + --> tests/ui/transmute_int_to_non_zero.rs:31:33 | LL | let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI8::new_unchecked(int_i8)` error: transmute from a `i16` to a `NonZeroI16` - --> tests/ui/transmute_int_to_non_zero.rs:32:34 + --> tests/ui/transmute_int_to_non_zero.rs:33:34 | LL | let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI16::new_unchecked(int_i16)` error: transmute from a `i32` to a `NonZeroI32` - --> tests/ui/transmute_int_to_non_zero.rs:34:34 + --> tests/ui/transmute_int_to_non_zero.rs:35:34 | LL | let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI32::new_unchecked(int_i32)` error: transmute from a `i64` to a `NonZeroI64` - --> tests/ui/transmute_int_to_non_zero.rs:36:34 + --> tests/ui/transmute_int_to_non_zero.rs:37:34 | LL | let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI64::new_unchecked(int_i64)` error: transmute from a `i128` to a `NonZeroI128` - --> tests/ui/transmute_int_to_non_zero.rs:38:35 + --> tests/ui/transmute_int_to_non_zero.rs:39:35 | LL | let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI128::new_unchecked(int_i128)` diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs index b07851e864f..c0196ad52d4 100644 --- a/tests/ui/transmute_null_to_fn.rs +++ b/tests/ui/transmute_null_to_fn.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] #![warn(clippy::transmute_null_to_fn)] -#![allow(clippy::zero_ptr)] +#![allow(clippy::zero_ptr, clippy::missing_transmute_annotations)] // Easy to lint because these only span one line. fn one_liners() { diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed index 696def08f14..b696a574ae3 100644 --- a/tests/ui/transmute_ptr_to_ptr.fixed +++ b/tests/ui/transmute_ptr_to_ptr.fixed @@ -1,5 +1,5 @@ #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(clippy::borrow_as_ptr)] +#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 0700d8c1957..85cc1d7802c 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -1,5 +1,5 @@ #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(clippy::borrow_as_ptr)] +#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index acec14ccb6b..56330d71938 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -1,5 +1,9 @@ #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] +#![allow( + clippy::match_single_binding, + clippy::unnecessary_cast, + clippy::missing_transmute_annotations +)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 3376401e284..ce1ee8bfbfa 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -1,5 +1,9 @@ #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] +#![allow( + clippy::match_single_binding, + clippy::unnecessary_cast, + clippy::missing_transmute_annotations +)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index d7d180398e1..44cda254c3f 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`) - --> tests/ui/transmute_ptr_to_ref.rs:5:17 + --> tests/ui/transmute_ptr_to_ref.rs:9:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -8,127 +8,127 @@ LL | let _: &T = std::mem::transmute(p); = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ref)]` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> tests/ui/transmute_ptr_to_ref.rs:8:21 + --> tests/ui/transmute_ptr_to_ref.rs:12: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`) - --> tests/ui/transmute_ptr_to_ref.rs:11:17 + --> tests/ui/transmute_ptr_to_ref.rs:15: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`) - --> tests/ui/transmute_ptr_to_ref.rs:14:21 + --> tests/ui/transmute_ptr_to_ref.rs:18: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`) - --> tests/ui/transmute_ptr_to_ref.rs:17:17 + --> tests/ui/transmute_ptr_to_ref.rs:21: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`) - --> tests/ui/transmute_ptr_to_ref.rs:20:21 + --> tests/ui/transmute_ptr_to_ref.rs:24: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`) - --> tests/ui/transmute_ptr_to_ref.rs:23:17 + --> tests/ui/transmute_ptr_to_ref.rs:27: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>`) - --> tests/ui/transmute_ptr_to_ref.rs:33:32 + --> tests/ui/transmute_ptr_to_ref.rs:37: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>`) - --> tests/ui/transmute_ptr_to_ref.rs:35:33 + --> tests/ui/transmute_ptr_to_ref.rs:39: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`) - --> tests/ui/transmute_ptr_to_ref.rs:39:14 + --> tests/ui/transmute_ptr_to_ref.rs:43: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`) - --> tests/ui/transmute_ptr_to_ref.rs:44:14 + --> tests/ui/transmute_ptr_to_ref.rs:48: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`) - --> tests/ui/transmute_ptr_to_ref.rs:45:14 + --> tests/ui/transmute_ptr_to_ref.rs:49: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`) - --> tests/ui/transmute_ptr_to_ref.rs:46:14 + --> tests/ui/transmute_ptr_to_ref.rs:50: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`) - --> tests/ui/transmute_ptr_to_ref.rs:47:14 + --> tests/ui/transmute_ptr_to_ref.rs:51: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`) - --> tests/ui/transmute_ptr_to_ref.rs:55:19 + --> tests/ui/transmute_ptr_to_ref.rs:59:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:56:19 + --> tests/ui/transmute_ptr_to_ref.rs:60: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`) - --> tests/ui/transmute_ptr_to_ref.rs:58:14 + --> tests/ui/transmute_ptr_to_ref.rs:62: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`) - --> tests/ui/transmute_ptr_to_ref.rs:59:14 + --> tests/ui/transmute_ptr_to_ref.rs:63: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`) - --> tests/ui/transmute_ptr_to_ref.rs:67:19 + --> tests/ui/transmute_ptr_to_ref.rs:71:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:68:19 + --> tests/ui/transmute_ptr_to_ref.rs:72: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`) - --> tests/ui/transmute_ptr_to_ref.rs:70:14 + --> tests/ui/transmute_ptr_to_ref.rs:74: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`) - --> tests/ui/transmute_ptr_to_ref.rs:71:14 + --> tests/ui/transmute_ptr_to_ref.rs:75:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs index bdc7b9f6478..44d7af44a80 100644 --- a/tests/ui/transmute_ref_to_ref.rs +++ b/tests/ui/transmute_ref_to_ref.rs @@ -1,7 +1,7 @@ //@no-rustfix #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code)] +#![allow(dead_code, clippy::missing_transmute_annotations)] fn main() { unsafe { diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs index b67386f8588..59177058754 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.rs +++ b/tests/ui/transmute_ref_to_ref_no_std.rs @@ -1,7 +1,7 @@ //@no-rustfix #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code)] +#![allow(dead_code, clippy::missing_transmute_annotations)] #![feature(lang_items)] #![no_std] diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs index a087d09c120..dd4bac7f1ed 100644 --- a/tests/ui/transmute_undefined_repr.rs +++ b/tests/ui/transmute_undefined_repr.rs @@ -1,5 +1,10 @@ #![warn(clippy::transmute_undefined_repr)] -#![allow(clippy::unit_arg, clippy::transmute_ptr_to_ref, clippy::useless_transmute)] +#![allow( + clippy::unit_arg, + clippy::transmute_ptr_to_ref, + clippy::useless_transmute, + clippy::missing_transmute_annotations +)] use core::any::TypeId; use core::ffi::c_void; diff --git a/tests/ui/transmute_undefined_repr.stderr b/tests/ui/transmute_undefined_repr.stderr index 5504fbe16e4..b41d37a5cd1 100644 --- a/tests/ui/transmute_undefined_repr.stderr +++ b/tests/ui/transmute_undefined_repr.stderr @@ -1,5 +1,5 @@ error: transmute from `Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:29:33 + --> tests/ui/transmute_undefined_repr.rs:34:33 | LL | let _: Ty2C = transmute(value::>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | let _: Ty2C = transmute(value::>()); = help: to override `-D warnings` add `#[allow(clippy::transmute_undefined_repr)]` error: transmute into `Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:33:32 + --> tests/ui/transmute_undefined_repr.rs:38:32 | LL | let _: Ty2 = transmute(value::>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `Ty>` to `Ty2`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:42:32 + --> tests/ui/transmute_undefined_repr.rs:47:32 | LL | let _: Ty2 = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | let _: Ty2 = transmute(value::>>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `Ty2` to `Ty>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:46:36 + --> tests/ui/transmute_undefined_repr.rs:51:36 | LL | let _: Ty> = transmute(value::>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | let _: Ty> = transmute(value::>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `Ty<&Ty2>` to `&Ty2`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:54:33 + --> tests/ui/transmute_undefined_repr.rs:59:33 | LL | let _: &Ty2 = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | let _: &Ty2 = transmute(value::>>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `&Ty2` to `Ty<&Ty2>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:58:37 + --> tests/ui/transmute_undefined_repr.rs:63:37 | LL | let _: Ty<&Ty2> = transmute(value::<&Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | let _: Ty<&Ty2> = transmute(value::<&Ty2>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `std::boxed::Box>` to `&mut Ty2`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:88:45 + --> tests/ui/transmute_undefined_repr.rs:93:45 | LL | let _: &'static mut Ty2 = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | let _: &'static mut Ty2 = transmute(value::` to `std::boxed::Box>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:92:37 + --> tests/ui/transmute_undefined_repr.rs:97:37 | LL | let _: Box> = transmute(value::<&'static mut Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | let _: Box> = transmute(value::<&'static mut Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:189:39 + --> tests/ui/transmute_undefined_repr.rs:194:39 | LL | let _: *const Ty2 = transmute(value::<*const Ty2C>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | let _: *const Ty2 = transmute(value::<*const Ty2C` has an undefined layout error: transmute from `*const Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:193:50 + --> tests/ui/transmute_undefined_repr.rs:198:50 | LL | let _: *const Ty2C> = transmute(value::<*const Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _: *const Ty2C> = transmute(value::<*const T = note: the contained type `Ty2` has an undefined layout error: transmute from `std::vec::Vec>` to `std::vec::Vec>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:240:35 + --> tests/ui/transmute_undefined_repr.rs:245:35 | LL | let _: Vec> = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL | let _: Vec> = transmute(value::>>()); = note: two instances of the same generic type (`Vec`) may have different layouts error: transmute from `std::vec::Vec>` to `std::vec::Vec>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:244:35 + --> tests/ui/transmute_undefined_repr.rs:249:35 | LL | let _: Vec> = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 2365695d691..51682da4a98 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -3,7 +3,7 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(unused, clippy::borrow_as_ptr)] +#![allow(unused, clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] use std::mem::{size_of, transmute}; diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs index cd1607b4c19..e5fcdef7a1c 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -3,7 +3,7 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(unused, clippy::borrow_as_ptr)] +#![allow(unused, clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] use std::mem::{size_of, transmute}; diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index 88b8c996523..c2deb6b6c46 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -2,7 +2,7 @@ #![warn(clippy::transmuting_null)] #![allow(clippy::zero_ptr)] #![allow(clippy::transmute_ptr_to_ref)] -#![allow(clippy::eq_op)] +#![allow(clippy::eq_op, clippy::missing_transmute_annotations)] // Easy to lint because these only span one line. fn one_liners() { diff --git a/tests/ui/uninhabited_references.rs b/tests/ui/uninhabited_references.rs index cd07b590a61..3569366ed05 100644 --- a/tests/ui/uninhabited_references.rs +++ b/tests/ui/uninhabited_references.rs @@ -1,4 +1,5 @@ #![warn(clippy::uninhabited_references)] +#![allow(clippy::missing_transmute_annotations)] #![feature(never_type)] fn ret_uninh_ref() -> &'static std::convert::Infallible { diff --git a/tests/ui/uninhabited_references.stderr b/tests/ui/uninhabited_references.stderr index 446d4e75557..8c9b206f429 100644 --- a/tests/ui/uninhabited_references.stderr +++ b/tests/ui/uninhabited_references.stderr @@ -1,5 +1,5 @@ error: dereferencing a reference to an uninhabited type would be undefined behavior - --> tests/ui/uninhabited_references.rs:4:23 + --> tests/ui/uninhabited_references.rs:5:23 | LL | fn ret_uninh_ref() -> &'static std::convert::Infallible { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn ret_uninh_ref() -> &'static std::convert::Infallible { = help: to override `-D warnings` add `#[allow(clippy::uninhabited_references)]` error: dereferencing a reference to an uninhabited type would be undefined behavior - --> tests/ui/uninhabited_references.rs:10:30 + --> tests/ui/uninhabited_references.rs:11:30 | LL | fn $name(x: &$ty) -> &$ty { | ^^^^ @@ -19,7 +19,7 @@ LL | ret_something!(id_never, !); = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior - --> tests/ui/uninhabited_references.rs:11:14 + --> tests/ui/uninhabited_references.rs:12:14 | LL | &*x | ^^ @@ -30,7 +30,7 @@ LL | ret_something!(id_never, !); = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior - --> tests/ui/uninhabited_references.rs:21:13 + --> tests/ui/uninhabited_references.rs:22:13 | LL | let _ = *x; | ^^ diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 6ea7857a238..37e9e627c4c 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -7,7 +7,9 @@ clippy::upper_case_acronyms, clippy::from_over_into, clippy::self_named_constructors, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::missing_transmute_annotations, + clippy::missing_transmute_annotations )] #[macro_use] diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 338cc00e45a..06792034b74 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -7,7 +7,9 @@ clippy::upper_case_acronyms, clippy::from_over_into, clippy::self_named_constructors, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::missing_transmute_annotations, + clippy::missing_transmute_annotations )] #[macro_use] diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index d7aa8410a47..65b8ac482ab 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> tests/ui/use_self.rs:22:21 + --> tests/ui/use_self.rs:24:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -8,253 +8,253 @@ LL | fn new() -> Foo { = help: to override `-D warnings` add `#[allow(clippy::use_self)]` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:23:13 + --> tests/ui/use_self.rs:25:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:25:22 + --> tests/ui/use_self.rs:27:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:26:13 + --> tests/ui/use_self.rs:28:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:31:25 + --> tests/ui/use_self.rs:33:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:32:13 + --> tests/ui/use_self.rs:34:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:73:28 + --> tests/ui/use_self.rs:75:28 | LL | fn clone(&self) -> Foo<'a> { | ^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:106:24 + --> tests/ui/use_self.rs:108:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:106:55 + --> tests/ui/use_self.rs:108:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:121:13 + --> tests/ui/use_self.rs:123:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:156:29 + --> tests/ui/use_self.rs:158:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:157:21 + --> tests/ui/use_self.rs:159:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:168:21 + --> tests/ui/use_self.rs:170:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:169:13 + --> tests/ui/use_self.rs:171:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:186:21 + --> tests/ui/use_self.rs:188:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:187:21 + --> tests/ui/use_self.rs:189:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:188:21 + --> tests/ui/use_self.rs:190:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:230:13 + --> tests/ui/use_self.rs:232:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:231:13 + --> tests/ui/use_self.rs:233:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:233:13 + --> tests/ui/use_self.rs:235:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:252:13 + --> tests/ui/use_self.rs:254:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:266:25 + --> tests/ui/use_self.rs:268:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:267:13 + --> tests/ui/use_self.rs:269:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:271:16 + --> tests/ui/use_self.rs:273:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:271:22 + --> tests/ui/use_self.rs:273:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:294:29 + --> tests/ui/use_self.rs:296:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:295:13 + --> tests/ui/use_self.rs:297:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:467:13 + --> tests/ui/use_self.rs:469:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:504:13 + --> tests/ui/use_self.rs:506:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:541:17 + --> tests/ui/use_self.rs:543:17 | LL | Foo::Bar => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:542:17 + --> tests/ui/use_self.rs:544:17 | LL | Foo::Baz => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:548:20 + --> tests/ui/use_self.rs:550:20 | LL | if let Foo::Bar = self { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:572:17 + --> tests/ui/use_self.rs:574:17 | LL | Something::Num(n) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:573:17 + --> tests/ui/use_self.rs:575:17 | LL | Something::TupleNums(n, _m) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:574:17 + --> tests/ui/use_self.rs:576:17 | LL | Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:580:17 + --> tests/ui/use_self.rs:582:17 | LL | crate::issue8845::Something::Num(n) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:581:17 + --> tests/ui/use_self.rs:583:17 | LL | crate::issue8845::Something::TupleNums(n, _m) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:582:17 + --> tests/ui/use_self.rs:584:17 | LL | crate::issue8845::Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:598:17 + --> tests/ui/use_self.rs:600:17 | LL | let Foo(x) = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:603:17 + --> tests/ui/use_self.rs:605:17 | LL | let crate::issue8845::Foo(x) = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:610:17 + --> tests/ui/use_self.rs:612:17 | LL | let Bar { x, .. } = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:615:17 + --> tests/ui/use_self.rs:617:17 | LL | let crate::issue8845::Bar { x, .. } = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:654:17 + --> tests/ui/use_self.rs:656:17 | LL | E::A => {}, | ^ help: use the applicable keyword: `Self` From ffa12798c0f24fb2fe8659aa917a9b9308f8bc7b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Feb 2024 18:12:32 +0100 Subject: [PATCH 37/79] Correctly handle `transmute` as return value from `block` and `let var: _ = transmute` --- .../missing_transmute_annotations.rs | 33 ++++++++++++++++--- tests/ui/missing_transmute_annotations.fixed | 7 ++++ tests/ui/missing_transmute_annotations.rs | 7 ++++ tests/ui/missing_transmute_annotations.stderr | 32 ++++++++++++------ 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs index cbc52b6b801..84f3d9c169a 100644 --- a/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -1,5 +1,5 @@ use rustc_errors::Applicability; -use rustc_hir::{GenericArg, HirId, Node, Path, TyKind}; +use rustc_hir::{GenericArg, HirId, Local, Node, Path, TyKind}; use rustc_lint::LateContext; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; @@ -8,6 +8,27 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS; +fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) -> Option> { + let mut parent_iter = cx.tcx.hir().parent_iter(expr_hir_id); + if let Some((_, node)) = parent_iter.next() { + match node { + Node::Local(local) => Some(*local), + Node::Block(_) => { + if let Some((parent_hir_id, Node::Expr(expr))) = parent_iter.next() + && matches!(expr.kind, rustc_hir::ExprKind::Block(_, _)) + { + get_parent_local_binding_ty(cx, parent_hir_id) + } else { + None + } + }, + _ => None, + } + } else { + None + } +} + pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, path: &Path<'tcx>, @@ -33,12 +54,14 @@ pub(super) fn check<'tcx>( return false; } // If it's being set as a local variable value... - if let Some((_, node)) = cx.tcx.hir().parent_iter(expr_hir_id).next() - && let Node::Local(local) = node + if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) // ... which does have type annotations. - && local.ty.is_some() + && let Some(ty) = local.ty { - return false; + // If this is a `let x: _ =`, we shouldn't lint. + if !matches!(ty.kind, TyKind::Infer) { + return false; + } } span_lint_and_sugg( cx, diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed index cf6117b171b..7fe8063f40f 100644 --- a/tests/ui/missing_transmute_annotations.fixed +++ b/tests/ui/missing_transmute_annotations.fixed @@ -1,6 +1,7 @@ //@aux-build:macro_rules.rs #![warn(clippy::missing_transmute_annotations)] +#![allow(clippy::let_with_type_underscore)] #[macro_use] extern crate macro_rules; @@ -68,7 +69,12 @@ unsafe fn foo9() -> i32 { } fn main() { + let x: _ = unsafe { std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) }; + //~^ ERROR: transmute used without annotations unsafe { + let x: _ = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + // Should not warn. std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); @@ -76,4 +82,5 @@ fn main() { let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); let x: i32 = std::mem::transmute([1u16, 2u16]); } + let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; } diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs index 53fd7a84939..9c42077054e 100644 --- a/tests/ui/missing_transmute_annotations.rs +++ b/tests/ui/missing_transmute_annotations.rs @@ -1,6 +1,7 @@ //@aux-build:macro_rules.rs #![warn(clippy::missing_transmute_annotations)] +#![allow(clippy::let_with_type_underscore)] #[macro_use] extern crate macro_rules; @@ -68,7 +69,12 @@ unsafe fn foo9() -> i32 { } fn main() { + let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) }; + //~^ ERROR: transmute used without annotations unsafe { + let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + // Should not warn. std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); @@ -76,4 +82,5 @@ fn main() { let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); let x: i32 = std::mem::transmute([1u16, 2u16]); } + let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; } diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr index 9f2e8e8c9e7..180cd007b13 100644 --- a/tests/ui/missing_transmute_annotations.stderr +++ b/tests/ui/missing_transmute_annotations.stderr @@ -1,5 +1,5 @@ error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:19:15 + --> tests/ui/missing_transmute_annotations.rs:20:15 | LL | std::mem::transmute([1u16, 2u16]) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` @@ -8,37 +8,37 @@ LL | std::mem::transmute([1u16, 2u16]) = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:24:15 + --> tests/ui/missing_transmute_annotations.rs:25:15 | LL | std::mem::transmute::<_, _>([1u16, 2u16]) | ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:29:15 + --> tests/ui/missing_transmute_annotations.rs:30:15 | LL | std::mem::transmute::<_, i32>([1u16, 2u16]) | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:34:15 + --> tests/ui/missing_transmute_annotations.rs:35:15 | LL | std::mem::transmute::<[u16; 2], _>([1u16, 2u16]) | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:39:32 + --> tests/ui/missing_transmute_annotations.rs:40:32 | LL | let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:41:19 + --> tests/ui/missing_transmute_annotations.rs:42:19 | LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])) | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:10:19 + --> tests/ui/missing_transmute_annotations.rs:11:19 | LL | std::mem::transmute($e) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` @@ -49,16 +49,28 @@ LL | local_bad_transmute!([1u16, 2u16]) = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:61:15 + --> tests/ui/missing_transmute_annotations.rs:62:15 | LL | std::mem::transmute(0i32) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:66:15 + --> tests/ui/missing_transmute_annotations.rs:67:15 | LL | std::mem::transmute(Foo::A) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` -error: aborting due to 9 previous errors +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:72:35 + | +LL | let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) }; + | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:75:30 + | +LL | let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]); + | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: aborting due to 11 previous errors From ee2558223f51b894475dcd1458b21f7ea393508a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 15 Mar 2024 18:42:35 +0100 Subject: [PATCH 38/79] Do no emit `missing_transmute_annotations` lint if the `transmute` is the only expr in the function --- .../missing_transmute_annotations.rs | 25 +++++-- tests/ui/missing_transmute_annotations.fixed | 68 ++++++++----------- tests/ui/missing_transmute_annotations.rs | 66 ++++++++---------- tests/ui/missing_transmute_annotations.stderr | 50 +++++++------- 4 files changed, 102 insertions(+), 107 deletions(-) diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs index 84f3d9c169a..ec7041b945b 100644 --- a/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -1,11 +1,10 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_errors::Applicability; use rustc_hir::{GenericArg, HirId, Local, Node, Path, TyKind}; use rustc_lint::LateContext; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; -use clippy_utils::diagnostics::span_lint_and_sugg; - use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS; fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) -> Option> { @@ -29,6 +28,15 @@ fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) } } +fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool { + let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id); + if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id) { + let body = cx.tcx.hir().body(body_id); + return body.value.peel_blocks().hir_id == expr_hir_id; + } + false +} + pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, path: &Path<'tcx>, @@ -54,14 +62,17 @@ pub(super) fn check<'tcx>( return false; } // If it's being set as a local variable value... - if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) + if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) { // ... which does have type annotations. - && let Some(ty) = local.ty - { - // If this is a `let x: _ =`, we shouldn't lint. - if !matches!(ty.kind, TyKind::Infer) { + if let Some(ty) = local.ty + // If this is a `let x: _ =`, we should lint. + && !matches!(ty.kind, TyKind::Infer) + { return false; } + // We check if this transmute is not the only element in the function + } else if is_function_block(cx, expr_hir_id) { + return false; } span_lint_and_sugg( cx, diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed index 7fe8063f40f..a3c94ab139e 100644 --- a/tests/ui/missing_transmute_annotations.fixed +++ b/tests/ui/missing_transmute_annotations.fixed @@ -9,6 +9,7 @@ extern crate macro_rules; macro_rules! local_bad_transmute { ($e:expr) => { std::mem::transmute::<[u16; 2], i32>($e) + //~^ ERROR: transmute used without annotations }; } @@ -17,55 +18,46 @@ fn bar(x: i32) -> i32 { } unsafe fn foo1() -> i32 { - std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations + // Should not warn! + std::mem::transmute([1u16, 2u16]) } -unsafe fn foo2() -> i32 { - std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo3() -> i32 { - std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo4() -> i32 { - std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo5() -> i32 { - let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])); - //~^ ERROR: transmute used without annotations - bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo6() -> i32 { - local_bad_transmute!([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo7() -> i32 { - // Should not warn. - bad_transmute!([1u16, 2u16]) -} +// Should not warn! +const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; #[repr(i32)] enum Foo { A = 0, } -unsafe fn foo8() -> Foo { - std::mem::transmute::(0i32) +unsafe fn foo2() -> i32 { + let mut i: i32 = 0; + i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); //~^ ERROR: transmute used without annotations -} -unsafe fn foo9() -> i32 { - std::mem::transmute::(Foo::A) + let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])); //~^ ERROR: transmute used without annotations + bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])); + //~^ ERROR: transmute used without annotations + + i = local_bad_transmute!([1u16, 2u16]); + + // Should not warn. + i = bad_transmute!([1u16, 2u16]); + + i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]); + //~^ ERROR: transmute used without annotations + + i = std::mem::transmute::(Foo::A); + //~^ ERROR: transmute used without annotations + + i } fn main() { diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs index 9c42077054e..c12e1b0f8d2 100644 --- a/tests/ui/missing_transmute_annotations.rs +++ b/tests/ui/missing_transmute_annotations.rs @@ -9,6 +9,7 @@ extern crate macro_rules; macro_rules! local_bad_transmute { ($e:expr) => { std::mem::transmute($e) + //~^ ERROR: transmute used without annotations }; } @@ -17,55 +18,46 @@ fn bar(x: i32) -> i32 { } unsafe fn foo1() -> i32 { + // Should not warn! std::mem::transmute([1u16, 2u16]) - //~^ ERROR: transmute used without annotations } -unsafe fn foo2() -> i32 { - std::mem::transmute::<_, _>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo3() -> i32 { - std::mem::transmute::<_, i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo4() -> i32 { - std::mem::transmute::<[u16; 2], _>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo5() -> i32 { - let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); - //~^ ERROR: transmute used without annotations - bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo6() -> i32 { - local_bad_transmute!([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo7() -> i32 { - // Should not warn. - bad_transmute!([1u16, 2u16]) -} +// Should not warn! +const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; #[repr(i32)] enum Foo { A = 0, } -unsafe fn foo8() -> Foo { - std::mem::transmute(0i32) +unsafe fn foo2() -> i32 { + let mut i: i32 = 0; + i = std::mem::transmute([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<_, _>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<_, i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]); //~^ ERROR: transmute used without annotations -} -unsafe fn foo9() -> i32 { - std::mem::transmute(Foo::A) + let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); //~^ ERROR: transmute used without annotations + bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); + //~^ ERROR: transmute used without annotations + + i = local_bad_transmute!([1u16, 2u16]); + + // Should not warn. + i = bad_transmute!([1u16, 2u16]); + + i = std::mem::transmute([0i16, 0i16]); + //~^ ERROR: transmute used without annotations + + i = std::mem::transmute(Foo::A); + //~^ ERROR: transmute used without annotations + + i } fn main() { diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr index 180cd007b13..5903ed488ef 100644 --- a/tests/ui/missing_transmute_annotations.stderr +++ b/tests/ui/missing_transmute_annotations.stderr @@ -1,40 +1,40 @@ error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:20:15 + --> tests/ui/missing_transmute_annotations.rs:35:19 | -LL | std::mem::transmute([1u16, 2u16]) - | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` +LL | i = std::mem::transmute([1u16, 2u16]); + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` | = note: `-D clippy::missing-transmute-annotations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:25:15 + --> tests/ui/missing_transmute_annotations.rs:37:19 | -LL | std::mem::transmute::<_, _>([1u16, 2u16]) - | ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` +LL | i = std::mem::transmute::<_, _>([1u16, 2u16]); + | ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:30:15 + --> tests/ui/missing_transmute_annotations.rs:39:19 | -LL | std::mem::transmute::<_, i32>([1u16, 2u16]) - | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` +LL | i = std::mem::transmute::<_, i32>([1u16, 2u16]); + | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:35:15 + --> tests/ui/missing_transmute_annotations.rs:41:19 | -LL | std::mem::transmute::<[u16; 2], _>([1u16, 2u16]) - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` +LL | i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:40:32 + --> tests/ui/missing_transmute_annotations.rs:44:32 | LL | let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:42:19 + --> tests/ui/missing_transmute_annotations.rs:46:19 | -LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])) +LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations @@ -43,31 +43,31 @@ error: transmute used without annotations LL | std::mem::transmute($e) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` ... -LL | local_bad_transmute!([1u16, 2u16]) - | ---------------------------------- in this macro invocation +LL | i = local_bad_transmute!([1u16, 2u16]); + | ---------------------------------- in this macro invocation | = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:62:15 + --> tests/ui/missing_transmute_annotations.rs:54:19 | -LL | std::mem::transmute(0i32) - | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` +LL | i = std::mem::transmute([0i16, 0i16]); + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[i16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:67:15 + --> tests/ui/missing_transmute_annotations.rs:57:19 | -LL | std::mem::transmute(Foo::A) - | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` +LL | i = std::mem::transmute(Foo::A); + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:72:35 + --> tests/ui/missing_transmute_annotations.rs:64:35 | LL | let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) }; | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:75:30 + --> tests/ui/missing_transmute_annotations.rs:67:30 | LL | let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]); | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` From 0cf9d9c440044b07351f0d3405fc675de8885c09 Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Sat, 23 Mar 2024 20:59:30 -0600 Subject: [PATCH 39/79] restrict manual_clamp to const case, bring it out of nursery --- clippy_lints/src/manual_clamp.rs | 30 ++- tests/ui/manual_clamp.fixed | 287 +++++++++++++++++++------- tests/ui/manual_clamp.rs | 333 ++++++++++++++++++++++--------- tests/ui/manual_clamp.stderr | 188 ++++++++--------- 4 files changed, 574 insertions(+), 264 deletions(-) diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 830af77968c..0148e6deb56 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -1,4 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::higher::If; use clippy_utils::sugg::Sugg; @@ -17,6 +18,7 @@ use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::Span; +use std::cmp::Ordering; use std::ops::Deref; declare_clippy_lint! { @@ -80,7 +82,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.66.0"] pub MANUAL_CLAMP, - nursery, + complexity, "using a clamp pattern instead of the clamp function" } impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]); @@ -103,6 +105,24 @@ struct ClampSuggestion<'tcx> { hir_with_ignore_attr: Option, } +impl<'tcx> ClampSuggestion<'tcx> { + /// This function will return true if and only if you can demonstrate at compile time that min + /// is less than max. + fn min_less_than_max(&self, cx: &LateContext<'tcx>) -> bool { + let max_type = cx.typeck_results().expr_ty(self.params.max); + let min_type = cx.typeck_results().expr_ty(self.params.min); + if max_type != min_type { + return false; + } + let max = constant(cx, cx.typeck_results(), self.params.max); + let min = constant(cx, cx.typeck_results(), self.params.min); + let cmp = max + .zip(min) + .and_then(|(max, min)| Constant::partial_cmp(cx.tcx, max_type, &min, &max)); + cmp.is_some_and(|cmp| cmp != Ordering::Greater) + } +} + #[derive(Debug)] struct InputMinMax<'tcx> { input: &'tcx Expr<'tcx>, @@ -123,7 +143,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp { .or_else(|| is_match_pattern(cx, expr)) .or_else(|| is_if_elseif_pattern(cx, expr)); if let Some(suggestion) = suggestion { - emit_suggestion(cx, &suggestion); + if suggestion.min_less_than_max(cx) { + emit_suggestion(cx, &suggestion); + } } } } @@ -133,7 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp { return; } for suggestion in is_two_if_pattern(cx, block) { - emit_suggestion(cx, &suggestion); + if suggestion.min_less_than_max(cx) { + emit_suggestion(cx, &suggestion); + } } } extract_msrv_attr!(LateContext); diff --git a/tests/ui/manual_clamp.fixed b/tests/ui/manual_clamp.fixed index c5355cce8e2..8d57cbbf51b 100644 --- a/tests/ui/manual_clamp.fixed +++ b/tests/ui/manual_clamp.fixed @@ -17,48 +17,171 @@ const CONST_F64_MIN: f64 = 4.0; fn main() { let (input, min, max) = (0, -2, 3); - // Lint - let x0 = input.clamp(min, max); + // Min and max are not const, so this shouldn't trigger the lint. + let x0 = if max < input { + max + } else if min > input { + min + } else { + input + }; - let x1 = input.clamp(min, max); + let x1 = if input > max { + max + } else if input < min { + min + } else { + input + }; - let x2 = input.clamp(min, max); + let x2 = if input < min { + min + } else if input > max { + max + } else { + input + }; - let x3 = input.clamp(min, max); + let x3 = if min > input { + min + } else if max < input { + max + } else { + input + }; - let x4 = input.clamp(min, max); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + let x4 = input.max(min).min(max); - let x5 = input.clamp(min, max); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + let x5 = input.min(max).max(min); - let x6 = input.clamp(min, max); + let x6 = match input { + x if x > max => max, + x if x < min => min, + x => x, + }; - let x7 = input.clamp(min, max); + let x7 = match input { + x if x < min => min, + x if x > max => max, + x => x, + }; - let x8 = input.clamp(min, max); + let x8 = match input { + x if max < x => max, + x if min > x => min, + x => x, + }; let mut x9 = input; - x9 = x9.clamp(min, max); + if x9 < min { + x9 = min; + } + if x9 > max { + x9 = max; + } - let x10 = input.clamp(min, max); + let x10 = match input { + x if min > x => min, + x if max < x => max, + x => x, + }; let mut x11 = input; let _ = 1; - x11 = x11.clamp(min, max); + if x11 > max { + x11 = max; + } + if x11 < min { + x11 = min; + } let mut x12 = input; - x12 = x12.clamp(min, max); + if min > x12 { + x12 = min; + } + if max < x12 { + x12 = max; + } let mut x13 = input; - x13 = x13.clamp(min, max); + if max < x13 { + x13 = max; + } + if min > x13 { + x13 = min; + } + + { + let (input, min, max) = (0.0f64, -2.0, 3.0); + let x14 = if input > max { + max + } else if input < min { + min + } else { + input + }; + } + let mut x15 = input; + if x15 < min { + x15 = min; + } else if x15 > max { + x15 = max; + } + + // It's important this be the last set of statements + let mut x16 = input; + if max < x16 { + x16 = max; + } + if min > x16 { + x16 = min; + } +} + +fn const_main() { + let input = 0; + // Min and max are const, so this should trigger the lint. + let x0 = input.clamp(CONST_MIN, CONST_MAX); + + let x1 = input.clamp(CONST_MIN, CONST_MAX); + + let x2 = input.clamp(CONST_MIN, CONST_MAX); + + let x3 = input.clamp(CONST_MIN, CONST_MAX); + + let x4 = input.clamp(CONST_MIN, CONST_MAX); + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + + let x5 = input.clamp(CONST_MIN, CONST_MAX); + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + + let x6 = input.clamp(CONST_MIN, CONST_MAX); + + let x7 = input.clamp(CONST_MIN, CONST_MAX); + + let x8 = input.clamp(CONST_MIN, CONST_MAX); + + let mut x9 = input; + x9 = x9.clamp(CONST_MIN, CONST_MAX); + + let x10 = input.clamp(CONST_MIN, CONST_MAX); + + let mut x11 = input; + let _ = 1; + x11 = x11.clamp(CONST_MIN, CONST_MAX); + + let mut x12 = input; + x12 = x12.clamp(CONST_MIN, CONST_MAX); + + let mut x13 = input; + x13 = x13.clamp(CONST_MIN, CONST_MAX); let x14 = input.clamp(CONST_MIN, CONST_MAX); { - let (input, min, max) = (0.0f64, -2.0, 3.0); - let x15 = input.clamp(min, max); + let input = 0.0f64; + let x15 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); } { let input: i32 = cmp_min_max(1); @@ -114,108 +237,128 @@ fn main() { //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() } let mut x32 = input; - x32 = x32.clamp(min, max); + x32 = x32.clamp(CONST_MIN, CONST_MAX); + + // Flip the script, swap the places of min and max. Make sure this doesn't + // trigger when clamp would be guaranteed to panic. + let mut x33 = input; + if x33 < CONST_MAX { + x33 = CONST_MAX; + } else if x33 > CONST_MIN { + x33 = CONST_MIN; + } + + // Do it again for NaN + #[allow(invalid_nan_comparisons)] + { + let mut x34 = input as f64; + if x34 < f64::NAN { + x34 = f64::NAN; + } else if x34 > CONST_F64_MAX { + x34 = CONST_F64_MAX; + } + } // It's important this be the last set of statements - let mut x33 = input; - x33 = x33.clamp(min, max); + let mut x35 = input; + x35 = x35.clamp(CONST_MIN, CONST_MAX); } // This code intentionally nonsense. fn no_lint() { - let (input, min, max) = (0, -2, 3); - let x0 = if max < input { - max - } else if min > input { - max + let input = 0; + let x0 = if CONST_MAX < input { + CONST_MAX + } else if CONST_MIN > input { + CONST_MAX } else { - min + CONST_MIN }; - let x1 = if input > max { - max - } else if input > min { - min + let x1 = if input > CONST_MAX { + CONST_MAX + } else if input > CONST_MIN { + CONST_MIN } else { - max + CONST_MAX }; - let x2 = if max < min { - min - } else if input > max { + let x2 = if CONST_MAX < CONST_MIN { + CONST_MIN + } else if input > CONST_MAX { input } else { input }; - let x3 = if min > input { + let x3 = if CONST_MIN > input { input - } else if max < input { - max + } else if CONST_MAX < input { + CONST_MAX } else { - max + CONST_MAX }; let x6 = match input { - x if x < max => x, - x if x < min => x, + x if x < CONST_MAX => x, + x if x < CONST_MIN => x, x => x, }; let x7 = match input { - x if x < min => max, - x if x > max => min, + x if x < CONST_MIN => CONST_MAX, + x if x > CONST_MAX => CONST_MIN, x => x, }; let x8 = match input { - x if max > x => max, - x if min > x => min, + x if CONST_MAX > x => CONST_MAX, + x if CONST_MIN > x => CONST_MIN, x => x, }; let mut x9 = input; - if x9 > min { - x9 = min; + if x9 > CONST_MIN { + x9 = CONST_MIN; } - if x9 > max { - x9 = max; + if x9 > CONST_MAX { + x9 = CONST_MAX; } let x10 = match input { - x if min > x => min, - x if max < x => max, - x => min, + x if CONST_MIN > x => CONST_MIN, + x if CONST_MAX < x => CONST_MAX, + x => CONST_MIN, }; let mut x11 = input; - if x11 > max { - x11 = min; + if x11 > CONST_MAX { + x11 = CONST_MIN; } - if x11 < min { - x11 = max; + if x11 < CONST_MIN { + x11 = CONST_MAX; } let mut x12 = input; - if min > x12 { - x12 = max * 3; + if CONST_MIN > x12 { + x12 = CONST_MAX * 3; } - if max < x12 { - x12 = min; + if CONST_MAX < x12 { + x12 = CONST_MIN; } let mut x13 = input; - if max < x13 { - let x13 = max; + if CONST_MAX < x13 { + let x13 = CONST_MAX; } - if min > x13 { - x13 = min; + if CONST_MIN > x13 { + x13 = CONST_MIN; } let mut x14 = input; - if x14 < min { + if x14 < CONST_MIN { x14 = 3; - } else if x14 > max { - x14 = max; + } else if x14 > CONST_MAX { + x14 = CONST_MAX; } { let input: i32 = cmp_min_max(1); @@ -272,8 +415,8 @@ fn msrv_1_49() { #[clippy::msrv = "1.50"] fn msrv_1_50() { - let (input, min, max) = (0, -1, 2); - let _ = input.clamp(min, max); + let input = 0; + let _ = input.clamp(CONST_MIN, CONST_MAX); } const fn _const() { diff --git a/tests/ui/manual_clamp.rs b/tests/ui/manual_clamp.rs index cacb40ae027..4d2a0c47bbd 100644 --- a/tests/ui/manual_clamp.rs +++ b/tests/ui/manual_clamp.rs @@ -17,10 +17,8 @@ const CONST_F64_MIN: f64 = 4.0; fn main() { let (input, min, max) = (0, -2, 3); - // Lint + // Min and max are not const, so this shouldn't trigger the lint. let x0 = if max < input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min max } else if min > input { min @@ -29,8 +27,6 @@ fn main() { }; let x1 = if input > max { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min max } else if input < min { min @@ -39,8 +35,6 @@ fn main() { }; let x2 = if input < min { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min min } else if input > max { max @@ -49,8 +43,6 @@ fn main() { }; let x3 = if min > input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min min } else if max < input { max @@ -59,32 +51,22 @@ fn main() { }; let x4 = input.max(min).min(max); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min let x5 = input.min(max).max(min); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min let x6 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x if x > max => max, x if x < min => min, x => x, }; let x7 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x if x < min => min, x if x > max => max, x => x, }; let x8 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x if max < x => max, x if min > x => min, x => x, @@ -92,8 +74,6 @@ fn main() { let mut x9 = input; if x9 < min { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x9 = min; } if x9 > max { @@ -101,8 +81,6 @@ fn main() { } let x10 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x if min > x => min, x if max < x => max, x => x, @@ -111,8 +89,6 @@ fn main() { let mut x11 = input; let _ = 1; if x11 > max { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x11 = max; } if x11 < min { @@ -121,8 +97,6 @@ fn main() { let mut x12 = input; if min > x12 { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x12 = min; } if max < x12 { @@ -131,14 +105,163 @@ fn main() { let mut x13 = input; if max < x13 { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min x13 = max; } if min > x13 { x13 = min; } + { + let (input, min, max) = (0.0f64, -2.0, 3.0); + let x14 = if input > max { + max + } else if input < min { + min + } else { + input + }; + } + let mut x15 = input; + if x15 < min { + x15 = min; + } else if x15 > max { + x15 = max; + } + + // It's important this be the last set of statements + let mut x16 = input; + if max < x16 { + x16 = max; + } + if min > x16 { + x16 = min; + } +} + +fn const_main() { + let input = 0; + // Min and max are const, so this should trigger the lint. + let x0 = if CONST_MAX < input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + CONST_MAX + } else if CONST_MIN > input { + CONST_MIN + } else { + input + }; + + let x1 = if input > CONST_MAX { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + CONST_MAX + } else if input < CONST_MIN { + CONST_MIN + } else { + input + }; + + let x2 = if input < CONST_MIN { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + CONST_MIN + } else if input > CONST_MAX { + CONST_MAX + } else { + input + }; + + let x3 = if CONST_MIN > input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + CONST_MIN + } else if CONST_MAX < input { + CONST_MAX + } else { + input + }; + + let x4 = input.max(CONST_MIN).min(CONST_MAX); + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + + let x5 = input.min(CONST_MAX).max(CONST_MIN); + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + + let x6 = match input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x if x > CONST_MAX => CONST_MAX, + x if x < CONST_MIN => CONST_MIN, + x => x, + }; + + let x7 = match input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x if x < CONST_MIN => CONST_MIN, + x if x > CONST_MAX => CONST_MAX, + x => x, + }; + + let x8 = match input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x if CONST_MAX < x => CONST_MAX, + x if CONST_MIN > x => CONST_MIN, + x => x, + }; + + let mut x9 = input; + if x9 < CONST_MIN { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x9 = CONST_MIN; + } + if x9 > CONST_MAX { + x9 = CONST_MAX; + } + + let x10 = match input { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x if CONST_MIN > x => CONST_MIN, + x if CONST_MAX < x => CONST_MAX, + x => x, + }; + + let mut x11 = input; + let _ = 1; + if x11 > CONST_MAX { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x11 = CONST_MAX; + } + if x11 < CONST_MIN { + x11 = CONST_MIN; + } + + let mut x12 = input; + if CONST_MIN > x12 { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x12 = CONST_MIN; + } + if CONST_MAX < x12 { + x12 = CONST_MAX; + } + + let mut x13 = input; + if CONST_MAX < x13 { + //~^ ERROR: clamp-like pattern without using clamp function + //~| NOTE: clamp will panic if max < min + x13 = CONST_MAX; + } + if CONST_MIN > x13 { + x13 = CONST_MIN; + } + let x14 = if input > CONST_MAX { //~^ ERROR: clamp-like pattern without using clamp function //~| NOTE: clamp will panic if max < min @@ -149,13 +272,13 @@ fn main() { input }; { - let (input, min, max) = (0.0f64, -2.0, 3.0); - let x15 = if input > max { + let input = 0.0f64; + let x15 = if input > CONST_F64_MAX { //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() - max - } else if input < min { - min + //~| NOTE: clamp will panic if max < min + CONST_F64_MAX + } else if input < CONST_F64_MIN { + CONST_F64_MIN } else { input }; @@ -214,121 +337,141 @@ fn main() { //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() } let mut x32 = input; - if x32 < min { + if x32 < CONST_MIN { //~^ ERROR: clamp-like pattern without using clamp function //~| NOTE: clamp will panic if max < min - x32 = min; - } else if x32 > max { - x32 = max; + x32 = CONST_MIN; + } else if x32 > CONST_MAX { + x32 = CONST_MAX; + } + + // Flip the script, swap the places of min and max. Make sure this doesn't + // trigger when clamp would be guaranteed to panic. + let mut x33 = input; + if x33 < CONST_MAX { + x33 = CONST_MAX; + } else if x33 > CONST_MIN { + x33 = CONST_MIN; + } + + // Do it again for NaN + #[allow(invalid_nan_comparisons)] + { + let mut x34 = input as f64; + if x34 < f64::NAN { + x34 = f64::NAN; + } else if x34 > CONST_F64_MAX { + x34 = CONST_F64_MAX; + } } // It's important this be the last set of statements - let mut x33 = input; - if max < x33 { + let mut x35 = input; + if CONST_MAX < x35 { //~^ ERROR: clamp-like pattern without using clamp function //~| NOTE: clamp will panic if max < min - x33 = max; + x35 = CONST_MAX; } - if min > x33 { - x33 = min; + if CONST_MIN > x35 { + x35 = CONST_MIN; } } // This code intentionally nonsense. fn no_lint() { - let (input, min, max) = (0, -2, 3); - let x0 = if max < input { - max - } else if min > input { - max + let input = 0; + let x0 = if CONST_MAX < input { + CONST_MAX + } else if CONST_MIN > input { + CONST_MAX } else { - min + CONST_MIN }; - let x1 = if input > max { - max - } else if input > min { - min + let x1 = if input > CONST_MAX { + CONST_MAX + } else if input > CONST_MIN { + CONST_MIN } else { - max + CONST_MAX }; - let x2 = if max < min { - min - } else if input > max { + let x2 = if CONST_MAX < CONST_MIN { + CONST_MIN + } else if input > CONST_MAX { input } else { input }; - let x3 = if min > input { + let x3 = if CONST_MIN > input { input - } else if max < input { - max + } else if CONST_MAX < input { + CONST_MAX } else { - max + CONST_MAX }; let x6 = match input { - x if x < max => x, - x if x < min => x, + x if x < CONST_MAX => x, + x if x < CONST_MIN => x, x => x, }; let x7 = match input { - x if x < min => max, - x if x > max => min, + x if x < CONST_MIN => CONST_MAX, + x if x > CONST_MAX => CONST_MIN, x => x, }; let x8 = match input { - x if max > x => max, - x if min > x => min, + x if CONST_MAX > x => CONST_MAX, + x if CONST_MIN > x => CONST_MIN, x => x, }; let mut x9 = input; - if x9 > min { - x9 = min; + if x9 > CONST_MIN { + x9 = CONST_MIN; } - if x9 > max { - x9 = max; + if x9 > CONST_MAX { + x9 = CONST_MAX; } let x10 = match input { - x if min > x => min, - x if max < x => max, - x => min, + x if CONST_MIN > x => CONST_MIN, + x if CONST_MAX < x => CONST_MAX, + x => CONST_MIN, }; let mut x11 = input; - if x11 > max { - x11 = min; + if x11 > CONST_MAX { + x11 = CONST_MIN; } - if x11 < min { - x11 = max; + if x11 < CONST_MIN { + x11 = CONST_MAX; } let mut x12 = input; - if min > x12 { - x12 = max * 3; + if CONST_MIN > x12 { + x12 = CONST_MAX * 3; } - if max < x12 { - x12 = min; + if CONST_MAX < x12 { + x12 = CONST_MIN; } let mut x13 = input; - if max < x13 { - let x13 = max; + if CONST_MAX < x13 { + let x13 = CONST_MAX; } - if min > x13 { - x13 = min; + if CONST_MIN > x13 { + x13 = CONST_MIN; } let mut x14 = input; - if x14 < min { + if x14 < CONST_MIN { x14 = 3; - } else if x14 > max { - x14 = max; + } else if x14 > CONST_MAX { + x14 = CONST_MAX; } { let input: i32 = cmp_min_max(1); @@ -385,13 +528,13 @@ fn msrv_1_49() { #[clippy::msrv = "1.50"] fn msrv_1_50() { - let (input, min, max) = (0, -1, 2); - let _ = if input < min { + let input = 0; + let _ = if input > CONST_MAX { //~^ ERROR: clamp-like pattern without using clamp function //~| NOTE: clamp will panic if max < min - min - } else if input > max { - max + CONST_MAX + } else if input < CONST_MIN { + CONST_MIN } else { input }; diff --git a/tests/ui/manual_clamp.stderr b/tests/ui/manual_clamp.stderr index 52c816f2b34..459d46796d8 100644 --- a/tests/ui/manual_clamp.stderr +++ b/tests/ui/manual_clamp.stderr @@ -1,213 +1,213 @@ error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:94:5 + --> tests/ui/manual_clamp.rs:217:5 | -LL | / if x9 < min { +LL | / if x9 < CONST_MIN { LL | | LL | | -LL | | x9 = min; +LL | | x9 = CONST_MIN; ... | -LL | | x9 = max; +LL | | x9 = CONST_MAX; LL | | } - | |_____^ help: replace with clamp: `x9 = x9.clamp(min, max);` + | |_____^ help: replace with clamp: `x9 = x9.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min = note: `-D clippy::manual-clamp` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_clamp)]` error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:113:5 + --> tests/ui/manual_clamp.rs:236:5 | -LL | / if x11 > max { +LL | / if x11 > CONST_MAX { LL | | LL | | -LL | | x11 = max; +LL | | x11 = CONST_MAX; ... | -LL | | x11 = min; +LL | | x11 = CONST_MIN; LL | | } - | |_____^ help: replace with clamp: `x11 = x11.clamp(min, max);` + | |_____^ help: replace with clamp: `x11 = x11.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:123:5 + --> tests/ui/manual_clamp.rs:246:5 | -LL | / if min > x12 { +LL | / if CONST_MIN > x12 { LL | | LL | | -LL | | x12 = min; +LL | | x12 = CONST_MIN; ... | -LL | | x12 = max; +LL | | x12 = CONST_MAX; LL | | } - | |_____^ help: replace with clamp: `x12 = x12.clamp(min, max);` + | |_____^ help: replace with clamp: `x12 = x12.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:133:5 + --> tests/ui/manual_clamp.rs:256:5 | -LL | / if max < x13 { +LL | / if CONST_MAX < x13 { LL | | LL | | -LL | | x13 = max; +LL | | x13 = CONST_MAX; ... | -LL | | x13 = min; +LL | | x13 = CONST_MIN; LL | | } - | |_____^ help: replace with clamp: `x13 = x13.clamp(min, max);` + | |_____^ help: replace with clamp: `x13 = x13.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:227:5 + --> tests/ui/manual_clamp.rs:370:5 | -LL | / if max < x33 { +LL | / if CONST_MAX < x35 { LL | | LL | | -LL | | x33 = max; +LL | | x35 = CONST_MAX; ... | -LL | | x33 = min; +LL | | x35 = CONST_MIN; LL | | } - | |_____^ help: replace with clamp: `x33 = x33.clamp(min, max);` + | |_____^ help: replace with clamp: `x35 = x35.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:21:14 + --> tests/ui/manual_clamp.rs:144:14 | -LL | let x0 = if max < input { +LL | let x0 = if CONST_MAX < input { | ______________^ LL | | LL | | -LL | | max +LL | | CONST_MAX ... | LL | | input LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:31:14 + --> tests/ui/manual_clamp.rs:154:14 | -LL | let x1 = if input > max { +LL | let x1 = if input > CONST_MAX { | ______________^ LL | | LL | | -LL | | max +LL | | CONST_MAX ... | LL | | input LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:41:14 + --> tests/ui/manual_clamp.rs:164:14 | -LL | let x2 = if input < min { +LL | let x2 = if input < CONST_MIN { | ______________^ LL | | LL | | -LL | | min +LL | | CONST_MIN ... | LL | | input LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:51:14 + --> tests/ui/manual_clamp.rs:174:14 | -LL | let x3 = if min > input { +LL | let x3 = if CONST_MIN > input { | ______________^ LL | | LL | | -LL | | min +LL | | CONST_MIN ... | LL | | input LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:61:14 + --> tests/ui/manual_clamp.rs:184:14 | -LL | let x4 = input.max(min).min(max); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` +LL | let x4 = input.max(CONST_MIN).min(CONST_MAX); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:65:14 + --> tests/ui/manual_clamp.rs:188:14 | -LL | let x5 = input.min(max).max(min); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` +LL | let x5 = input.min(CONST_MAX).max(CONST_MIN); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:69:14 + --> tests/ui/manual_clamp.rs:192:14 | LL | let x6 = match input { | ______________^ LL | | LL | | -LL | | x if x > max => max, -LL | | x if x < min => min, +LL | | x if x > CONST_MAX => CONST_MAX, +LL | | x if x < CONST_MIN => CONST_MIN, LL | | x => x, LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:77:14 + --> tests/ui/manual_clamp.rs:200:14 | LL | let x7 = match input { | ______________^ LL | | LL | | -LL | | x if x < min => min, -LL | | x if x > max => max, +LL | | x if x < CONST_MIN => CONST_MIN, +LL | | x if x > CONST_MAX => CONST_MAX, LL | | x => x, LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:85:14 + --> tests/ui/manual_clamp.rs:208:14 | LL | let x8 = match input { | ______________^ LL | | LL | | -LL | | x if max < x => max, -LL | | x if min > x => min, +LL | | x if CONST_MAX < x => CONST_MAX, +LL | | x if CONST_MIN > x => CONST_MIN, LL | | x => x, LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:103:15 + --> tests/ui/manual_clamp.rs:226:15 | LL | let x10 = match input { | _______________^ LL | | LL | | -LL | | x if min > x => min, -LL | | x if max < x => max, +LL | | x if CONST_MIN > x => CONST_MIN, +LL | | x if CONST_MAX < x => CONST_MAX, LL | | x => x, LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:142:15 + --> tests/ui/manual_clamp.rs:265:15 | LL | let x14 = if input > CONST_MAX { | _______________^ @@ -222,23 +222,23 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:153:19 + --> tests/ui/manual_clamp.rs:276:19 | -LL | let x15 = if input > max { +LL | let x15 = if input > CONST_F64_MAX { | ___________________^ LL | | LL | | -LL | | max +LL | | CONST_F64_MAX ... | LL | | input LL | | }; - | |_________^ help: replace with clamp: `input.clamp(min, max)` + | |_________^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` | = note: clamp will panic if max < min, min.is_nan(), or max.is_nan() = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:166:19 + --> tests/ui/manual_clamp.rs:289:19 | LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -246,7 +246,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 - --> tests/ui/manual_clamp.rs:169:19 + --> tests/ui/manual_clamp.rs:292:19 | LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -254,7 +254,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 - --> tests/ui/manual_clamp.rs:172:19 + --> tests/ui/manual_clamp.rs:295:19 | LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -262,7 +262,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 - --> tests/ui/manual_clamp.rs:175:19 + --> tests/ui/manual_clamp.rs:298:19 | LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -270,7 +270,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 - --> tests/ui/manual_clamp.rs:178:19 + --> tests/ui/manual_clamp.rs:301:19 | LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -278,7 +278,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 - --> tests/ui/manual_clamp.rs:181:19 + --> tests/ui/manual_clamp.rs:304:19 | LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -286,7 +286,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 - --> tests/ui/manual_clamp.rs:184:19 + --> tests/ui/manual_clamp.rs:307:19 | LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -294,7 +294,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 - --> tests/ui/manual_clamp.rs:187:19 + --> tests/ui/manual_clamp.rs:310:19 | LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -302,7 +302,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 - --> tests/ui/manual_clamp.rs:191:19 + --> tests/ui/manual_clamp.rs:314: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)` @@ -311,7 +311,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 - --> tests/ui/manual_clamp.rs:194:19 + --> tests/ui/manual_clamp.rs:317: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)` @@ -320,7 +320,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 - --> tests/ui/manual_clamp.rs:197:19 + --> tests/ui/manual_clamp.rs:320: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)` @@ -329,7 +329,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 - --> tests/ui/manual_clamp.rs:200:19 + --> tests/ui/manual_clamp.rs:323: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)` @@ -338,7 +338,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 - --> tests/ui/manual_clamp.rs:203:19 + --> tests/ui/manual_clamp.rs:326: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)` @@ -347,7 +347,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 - --> tests/ui/manual_clamp.rs:206:19 + --> tests/ui/manual_clamp.rs:329: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)` @@ -356,7 +356,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 - --> tests/ui/manual_clamp.rs:209:19 + --> tests/ui/manual_clamp.rs:332: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)` @@ -365,7 +365,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 - --> tests/ui/manual_clamp.rs:212:19 + --> tests/ui/manual_clamp.rs:335: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)` @@ -374,31 +374,31 @@ 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 - --> tests/ui/manual_clamp.rs:217:5 + --> tests/ui/manual_clamp.rs:340:5 | -LL | / if x32 < min { +LL | / if x32 < CONST_MIN { LL | | LL | | -LL | | x32 = min; -LL | | } else if x32 > max { -LL | | x32 = max; +LL | | x32 = CONST_MIN; +LL | | } else if x32 > CONST_MAX { +LL | | x32 = CONST_MAX; LL | | } - | |_____^ help: replace with clamp: `x32 = x32.clamp(min, max);` + | |_____^ help: replace with clamp: `x32 = x32.clamp(CONST_MIN, CONST_MAX);` | = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:389:13 + --> tests/ui/manual_clamp.rs:532:13 | -LL | let _ = if input < min { +LL | let _ = if input > CONST_MAX { | _____________^ LL | | LL | | -LL | | min +LL | | CONST_MAX ... | LL | | input LL | | }; - | |_____^ help: replace with clamp: `input.clamp(min, max)` + | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` | = note: clamp will panic if max < min From 94fe2fac633e4a17f9ba63ee74689beae62d24b6 Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Sun, 24 Mar 2024 11:00:09 +0100 Subject: [PATCH 40/79] Remove `unwrap` from `match_trait_method` Unused_IO_amount relies on `match_trait_method` in order to match trait methods that exist in Tokio traits as the corresponding symbols don't exist. With this commit we remove the unwrap that may have caused 12366. Note: author (@m-rph) and @GuillaumeGomez couldn't replicate 12366. --- clippy_utils/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index b013e4196ea..c5782ca521d 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -298,9 +298,10 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { /// Checks if the method call given in `expr` belongs to the given trait. /// This is a deprecated function, consider using [`is_trait_method`]. pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { - let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); - let trt_id = cx.tcx.trait_of_item(def_id); - trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path)) + cx.typeck_results() + .type_dependent_def_id(expr.hir_id) + .and_then(|defid| cx.tcx.trait_of_item(defid)) + .map_or(false, |trt_id| match_def_path(cx, trt_id, path)) } /// Checks if a method is defined in an impl of a diagnostic item From 733c7af87f44a2e71540d3ff12c66f1a0a1a6b16 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 24 Mar 2024 14:57:57 +0000 Subject: [PATCH 41/79] Rename `{enter,exit}_lint_attrs` to `check_attributes{,_post}` --- clippy_config/src/msrvs.rs | 4 ++-- clippy_lints/src/cognitive_complexity.rs | 4 ++-- clippy_lints/src/missing_doc.rs | 4 ++-- clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs | 2 +- clippy_utils/src/lib.rs | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index bf4da5f14fe..149c4776dc9 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -143,13 +143,13 @@ impl Msrv { None } - pub fn enter_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) { + pub fn check_attributes(&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]) { + pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) { if Self::parse_attr(sess, attrs).is_some() { self.stack.pop(); } diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 60f436dc5d2..7dac3c5d9da 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -158,10 +158,10 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity { } } - fn enter_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { + fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity"); } - fn exit_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { + fn check_attributes_post(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity"); } } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 6878fb3349d..2773427e72d 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -162,12 +162,12 @@ impl MissingDoc { impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); impl<'tcx> LateLintPass<'tcx> for MissingDoc { - fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) { + fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) { let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs); self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) { + fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } 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 6d5240db832..8d208fbb7e9 100644 --- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -42,7 +42,7 @@ impl LateLintPass<'_> for MsrvAttrImpl { .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_))) .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV)) }) - && !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs)) + && !items.iter().any(|item| item.ident.name == sym!(check_attributes)) { let context = if is_late_pass { "LateContext" } else { "EarlyContext" }; let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" }; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 3b1b99caebe..8251bdf78fc 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -131,14 +131,14 @@ use rustc_middle::hir::nested_filter; #[macro_export] macro_rules! extract_msrv_attr { ($context:ident) => { - fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { + fn check_attributes(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); - self.msrv.enter_lint_attrs(sess, attrs); + self.msrv.check_attributes(sess, attrs); } - fn exit_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { + fn check_attributes_post(&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); + self.msrv.check_attributes_post(sess, attrs); } }; } From f2e91ab1b9aaab23b81fc5ea5de43367cb9b9e6d Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sun, 24 Mar 2024 10:16:45 -0600 Subject: [PATCH 42/79] match syms, remove lint_reasons --- clippy_lints/src/legacy_numeric_constants.rs | 203 +++++++++--------- tests/ui/legacy_numeric_constants.fixed | 1 - tests/ui/legacy_numeric_constants.rs | 1 - tests/ui/legacy_numeric_constants.stderr | 32 +-- .../ui/legacy_numeric_constants_unfixable.rs | 1 - .../legacy_numeric_constants_unfixable.stderr | 18 +- 6 files changed, 128 insertions(+), 128 deletions(-) diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index a325b4d5493..c5f1afe68c3 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -164,81 +164,83 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { } fn is_integer_module(cx: &LateContext<'_>, did: DefId) -> bool { - [ - sym::isize_legacy_mod, - sym::i128_legacy_mod, - sym::i64_legacy_mod, - sym::i32_legacy_mod, - sym::i16_legacy_mod, - sym::i8_legacy_mod, - sym::usize_legacy_mod, - sym::u128_legacy_mod, - sym::u64_legacy_mod, - sym::u32_legacy_mod, - sym::u16_legacy_mod, - sym::u8_legacy_mod, - ] - .iter() - .any(|&name| cx.tcx.is_diagnostic_item(name, did)) + matches!( + cx.tcx.get_diagnostic_name(did), + Some( + sym::isize_legacy_mod + | sym::i128_legacy_mod + | sym::i64_legacy_mod + | sym::i32_legacy_mod + | sym::i16_legacy_mod + | sym::i8_legacy_mod + | sym::usize_legacy_mod + | sym::u128_legacy_mod + | sym::u64_legacy_mod + | sym::u32_legacy_mod + | sym::u16_legacy_mod + | sym::u8_legacy_mod + ) + ) } fn is_numeric_const(cx: &LateContext<'_>, did: DefId) -> bool { - [ - sym::isize_legacy_const_max, - sym::isize_legacy_const_min, - sym::i128_legacy_const_max, - sym::i128_legacy_const_min, - sym::i16_legacy_const_max, - sym::i16_legacy_const_min, - sym::i32_legacy_const_max, - sym::i32_legacy_const_min, - sym::i64_legacy_const_max, - sym::i64_legacy_const_min, - sym::i8_legacy_const_max, - sym::i8_legacy_const_min, - sym::usize_legacy_const_max, - sym::usize_legacy_const_min, - sym::u128_legacy_const_max, - sym::u128_legacy_const_min, - sym::u16_legacy_const_max, - sym::u16_legacy_const_min, - sym::u32_legacy_const_max, - sym::u32_legacy_const_min, - sym::u64_legacy_const_max, - sym::u64_legacy_const_min, - sym::u8_legacy_const_max, - sym::u8_legacy_const_min, - sym::f32_legacy_const_digits, - sym::f32_legacy_const_epsilon, - sym::f32_legacy_const_infinity, - sym::f32_legacy_const_mantissa_dig, - sym::f32_legacy_const_max, - sym::f32_legacy_const_max_10_exp, - sym::f32_legacy_const_max_exp, - sym::f32_legacy_const_min, - sym::f32_legacy_const_min_10_exp, - sym::f32_legacy_const_min_exp, - sym::f32_legacy_const_min_positive, - sym::f32_legacy_const_nan, - sym::f32_legacy_const_neg_infinity, - sym::f32_legacy_const_radix, - sym::f64_legacy_const_digits, - sym::f64_legacy_const_epsilon, - sym::f64_legacy_const_infinity, - sym::f64_legacy_const_mantissa_dig, - sym::f64_legacy_const_max, - sym::f64_legacy_const_max_10_exp, - sym::f64_legacy_const_max_exp, - sym::f64_legacy_const_min, - sym::f64_legacy_const_min_10_exp, - sym::f64_legacy_const_min_exp, - sym::f64_legacy_const_min_positive, - sym::f64_legacy_const_nan, - sym::f64_legacy_const_neg_infinity, - sym::f64_legacy_const_radix, - ] - .iter() - .any(|&name| cx.tcx.is_diagnostic_item(name, did)) + matches!( + cx.tcx.get_diagnostic_name(did), + Some( + sym::isize_legacy_const_max + | sym::isize_legacy_const_min + | sym::i128_legacy_const_max + | sym::i128_legacy_const_min + | sym::i16_legacy_const_max + | sym::i16_legacy_const_min + | sym::i32_legacy_const_max + | sym::i32_legacy_const_min + | sym::i64_legacy_const_max + | sym::i64_legacy_const_min + | sym::i8_legacy_const_max + | sym::i8_legacy_const_min + | sym::usize_legacy_const_max + | sym::usize_legacy_const_min + | sym::u128_legacy_const_max + | sym::u128_legacy_const_min + | sym::u16_legacy_const_max + | sym::u16_legacy_const_min + | sym::u32_legacy_const_max + | sym::u32_legacy_const_min + | sym::u64_legacy_const_max + | sym::u64_legacy_const_min + | sym::u8_legacy_const_max + | sym::u8_legacy_const_min + | sym::f32_legacy_const_digits + | sym::f32_legacy_const_epsilon + | sym::f32_legacy_const_infinity + | sym::f32_legacy_const_mantissa_dig + | sym::f32_legacy_const_max + | sym::f32_legacy_const_max_10_exp + | sym::f32_legacy_const_max_exp + | sym::f32_legacy_const_min + | sym::f32_legacy_const_min_10_exp + | sym::f32_legacy_const_min_exp + | sym::f32_legacy_const_min_positive + | sym::f32_legacy_const_nan + | sym::f32_legacy_const_neg_infinity + | sym::f32_legacy_const_radix + | sym::f64_legacy_const_digits + | sym::f64_legacy_const_epsilon + | sym::f64_legacy_const_infinity + | sym::f64_legacy_const_mantissa_dig + | sym::f64_legacy_const_max + | sym::f64_legacy_const_max_10_exp + | sym::f64_legacy_const_max_exp + | sym::f64_legacy_const_min + | sym::f64_legacy_const_min_10_exp + | sym::f64_legacy_const_min_exp + | sym::f64_legacy_const_min_positive + | sym::f64_legacy_const_nan + | sym::f64_legacy_const_neg_infinity + | sym::f64_legacy_const_radix + ) + ) } // Whether path expression looks like `i32::MAX` @@ -259,32 +261,33 @@ fn is_numeric_const_path_canonical(expr_path: &hir::Path<'_>, [mod_name, name]: } fn is_integer_method(cx: &LateContext<'_>, did: DefId) -> bool { - [ - sym::isize_legacy_fn_max_value, - sym::isize_legacy_fn_min_value, - sym::i128_legacy_fn_max_value, - sym::i128_legacy_fn_min_value, - sym::i16_legacy_fn_max_value, - sym::i16_legacy_fn_min_value, - sym::i32_legacy_fn_max_value, - sym::i32_legacy_fn_min_value, - sym::i64_legacy_fn_max_value, - sym::i64_legacy_fn_min_value, - sym::i8_legacy_fn_max_value, - sym::i8_legacy_fn_min_value, - sym::usize_legacy_fn_max_value, - sym::usize_legacy_fn_min_value, - sym::u128_legacy_fn_max_value, - sym::u128_legacy_fn_min_value, - sym::u16_legacy_fn_max_value, - sym::u16_legacy_fn_min_value, - sym::u32_legacy_fn_max_value, - sym::u32_legacy_fn_min_value, - sym::u64_legacy_fn_max_value, - sym::u64_legacy_fn_min_value, - sym::u8_legacy_fn_max_value, - sym::u8_legacy_fn_min_value, - ] - .iter() - .any(|&name| cx.tcx.is_diagnostic_item(name, did)) + matches!( + cx.tcx.get_diagnostic_name(did), + Some( + sym::isize_legacy_fn_max_value + | sym::isize_legacy_fn_min_value + | sym::i128_legacy_fn_max_value + | sym::i128_legacy_fn_min_value + | sym::i16_legacy_fn_max_value + | sym::i16_legacy_fn_min_value + | sym::i32_legacy_fn_max_value + | sym::i32_legacy_fn_min_value + | sym::i64_legacy_fn_max_value + | sym::i64_legacy_fn_min_value + | sym::i8_legacy_fn_max_value + | sym::i8_legacy_fn_min_value + | sym::usize_legacy_fn_max_value + | sym::usize_legacy_fn_min_value + | sym::u128_legacy_fn_max_value + | sym::u128_legacy_fn_min_value + | sym::u16_legacy_fn_max_value + | sym::u16_legacy_fn_min_value + | sym::u32_legacy_fn_max_value + | sym::u32_legacy_fn_min_value + | sym::u64_legacy_fn_max_value + | sym::u64_legacy_fn_min_value + | sym::u8_legacy_fn_max_value + | sym::u8_legacy_fn_min_value + ) + ) } diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed index 31a6c1b3944..a6ef8f8c119 100644 --- a/tests/ui/legacy_numeric_constants.fixed +++ b/tests/ui/legacy_numeric_constants.fixed @@ -1,7 +1,6 @@ //@aux-build:proc_macros.rs #![allow(clippy::no_effect, deprecated, unused)] #![allow(clippy::legacy_numeric_constants)] // For imports. -#![feature(lint_reasons)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs index e4dd3d5896f..cd633545372 100644 --- a/tests/ui/legacy_numeric_constants.rs +++ b/tests/ui/legacy_numeric_constants.rs @@ -1,7 +1,6 @@ //@aux-build:proc_macros.rs #![allow(clippy::no_effect, deprecated, unused)] #![allow(clippy::legacy_numeric_constants)] // For imports. -#![feature(lint_reasons)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr index af9b003ed54..267b9ac8e4d 100644 --- a/tests/ui/legacy_numeric_constants.stderr +++ b/tests/ui/legacy_numeric_constants.stderr @@ -1,5 +1,5 @@ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:32:5 + --> tests/ui/legacy_numeric_constants.rs:31:5 | LL | std::f32::EPSILON; | ^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | f32::EPSILON; | ~~~~~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:35:5 + --> tests/ui/legacy_numeric_constants.rs:34:5 | LL | std::u8::MIN; | ^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | u8::MIN; | ~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:38:5 + --> tests/ui/legacy_numeric_constants.rs:37:5 | LL | std::usize::MIN; | ^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | usize::MIN; | ~~~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:41:5 + --> tests/ui/legacy_numeric_constants.rs:40:5 | LL | std::u32::MAX; | ^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | u32::MAX; | ~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:44:5 + --> tests/ui/legacy_numeric_constants.rs:43:5 | LL | core::u32::MAX; | ^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | u32::MAX; | ~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:47:5 + --> tests/ui/legacy_numeric_constants.rs:46:5 | LL | MAX; | ^^^ @@ -67,7 +67,7 @@ LL | u32::MAX; | ~~~~~~~~ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:50:10 + --> tests/ui/legacy_numeric_constants.rs:49:10 | LL | i32::max_value(); | ^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | i32::MAX; | ~~~ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:53:9 + --> tests/ui/legacy_numeric_constants.rs:52:9 | LL | u8::max_value(); | ^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | u8::MAX; | ~~~ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:56:9 + --> tests/ui/legacy_numeric_constants.rs:55:9 | LL | u8::min_value(); | ^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | u8::MIN; | ~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:59:5 + --> tests/ui/legacy_numeric_constants.rs:58:5 | LL | ::std::u8::MIN; | ^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | u8::MIN; | ~~~~~~~ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:62:27 + --> tests/ui/legacy_numeric_constants.rs:61:27 | LL | ::std::primitive::u8::min_value(); | ^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | ::std::primitive::u8::MIN; | ~~~ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:65:26 + --> tests/ui/legacy_numeric_constants.rs:64:26 | LL | std::primitive::i32::max_value(); | ^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | std::primitive::i32::MAX; | ~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:68:5 + --> tests/ui/legacy_numeric_constants.rs:67:5 | LL | self::a::u128::MAX; | ^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | u128::MAX; | ~~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:18:25 + --> tests/ui/legacy_numeric_constants.rs:17:25 | LL | let x = std::u64::MAX; | ^^^^^^^^^^^^^ @@ -159,7 +159,7 @@ LL | let x = u64::MAX; | ~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:82:14 + --> tests/ui/legacy_numeric_constants.rs:81:14 | LL | [(0, "", std::i128::MAX)]; | ^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL | [(0, "", i128::MAX)]; | ~~~~~~~~~ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:116:5 + --> tests/ui/legacy_numeric_constants.rs:115:5 | LL | std::u32::MAX; | ^^^^^^^^^^^^^ diff --git a/tests/ui/legacy_numeric_constants_unfixable.rs b/tests/ui/legacy_numeric_constants_unfixable.rs index 228ebdd6a6c..86738ede210 100644 --- a/tests/ui/legacy_numeric_constants_unfixable.rs +++ b/tests/ui/legacy_numeric_constants_unfixable.rs @@ -2,7 +2,6 @@ //@aux-build:proc_macros.rs #![allow(clippy::no_effect, deprecated, unused)] #![warn(clippy::legacy_numeric_constants)] -#![feature(lint_reasons)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/legacy_numeric_constants_unfixable.stderr b/tests/ui/legacy_numeric_constants_unfixable.stderr index 96e6c9ef975..2edcf718836 100644 --- a/tests/ui/legacy_numeric_constants_unfixable.stderr +++ b/tests/ui/legacy_numeric_constants_unfixable.stderr @@ -1,5 +1,5 @@ error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:10:5 + --> tests/ui/legacy_numeric_constants_unfixable.rs:9:5 | LL | use std::u128 as _; | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | use std::u128 as _; = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]` error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:14:24 + --> tests/ui/legacy_numeric_constants_unfixable.rs:13:24 | LL | pub use std::{mem, u128}; | ^^^^ @@ -18,7 +18,7 @@ LL | pub use std::{mem, u128}; = note: then `u128::` will resolve to the respective associated constant error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:30:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:29:9 | LL | use std::u32::MAX; | ^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | use std::u32::MAX; = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:33:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:32:9 | LL | use std::u8::MIN; | ^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | use std::u8::MIN; = help: remove this import and use the associated constant `u8::MIN` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:37:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:36:9 | LL | use std::u32; | ^^^^^^^^ @@ -43,7 +43,7 @@ LL | use std::u32; = note: then `u32::` will resolve to the respective associated constant error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:41:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:40:9 | LL | use std::f32::MIN_POSITIVE; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | use std::f32::MIN_POSITIVE; = help: remove this import and use the associated constant `f32::MIN_POSITIVE` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:45:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:44:9 | LL | use std::i16::*; | ^^^^^^^^ @@ -59,7 +59,7 @@ LL | use std::i16::*; = help: remove this import and use associated constants `i16::` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:22:17 + --> tests/ui/legacy_numeric_constants_unfixable.rs:21:17 | LL | use std::u32; | ^^^^^^^^ @@ -72,7 +72,7 @@ LL | b!(); = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:77:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:76:9 | LL | use std::u32::MAX; | ^^^^^^^^^^^^^ From 2a62200b8d5ba65d583199a296c3fbbf8e58aa25 Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Mon, 25 Mar 2024 02:17:56 +0900 Subject: [PATCH 43/79] fix: suspicious_else_formatting false positive when else is included in comments --- clippy_lints/src/formatting.rs | 43 +++++++++++++++++++++++++- tests/ui/suspicious_else_formatting.rs | 28 +++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index c3ef6f180c9..5b8d4ea8956 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -214,7 +214,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” && let Some(else_snippet) = snippet_opt(cx, else_span) - && let Some((pre_else, post_else)) = else_snippet.split_once("else") + && let Some((pre_else, post_else)) = split_once_with_else(&else_snippet) && let Some((_, post_else_post_eol)) = post_else.split_once('\n') { // Allow allman style braces `} \n else \n {` @@ -323,3 +323,44 @@ fn is_block(expr: &Expr) -> bool { fn is_if(expr: &Expr) -> bool { matches!(expr.kind, ExprKind::If(..)) } + +fn split_once_with_else(base: &str) -> Option<(&str, &str)> { + let else_str = "else"; + + let indices: Vec<_> = base.match_indices(else_str).map(|(i, _)| i).collect(); + + match indices.len() { + 0 => return None, + 1 => return base.split_once(else_str), + _ => {}, + } + + let mut i = 0; + let mut is_in_comment = false; + + for line in base.lines() { + if let Some(else_pos) = line.find(else_str) { + if let Some(pos) = line.find("//") { + if pos > else_pos { + return Some(base.split_at(indices[i])); + } + } else if let Some(pos) = line.find("/*") { + if pos > else_pos { + return Some(base.split_at(indices[i])); + } + is_in_comment = true; + } else if let Some(pos) = line.find("*/") { + if pos < else_pos { + return Some(base.split_at(indices[i])); + } + is_in_comment = false; + } else if !is_in_comment { + return Some(base.split_at(indices[i])); + } + + i += 1; + } + } + + None +} diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index c0856427eae..3d5c892eb60 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -120,6 +120,34 @@ fn main() { /* whelp */ { } + + // #12497 Don't trigger lint as rustfmt wants it + if true { + println!("true"); + } + /*else if false { +}*/ + else { + println!("false"); + } + + if true { + println!("true"); + } // else if false {} + else { + println!("false"); + } + + if true { + println!("true"); + } /* if true { + println!("true"); +} + */ + else { + println!("false"); + } + } // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions. From dafb7f6d63acf750e4618e5ebd8df20d7cf2f0b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 25 Mar 2024 10:24:13 +0100 Subject: [PATCH 44/79] Change applicability of `assigning_clones` to `Unspecified` --- clippy_lints/src/assigning_clones.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 88d9f762a87..4b0cfb399f6 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -212,7 +212,7 @@ fn suggest<'tcx>( call: &CallCandidate<'tcx>, ) { span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| { - let mut applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::Unspecified; diag.span_suggestion( assign_expr.span, From b9da637655c4e1c66dde2fb291ae4786b2b7e057 Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Tue, 26 Mar 2024 00:46:57 +0900 Subject: [PATCH 45/79] Refine the logic to accurately assess if 'else' resides within comments --- clippy_lints/src/formatting.rs | 44 ++-------------------------------- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 5b8d4ea8956..5f8d787357d 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -214,7 +214,8 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” && let Some(else_snippet) = snippet_opt(cx, else_span) - && let Some((pre_else, post_else)) = split_once_with_else(&else_snippet) + && let Some((pre_else, post_else)) = else_snippet.split_once("else") + && !else_snippet.contains('/') && let Some((_, post_else_post_eol)) = post_else.split_once('\n') { // Allow allman style braces `} \n else \n {` @@ -323,44 +324,3 @@ fn is_block(expr: &Expr) -> bool { fn is_if(expr: &Expr) -> bool { matches!(expr.kind, ExprKind::If(..)) } - -fn split_once_with_else(base: &str) -> Option<(&str, &str)> { - let else_str = "else"; - - let indices: Vec<_> = base.match_indices(else_str).map(|(i, _)| i).collect(); - - match indices.len() { - 0 => return None, - 1 => return base.split_once(else_str), - _ => {}, - } - - let mut i = 0; - let mut is_in_comment = false; - - for line in base.lines() { - if let Some(else_pos) = line.find(else_str) { - if let Some(pos) = line.find("//") { - if pos > else_pos { - return Some(base.split_at(indices[i])); - } - } else if let Some(pos) = line.find("/*") { - if pos > else_pos { - return Some(base.split_at(indices[i])); - } - is_in_comment = true; - } else if let Some(pos) = line.find("*/") { - if pos < else_pos { - return Some(base.split_at(indices[i])); - } - is_in_comment = false; - } else if !is_in_comment { - return Some(base.split_at(indices[i])); - } - - i += 1; - } - } - - None -} From e0b6f30397ba152a7bd190d98c1389383e276ba3 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 25 Mar 2024 17:10:26 +0100 Subject: [PATCH 46/79] Remove unnecessary dot in the 'unconditional recursion' lint description --- clippy_lints/src/unconditional_recursion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index d638af2b78b..52338027dea 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// implementations. /// /// ### Why is this bad? - /// This is a hard to find infinite recursion that will crash any code. + /// This is a hard to find infinite recursion that will crash any code /// using it. /// /// ### Example From 9e82ad87b9ae43bee6f06308631fbe0fb0a1c847 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:47:20 +0000 Subject: [PATCH 47/79] [`let_and_return`]: avoid linting when `#[cfg]` attributes are present --- clippy_lints/src/matches/mod.rs | 32 +++----------------------------- clippy_lints/src/returns.rs | 3 ++- clippy_utils/src/attrs.rs | 32 +++++++++++++++++++++++++++++++- tests/ui/let_and_return.fixed | 7 +++++++ tests/ui/let_and_return.rs | 7 +++++++ 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 50494f4819f..dd83e32a943 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -25,14 +25,13 @@ mod try_err; mod wild_in_or_pats; use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::source::{snippet_opt, walk_span_to_context}; -use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text}; +use clippy_utils::source::walk_span_to_context; +use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg}; use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat}; -use rustc_lexer::TokenKind; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; -use rustc_span::{Span, SpanData, SyntaxContext}; +use rustc_span::{SpanData, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -1196,28 +1195,3 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar Err(()) => true, } } - -/// Checks if the given span contains a `#[cfg(..)]` attribute -fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { - let Some(snip) = snippet_opt(cx, s) else { - // Assume true. This would require either an invalid span, or one which crosses file boundaries. - return true; - }; - let mut iter = tokenize_with_text(&snip); - - // Search for the token sequence [`#`, `[`, `cfg`] - while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { - let mut iter = iter.by_ref().skip_while(|(t, _)| { - matches!( - t, - TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } - ) - }); - if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) - && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) - { - return true; - } - } - false -} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 8bc24eda465..e8f9d438104 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; use clippy_utils::{ - fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id, + fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id, span_contains_cfg, span_find_starting_semi, }; use core::ops::ControlFlow; @@ -232,6 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { && !in_external_macro(cx.sess(), initexpr.span) && !in_external_macro(cx.sess(), retexpr.span) && !local.span.from_expansion() + && !span_contains_cfg(cx, stmt.span.between(retexpr.span)) { span_lint_hir_and_then( cx, diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 2d0c2cf1253..d2200bcf710 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -1,10 +1,15 @@ use rustc_ast::{ast, attr}; use rustc_errors::Applicability; +use rustc_lexer::TokenKind; +use rustc_lint::LateContext; use rustc_middle::ty::{AdtDef, TyCtxt}; use rustc_session::Session; -use rustc_span::sym; +use rustc_span::{sym, Span}; use std::str::FromStr; +use crate::source::snippet_opt; +use crate::tokenize_with_text; + /// Deprecation status of attributes known by Clippy. pub enum DeprecationStatus { /// Attribute is deprecated @@ -171,3 +176,28 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { .all_fields() .any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive)) } + +/// Checks if the given span contains a `#[cfg(..)]` attribute +pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { + let Some(snip) = snippet_opt(cx, s) else { + // Assume true. This would require either an invalid span, or one which crosses file boundaries. + return true; + }; + let mut iter = tokenize_with_text(&snip); + + // Search for the token sequence [`#`, `[`, `cfg`] + while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { + let mut iter = iter.by_ref().skip_while(|(t, _)| { + matches!( + t, + TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } + ) + }); + if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) + && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) + { + return true; + } + } + false +} diff --git a/tests/ui/let_and_return.fixed b/tests/ui/let_and_return.fixed index b5584fcde8c..4187019e589 100644 --- a/tests/ui/let_and_return.fixed +++ b/tests/ui/let_and_return.fixed @@ -203,4 +203,11 @@ fn_in_macro!({ return 1; }); +fn issue9150() -> usize { + let x = 1; + #[cfg(any())] + panic!("can't see me"); + x +} + fn main() {} diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index f13c7c4e203..54444957b7d 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -203,4 +203,11 @@ fn_in_macro!({ return 1; }); +fn issue9150() -> usize { + let x = 1; + #[cfg(any())] + panic!("can't see me"); + x +} + fn main() {} From 9655231eb825500d69738382f791374660311390 Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Mon, 25 Mar 2024 23:29:34 +0100 Subject: [PATCH 48/79] Allow `filter_map_identity` when the closure is typed This extends the `filter_map_identity` lint to support typed closures. For untyped closures, we know that the program compiles, and therefore we can safely suggest using flatten. For typed closures, they may participate in type resolution. In this case we use `Applicability::MaybeIncorrect`. Details: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/Should.20.60filter_map_identity.60.20lint.20when.20closures.20are.20typed.3F --- .../src/methods/filter_map_identity.rs | 18 ++- tests/ui/filter_map_identity.fixed | 86 +++++++++-- tests/ui/filter_map_identity.rs | 86 +++++++++-- tests/ui/filter_map_identity.stderr | 134 ++++++++++++++++-- 4 files changed, 288 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs index 8291c373f37..15b11a731c9 100644 --- a/clippy_lints/src/methods/filter_map_identity.rs +++ b/clippy_lints/src/methods/filter_map_identity.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{is_expr_untyped_identity_function, is_trait_method}; +use clippy_utils::{is_expr_identity_function, is_expr_untyped_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -7,8 +7,20 @@ use rustc_span::{sym, Span}; use super::FILTER_MAP_IDENTITY; +fn is_identity(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { + if is_expr_untyped_identity_function(cx, expr) { + return Some(Applicability::MachineApplicable); + } + if is_expr_identity_function(cx, expr) { + return Some(Applicability::MaybeIncorrect); + } + None +} + pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) { - if is_trait_method(cx, expr, sym::Iterator) && is_expr_untyped_identity_function(cx, filter_map_arg) { + if is_trait_method(cx, expr, sym::Iterator) + && let Some(applicability) = is_identity(cx, filter_map_arg) + { span_lint_and_sugg( cx, FILTER_MAP_IDENTITY, @@ -16,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: "use of `filter_map` with an identity function", "try", "flatten()".to_string(), - Applicability::MachineApplicable, + applicability, ); } } diff --git a/tests/ui/filter_map_identity.fixed b/tests/ui/filter_map_identity.fixed index ad438afaca7..f3f6848e5f9 100644 --- a/tests/ui/filter_map_identity.fixed +++ b/tests/ui/filter_map_identity.fixed @@ -1,17 +1,83 @@ -#![allow(unused_imports, clippy::needless_return)] +#![allow(unused_imports, clippy::needless_return, clippy::useless_vec)] #![warn(clippy::filter_map_identity)] +#![feature(stmt_expr_attributes)] + +use std::option::Option; +struct NonCopy; +use std::convert::identity; + +fn non_copy_vec() -> Vec> { + todo!() +} + +fn copy_vec() -> Vec> { + todo!() +} + +fn copy_vec_non_inferred() -> Vec> { + todo!() +} + +fn opaque() -> impl IntoIterator> { + vec![Some(T::default())] +} fn main() { - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.flatten(); + { + // into_iter + copy_vec_non_inferred().into_iter().flatten(); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().flatten(); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().flatten(); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().flatten(); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().flatten(); + //~^ ERROR: use of - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.flatten(); + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of - use std::convert::identity; - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.flatten(); + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of + non_copy_vec().into_iter().flatten(); + //~^ ERROR: use of - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.flatten(); + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + + // we are forced to pass the type in the call. + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + #[rustfmt::skip] + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + #[rustfmt::skip] + copy_vec::().into_iter().flatten(); + //~^ ERROR: use of + + // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference, + // it behaves the same as copy_vec. + opaque::().into_iter().flatten(); + //~^ ERROR: use of + } } diff --git a/tests/ui/filter_map_identity.rs b/tests/ui/filter_map_identity.rs index d7423276872..b9aa9c05be8 100644 --- a/tests/ui/filter_map_identity.rs +++ b/tests/ui/filter_map_identity.rs @@ -1,17 +1,83 @@ -#![allow(unused_imports, clippy::needless_return)] +#![allow(unused_imports, clippy::needless_return, clippy::useless_vec)] #![warn(clippy::filter_map_identity)] +#![feature(stmt_expr_attributes)] + +use std::option::Option; +struct NonCopy; +use std::convert::identity; + +fn non_copy_vec() -> Vec> { + todo!() +} + +fn copy_vec() -> Vec> { + todo!() +} + +fn copy_vec_non_inferred() -> Vec> { + todo!() +} + +fn opaque() -> impl IntoIterator> { + vec![Some(T::default())] +} fn main() { - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.filter_map(|x| x); + { + // into_iter + copy_vec_non_inferred().into_iter().filter_map(|x| x); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().filter_map(std::convert::identity); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().filter_map(identity); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().filter_map(|x| return x); + //~^ ERROR: use of + copy_vec_non_inferred().into_iter().filter_map(|x| return x); + //~^ ERROR: use of - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.filter_map(std::convert::identity); + non_copy_vec().into_iter().filter_map(|x| x); + //~^ ERROR: use of + non_copy_vec().into_iter().filter_map(|x| x); + //~^ ERROR: use of - use std::convert::identity; - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.filter_map(identity); + non_copy_vec().into_iter().filter_map(std::convert::identity); + //~^ ERROR: use of + non_copy_vec().into_iter().filter_map(identity); + //~^ ERROR: use of + non_copy_vec().into_iter().filter_map(|x| return x); + //~^ ERROR: use of + non_copy_vec().into_iter().filter_map(|x| return x); + //~^ ERROR: use of - let iterator = vec![Some(1), None, Some(2)].into_iter(); - let _ = iterator.filter_map(|x| return x); + copy_vec::().into_iter().filter_map(|x: Option<_>| x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option<_>| x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + //~^ ERROR: use of + + // we are forced to pass the type in the call. + copy_vec::().into_iter().filter_map(|x: Option| x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option| x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option| return x); + //~^ ERROR: use of + copy_vec::().into_iter().filter_map(|x: Option| return x); + //~^ ERROR: use of + #[rustfmt::skip] + copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ x }}); + //~^ ERROR: use of + #[rustfmt::skip] + copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ return x }}); + //~^ ERROR: use of + + // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference, + // it behaves the same as copy_vec. + opaque::().into_iter().filter_map(|x| x); + //~^ ERROR: use of + } } diff --git a/tests/ui/filter_map_identity.stderr b/tests/ui/filter_map_identity.stderr index 5aa46ad6d23..55068db4e9d 100644 --- a/tests/ui/filter_map_identity.stderr +++ b/tests/ui/filter_map_identity.stderr @@ -1,29 +1,137 @@ error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:6:22 + --> tests/ui/filter_map_identity.rs:28:45 | -LL | let _ = iterator.filter_map(|x| x); - | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` +LL | copy_vec_non_inferred().into_iter().filter_map(|x| x); + | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` | = note: `-D clippy::filter-map-identity` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_identity)]` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:9:22 + --> tests/ui/filter_map_identity.rs:30:45 | -LL | let _ = iterator.filter_map(std::convert::identity); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` +LL | copy_vec_non_inferred().into_iter().filter_map(std::convert::identity); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:13:22 + --> tests/ui/filter_map_identity.rs:32:45 | -LL | let _ = iterator.filter_map(identity); - | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` +LL | copy_vec_non_inferred().into_iter().filter_map(identity); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:16:22 + --> tests/ui/filter_map_identity.rs:34:45 | -LL | let _ = iterator.filter_map(|x| return x); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` +LL | copy_vec_non_inferred().into_iter().filter_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: aborting due to 4 previous errors +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:36:45 + | +LL | copy_vec_non_inferred().into_iter().filter_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:39:36 + | +LL | non_copy_vec().into_iter().filter_map(|x| x); + | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:41:36 + | +LL | non_copy_vec().into_iter().filter_map(|x| x); + | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:44:36 + | +LL | non_copy_vec().into_iter().filter_map(std::convert::identity); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:46:36 + | +LL | non_copy_vec().into_iter().filter_map(identity); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:48:36 + | +LL | non_copy_vec().into_iter().filter_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:50:36 + | +LL | non_copy_vec().into_iter().filter_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:53:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:55:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:57:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:59:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:63:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:65:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:67:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:69:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:72:43 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ x }}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:75:43 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ return x }}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:80:37 + | +LL | opaque::().into_iter().filter_map(|x| x); + | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: aborting due to 22 previous errors From e3f3a4b7dc0eb64b92497045db475fa8f0bbe5d0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Mar 2024 12:15:48 +0100 Subject: [PATCH 49/79] Don't emit `duplicated_attribute` lint on "complex" `cfg`s --- .../src/attrs/duplicated_attributes.rs | 13 ++- tests/ui/duplicated_attributes.rs | 13 +-- tests/ui/duplicated_attributes.stderr | 94 +++---------------- 3 files changed, 32 insertions(+), 88 deletions(-) diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs index 3c5ac597fd5..d0ccfc4c36d 100644 --- a/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/clippy_lints/src/attrs/duplicated_attributes.rs @@ -25,12 +25,16 @@ fn emit_if_duplicated( } } +#[allow(clippy::needless_return)] fn check_duplicated_attr( cx: &EarlyContext<'_>, attr: &MetaItem, attr_paths: &mut FxHashMap, parent: &mut Vec, ) { + if attr.span.from_expansion() { + return; + } let Some(ident) = attr.ident() else { return }; let name = ident.name; if name == sym::doc || name == sym::cfg_attr { @@ -38,7 +42,14 @@ fn check_duplicated_attr( // conditions are the same. return; } - if let Some(value) = attr.value_str() { + if let Some(direct_parent) = parent.last() + && ["cfg", "cfg_attr"].contains(&direct_parent.as_str()) + && [sym::all, sym::not, sym::any].contains(&name) + { + // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one + // level `cfg`, we leave. + return; + } else if let Some(value) = attr.value_str() { emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":"))); } else if let Some(sub_attrs) = attr.meta_item_list() { parent.push(name.as_str().to_string()); diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs index 0f036c684c1..d051c881f15 100644 --- a/tests/ui/duplicated_attributes.rs +++ b/tests/ui/duplicated_attributes.rs @@ -2,16 +2,17 @@ #![cfg(any(unix, windows))] #![allow(dead_code)] #![allow(dead_code)] //~ ERROR: duplicated attribute -#![cfg(any(unix, windows))] -//~^ ERROR: duplicated attribute -//~| ERROR: duplicated attribute +#![cfg(any(unix, windows))] // Should not warn! #[cfg(any(unix, windows, target_os = "linux"))] #[allow(dead_code)] #[allow(dead_code)] //~ ERROR: duplicated attribute -#[cfg(any(unix, windows, target_os = "linux"))] -//~^ ERROR: duplicated attribute -//~| ERROR: duplicated attribute +#[cfg(any(unix, windows, target_os = "linux"))] // Should not warn! fn foo() {} +#[cfg(unix)] +#[cfg(windows)] +#[cfg(unix)] //~ ERROR: duplicated attribute +fn bar() {} + fn main() {} diff --git a/tests/ui/duplicated_attributes.stderr b/tests/ui/duplicated_attributes.stderr index 1c6578dbb43..9e26ba990ac 100644 --- a/tests/ui/duplicated_attributes.stderr +++ b/tests/ui/duplicated_attributes.stderr @@ -18,106 +18,38 @@ LL | #![allow(dead_code)] = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:5:12 - | -LL | #![cfg(any(unix, windows))] - | ^^^^ - | -note: first defined here - --> tests/ui/duplicated_attributes.rs:2:12 - | -LL | #![cfg(any(unix, windows))] - | ^^^^ -help: remove this attribute - --> tests/ui/duplicated_attributes.rs:5:12 - | -LL | #![cfg(any(unix, windows))] - | ^^^^ - -error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:5:18 - | -LL | #![cfg(any(unix, windows))] - | ^^^^^^^ - | -note: first defined here - --> tests/ui/duplicated_attributes.rs:2:18 - | -LL | #![cfg(any(unix, windows))] - | ^^^^^^^ -help: remove this attribute - --> tests/ui/duplicated_attributes.rs:5:18 - | -LL | #![cfg(any(unix, windows))] - | ^^^^^^^ - -error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:11:9 + --> tests/ui/duplicated_attributes.rs:9:9 | LL | #[allow(dead_code)] | ^^^^^^^^^ | note: first defined here - --> tests/ui/duplicated_attributes.rs:10:9 + --> tests/ui/duplicated_attributes.rs:8:9 | LL | #[allow(dead_code)] | ^^^^^^^^^ help: remove this attribute - --> tests/ui/duplicated_attributes.rs:11:9 + --> tests/ui/duplicated_attributes.rs:9:9 | LL | #[allow(dead_code)] | ^^^^^^^^^ error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:12:11 + --> tests/ui/duplicated_attributes.rs:15:7 | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^ +LL | #[cfg(unix)] + | ^^^^ | note: first defined here - --> tests/ui/duplicated_attributes.rs:9:11 + --> tests/ui/duplicated_attributes.rs:13:7 | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^ +LL | #[cfg(unix)] + | ^^^^ help: remove this attribute - --> tests/ui/duplicated_attributes.rs:12:11 + --> tests/ui/duplicated_attributes.rs:15:7 | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^ +LL | #[cfg(unix)] + | ^^^^ -error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:12:17 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^ - | -note: first defined here - --> tests/ui/duplicated_attributes.rs:9:17 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^ -help: remove this attribute - --> tests/ui/duplicated_attributes.rs:12:17 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^ - -error: duplicated attribute - --> tests/ui/duplicated_attributes.rs:12:26 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^^^^^^^^^^^^^ - | -note: first defined here - --> tests/ui/duplicated_attributes.rs:9:26 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^^^^^^^^^^^^^ -help: remove this attribute - --> tests/ui/duplicated_attributes.rs:12:26 - | -LL | #[cfg(any(unix, windows, target_os = "linux"))] - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors From aecdb921aed81bf3dde849e696843deddc84905e Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Tue, 26 Mar 2024 10:45:27 -0600 Subject: [PATCH 50/79] short circuit logic better --- clippy_lints/src/manual_clamp.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 0148e6deb56..f484672bc3a 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -114,12 +114,13 @@ impl<'tcx> ClampSuggestion<'tcx> { if max_type != min_type { return false; } - let max = constant(cx, cx.typeck_results(), self.params.max); - let min = constant(cx, cx.typeck_results(), self.params.min); - let cmp = max - .zip(min) - .and_then(|(max, min)| Constant::partial_cmp(cx.tcx, max_type, &min, &max)); - cmp.is_some_and(|cmp| cmp != Ordering::Greater) + if let Some(max) = constant(cx, cx.typeck_results(), self.params.max) + && let Some(min) = constant(cx, cx.typeck_results(), self.params.min) + { + Constant::partial_cmp(cx.tcx, max_type, &min, &max).is_some_and(|o| o != Ordering::Greater) + } else { + false + } } } From 4d7d66462f1907d6cd0240c30636e01429fb8f89 Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Tue, 26 Mar 2024 10:53:41 -0600 Subject: [PATCH 51/79] the power of if let chain compels you --- clippy_lints/src/manual_clamp.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index f484672bc3a..59fc8948c2f 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -116,8 +116,9 @@ impl<'tcx> ClampSuggestion<'tcx> { } if let Some(max) = constant(cx, cx.typeck_results(), self.params.max) && let Some(min) = constant(cx, cx.typeck_results(), self.params.min) + && let Some(ord) = Constant::partial_cmp(cx.tcx, max_type, &min, &max) { - Constant::partial_cmp(cx.tcx, max_type, &min, &max).is_some_and(|o| o != Ordering::Greater) + ord != Ordering::Greater } else { false } From 57627d254d29110fa82c982fedd839d293d0d418 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 26 Mar 2024 05:48:13 -0400 Subject: [PATCH 52/79] Change `f16` and `f128` clippy stubs to be nonpanicking It turns out there is a bit of a circular dependency - I cannot add anything to `core` because Clippy fails, and I can't actually add correct Clippy implementations without new implementations from `core`. Change some of the Clippy stubs from `unimplemented!` to success values and leave a FIXME in their place to mitigate this. Fixes --- clippy_lints/src/float_literal.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 07fbb1cb5c9..981a76d683d 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -83,7 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { LitFloatType::Unsuffixed => None, }; let (is_whole, is_inf, mut float_str) = match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, FloatTy::F32 => { let value = sym_str.parse::().unwrap(); @@ -94,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, }; if is_inf { @@ -139,10 +145,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { #[must_use] fn max_digits(fty: FloatTy) -> u32 { match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + // FIXME(f16_f128): replace the magic numbers once `{f16,f128}::DIGITS` are available + FloatTy::F16 => 3, FloatTy::F32 => f32::DIGITS, FloatTy::F64 => f64::DIGITS, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => 33, } } From 60937bf2dbf68e36c078087b3a0dc01d6857465a Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Tue, 26 Mar 2024 18:59:09 +0100 Subject: [PATCH 53/79] :adjust applicability for typed identity closures in `filter_map_identity` --- clippy_lints/src/methods/filter_map_identity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs index 15b11a731c9..999df875c75 100644 --- a/clippy_lints/src/methods/filter_map_identity.rs +++ b/clippy_lints/src/methods/filter_map_identity.rs @@ -12,7 +12,7 @@ fn is_identity(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option Date: Tue, 26 Mar 2024 14:11:51 -0400 Subject: [PATCH 54/79] Inherited -> TypeckRootCtxt --- clippy_lints/src/methods/unnecessary_to_owned.rs | 6 +++--- clippy_lints/src/transmute/utils.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index bc5dd10cad0..e58d4776427 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -12,7 +12,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; -use rustc_hir_typeck::{FnCtxt, Inherited}; +use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; @@ -438,8 +438,8 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< Node::Item(item) => { if let ItemKind::Fn(_, _, body_id) = &item.kind && let output_ty = return_ty(cx, item.owner_id) - && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id) - && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id) + && let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id) + && let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id) && fn_ctxt.can_coerce(ty, output_ty) { if has_lifetime(output_ty) && has_lifetime(ty) { diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs index 7a7bb9f9c94..15f1890aa39 100644 --- a/clippy_lints/src/transmute/utils.rs +++ b/clippy_lints/src/transmute/utils.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_hir::Expr; -use rustc_hir_typeck::{cast, FnCtxt, Inherited}; +use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt}; use rustc_lint::LateContext; use rustc_middle::ty::cast::CastKind; use rustc_middle::ty::Ty; @@ -34,8 +34,8 @@ pub(super) fn check_cast<'tcx>( let hir_id = e.hir_id; let local_def_id = hir_id.owner.def_id; - let inherited = Inherited::new(cx.tcx, local_def_id); - let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id); + let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id); + let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id); if let Ok(check) = cast::CastCheck::new( &fn_ctxt, From 91f3fad8e732a0c13f58f3c4395fb69d9ec989c6 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Wed, 27 Mar 2024 08:36:08 +0800 Subject: [PATCH 55/79] check for init expr when linting [`question_mark`] --- clippy_lints/src/question_mark.rs | 21 +++++++++++++++++- tests/ui/question_mark.fixed | 34 +++++++++++++++++++++++++++++ tests/ui/question_mark.rs | 36 +++++++++++++++++++++++++++++++ tests/ui/question_mark.stderr | 10 ++++++++- 4 files changed, 99 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 09bbcdb9c79..771ea33d1bf 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -4,7 +4,7 @@ use clippy_config::msrvs::Msrv; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{ eq_expr_value, higher, in_constant, is_else_clause, is_lint_allowed, is_path_lang_item, is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, @@ -109,12 +109,31 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir } fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { + /// Make sure the init expr implements try trait so a valid suggestion could be given. + /// + /// Because the init expr could have the type of `&Option` which does not implements `Try`. + /// + /// NB: This conveniently prevents the cause of + /// issue [#12412](https://github.com/rust-lang/rust-clippy/issues/12412), + /// since accessing an `Option` field from a borrowed struct requires borrow, such as + /// `&some_struct.opt`, which is type of `&Option`. And we can't suggest `&some_struct.opt?` + /// or `(&some_struct.opt)?` since the first one has different semantics and the later does + /// not implements `Try`. + fn init_expr_can_use_question_mark(cx: &LateContext<'_>, init_expr: &Expr<'_>) -> bool { + let init_ty = cx.typeck_results().expr_ty_adjusted(init_expr); + cx.tcx + .lang_items() + .try_trait() + .map_or(false, |did| implements_trait(cx, init_ty, did, &[])) + } + if let StmtKind::Let(Local { pat, init: Some(init_expr), els: Some(els), .. }) = stmt.kind + && init_expr_can_use_question_mark(cx, init_expr) && let Some(ret) = find_let_else_ret_expression(els) && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, ret) && !span_contains_comment(cx.tcx.sess.source_map(), els.span) diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 567472a8af2..679388372e6 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -283,3 +283,37 @@ fn issue12337() -> Option { }; Some(42) } + +fn issue11983(option: &Option) -> Option<()> { + // Don't lint, `&Option` dose not impl `Try`. + let Some(v) = option else { return None }; + + let opt = Some(String::new()); + // Don't lint, `branch` method in `Try` takes ownership of `opt`, + // and `(&opt)?` also doesn't work since it's `&Option`. + let Some(v) = &opt else { return None }; + let mov = opt; + + Some(()) +} + +struct Foo { + owned: Option, +} +struct Bar { + foo: Foo, +} +#[allow(clippy::disallowed_names)] +fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { + // Don't lint, `owned` is behind a shared reference. + let Some(v) = &foo.owned else { + return None; + }; + // Don't lint, `owned` is behind a shared reference. + let Some(v) = &bar.foo.owned else { + return None; + }; + // lint + let v = bar.foo.owned.clone()?; + Some(()) +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index abf8c270de8..601ab78bf5a 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -323,3 +323,39 @@ fn issue12337() -> Option { }; Some(42) } + +fn issue11983(option: &Option) -> Option<()> { + // Don't lint, `&Option` dose not impl `Try`. + let Some(v) = option else { return None }; + + let opt = Some(String::new()); + // Don't lint, `branch` method in `Try` takes ownership of `opt`, + // and `(&opt)?` also doesn't work since it's `&Option`. + let Some(v) = &opt else { return None }; + let mov = opt; + + Some(()) +} + +struct Foo { + owned: Option, +} +struct Bar { + foo: Foo, +} +#[allow(clippy::disallowed_names)] +fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { + // Don't lint, `owned` is behind a shared reference. + let Some(v) = &foo.owned else { + return None; + }; + // Don't lint, `owned` is behind a shared reference. + let Some(v) = &bar.foo.owned else { + return None; + }; + // lint + let Some(v) = bar.foo.owned.clone() else { + return None; + }; + Some(()) +} diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 4fcccdf5512..5f26a7ea2c3 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -141,5 +141,13 @@ LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#is LL | | } | |_____________^ help: replace it with: `a?;` -error: aborting due to 16 previous errors +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:357:5 + | +LL | / let Some(v) = bar.foo.owned.clone() else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;` + +error: aborting due to 17 previous errors From c27f52d611928ed0bb11665e03de21484c2061aa Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Wed, 27 Mar 2024 16:28:15 +0800 Subject: [PATCH 56/79] allow [`manual_unwrap_or_default`] in const function --- clippy_lints/src/manual_unwrap_or_default.rs | 4 ++-- tests/ui/manual_unwrap_or_default.fixed | 7 +++++++ tests/ui/manual_unwrap_or_default.rs | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs index fc6b0d6f9f6..8f189cf6e09 100644 --- a/clippy_lints/src/manual_unwrap_or_default.rs +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -7,9 +7,9 @@ use rustc_session::declare_lint_pass; use rustc_span::sym; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_default_equivalent; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; +use clippy_utils::{in_constant, is_default_equivalent}; declare_clippy_lint! { /// ### What it does @@ -172,7 +172,7 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if expr.span.from_expansion() { + if expr.span.from_expansion() || in_constant(cx, expr.hir_id) { return; } if !handle_match(cx, expr) { diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed index b24967242eb..182c9b317b6 100644 --- a/tests/ui/manual_unwrap_or_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -26,3 +26,10 @@ unsafe fn no_deref_ptr(a: Option, b: *const Option) -> i32 { _ => 0, } } + +const fn issue_12568(opt: Option) -> bool { + match opt { + Some(s) => s, + None => false, + } +} diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index ed5e54b4e14..e8eaddc1d14 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -50,3 +50,10 @@ unsafe fn no_deref_ptr(a: Option, b: *const Option) -> i32 { _ => 0, } } + +const fn issue_12568(opt: Option) -> bool { + match opt { + Some(s) => s, + None => false, + } +} From 5b95e9099c96a9f156d7473daf10644471172477 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:06:32 +0100 Subject: [PATCH 57/79] move `mixed_attributes_style` to the style category --- clippy_lints/src/attrs/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 6f4575f1b9a..684ad7de2f0 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -496,7 +496,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.78.0"] pub MIXED_ATTRIBUTES_STYLE, - suspicious, + style, "item has both inner and outer attributes" } From 11b28d44bd428cdb4c939e51b064426c4b73a293 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 23 Mar 2024 21:04:45 -0400 Subject: [PATCH 58/79] Implement `mut ref`/`mut ref mut` --- clippy_lints/src/functions/misnamed_getters.rs | 4 ++-- clippy_lints/src/index_refutable_slice.rs | 4 ++-- clippy_lints/src/iter_without_into_iter.rs | 4 ++-- clippy_lints/src/len_zero.rs | 8 ++++---- .../src/matches/infallible_destructuring_match.rs | 4 ++-- clippy_lints/src/matches/match_as_ref.rs | 2 +- clippy_lints/src/matches/needless_match.rs | 2 +- clippy_lints/src/matches/redundant_guards.rs | 2 +- clippy_lints/src/methods/clone_on_copy.rs | 2 +- clippy_lints/src/methods/iter_kv_map.rs | 5 ++--- clippy_lints/src/misc.rs | 4 ++-- clippy_lints/src/question_mark.rs | 10 +++++++--- clippy_lints/src/utils/author.rs | 2 ++ clippy_utils/src/lib.rs | 10 +++++----- 14 files changed, 34 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs index bf96c0d62b0..8ac17e17688 100644 --- a/clippy_lints/src/functions/misnamed_getters.rs +++ b/clippy_lints/src/functions/misnamed_getters.rs @@ -24,13 +24,13 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: let name = ident.name.as_str(); let name = match decl.implicit_self { - ImplicitSelfKind::MutRef => { + ImplicitSelfKind::RefMut => { let Some(name) = name.strip_suffix("_mut") else { return; }; name }, - ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::ImmRef => name, + ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::RefImm => name, ImplicitSelfKind::None => return, }; diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 5b5eb355f86..4d1f89b1d9d 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -97,7 +97,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap, pat: &hir::Pat<'_>) -> FxIndexMap, item: &rustc_hir::ImplItem<'_>) { let item_did = item.owner_id.to_def_id(); let (borrow_prefix, expected_implicit_self) = match item.ident.name { - sym::iter => ("&", ImplicitSelfKind::ImmRef), - sym::iter_mut => ("&mut ", ImplicitSelfKind::MutRef), + sym::iter => ("&", ImplicitSelfKind::RefImm), + sym::iter_mut => ("&mut ", ImplicitSelfKind::RefMut), _ => return, }; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 27d85cde532..cae9ada5a33 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -384,8 +384,8 @@ impl LenOutput { fn expected_sig(self, self_kind: ImplicitSelfKind) -> String { let self_ref = match self_kind { - ImplicitSelfKind::ImmRef => "&", - ImplicitSelfKind::MutRef => "&mut ", + ImplicitSelfKind::RefImm => "&", + ImplicitSelfKind::RefMut => "&mut ", _ => "", }; match self { @@ -411,8 +411,8 @@ fn check_is_empty_sig<'tcx>( [arg, res] if len_output.matches_is_empty_output(cx, *res) => { matches!( (arg.kind(), self_kind), - (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::ImmRef) - | (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::MutRef) + (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::RefImm) + | (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::RefMut) ) || (!arg.is_ref() && matches!(self_kind, ImplicitSelfKind::Imm | ImplicitSelfKind::Mut)) }, _ => false, diff --git a/clippy_lints/src/matches/infallible_destructuring_match.rs b/clippy_lints/src/matches/infallible_destructuring_match.rs index 0f242e0b9e1..93d7683d2af 100644 --- a/clippy_lints/src/matches/infallible_destructuring_match.rs +++ b/clippy_lints/src/matches/infallible_destructuring_match.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs}; use rustc_errors::Applicability; -use rustc_hir::{ByRef, ExprKind, LetStmt, MatchSource, PatKind, QPath}; +use rustc_hir::{ExprKind, LetStmt, MatchSource, PatKind, QPath}; use rustc_lint::LateContext; use super::INFALLIBLE_DESTRUCTURING_MATCH; @@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool { format!( "let {}({}{}) = {};", snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), - if binding.0 == ByRef::Yes { "ref " } else { "" }, + binding.prefix_str(), snippet_with_applicability(cx, local.pat.span, "..", &mut applicability), snippet_with_applicability(cx, target.span, "..", &mut applicability), ), diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs index 3f737da92c0..6b484ff2749 100644 --- a/clippy_lints/src/matches/match_as_ref.rs +++ b/clippy_lints/src/matches/match_as_ref.rs @@ -67,7 +67,7 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option { if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome) - && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind + && let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind && let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind && is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome) && let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind diff --git a/clippy_lints/src/matches/needless_match.rs b/clippy_lints/src/matches/needless_match.rs index cee77f62b61..fe83e784c3c 100644 --- a/clippy_lints/src/matches/needless_match.rs +++ b/clippy_lints/src/matches/needless_match.rs @@ -178,7 +178,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { }, )), ) => { - return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name; + return !matches!(annot, BindingAnnotation(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name; }, // Example: `Custom::TypeA => Custom::TypeB`, or `None => None` (PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => { diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index 6bae51b45b8..50cbccc3968 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/clippy_lints/src/matches/redundant_guards.rs @@ -182,7 +182,7 @@ fn get_pat_binding<'tcx>( if let PatKind::Binding(bind_annot, hir_id, ident, _) = pat.kind && hir_id == local { - if matches!(bind_annot.0, rustc_ast::ByRef::Yes) { + if matches!(bind_annot.0, rustc_ast::ByRef::Yes(_)) { let _ = byref_ident.insert(ident); } // the second call of `replace()` returns a `Some(span)`, meaning a multi-binding pattern diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index d4a5de3d1de..3e099004c47 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -69,7 +69,7 @@ pub(super) fn check( _ => false, }, // local binding capturing a reference - Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => { + Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..)) => { return; }, _ => false, diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 6394f35f860..1431a5db2d9 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -60,8 +60,6 @@ pub(super) fn check<'tcx>( applicability, ); } else { - let ref_annotation = if annotation.0 == ByRef::Yes { "ref " } else { "" }; - let mut_annotation = if annotation.1 == Mutability::Mut { "mut " } else { "" }; span_lint_and_sugg( cx, ITER_KV_MAP, @@ -69,7 +67,8 @@ pub(super) fn check<'tcx>( &format!("iterating on a map's {replacement_kind}s"), "try", format!( - "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})", + "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{}{bound_ident}| {})", + annotation.prefix_str(), snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability) ), applicability, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index ea6e662b4be..11fecb7d72e 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) { return; } - if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind { + if let PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..) = arg.pat.kind { span_lint( cx, TOPLEVEL_REF_ARG, @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.tcx.sess, stmt.span) && let StmtKind::Let(local) = stmt.kind - && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind + && let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index f1db571e113..b57220e6cf0 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -14,7 +14,7 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, + BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -283,9 +283,13 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_)); + let method_call_str = match by_ref { + ByRef::Yes(Mutability::Mut) => ".as_mut()", + ByRef::Yes(Mutability::Not) => ".as_ref()", + ByRef::No => "", + }; let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + "{receiver_str}{method_call_str}?{}", if requires_semi { ";" } else { "" } ); span_lint_and_sugg( diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 5319915b2ea..e45beb4910b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -649,6 +649,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { BindingAnnotation::REF => "REF", BindingAnnotation::MUT => "MUT", BindingAnnotation::REF_MUT => "REF_MUT", + BindingAnnotation::MUT_REF => "MUT_REF", + BindingAnnotation::MUT_REF_MUT => "MUT_REF_MUT", }; kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})"); self.ident(name); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8251bdf78fc..95bab5801d1 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -97,7 +97,7 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, + self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, ByRef, Closure, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, @@ -107,7 +107,6 @@ use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::Const; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; -use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ @@ -1006,11 +1005,12 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { .typeck_results() .extract_binding_mode(cx.sess(), id, span) .unwrap() + .0 { - BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => { + ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => { capture = CaptureKind::Value; }, - BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => { + ByRef::Yes(Mutability::Mut) if capture != CaptureKind::Value => { capture = CaptureKind::Ref(Mutability::Mut); }, _ => (), @@ -2035,7 +2035,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { .typeck_results() .pat_binding_modes() .get(pat.hir_id) - .is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_))) + .is_some_and(|mode| matches!(mode.0, ByRef::Yes(_))) { // If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics, // the inner patterns become references. Don't consider this the identity function From 01646457a9206429c9a463984d075de25805791e Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 27 Mar 2024 22:52:34 -0700 Subject: [PATCH 59/79] `large_stack_frames`: print total size and largest component. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of just saying “this function's stack frame is big”, report: * the (presumed) size of the frame * the size and type of the largest local contributing to that size * the configurable limit that was exceeded (once) --- clippy_lints/src/large_stack_frames.rs | 106 ++++++++++++++---- .../large_stack_frames/large_stack_frames.rs | 2 +- .../large_stack_frames.stderr | 17 +-- tests/ui/large_stack_frames.rs | 17 ++- tests/ui/large_stack_frames.stderr | 60 +++++----- 5 files changed, 134 insertions(+), 68 deletions(-) diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index b397180a69c..059ba981ef3 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -1,10 +1,12 @@ -use std::ops::AddAssign; +use std::{fmt, ops}; -use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::fn_has_unsatisfiable_preds; +use clippy_utils::source::snippet_opt; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; +use rustc_lexer::is_ident; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -108,13 +110,25 @@ impl Space { } } -impl AddAssign for Space { - fn add_assign(&mut self, rhs: u64) { - if let Self::Used(lhs) = self { - match lhs.checked_add(rhs) { - Some(sum) => *self = Self::Used(sum), - None => *self = Self::Overflow, - } +impl fmt::Display for Space { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Space::Used(1) => write!(f, "1 byte"), + Space::Used(n) => write!(f, "{n} bytes"), + Space::Overflow => write!(f, "over 2⁶⁴-1 bytes"), + } + } +} + +impl ops::Add for Space { + type Output = Self; + fn add(self, rhs: u64) -> Self { + match self { + Self::Used(lhs) => match lhs.checked_add(rhs) { + Some(sum) => Self::Used(sum), + None => Self::Overflow, + }, + Self::Overflow => self, } } } @@ -123,10 +137,10 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { fn check_fn( &mut self, cx: &LateContext<'tcx>, - _: FnKind<'tcx>, + fn_kind: FnKind<'tcx>, _: &'tcx FnDecl<'tcx>, _: &'tcx Body<'tcx>, - span: Span, + entire_fn_span: Span, local_def_id: LocalDefId, ) { let def_id = local_def_id.to_def_id(); @@ -138,22 +152,68 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { let mir = cx.tcx.optimized_mir(def_id); let param_env = cx.tcx.param_env(def_id); - let mut frame_size = Space::Used(0); + let sizes_of_locals = || { + mir.local_decls.iter().filter_map(|local| { + let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?; + Some((local, layout.size.bytes())) + }) + }; - for local in &mir.local_decls { - if let Ok(layout) = cx.tcx.layout_of(param_env.and(local.ty)) { - frame_size += layout.size.bytes(); - } - } + let frame_size = sizes_of_locals().fold(Space::Used(0), |sum, (_, size)| sum + size); - if frame_size.exceeds_limit(self.maximum_allowed_size) { - span_lint_and_note( + let limit = self.maximum_allowed_size; + if frame_size.exceeds_limit(limit) { + // Point at just the function name if possible, because lints that span + // the entire body and don't have to are less legible. + let fn_span = match fn_kind { + FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span, + FnKind::Closure => entire_fn_span, + }; + + span_lint_and_then( cx, LARGE_STACK_FRAMES, - span, - "this function allocates a large amount of stack space", - None, - "allocating large amounts of stack space can overflow the stack", + fn_span, + &format!("this function may allocate {frame_size} on the stack"), + |diag| { + // Point out the largest individual contribution to this size, because + // it is the most likely to be unintentionally large. + if let Some((local, size)) = sizes_of_locals().max_by_key(|&(_, size)| size) { + let local_span: Span = local.source_info.span; + let size = Space::Used(size); // pluralizes for us + let ty = local.ty; + + // TODO: Is there a cleaner, robust way to ask this question? + // The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data", + // and that doesn't get us the true name in scope rather than the span text either. + if let Some(name) = snippet_opt(cx, local_span) + && is_ident(&name) + { + // If the local is an ordinary named variable, + // print its name rather than relying solely on the span. + diag.span_label( + local_span, + format!("`{name}` is the largest part, at {size} for type `{ty}`"), + ); + } else { + diag.span_label( + local_span, + format!("this is the largest part, at {size} for type `{ty}`"), + ); + } + } + + // Explain why we are linting this and not other functions. + diag.note(format!( + "{frame_size} is larger than Clippy's configured `stack-size-threshold` of {limit}" + )); + + // Explain why the user should care, briefly. + diag.note_once( + "allocating large amounts of stack space can overflow the stack \ + and cause the program to abort", + ); + }, ); } } diff --git a/tests/ui-toml/large_stack_frames/large_stack_frames.rs b/tests/ui-toml/large_stack_frames/large_stack_frames.rs index 39798ffea49..a612e56570f 100644 --- a/tests/ui-toml/large_stack_frames/large_stack_frames.rs +++ b/tests/ui-toml/large_stack_frames/large_stack_frames.rs @@ -10,7 +10,7 @@ fn f() { let _x = create_array::<1000>(); } fn f2() { - //~^ ERROR: this function allocates a large amount of stack space + //~^ ERROR: this function may allocate 1001 bytes on the stack let _x = create_array::<1001>(); } diff --git a/tests/ui-toml/large_stack_frames/large_stack_frames.stderr b/tests/ui-toml/large_stack_frames/large_stack_frames.stderr index c23fac14564..19983e2f3e8 100644 --- a/tests/ui-toml/large_stack_frames/large_stack_frames.stderr +++ b/tests/ui-toml/large_stack_frames/large_stack_frames.stderr @@ -1,13 +1,14 @@ -error: this function allocates a large amount of stack space - --> tests/ui-toml/large_stack_frames/large_stack_frames.rs:12:1 +error: this function may allocate 1001 bytes on the stack + --> tests/ui-toml/large_stack_frames/large_stack_frames.rs:12:4 | -LL | / fn f2() { -LL | | -LL | | let _x = create_array::<1001>(); -LL | | } - | |_^ +LL | fn f2() { + | ^^ +LL | +LL | let _x = create_array::<1001>(); + | -- `_x` is the largest part, at 1001 bytes for type `[u8; 1001]` | - = note: allocating large amounts of stack space can overflow the stack + = note: 1001 bytes is larger than Clippy's configured `stack-size-threshold` of 1000 + = note: allocating large amounts of stack space can overflow the stack and cause the program to abort = note: `-D clippy::large-stack-frames` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs index f32368f9397..e6c030b8a9e 100644 --- a/tests/ui/large_stack_frames.rs +++ b/tests/ui/large_stack_frames.rs @@ -1,3 +1,5 @@ +//@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR" +//@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR" #![allow(unused, incomplete_features)] #![warn(clippy::large_stack_frames)] #![feature(unsized_locals)] @@ -23,8 +25,7 @@ impl Default for ArrayDefault { } fn many_small_arrays() { - //~^ ERROR: this function allocates a large amount of stack space - //~| NOTE: allocating large amounts of stack space can overflow the stack + //~^ ERROR: this function may allocate let x = [0u8; 500_000]; let x2 = [0u8; 500_000]; let x3 = [0u8; 500_000]; @@ -34,17 +35,21 @@ fn many_small_arrays() { } fn large_return_value() -> ArrayDefault<1_000_000> { - //~^ ERROR: this function allocates a large amount of stack space - //~| NOTE: allocating large amounts of stack space can overflow the stack + //~^ ERROR: this function may allocate 1000000 bytes on the stack Default::default() } fn large_fn_arg(x: ArrayDefault<1_000_000>) { - //~^ ERROR: this function allocates a large amount of stack space - //~| NOTE: allocating large amounts of stack space can overflow the stack + //~^ ERROR: this function may allocate black_box(&x); } +fn has_large_closure() { + let f = || black_box(&[0u8; 1_000_000]); + //~^ ERROR: this function may allocate + f(); +} + fn main() { generic::>(); } diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr index b99500fd9c3..f2e0a127f5f 100644 --- a/tests/ui/large_stack_frames.stderr +++ b/tests/ui/large_stack_frames.stderr @@ -1,42 +1,42 @@ -error: this function allocates a large amount of stack space - --> tests/ui/large_stack_frames.rs:25:1 +error: this function may allocate 250$PTR bytes on the stack + --> tests/ui/large_stack_frames.rs:27:4 | -LL | / fn many_small_arrays() { -LL | | -LL | | -LL | | let x = [0u8; 500_000]; -... | -LL | | black_box((&x, &x2, &x3, &x4, &x5)); -LL | | } - | |_^ +LL | fn many_small_arrays() { + | ^^^^^^^^^^^^^^^^^ +... +LL | let x5 = [0u8; 500_000]; + | -- `x5` is the largest part, at 500000 bytes for type `[u8; 500000]` | - = note: allocating large amounts of stack space can overflow the stack + = note: 250$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 + = note: allocating large amounts of stack space can overflow the stack and cause the program to abort = note: `-D clippy::large-stack-frames` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` -error: this function allocates a large amount of stack space - --> tests/ui/large_stack_frames.rs:36:1 +error: this function may allocate 1000000 bytes on the stack + --> tests/ui/large_stack_frames.rs:37:4 | -LL | / fn large_return_value() -> ArrayDefault<1_000_000> { -LL | | -LL | | -LL | | Default::default() -LL | | } - | |_^ +LL | fn large_return_value() -> ArrayDefault<1_000_000> { + | ^^^^^^^^^^^^^^^^^^ ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` | - = note: allocating large amounts of stack space can overflow the stack + = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000 -error: this function allocates a large amount of stack space - --> tests/ui/large_stack_frames.rs:42:1 +error: this function may allocate 100$PTR bytes on the stack + --> tests/ui/large_stack_frames.rs:42:4 | -LL | / fn large_fn_arg(x: ArrayDefault<1_000_000>) { -LL | | -LL | | -LL | | black_box(&x); -LL | | } - | |_^ +LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { + | ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` | - = note: allocating large amounts of stack space can overflow the stack + = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 -error: aborting due to 3 previous errors +error: this function may allocate 100$PTR bytes on the stack + --> tests/ui/large_stack_frames.rs:48:13 + | +LL | let f = || black_box(&[0u8; 1_000_000]); + | ^^^^^^^^^^^^^^----------------^ + | | + | this is the largest part, at 1000000 bytes for type `[u8; 1000000]` + | + = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 + +error: aborting due to 4 previous errors From 7aac504e4160c9524412af5f83eeb111918cc6ab Mon Sep 17 00:00:00 2001 From: shandongbinzhou Date: Fri, 29 Mar 2024 16:17:07 +0800 Subject: [PATCH 60/79] Fix typo in comment Signed-off-by: shandongbinzhou --- clippy_lints/src/serde_api.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index b4278d879e5..f1ec91d7aff 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -9,7 +9,7 @@ declare_clippy_lint! { /// Checks for misuses of the serde API. /// /// ### Why is this bad? - /// Serde is very finnicky about how its API should be + /// Serde is very finicky about how its API should be /// used, but the type system can't be used to enforce it (yet?). /// /// ### Example From 89588f41f8a96984601b0abc7f8eaacfa3b7da8f Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Fri, 29 Mar 2024 09:38:59 -0600 Subject: [PATCH 61/79] Add limitations section, move check --- clippy_lints/src/manual_clamp.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 59fc8948c2f..1eadc200bed 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -28,6 +28,11 @@ declare_clippy_lint! { /// ### Why is this bad? /// clamp is much shorter, easier to read, and doesn't use any control flow. /// + /// ### Limitations + /// + /// This lint will only trigger if max and min are known at compile time, and max is + /// greater than min. + /// /// ### Known issue(s) /// If the clamped variable is NaN this suggestion will cause the code to propagate NaN /// rather than returning either `max` or `min`. @@ -145,9 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp { .or_else(|| is_match_pattern(cx, expr)) .or_else(|| is_if_elseif_pattern(cx, expr)); if let Some(suggestion) = suggestion { - if suggestion.min_less_than_max(cx) { - emit_suggestion(cx, &suggestion); - } + maybe_emit_suggestion(cx, &suggestion); } } } @@ -157,15 +160,16 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp { return; } for suggestion in is_two_if_pattern(cx, block) { - if suggestion.min_less_than_max(cx) { - emit_suggestion(cx, &suggestion); - } + maybe_emit_suggestion(cx, &suggestion); } } extract_msrv_attr!(LateContext); } -fn emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) { +fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) { + if !suggestion.min_less_than_max(cx) { + return; + } let ClampSuggestion { params: InputMinMax { input, From 37be3e4dd5ec4aa11959f9fd24d1c1dc53da44bd Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 18 Aug 2023 09:25:18 +0200 Subject: [PATCH 62/79] [`type_id_on_box`]: lint of `Any` subtraits --- clippy_lints/src/methods/type_id_on_box.rs | 46 ++++++++++++++++------ tests/ui/type_id_on_box.fixed | 24 +++++++++++ tests/ui/type_id_on_box.rs | 24 +++++++++++ tests/ui/type_id_on_box.stderr | 31 ++++++++++----- 4 files changed, 103 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index 4917936a932..cec5d3b2b6d 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::methods::TYPE_ID_ON_BOX; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; @@ -5,17 +7,37 @@ use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{sym, Span}; -fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { +/// Checks if a [`Ty`] is a `dyn Any` or a `dyn Trait` where `Trait: Any` +/// and returns the name of the trait object. +fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> Option> { if let ty::Dynamic(preds, ..) = ty.kind() { - preds.iter().any(|p| match p.skip_binder() { - ExistentialPredicate::Trait(tr) => cx.tcx.is_diagnostic_item(sym::Any, tr.def_id), - _ => false, + preds.iter().find_map(|p| match p.skip_binder() { + ExistentialPredicate::Trait(tr) => { + if cx.tcx.is_diagnostic_item(sym::Any, tr.def_id) { + Some(Cow::Borrowed("Any")) + } else if cx + .tcx + .super_predicates_of(tr.def_id) + .predicates + .iter() + .any(|(clause, _)| { + matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr) + if cx.tcx.is_diagnostic_item(sym::Any, super_tr.def_id())) + }) + { + Some(Cow::Owned(with_forced_trimmed_paths!(cx.tcx.def_path_str(tr.def_id)))) + } else { + None + } + }, + _ => None, }) } else { - false + None } } @@ -26,13 +48,13 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) && let ty::Ref(_, ty, _) = recv_ty.kind() && let ty::Adt(adt, args) = ty.kind() && adt.is_box() - && is_dyn_any(cx, args.type_at(0)) + && let Some(trait_path) = is_dyn_any(cx, args.type_at(0)) { span_lint_and_then( cx, TYPE_ID_ON_BOX, call_span, - "calling `.type_id()` on a `Box`", + &format!("calling `.type_id()` on `Box`"), |diag| { let derefs = recv_adjusts .iter() @@ -43,13 +65,13 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) sugg += &snippet(cx, receiver.span, ""); diag.note( - "this returns the type id of the literal type `Box` instead of the \ + "this returns the type id of the literal type `Box<_>` instead of the \ type id of the boxed value, which is most likely not what you want", ) - .note( - "if this is intentional, use `TypeId::of::>()` instead, \ - which makes it more clear", - ) + .note(format!( + "if this is intentional, use `TypeId::of::>()` instead, \ + which makes it more clear" + )) .span_suggestion( receiver.span, "consider dereferencing first", diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed index 538c38b70e6..bdc45a93e71 100644 --- a/tests/ui/type_id_on_box.fixed +++ b/tests/ui/type_id_on_box.fixed @@ -19,6 +19,21 @@ fn existential() -> impl Any { Box::new(1) as Box } +trait AnySubTrait: Any {} +impl AnySubTrait for T {} + +// `Any` is an indirect supertrait +trait AnySubSubTrait: AnySubTrait {} +impl AnySubSubTrait for T {} + +// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`. +trait NormalTrait +where + i32: Any, +{ +} +impl NormalTrait for T {} + fn main() { let any_box: Box = Box::new(0usize); let _ = (*any_box).type_id(); @@ -35,4 +50,13 @@ fn main() { let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! + + let b: Box = Box::new(1); + let _ = (*b).type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` + + let b: Box = Box::new(1); + let _ = b.type_id(); // Known FN - Any is not an "immediate" supertrait + + let b: Box = Box::new(1); + let _ = b.type_id(); // `NormalTrait` does not have `Any` as its supertrait (even though it mentions it in `i32: Any`) } diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs index f224d273bc2..e087d9989d8 100644 --- a/tests/ui/type_id_on_box.rs +++ b/tests/ui/type_id_on_box.rs @@ -19,6 +19,21 @@ fn existential() -> impl Any { Box::new(1) as Box } +trait AnySubTrait: Any {} +impl AnySubTrait for T {} + +// `Any` is an indirect supertrait +trait AnySubSubTrait: AnySubTrait {} +impl AnySubSubTrait for T {} + +// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`. +trait NormalTrait +where + i32: Any, +{ +} +impl NormalTrait for T {} + fn main() { let any_box: Box = Box::new(0usize); let _ = any_box.type_id(); @@ -35,4 +50,13 @@ fn main() { let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! + + let b: Box = Box::new(1); + let _ = b.type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` + + let b: Box = Box::new(1); + let _ = b.type_id(); // Known FN - Any is not an "immediate" supertrait + + let b: Box = Box::new(1); + let _ = b.type_id(); // `NormalTrait` does not have `Any` as its supertrait (even though it mentions it in `i32: Any`) } diff --git a/tests/ui/type_id_on_box.stderr b/tests/ui/type_id_on_box.stderr index 0fce6a37c00..8edecc47c74 100644 --- a/tests/ui/type_id_on_box.stderr +++ b/tests/ui/type_id_on_box.stderr @@ -1,37 +1,48 @@ -error: calling `.type_id()` on a `Box` - --> tests/ui/type_id_on_box.rs:24:13 +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box.rs:39:13 | LL | let _ = any_box.type_id(); | -------^^^^^^^^^^ | | | help: consider dereferencing first: `(*any_box)` | - = note: this returns the type id of the literal type `Box` instead of the type id of the boxed value, which is most likely not what you want + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear = note: `-D clippy::type-id-on-box` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::type_id_on_box)]` -error: calling `.type_id()` on a `Box` - --> tests/ui/type_id_on_box.rs:28:13 +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box.rs:43:13 | LL | let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any` | -------^^^^^^^^^^ | | | help: consider dereferencing first: `(**any_box)` | - = note: this returns the type id of the literal type `Box` instead of the type id of the boxed value, which is most likely not what you want + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear -error: calling `.type_id()` on a `Box` - --> tests/ui/type_id_on_box.rs:34:13 +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box.rs:49:13 | LL | let _ = b.type_id(); | -^^^^^^^^^^ | | | help: consider dereferencing first: `(*b)` | - = note: this returns the type id of the literal type `Box` instead of the type id of the boxed value, which is most likely not what you want + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear -error: aborting due to 3 previous errors +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box.rs:55:13 + | +LL | let _ = b.type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` + | -^^^^^^^^^^ + | | + | help: consider dereferencing first: `(*b)` + | + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want + = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + +error: aborting due to 4 previous errors From 5750e4670b7e217bb1c6260bf54dfcc0ef2e76cb Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Sat, 30 Mar 2024 09:18:53 +0800 Subject: [PATCH 63/79] fix [`manual_unwrap_or_default`] suggestion ignoring side-effects --- clippy_lints/src/manual_unwrap_or_default.rs | 26 ++++++++++++------ tests/ui/manual_unwrap_or_default.fixed | 29 ++++++++++++++++++++ tests/ui/manual_unwrap_or_default.rs | 29 ++++++++++++++++++++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs index 8f189cf6e09..c562ceb5bce 100644 --- a/clippy_lints/src/manual_unwrap_or_default.rs +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -2,14 +2,14 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::sym; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; -use clippy_utils::{in_constant, is_default_equivalent}; +use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment}; declare_clippy_lint! { /// ### What it does @@ -119,14 +119,19 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { // We now get the bodies for both the `Some` and `None` arms. && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. - && let ExprKind::Path(QPath::Resolved(_, path)) = body_some.peel_blocks().kind + && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind && let Res::Local(local_id) = path.res && local_id == binding_id // We now check the `None` arm is calling a method equivalent to `Default::default`. - && let body_none = body_none.peel_blocks() + && let body_none = peel_blocks(body_none) && is_default_equivalent(cx, body_none) && let Some(receiver) = Sugg::hir_opt(cx, match_expr).map(Sugg::maybe_par) { + let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; span_lint_and_sugg( cx, MANUAL_UNWRAP_OR_DEFAULT, @@ -134,7 +139,7 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { "match can be simplified with `.unwrap_or_default()`", "replace it with", format!("{receiver}.unwrap_or_default()"), - Applicability::MachineApplicable, + applicability, ); } true @@ -150,14 +155,19 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { && implements_trait(cx, match_ty, default_trait_id, &[]) && let Some(binding_id) = get_some(cx, let_.pat) // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. - && let ExprKind::Path(QPath::Resolved(_, path)) = if_block.peel_blocks().kind + && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind && let Res::Local(local_id) = path.res && local_id == binding_id // We now check the `None` arm is calling a method equivalent to `Default::default`. - && let body_else = else_expr.peel_blocks() + && let body_else = peel_blocks(else_expr) && is_default_equivalent(cx, body_else) && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span) { + let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; span_lint_and_sugg( cx, MANUAL_UNWRAP_OR_DEFAULT, @@ -165,7 +175,7 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { "if let can be simplified with `.unwrap_or_default()`", "replace it with", format!("{if_let_expr_snippet}.unwrap_or_default()"), - Applicability::MachineApplicable, + applicability, ); } } diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed index 182c9b317b6..a0b707628a8 100644 --- a/tests/ui/manual_unwrap_or_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -33,3 +33,32 @@ const fn issue_12568(opt: Option) -> bool { None => false, } } + +fn issue_12569() { + let match_none_se = match 1u32.checked_div(0) { + Some(v) => v, + None => { + println!("important"); + 0 + }, + }; + let match_some_se = match 1u32.checked_div(0) { + Some(v) => { + println!("important"); + v + }, + None => 0, + }; + let iflet_else_se = if let Some(v) = 1u32.checked_div(0) { + v + } else { + println!("important"); + 0 + }; + let iflet_then_se = if let Some(v) = 1u32.checked_div(0) { + println!("important"); + v + } else { + 0 + }; +} diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index e8eaddc1d14..1d4cca12f6c 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -57,3 +57,32 @@ const fn issue_12568(opt: Option) -> bool { None => false, } } + +fn issue_12569() { + let match_none_se = match 1u32.checked_div(0) { + Some(v) => v, + None => { + println!("important"); + 0 + }, + }; + let match_some_se = match 1u32.checked_div(0) { + Some(v) => { + println!("important"); + v + }, + None => 0, + }; + let iflet_else_se = if let Some(v) = 1u32.checked_div(0) { + v + } else { + println!("important"); + 0 + }; + let iflet_then_se = if let Some(v) = 1u32.checked_div(0) { + println!("important"); + v + } else { + 0 + }; +} From 36e4c2083b540132cbcb7761f3133b2ed561ad29 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:52:53 +0100 Subject: [PATCH 64/79] lint on any `Box`, but provide a suggestion for subtypes of `dyn Any` --- clippy_lints/src/methods/mod.rs | 21 ++++-- clippy_lints/src/methods/type_id_on_box.rs | 76 ++++++++++++---------- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index df5dad0423c..3ad92a91ea7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3002,13 +3002,22 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Looks for calls to ` as Any>::type_id`. + /// Looks for calls to `.type_id()` on a `Box`. /// /// ### Why is this bad? - /// This most certainly does not do what the user expects and is very easy to miss. - /// Calling `type_id` on a `Box` calls `type_id` on the `Box<..>` itself, - /// so this will return the `TypeId` of the `Box` type (not the type id - /// of the value referenced by the box!). + /// This almost certainly does not do what the user expects and can lead to subtle bugs. + /// Calling `.type_id()` on a `Box` returns a fixed `TypeId` of the `Box` itself, + /// rather than returning the `TypeId` of the underlying type behind the trait object. + /// + /// For `Box` specifically (and trait objects that have `Any` as its supertrait), + /// this lint will provide a suggestion, which is to dereference the receiver explicitly + /// to go from `Box` to `dyn Any`. + /// This makes sure that `.type_id()` resolves to a dynamic call on the trait object + /// and not on the box. + /// + /// If the fixed `TypeId` of the `Box` is the intended behavior, it's better to be explicit about it + /// and write `TypeId::of::>()`: + /// this makes it clear that a fixed `TypeId` is returned and not the `TypeId` of the implementor. /// /// ### Example /// ```rust,ignore @@ -3028,7 +3037,7 @@ declare_clippy_lint! { #[clippy::version = "1.73.0"] pub TYPE_ID_ON_BOX, suspicious, - "calling `.type_id()` on `Box`" + "calling `.type_id()` on a boxed trait object" } declare_clippy_lint! { diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index cec5d3b2b6d..31e6ccb950a 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use crate::methods::TYPE_ID_ON_BOX; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; @@ -11,33 +9,33 @@ use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{sym, Span}; -/// Checks if a [`Ty`] is a `dyn Any` or a `dyn Trait` where `Trait: Any` -/// and returns the name of the trait object. -fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> Option> { +/// Checks if the given type is `dyn Any`, or a trait object that has `Any` as a supertrait. +/// Only in those cases will its vtable have a `type_id` method that returns the implementor's +/// `TypeId`, and only in those cases can we give a proper suggestion to dereference the box. +/// +/// If this returns false, then `.type_id()` likely (this may have FNs) will not be what the user +/// expects in any case and dereferencing it won't help either. It will likely require some +/// other changes, but it is still worth emitting a lint. +/// See for more details. +fn is_subtrait_of_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { if let ty::Dynamic(preds, ..) = ty.kind() { - preds.iter().find_map(|p| match p.skip_binder() { + preds.iter().any(|p| match p.skip_binder() { ExistentialPredicate::Trait(tr) => { - if cx.tcx.is_diagnostic_item(sym::Any, tr.def_id) { - Some(Cow::Borrowed("Any")) - } else if cx - .tcx - .super_predicates_of(tr.def_id) - .predicates - .iter() - .any(|(clause, _)| { - matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr) + cx.tcx.is_diagnostic_item(sym::Any, tr.def_id) + || cx + .tcx + .super_predicates_of(tr.def_id) + .predicates + .iter() + .any(|(clause, _)| { + matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr) if cx.tcx.is_diagnostic_item(sym::Any, super_tr.def_id())) - }) - { - Some(Cow::Owned(with_forced_trimmed_paths!(cx.tcx.def_path_str(tr.def_id)))) - } else { - None - } + }) }, - _ => None, + _ => false, }) } else { - None + false } } @@ -48,36 +46,42 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) && let ty::Ref(_, ty, _) = recv_ty.kind() && let ty::Adt(adt, args) = ty.kind() && adt.is_box() - && let Some(trait_path) = is_dyn_any(cx, args.type_at(0)) + && let inner_box_ty = args.type_at(0) + && let ty::Dynamic(..) = inner_box_ty.kind() { + let ty_name = with_forced_trimmed_paths!(ty.to_string()); + span_lint_and_then( cx, TYPE_ID_ON_BOX, call_span, - &format!("calling `.type_id()` on `Box`"), + &format!("calling `.type_id()` on `{ty_name}`"), |diag| { let derefs = recv_adjusts .iter() .filter(|adj| matches!(adj.kind, Adjust::Deref(None))) .count(); - let mut sugg = "*".repeat(derefs + 1); - sugg += &snippet(cx, receiver.span, ""); - diag.note( "this returns the type id of the literal type `Box<_>` instead of the \ type id of the boxed value, which is most likely not what you want", ) .note(format!( - "if this is intentional, use `TypeId::of::>()` instead, \ + "if this is intentional, use `TypeId::of::<{ty_name}>()` instead, \ which makes it more clear" - )) - .span_suggestion( - receiver.span, - "consider dereferencing first", - format!("({sugg})"), - Applicability::MaybeIncorrect, - ); + )); + + if is_subtrait_of_any(cx, inner_box_ty) { + let mut sugg = "*".repeat(derefs + 1); + sugg += &snippet(cx, receiver.span, ""); + + diag.span_suggestion( + receiver.span, + "consider dereferencing first", + format!("({sugg})"), + Applicability::MaybeIncorrect, + ); + } }, ); } From f6c006364bbccd6308f6698dae276cd24b842ba9 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:54:16 +0100 Subject: [PATCH 65/79] split up tests into fixable and unfixable now and add annotations --- tests/ui/type_id_on_box.fixed | 42 ++++++++++-------------- tests/ui/type_id_on_box.rs | 42 ++++++++++-------------- tests/ui/type_id_on_box.stderr | 30 ++++++++--------- tests/ui/type_id_on_box_unfixable.rs | 31 +++++++++++++++++ tests/ui/type_id_on_box_unfixable.stderr | 22 +++++++++++++ 5 files changed, 104 insertions(+), 63 deletions(-) create mode 100644 tests/ui/type_id_on_box_unfixable.rs create mode 100644 tests/ui/type_id_on_box_unfixable.stderr diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed index bdc45a93e71..3656043700f 100644 --- a/tests/ui/type_id_on_box.fixed +++ b/tests/ui/type_id_on_box.fixed @@ -22,41 +22,35 @@ fn existential() -> impl Any { trait AnySubTrait: Any {} impl AnySubTrait for T {} -// `Any` is an indirect supertrait -trait AnySubSubTrait: AnySubTrait {} -impl AnySubSubTrait for T {} - -// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`. -trait NormalTrait -where - i32: Any, -{ -} -impl NormalTrait for T {} - fn main() { + // Don't lint, calling `.type_id()` on a `&dyn Any` does the expected thing + let ref_dyn: &dyn Any = &42; + let _ = ref_dyn.type_id(); + let any_box: Box = Box::new(0usize); let _ = (*any_box).type_id(); - let _ = TypeId::of::>(); // Don't lint. We explicitly say "do this instead" if this is intentional + //~^ ERROR: calling `.type_id()` on + + // Don't lint. We explicitly say "do this instead" if this is intentional + let _ = TypeId::of::>(); let _ = (*any_box).type_id(); + + // 2 derefs are needed here to get to the `dyn Any` let any_box: &Box = &(Box::new(0usize) as Box); - let _ = (**any_box).type_id(); // 2 derefs are needed here to get to the `dyn Any` + let _ = (**any_box).type_id(); + //~^ ERROR: calling `.type_id()` on let b = existential(); - let _ = b.type_id(); // Don't lint. + let _ = b.type_id(); // Don't + + let b: Box = Box::new(1); + let _ = (*b).type_id(); + //~^ ERROR: calling `.type_id()` on let b: SomeBox = Box::new(0usize); let _ = (*b).type_id(); + //~^ ERROR: calling `.type_id()` on let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! - - let b: Box = Box::new(1); - let _ = (*b).type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` - - let b: Box = Box::new(1); - let _ = b.type_id(); // Known FN - Any is not an "immediate" supertrait - - let b: Box = Box::new(1); - let _ = b.type_id(); // `NormalTrait` does not have `Any` as its supertrait (even though it mentions it in `i32: Any`) } diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs index e087d9989d8..4bd9e73f2da 100644 --- a/tests/ui/type_id_on_box.rs +++ b/tests/ui/type_id_on_box.rs @@ -22,41 +22,35 @@ fn existential() -> impl Any { trait AnySubTrait: Any {} impl AnySubTrait for T {} -// `Any` is an indirect supertrait -trait AnySubSubTrait: AnySubTrait {} -impl AnySubSubTrait for T {} - -// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`. -trait NormalTrait -where - i32: Any, -{ -} -impl NormalTrait for T {} - fn main() { + // Don't lint, calling `.type_id()` on a `&dyn Any` does the expected thing + let ref_dyn: &dyn Any = &42; + let _ = ref_dyn.type_id(); + let any_box: Box = Box::new(0usize); let _ = any_box.type_id(); - let _ = TypeId::of::>(); // Don't lint. We explicitly say "do this instead" if this is intentional + //~^ ERROR: calling `.type_id()` on + + // Don't lint. We explicitly say "do this instead" if this is intentional + let _ = TypeId::of::>(); let _ = (*any_box).type_id(); + + // 2 derefs are needed here to get to the `dyn Any` let any_box: &Box = &(Box::new(0usize) as Box); - let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any` + let _ = any_box.type_id(); + //~^ ERROR: calling `.type_id()` on let b = existential(); - let _ = b.type_id(); // Don't lint. + let _ = b.type_id(); // Don't + + let b: Box = Box::new(1); + let _ = b.type_id(); + //~^ ERROR: calling `.type_id()` on let b: SomeBox = Box::new(0usize); let _ = b.type_id(); + //~^ ERROR: calling `.type_id()` on let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! - - let b: Box = Box::new(1); - let _ = b.type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` - - let b: Box = Box::new(1); - let _ = b.type_id(); // Known FN - Any is not an "immediate" supertrait - - let b: Box = Box::new(1); - let _ = b.type_id(); // `NormalTrait` does not have `Any` as its supertrait (even though it mentions it in `i32: Any`) } diff --git a/tests/ui/type_id_on_box.stderr b/tests/ui/type_id_on_box.stderr index 8edecc47c74..4528195607d 100644 --- a/tests/ui/type_id_on_box.stderr +++ b/tests/ui/type_id_on_box.stderr @@ -1,5 +1,5 @@ error: calling `.type_id()` on `Box` - --> tests/ui/type_id_on_box.rs:39:13 + --> tests/ui/type_id_on_box.rs:31:13 | LL | let _ = any_box.type_id(); | -------^^^^^^^^^^ @@ -12,9 +12,9 @@ LL | let _ = any_box.type_id(); = help: to override `-D warnings` add `#[allow(clippy::type_id_on_box)]` error: calling `.type_id()` on `Box` - --> tests/ui/type_id_on_box.rs:43:13 + --> tests/ui/type_id_on_box.rs:40:13 | -LL | let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any` +LL | let _ = any_box.type_id(); | -------^^^^^^^^^^ | | | help: consider dereferencing first: `(**any_box)` @@ -22,8 +22,19 @@ LL | let _ = any_box.type_id(); // 2 derefs are needed here to get to the `d = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box.rs:47:13 + | +LL | let _ = b.type_id(); + | -^^^^^^^^^^ + | | + | help: consider dereferencing first: `(*b)` + | + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want + = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + error: calling `.type_id()` on `Box` - --> tests/ui/type_id_on_box.rs:49:13 + --> tests/ui/type_id_on_box.rs:51:13 | LL | let _ = b.type_id(); | -^^^^^^^^^^ @@ -33,16 +44,5 @@ LL | let _ = b.type_id(); = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear -error: calling `.type_id()` on `Box` - --> tests/ui/type_id_on_box.rs:55:13 - | -LL | let _ = b.type_id(); // Lint if calling `type_id` on a `dyn Trait` where `Trait: Any` - | -^^^^^^^^^^ - | | - | help: consider dereferencing first: `(*b)` - | - = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want - = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear - error: aborting due to 4 previous errors diff --git a/tests/ui/type_id_on_box_unfixable.rs b/tests/ui/type_id_on_box_unfixable.rs new file mode 100644 index 00000000000..f6d09834adb --- /dev/null +++ b/tests/ui/type_id_on_box_unfixable.rs @@ -0,0 +1,31 @@ +#![warn(clippy::type_id_on_box)] + +use std::any::{Any, TypeId}; +use std::ops::Deref; + +trait AnySubTrait: Any {} +impl AnySubTrait for T {} + +// `Any` is an indirect supertrait +trait AnySubSubTrait: AnySubTrait {} +impl AnySubSubTrait for T {} + +// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`. +trait NormalTrait +where + i32: Any, +{ +} +impl NormalTrait for T {} + +fn main() { + // (currently we don't look deeper than one level into the supertrait hierachy, but we probably + // could) + let b: Box = Box::new(1); + let _ = b.type_id(); + //~^ ERROR: calling `.type_id()` on + + let b: Box = Box::new(1); + let _ = b.type_id(); + //~^ ERROR: calling `.type_id()` on +} diff --git a/tests/ui/type_id_on_box_unfixable.stderr b/tests/ui/type_id_on_box_unfixable.stderr new file mode 100644 index 00000000000..539ed481ec1 --- /dev/null +++ b/tests/ui/type_id_on_box_unfixable.stderr @@ -0,0 +1,22 @@ +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box_unfixable.rs:25:13 + | +LL | let _ = b.type_id(); + | ^^^^^^^^^^^ + | + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want + = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + = note: `-D clippy::type-id-on-box` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::type_id_on_box)]` + +error: calling `.type_id()` on `Box` + --> tests/ui/type_id_on_box_unfixable.rs:29:13 + | +LL | let _ = b.type_id(); + | ^^^^^^^^^^^ + | + = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want + = note: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + +error: aborting due to 2 previous errors + From 0f63fa8c3332d4c678396ab019a1b24bd6373a5f Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 31 Mar 2024 13:22:04 +0000 Subject: [PATCH 66/79] Move box_default to style, do not suggest turbofishes `Box::default()` had its `#[rustc_box]` attribute removed in 1.69 so is no longer a perf related lint The lint is moved to style but no longer produces suggestions containing turbofishes, as they're often longer/more annoying to type --- clippy_lints/src/box_default.rs | 51 +++------------- tests/ui/box_default.fixed | 85 ++++++++++++++------------ tests/ui/box_default.rs | 75 +++++++++++++---------- tests/ui/box_default.stderr | 104 ++++++++------------------------ 4 files changed, 122 insertions(+), 193 deletions(-) diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index e83f5c2a74c..c7b0006c8cb 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; -use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; use clippy_utils::{is_default_equivalent, path_def_id}; use rustc_errors::Applicability; @@ -9,20 +8,16 @@ use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_middle::ty::IsSuggestable; use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// checks for `Box::new(T::default())`, which is better written as - /// `Box::::default()`. + /// checks for `Box::new(Default::default())`, which can be written as + /// `Box::default()`. /// /// ### Why is this bad? - /// First, it's more complex, involving two calls instead of one. - /// Second, `Box::default()` can be faster - /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box). + /// `Box::default()` is equivalent and more concise. /// /// ### Example /// ```no_run @@ -34,7 +29,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.66.0"] pub BOX_DEFAULT, - perf, + style, "Using Box::new(T::default()) instead of Box::default()" } @@ -53,14 +48,14 @@ impl LateLintPass<'_> for BoxDefault { && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box()) // And the single argument to the call is another function call // This is the `T::default()` of `Box::new(T::default())` - && let ExprKind::Call(arg_path, inner_call_args) = arg.kind + && let ExprKind::Call(arg_path, _) = arg.kind // And we are not in a foreign crate's macro && !in_external_macro(cx.sess(), expr.span) // And the argument expression has the same context as the outer call expression // or that we are inside a `vec!` macro expansion && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr)) - // And the argument is equivalent to `Default::default()` - && is_default_equivalent(cx, arg) + // And the argument is `Default::default()` or the type is specified + && (is_plain_default(cx, arg_path) || (given_type(cx, expr) && is_default_equivalent(cx, arg))) { span_lint_and_sugg( cx, @@ -68,23 +63,7 @@ impl LateLintPass<'_> for BoxDefault { expr.span, "`Box::new(_)` of default value", "try", - if is_plain_default(cx, arg_path) || given_type(cx, expr) { - "Box::default()".into() - } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { - // Check if we can copy from the source expression in the replacement. - // We need the call to have no argument (see `explicit_default_type`). - if inner_call_args.is_empty() - && let Some(ty) = explicit_default_type(arg_path) - && let Some(s) = snippet_opt(cx, ty.span) - { - format!("Box::<{s}>::default()") - } else { - // Otherwise, use the inferred type's formatting. - with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) - } - } else { - return; - }, + "Box::default()".into(), Applicability::MachineApplicable, ); } @@ -103,20 +82,6 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool { } } -// Checks whether the call is of the form `A::B::f()`. Returns `A::B` if it is. -// -// In the event we have this kind of construct, it's easy to use `A::B` as a replacement in the -// quickfix. `f` must however have no parameter. Should `f` have some, then some of the type of -// `A::B` may be inferred from the arguments. This would be the case for `Vec::from([0; false])`, -// where the argument to `from` allows inferring this is a `Vec` -fn explicit_default_type<'a>(arg_path: &'a Expr<'_>) -> Option<&'a Ty<'a>> { - if let ExprKind::Path(QPath::TypeRelative(ty, _)) = &arg_path.kind { - Some(ty) - } else { - None - } -} - fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool { macro_backtrace(expr.span).next().map_or(false, |call| { cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span) diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed index fea7405c685..6c2896b3aa0 100644 --- a/tests/ui/box_default.fixed +++ b/tests/ui/box_default.fixed @@ -1,5 +1,5 @@ #![warn(clippy::box_default)] -#![allow(clippy::default_constructed_unit_structs)] +#![allow(clippy::boxed_local, clippy::default_constructed_unit_structs)] #[derive(Default)] struct ImplementsDefault; @@ -12,26 +12,50 @@ impl OwnDefault { } } -macro_rules! outer { - ($e: expr) => { - $e +macro_rules! default { + () => { + Default::default() + }; +} + +macro_rules! string_new { + () => { + String::new() + }; +} + +macro_rules! box_new { + ($e:expr) => { + Box::new($e) }; } fn main() { - let _string: Box = Box::default(); - let _byte = Box::::default(); - let _vec = Box::>::default(); - let _impl = Box::::default(); - let _impl2 = Box::::default(); - let _impl3: Box = Box::default(); - let _own = Box::new(OwnDefault::default()); // should not lint - let _in_macro = outer!(Box::::default()); - let _string_default = outer!(Box::::default()); - let _vec2: Box> = Box::default(); - let _vec3: Box> = Box::default(); - let _vec4: Box<_> = Box::>::default(); - let _more = ret_ty_fn(); + let string1: Box = Box::default(); + let string2: Box = Box::default(); + let impl1: Box = Box::default(); + let vec: Box> = Box::default(); + let byte: Box = Box::default(); + let vec2: Box> = Box::default(); + let vec3: Box> = Box::default(); + + let plain_default = Box::default(); + let _: Box = plain_default; + + let _: Box = Box::new(default!()); + let _: Box = Box::new(string_new!()); + let _: Box = box_new!(Default::default()); + let _: Box = box_new!(String::new()); + let _: Box = box_new!(default!()); + let _: Box = box_new!(string_new!()); + + let own: Box = Box::new(OwnDefault::default()); // should not lint + + // Do not suggest where a turbofish would be required + let impl2 = Box::new(ImplementsDefault::default()); + let impl3 = Box::new(::default()); + let vec4: Box<_> = Box::new(Vec::from([false; 0])); + let more = ret_ty_fn(); call_ty_fn(Box::default()); issue_10381(); @@ -44,10 +68,9 @@ fn main() { } fn ret_ty_fn() -> Box { - Box::::default() + Box::new(bool::default()) // Could lint, currently doesn't } -#[allow(clippy::boxed_local)] fn call_ty_fn(_b: Box) { issue_9621_dyn_trait(); } @@ -61,7 +84,7 @@ impl Read for ImplementsDefault { } fn issue_9621_dyn_trait() { - let _: Box = Box::::default(); + let _: Box = Box::new(ImplementsDefault::default()); issue_10089(); } @@ -70,7 +93,7 @@ fn issue_10089() { #[derive(Default)] struct WeirdPathed; - let _ = Box::::default(); + let _ = Box::new(WeirdPathed::default()); }; } @@ -82,7 +105,7 @@ fn issue_10381() { fn maybe_get_bar(i: u32) -> Option> { if i % 2 == 0 { - Some(Box::::default()) + Some(Box::new(Foo::default())) } else { None } @@ -91,20 +114,6 @@ fn issue_10381() { assert!(maybe_get_bar(2).is_some()); } -#[allow(unused)] -fn issue_11868() { - fn foo(_: &mut Vec) {} - - macro_rules! bar { - ($baz:expr) => { - Box::leak(Box::new($baz)) - }; - } - - foo(bar!(vec![])); - foo(bar!(vec![1])); -} - // Issue #11927: The quickfix for the `Box::new` suggests replacing with `Box::::default()`, // removing the `outer::` segment. fn issue_11927() { @@ -116,7 +125,7 @@ fn issue_11927() { } fn foo() { - let _b = Box::::default(); - let _b = Box::>::default(); + let _b = Box::new(outer::Inner::default()); + let _b = Box::new(std::collections::HashSet::::new()); } } diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs index eecba7464ec..e19a62a9022 100644 --- a/tests/ui/box_default.rs +++ b/tests/ui/box_default.rs @@ -1,5 +1,5 @@ #![warn(clippy::box_default)] -#![allow(clippy::default_constructed_unit_structs)] +#![allow(clippy::boxed_local, clippy::default_constructed_unit_structs)] #[derive(Default)] struct ImplementsDefault; @@ -12,26 +12,50 @@ impl OwnDefault { } } -macro_rules! outer { - ($e: expr) => { - $e +macro_rules! default { + () => { + Default::default() + }; +} + +macro_rules! string_new { + () => { + String::new() + }; +} + +macro_rules! box_new { + ($e:expr) => { + Box::new($e) }; } fn main() { - let _string: Box = Box::new(Default::default()); - let _byte = Box::new(u8::default()); - let _vec = Box::new(Vec::::new()); - let _impl = Box::new(ImplementsDefault::default()); - let _impl2 = Box::new(::default()); - let _impl3: Box = Box::new(Default::default()); - let _own = Box::new(OwnDefault::default()); // should not lint - let _in_macro = outer!(Box::new(String::new())); - let _string_default = outer!(Box::new(String::from(""))); - let _vec2: Box> = Box::new(vec![]); - let _vec3: Box> = Box::new(Vec::from([])); - let _vec4: Box<_> = Box::new(Vec::from([false; 0])); - let _more = ret_ty_fn(); + let string1: Box = Box::new(Default::default()); + let string2: Box = Box::new(String::new()); + let impl1: Box = Box::new(Default::default()); + let vec: Box> = Box::new(Vec::new()); + let byte: Box = Box::new(u8::default()); + let vec2: Box> = Box::new(vec![]); + let vec3: Box> = Box::new(Vec::from([])); + + let plain_default = Box::new(Default::default()); + let _: Box = plain_default; + + let _: Box = Box::new(default!()); + let _: Box = Box::new(string_new!()); + let _: Box = box_new!(Default::default()); + let _: Box = box_new!(String::new()); + let _: Box = box_new!(default!()); + let _: Box = box_new!(string_new!()); + + let own: Box = Box::new(OwnDefault::default()); // should not lint + + // Do not suggest where a turbofish would be required + let impl2 = Box::new(ImplementsDefault::default()); + let impl3 = Box::new(::default()); + let vec4: Box<_> = Box::new(Vec::from([false; 0])); + let more = ret_ty_fn(); call_ty_fn(Box::new(u8::default())); issue_10381(); @@ -44,10 +68,9 @@ fn main() { } fn ret_ty_fn() -> Box { - Box::new(bool::default()) + Box::new(bool::default()) // Could lint, currently doesn't } -#[allow(clippy::boxed_local)] fn call_ty_fn(_b: Box) { issue_9621_dyn_trait(); } @@ -91,20 +114,6 @@ fn issue_10381() { assert!(maybe_get_bar(2).is_some()); } -#[allow(unused)] -fn issue_11868() { - fn foo(_: &mut Vec) {} - - macro_rules! bar { - ($baz:expr) => { - Box::leak(Box::new($baz)) - }; - } - - foo(bar!(vec![])); - foo(bar!(vec![1])); -} - // Issue #11927: The quickfix for the `Box::new` suggests replacing with `Box::::default()`, // removing the `outer::` segment. fn issue_11927() { diff --git a/tests/ui/box_default.stderr b/tests/ui/box_default.stderr index 8bb5917a627..f172a875dce 100644 --- a/tests/ui/box_default.stderr +++ b/tests/ui/box_default.stderr @@ -1,113 +1,59 @@ error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:22:32 + --> tests/ui/box_default.rs:34:32 | -LL | let _string: Box = Box::new(Default::default()); +LL | let string1: Box = Box::new(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` | = note: `-D clippy::box-default` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::box_default)]` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:23:17 + --> tests/ui/box_default.rs:35:32 | -LL | let _byte = Box::new(u8::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` +LL | let string2: Box = Box::new(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:24:16 + --> tests/ui/box_default.rs:36:41 | -LL | let _vec = Box::new(Vec::::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::>::default()` +LL | let impl1: Box = Box::new(Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:25:17 + --> tests/ui/box_default.rs:37:29 | -LL | let _impl = Box::new(ImplementsDefault::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` +LL | let vec: Box> = Box::new(Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:26:18 + --> tests/ui/box_default.rs:38:25 | -LL | let _impl2 = Box::new(::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` +LL | let byte: Box = Box::new(u8::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:27:42 + --> tests/ui/box_default.rs:39:45 | -LL | let _impl3: Box = Box::new(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` +LL | let vec2: Box> = Box::new(vec![]); + | ^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:29:28 + --> tests/ui/box_default.rs:40:32 | -LL | let _in_macro = outer!(Box::new(String::new())); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` +LL | let vec3: Box> = Box::new(Vec::from([])); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:30:34 + --> tests/ui/box_default.rs:42:25 | -LL | let _string_default = outer!(Box::new(String::from(""))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` +LL | let plain_default = Box::new(Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:31:46 - | -LL | let _vec2: Box> = Box::new(vec![]); - | ^^^^^^^^^^^^^^^^ help: try: `Box::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:32:33 - | -LL | let _vec3: Box> = Box::new(Vec::from([])); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:33:25 - | -LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0])); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::>::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:35:16 + --> tests/ui/box_default.rs:59:16 | LL | call_ty_fn(Box::new(u8::default())); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:47:5 - | -LL | Box::new(bool::default()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:64:28 - | -LL | let _: Box = Box::new(ImplementsDefault::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:73:17 - | -LL | let _ = Box::new(WeirdPathed::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:85:18 - | -LL | Some(Box::new(Foo::default())) - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:119:18 - | -LL | let _b = Box::new(outer::Inner::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` - -error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:120:18 - | -LL | let _b = Box::new(std::collections::HashSet::::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::>::default()` - -error: aborting due to 18 previous errors +error: aborting due to 9 previous errors From 17a61b261061365e9708478ccf95a8103dbc1944 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Mon, 1 Apr 2024 12:03:16 +0200 Subject: [PATCH 67/79] Ignore `rustc-ice-` files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 503ae3c5090..181b71a658b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Generated by ui-test +rustc-ice-* + # Used by CI to be able to push: /.github/deploy_key out From eee4db928fa745fba934e008be01765c22abb4de Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Sun, 31 Mar 2024 17:53:13 +0200 Subject: [PATCH 68/79] Replace elided variable in `let_unit` with `()` when used Situation: `let_unit` lints when an expression binds a unit (`()`) to a variable. In some cases this binding may be passed down to another function. Currently, the lint removes the binding without considering usage. Change: All usages of the elided variable are now replaced with `()`. fixes: #12594 --- clippy_lints/src/unit_types/let_unit_value.rs | 46 ++++++++++++++++++- tests/ui/let_unit.fixed | 18 ++++++++ tests/ui/let_unit.rs | 18 ++++++++ tests/ui/let_unit.stderr | 21 ++++++++- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 9406d160769..d7ab40c4b66 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_context; -use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source}; +use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source, is_local_used}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::intravisit::{walk_body, Visitor}; use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, Local, MatchSource, Node, PatKind, QPath, TyKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::{in_external_macro, is_from_async_await}; @@ -11,7 +12,7 @@ use rustc_middle::ty; use super::LET_UNIT_VALUE; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { // skip `let () = { ... }` if let PatKind::Tuple(fields, ..) = local.pat.kind && fields.is_empty() @@ -75,12 +76,53 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { let snip = snippet_with_context(cx, expr.span, local.span.ctxt(), "()", &mut app).0; diag.span_suggestion(local.span, "omit the `let` binding", format!("{snip};"), app); } + + if let PatKind::Binding(_, binding_hir_id, ident, ..) = local.pat.kind + && let Some(body_id) = cx.enclosing_body.as_ref() + && let body = cx.tcx.hir().body(*body_id) + && is_local_used(cx, body, binding_hir_id) + { + let identifier = ident.as_str(); + let mut visitor = UnitVariableCollector::new(binding_hir_id); + walk_body(&mut visitor, body); + visitor.spans.into_iter().for_each(|span| { + let msg = + format!("variable `{identifier}` of type `()` can be replaced with explicit `()`"); + diag.span_suggestion(span, msg, "()", Applicability::MachineApplicable); + }); + } }, ); } } } +struct UnitVariableCollector { + id: HirId, + spans: Vec, +} + +impl UnitVariableCollector { + fn new(id: HirId) -> Self { + Self { id, spans: vec![] } + } +} + +/** + * Collect all instances where a variable is used based on its `HirId`. + */ +impl<'tcx> Visitor<'tcx> for UnitVariableCollector { + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result { + if let ExprKind::Path(QPath::Resolved(None, path)) = ex.kind + && let Res::Local(id) = path.res + && id == self.id + { + self.spans.push(path.span); + } + rustc_hir::intravisit::walk_expr(self, ex); + } +} + /// Checks sub-expressions which create the value returned by the given expression for whether /// return value inference is needed. This checks through locals to see if they also need inference /// at this point. diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed index 4d41b5e5e50..20940daffa7 100644 --- a/tests/ui/let_unit.fixed +++ b/tests/ui/let_unit.fixed @@ -177,3 +177,21 @@ async fn issue10433() { } pub async fn issue11502(a: ()) {} + +pub fn issue12594() { + fn returns_unit() {} + + fn returns_result(res: T) -> Result { + Ok(res) + } + + fn actual_test() { + // create first a unit value'd value + returns_unit(); + returns_result(()).unwrap(); + returns_result(()).unwrap(); + // make sure we replace only the first variable + let res = 1; + returns_result(res).unwrap(); + } +} diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index daa660be25e..dca66f2e3ed 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -177,3 +177,21 @@ async fn issue10433() { } pub async fn issue11502(a: ()) {} + +pub fn issue12594() { + fn returns_unit() {} + + fn returns_result(res: T) -> Result { + Ok(res) + } + + fn actual_test() { + // create first a unit value'd value + let res = returns_unit(); + returns_result(res).unwrap(); + returns_result(res).unwrap(); + // make sure we replace only the first variable + let res = 1; + returns_result(res).unwrap(); + } +} diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index 0f1f3d78223..aafb77bcd0d 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -51,5 +51,24 @@ LL + Some(_) => (), LL + }; | -error: aborting due to 3 previous errors +error: this let-binding has unit value + --> tests/ui/let_unit.rs:190:9 + | +LL | let res = returns_unit(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: omit the `let` binding + | +LL | returns_unit(); + | +help: variable `res` of type `()` can be replaced with explicit `()` + | +LL | returns_result(()).unwrap(); + | ~~ +help: variable `res` of type `()` can be replaced with explicit `()` + | +LL | returns_result(()).unwrap(); + | ~~ + +error: aborting due to 4 previous errors From bd4d4561386c5b1219d8e8830869d39dea8149ed Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 23 Mar 2024 06:51:42 +0100 Subject: [PATCH 69/79] accept Into<{Sub}DiagMessage> in span_lint functions --- clippy_utils/src/diagnostics.rs | 55 ++++++++++++++++----------------- clippy_utils/src/sugg.rs | 7 +++++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 0352696f93e..dc0a139e3c7 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, MultiSpan}; +use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::Span; @@ -59,9 +59,9 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// 17 | std::mem::forget(seven); /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` -pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: &str) { +pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: impl Into) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, sp, msg.to_string(), |diag| { + cx.span_lint(lint, sp, msg.into(), |diag| { docs_link(diag, lint); }); } @@ -104,17 +104,16 @@ pub fn span_lint_and_help( cx: &T, lint: &'static Lint, span: impl Into, - msg: &str, + msg: impl Into, help_span: Option, - help: &str, + help: impl Into, ) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, msg.to_string(), |diag| { - let help = help.to_string(); + cx.span_lint(lint, span, msg.into(), |diag| { if let Some(help_span) = help_span { - diag.span_help(help_span, help); + diag.span_help(help_span, help.into()); } else { - diag.help(help); + diag.help(help.into()); } docs_link(diag, lint); }); @@ -161,17 +160,16 @@ pub fn span_lint_and_note( cx: &T, lint: &'static Lint, span: impl Into, - msg: &str, + msg: impl Into, note_span: Option, - note: &str, + note: impl Into, ) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, msg.to_string(), |diag| { - let note = note.to_string(); + cx.span_lint(lint, span, msg.into(), |diag| { if let Some(note_span) = note_span { - diag.span_note(note_span, note); + diag.span_note(note_span, note.into()); } else { - diag.note(note); + diag.note(note.into()); } docs_link(diag, lint); }); @@ -195,14 +193,15 @@ pub fn span_lint_and_note( /// If you're unsure which function you should use, you can test if the `#[allow]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. -pub fn span_lint_and_then(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F) +pub fn span_lint_and_then(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F) where C: LintContext, S: Into, + M: Into, F: FnOnce(&mut Diag<'_, ()>), { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, sp, msg.to_string(), |diag| { + cx.span_lint(lint, sp, msg, |diag| { f(diag); docs_link(diag, lint); }); @@ -232,9 +231,9 @@ where /// Instead, use this function and also pass the `HirId` of ``, which will let /// the compiler check lint level attributes at the place of the expression and /// the `#[allow]` will work. -pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { +pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into) { #[expect(clippy::disallowed_methods)] - cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| { docs_link(diag, lint); }); } @@ -268,11 +267,11 @@ pub fn span_lint_hir_and_then( lint: &'static Lint, hir_id: HirId, sp: impl Into, - msg: &str, + msg: impl Into, f: impl FnOnce(&mut Diag<'_, ()>), ) { #[expect(clippy::disallowed_methods)] - cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| { f(diag); docs_link(diag, lint); }); @@ -316,13 +315,13 @@ pub fn span_lint_and_sugg( cx: &T, lint: &'static Lint, sp: Span, - msg: &str, - help: &str, + msg: impl Into, + help: impl Into, sugg: String, applicability: Applicability, ) { - span_lint_and_then(cx, lint, sp, msg, |diag| { - diag.span_suggestion(sp, help.to_string(), sugg, applicability); + span_lint_and_then(cx, lint, sp, msg.into(), |diag| { + diag.span_suggestion(sp, help.into(), sugg, applicability); }); } @@ -332,7 +331,7 @@ pub fn span_lint_and_sugg( /// appear once per /// replacement. In human-readable format though, it only appears once before /// the whole suggestion. -pub fn multispan_sugg(diag: &mut Diag<'_, ()>, help_msg: &str, sugg: I) +pub fn multispan_sugg(diag: &mut Diag<'_, ()>, help_msg: impl Into, sugg: I) where I: IntoIterator, { @@ -346,11 +345,11 @@ where /// Suggestions with multiple spans will be silently ignored. pub fn multispan_sugg_with_applicability( diag: &mut Diag<'_, ()>, - help_msg: &str, + help_msg: impl Into, applicability: Applicability, sugg: I, ) where I: IntoIterator, { - diag.multipart_suggestion(help_msg.to_string(), sugg.into_iter().collect(), applicability); + diag.multipart_suggestion(help_msg.into(), sugg.into_iter().collect(), applicability); } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 18949faf022..8d6057272c4 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -358,6 +358,13 @@ impl<'a> Sugg<'a> { }, } } + + pub fn into_string(self) -> String { + match self { + Sugg::NonParen(p) | Sugg::MaybeParen(p) => p.into_owned(), + Sugg::BinOp(b, l, r) => binop_to_string(b, &l, &r), + } + } } /// Generates a string from the operator and both sides. From 91f514cc8360b369a7fe5f6108aae025b22a38db Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 23 Mar 2024 06:52:11 +0100 Subject: [PATCH 70/79] fix fallout from previous commit --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/asm_syntax.rs | 4 ++-- clippy_lints/src/assertions_on_constants.rs | 6 +++--- .../src/attrs/allow_attributes_without_reason.rs | 2 +- clippy_lints/src/attrs/inline_always.rs | 2 +- clippy_lints/src/attrs/maybe_misused_cfg.rs | 2 +- clippy_lints/src/attrs/unnecessary_clippy_cfg.rs | 2 +- clippy_lints/src/await_holding_invalid.rs | 2 +- clippy_lints/src/blocks_in_conditions.rs | 4 ++-- clippy_lints/src/bool_assert_comparison.rs | 2 +- clippy_lints/src/cargo/common_metadata.rs | 2 +- clippy_lints/src/cargo/feature_name.rs | 4 ++-- clippy_lints/src/cargo/lint_groups_priority.rs | 2 +- clippy_lints/src/cargo/mod.rs | 4 ++-- .../src/cargo/multiple_crate_versions.rs | 2 +- clippy_lints/src/cargo/wildcard_dependencies.rs | 2 +- clippy_lints/src/casts/as_ptr_cast_mut.rs | 2 +- clippy_lints/src/casts/cast_abs_to_unsigned.rs | 2 +- clippy_lints/src/casts/cast_lossless.rs | 2 +- clippy_lints/src/casts/cast_nan_to_int.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 4 ++-- clippy_lints/src/casts/cast_possible_wrap.rs | 2 +- clippy_lints/src/casts/cast_precision_loss.rs | 2 +- clippy_lints/src/casts/cast_ptr_alignment.rs | 2 +- clippy_lints/src/casts/cast_sign_loss.rs | 2 +- .../src/casts/cast_slice_different_sizes.rs | 2 +- .../src/casts/cast_slice_from_raw_parts.rs | 2 +- clippy_lints/src/casts/fn_to_numeric_cast.rs | 2 +- clippy_lints/src/casts/fn_to_numeric_cast_any.rs | 2 +- .../casts/fn_to_numeric_cast_with_truncation.rs | 2 +- clippy_lints/src/casts/ptr_cast_constness.rs | 2 +- clippy_lints/src/casts/unnecessary_cast.rs | 6 +++--- clippy_lints/src/cognitive_complexity.rs | 2 +- clippy_lints/src/default.rs | 4 ++-- .../src/default_instead_of_iter_empty.rs | 2 +- clippy_lints/src/default_union_representation.rs | 2 +- clippy_lints/src/disallowed_macros.rs | 4 ++-- clippy_lints/src/disallowed_methods.rs | 2 +- clippy_lints/src/disallowed_names.rs | 2 +- clippy_lints/src/disallowed_script_idents.rs | 2 +- clippy_lints/src/disallowed_types.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 4 ++-- clippy_lints/src/duplicate_mod.rs | 2 +- clippy_lints/src/endian_bytes.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/excessive_bools.rs | 4 ++-- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/extra_unused_type_parameters.rs | 8 ++++---- clippy_lints/src/format_args.rs | 6 +++--- clippy_lints/src/format_impl.rs | 4 ++-- clippy_lints/src/formatting.rs | 16 ++++++++-------- clippy_lints/src/from_raw_with_void_ptr.rs | 2 +- clippy_lints/src/functions/must_use.rs | 2 +- clippy_lints/src/functions/too_many_arguments.rs | 2 +- clippy_lints/src/functions/too_many_lines.rs | 2 +- clippy_lints/src/if_then_some_else_none.rs | 4 ++-- clippy_lints/src/implicit_hasher.rs | 4 ++-- clippy_lints/src/implied_bounds_in_impls.rs | 2 +- clippy_lints/src/incompatible_msrv.rs | 2 +- clippy_lints/src/inherent_to_string.rs | 8 ++++---- clippy_lints/src/inline_fn_without_body.rs | 2 +- .../src/integer_division_remainder_used.rs | 2 +- clippy_lints/src/invalid_upcast_comparisons.rs | 2 +- clippy_lints/src/item_name_repetitions.rs | 8 ++++---- clippy_lints/src/iter_not_returning_iterator.rs | 2 +- clippy_lints/src/iter_without_into_iter.rs | 4 ++-- clippy_lints/src/large_futures.rs | 2 +- clippy_lints/src/large_include_file.rs | 2 +- clippy_lints/src/large_stack_arrays.rs | 4 ++-- clippy_lints/src/large_stack_frames.rs | 2 +- clippy_lints/src/len_zero.rs | 10 +++++----- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/lines_filter_map_ok.rs | 2 +- clippy_lints/src/loops/explicit_counter_loop.rs | 4 ++-- clippy_lints/src/loops/for_kv_map.rs | 2 +- clippy_lints/src/loops/manual_flatten.rs | 2 +- clippy_lints/src/loops/needless_range_loop.rs | 4 ++-- clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/loops/single_element_loop.rs | 2 +- clippy_lints/src/main_recursion.rs | 2 +- clippy_lints/src/manual_strip.rs | 4 ++-- clippy_lints/src/map_unit_fn.rs | 4 ++-- clippy_lints/src/match_result_ok.rs | 2 +- clippy_lints/src/matches/collapsible_match.rs | 2 +- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- clippy_lints/src/matches/match_as_ref.rs | 2 +- clippy_lints/src/matches/match_like_matches.rs | 2 +- .../src/matches/match_str_case_mismatch.rs | 2 +- clippy_lints/src/matches/match_wild_err_arm.rs | 2 +- .../src/matches/redundant_pattern_match.rs | 8 ++++---- clippy_lints/src/mem_replace.rs | 2 +- clippy_lints/src/methods/bind_instead_of_map.rs | 6 +++--- clippy_lints/src/methods/bytes_nth.rs | 4 ++-- clippy_lints/src/methods/chars_cmp.rs | 2 +- .../src/methods/chars_cmp_with_unwrap.rs | 2 +- clippy_lints/src/methods/clear_with_drain.rs | 2 +- clippy_lints/src/methods/clone_on_copy.rs | 2 +- clippy_lints/src/methods/drain_collect.rs | 2 +- clippy_lints/src/methods/expect_fun_call.rs | 4 ++-- clippy_lints/src/methods/filetype_is_file.rs | 2 +- clippy_lints/src/methods/filter_map.rs | 2 +- clippy_lints/src/methods/get_first.rs | 4 ++-- clippy_lints/src/methods/get_last_with_len.rs | 2 +- clippy_lints/src/methods/get_unwrap.rs | 2 +- clippy_lints/src/methods/implicit_clone.rs | 2 +- .../src/methods/inefficient_to_string.rs | 2 +- clippy_lints/src/methods/into_iter_on_ref.rs | 2 +- clippy_lints/src/methods/is_digit_ascii_radix.rs | 2 +- clippy_lints/src/methods/is_empty.rs | 2 +- clippy_lints/src/methods/iter_cloned_collect.rs | 2 +- clippy_lints/src/methods/iter_count.rs | 2 +- clippy_lints/src/methods/iter_kv_map.rs | 4 ++-- clippy_lints/src/methods/iter_nth.rs | 2 +- .../iter_on_single_or_empty_collections.rs | 4 ++-- clippy_lints/src/methods/iter_with_drain.rs | 2 +- .../src/methods/manual_saturating_arithmetic.rs | 2 +- clippy_lints/src/methods/map_clone.rs | 4 ++-- clippy_lints/src/methods/map_flatten.rs | 4 ++-- clippy_lints/src/methods/map_identity.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/methods/open_options.rs | 2 +- clippy_lints/src/methods/option_as_ref_cloned.rs | 2 +- clippy_lints/src/methods/option_as_ref_deref.rs | 4 ++-- clippy_lints/src/methods/option_map_unwrap_or.rs | 2 +- clippy_lints/src/methods/or_fun_call.rs | 4 ++-- clippy_lints/src/methods/range_zip_with_len.rs | 2 +- clippy_lints/src/methods/search_is_some.rs | 10 +++++----- .../src/methods/stable_sort_primitive.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 4 ++-- clippy_lints/src/methods/suspicious_splitn.rs | 2 +- clippy_lints/src/methods/suspicious_to_owned.rs | 2 +- clippy_lints/src/methods/type_id_on_box.rs | 2 +- .../src/methods/unnecessary_filter_map.rs | 2 +- .../src/methods/unnecessary_get_then_check.rs | 4 ++-- .../src/methods/unnecessary_iter_cloned.rs | 2 +- .../src/methods/unnecessary_literal_unwrap.rs | 2 +- clippy_lints/src/methods/unnecessary_to_owned.rs | 16 ++++++++-------- clippy_lints/src/methods/unwrap_expect_used.rs | 2 +- clippy_lints/src/methods/useless_asref.rs | 4 ++-- clippy_lints/src/methods/verbose_file_reads.rs | 2 +- .../src/methods/wrong_self_convention.rs | 2 +- clippy_lints/src/min_ident_chars.rs | 2 +- clippy_lints/src/misc.rs | 2 +- .../src/misc_early/builtin_type_shadow.rs | 2 +- clippy_lints/src/misc_early/literal_suffix.rs | 4 ++-- clippy_lints/src/misc_early/mod.rs | 2 +- clippy_lints/src/misc_early/redundant_pattern.rs | 2 +- .../src/misc_early/unneeded_field_pattern.rs | 4 ++-- clippy_lints/src/mismatching_type_param_order.rs | 2 +- clippy_lints/src/missing_asserts_for_indexing.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/missing_trait_methods.rs | 2 +- .../src/mixed_read_write_in_expression.rs | 2 +- clippy_lints/src/module_style.rs | 8 ++++---- .../src/multiple_unsafe_ops_per_block.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/mutable_debug_assertion.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 6 +++--- clippy_lints/src/needless_bool.rs | 16 ++++++++-------- clippy_lints/src/needless_borrowed_ref.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_question_mark.rs | 2 +- clippy_lints/src/new_without_default.rs | 4 +--- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/non_send_fields_in_send_ty.rs | 2 +- clippy_lints/src/nonstandard_macro_braces.rs | 2 +- clippy_lints/src/octal_escapes.rs | 2 +- .../src/operators/absurd_extreme_comparisons.rs | 2 +- clippy_lints/src/operators/bit_mask.rs | 16 ++++++++-------- clippy_lints/src/operators/const_comparisons.rs | 6 +++--- clippy_lints/src/operators/duration_subsec.rs | 2 +- clippy_lints/src/operators/eq_op.rs | 4 ++-- clippy_lints/src/operators/modulo_arithmetic.rs | 2 +- clippy_lints/src/operators/ptr_eq.rs | 2 +- clippy_lints/src/operators/self_assignment.rs | 2 +- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/pass_by_ref_or_value.rs | 4 ++-- clippy_lints/src/pattern_type_mismatch.rs | 2 +- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/ptr_offset_with_cast.rs | 4 ++-- clippy_lints/src/ranges.rs | 4 ++-- clippy_lints/src/redundant_locals.rs | 4 ++-- clippy_lints/src/redundant_pub_crate.rs | 2 +- clippy_lints/src/redundant_static_lifetimes.rs | 2 +- clippy_lints/src/regex.rs | 6 +++--- clippy_lints/src/repeat_vec_with_capacity.rs | 2 +- clippy_lints/src/self_named_constructors.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- clippy_lints/src/single_range_in_vec_init.rs | 2 +- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 4 ++-- clippy_lints/src/strings.rs | 4 ++-- clippy_lints/src/suspicious_trait_impl.rs | 2 +- clippy_lints/src/swap.rs | 6 +++--- clippy_lints/src/trailing_empty_array.rs | 2 +- clippy_lints/src/trait_bounds.rs | 8 ++++++-- .../src/transmute/crosspointer_transmute.rs | 4 ++-- .../src/transmute/transmute_float_to_int.rs | 2 +- .../src/transmute/transmute_int_to_bool.rs | 2 +- .../src/transmute/transmute_int_to_char.rs | 2 +- .../src/transmute/transmute_int_to_float.rs | 2 +- .../src/transmute/transmute_int_to_non_zero.rs | 2 +- .../src/transmute/transmute_num_to_bytes.rs | 2 +- .../src/transmute/transmute_ptr_to_ref.rs | 2 +- .../src/transmute/transmute_ref_to_ref.rs | 2 +- .../src/transmute/transmute_undefined_repr.rs | 10 +++++----- .../transmutes_expressible_as_ptr_casts.rs | 2 +- .../transmute/unsound_collection_transmute.rs | 2 +- clippy_lints/src/transmute/useless_transmute.rs | 2 +- clippy_lints/src/transmute/wrong_transmute.rs | 2 +- clippy_lints/src/types/box_collection.rs | 4 ++-- clippy_lints/src/types/redundant_allocation.rs | 6 +++--- clippy_lints/src/undocumented_unsafe_blocks.rs | 4 ++-- clippy_lints/src/unit_return_expecting_ord.rs | 4 ++-- clippy_lints/src/unit_types/unit_arg.rs | 2 +- clippy_lints/src/unit_types/unit_cmp.rs | 4 ++-- clippy_lints/src/unnecessary_box_returns.rs | 2 +- .../src/unnecessary_map_on_constructor.rs | 2 +- clippy_lints/src/unnecessary_wraps.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unused_rounding.rs | 4 ++-- clippy_lints/src/unwrap.rs | 4 ++-- clippy_lints/src/upper_case_acronyms.rs | 2 +- clippy_lints/src/useless_conversion.rs | 14 +++++++------- .../almost_standard_lint_formulation.rs | 2 +- .../internal_lints/compiler_lint_functions.rs | 2 +- .../internal_lints/lint_without_lint_pass.rs | 6 +++--- .../utils/internal_lints/metadata_collector.rs | 2 +- .../src/utils/internal_lints/msrv_attr_impl.rs | 4 ++-- .../utils/internal_lints/unnecessary_def_path.rs | 4 ++-- clippy_lints/src/visibility.rs | 2 +- clippy_lints/src/write.rs | 8 ++++---- clippy_lints/src/zero_div_zero.rs | 2 +- 234 files changed, 373 insertions(+), 371 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 25606f4253e..ec28fd46111 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -95,7 +95,7 @@ impl ApproxConstant { cx, APPROX_CONSTANT, e.span, - &format!("approximate value of `{module}::consts::{}` found", &name), + format!("approximate value of `{module}::consts::{}` found", &name), None, "consider using the constant directly", ); diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs index c2fa56e1360..7c88bfc97ca 100644 --- a/clippy_lints/src/asm_syntax.rs +++ b/clippy_lints/src/asm_syntax.rs @@ -53,9 +53,9 @@ fn check_asm_syntax( cx, lint, span, - &format!("{style} x86 assembly syntax used"), + format!("{style} x86 assembly syntax used"), None, - &format!("use {} x86 assembly syntax", !style), + format!("use {} x86 assembly syntax", !style), ); } } diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 9365fbfaed0..2003dd1fb0e 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { cx, ASSERTIONS_ON_CONSTANTS, macro_call.span, - &format!( + format!( "`{}!(true)` will be optimized out by the compiler", cx.tcx.item_name(macro_call.def_id) ), @@ -74,9 +74,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { cx, ASSERTIONS_ON_CONSTANTS, macro_call.span, - &format!("`assert!(false{assert_arg})` should probably be replaced"), + format!("`assert!(false{assert_arg})` should probably be replaced"), None, - &format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"), + format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"), ); } } diff --git a/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/clippy_lints/src/attrs/allow_attributes_without_reason.rs index df00f23e37e..4a22e17463f 100644 --- a/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -30,7 +30,7 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet cx, ALLOW_ATTRIBUTES_WITHOUT_REASON, attr.span, - &format!("`{}` attribute without specifying a reason", name.as_str()), + format!("`{}` attribute without specifying a reason", name.as_str()), None, "try adding a reason at the end with `, reason = \"..\"`", ); diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs index cfcd2cc6a00..3b5b80ffefa 100644 --- a/clippy_lints/src/attrs/inline_always.rs +++ b/clippy_lints/src/attrs/inline_always.rs @@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att cx, INLINE_ALWAYS, attr.span, - &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"), + format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"), ); } } diff --git a/clippy_lints/src/attrs/maybe_misused_cfg.rs b/clippy_lints/src/attrs/maybe_misused_cfg.rs index 5a70866eda5..e6b2e835be8 100644 --- a/clippy_lints/src/attrs/maybe_misused_cfg.rs +++ b/clippy_lints/src/attrs/maybe_misused_cfg.rs @@ -40,7 +40,7 @@ fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { cx, MAYBE_MISUSED_CFG, meta.span, - &format!("'test' may be misspelled as '{}'", ident.name.as_str()), + format!("'test' may be misspelled as '{}'", ident.name.as_str()), "did you mean", "test".to_string(), Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs index 05da69636c6..486e7c6ec4f 100644 --- a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs +++ b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -58,7 +58,7 @@ pub(super) fn check( clippy_lints, "no need to put clippy lints behind a `clippy` cfg", None, - &format!( + format!( "write instead: `#{}[{}({})]`", if attr.style == AttrStyle::Inner { "!" } else { "" }, ident.name, diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 765cc7c0a54..f25a474d9bb 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -267,7 +267,7 @@ fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPa cx, AWAIT_HOLDING_INVALID_TYPE, span, - &format!( + format!( "`{}` may not be held across an `await` point per `clippy.toml`", disallowed.path() ), diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs index 2eb0dac9742..171f3031860 100644 --- a/clippy_lints/src/blocks_in_conditions.rs +++ b/clippy_lints/src/blocks_in_conditions.rs @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { else { return; }; - let complex_block_message = &format!( + let complex_block_message = format!( "in {desc}, avoid complex blocks or closures with blocks; \ instead, move the block or closure higher and bind it with a `let`", ); @@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { let ex = &body.value; if let ExprKind::Block(block, _) = ex.kind { if !body.value.span.from_expansion() && !block.stmts.is_empty() { - span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message); + span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message.clone()); return ControlFlow::Continue(Descend::No); } } diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs index 74201e9cc30..58c1a2f2706 100644 --- a/clippy_lints/src/bool_assert_comparison.rs +++ b/clippy_lints/src/bool_assert_comparison.rs @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison { cx, BOOL_ASSERT_COMPARISON, macro_call.span, - &format!("used `{macro_name}!` with a literal bool"), + format!("used `{macro_name}!` with a literal bool"), |diag| { // assert_eq!(...) // ^^^^^^^^^ diff --git a/clippy_lints/src/cargo/common_metadata.rs b/clippy_lints/src/cargo/common_metadata.rs index 99fe6c1e790..3af2d8c0256 100644 --- a/clippy_lints/src/cargo/common_metadata.rs +++ b/clippy_lints/src/cargo/common_metadata.rs @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) { let message = format!("package `{}` is missing `{field}` metadata", package.name); - span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message); + span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, message); } fn is_empty_str>(value: &Option) -> bool { diff --git a/clippy_lints/src/cargo/feature_name.rs b/clippy_lints/src/cargo/feature_name.rs index 9e69919c727..6982b96dd3b 100644 --- a/clippy_lints/src/cargo/feature_name.rs +++ b/clippy_lints/src/cargo/feature_name.rs @@ -56,13 +56,13 @@ fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) { REDUNDANT_FEATURE_NAMES }, DUMMY_SP, - &format!( + format!( "the \"{substring}\" {} in the feature name \"{feature}\" is {}", if is_prefix { "prefix" } else { "suffix" }, if is_negative { "negative" } else { "redundant" } ), None, - &format!( + format!( "consider renaming the feature to \"{}\"{}", if is_prefix { feature.strip_prefix(substring) diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs index a39b972b56a..a3291c9da10 100644 --- a/clippy_lints/src/cargo/lint_groups_priority.rs +++ b/clippy_lints/src/cargo/lint_groups_priority.rs @@ -102,7 +102,7 @@ fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>, cx, LINT_GROUPS_PRIORITY, toml_span(group.span(), file), - &format!( + format!( "lint group `{}` has the same priority ({priority}) as a lint", group.as_ref() ), diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs index 95d5449781b..ca7fa4e5a41 100644 --- a/clippy_lints/src/cargo/mod.rs +++ b/clippy_lints/src/cargo/mod.rs @@ -241,7 +241,7 @@ impl LateLintPass<'_> for Cargo { }, Err(e) => { for lint in NO_DEPS_LINTS { - span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}")); + span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}")); } }, } @@ -257,7 +257,7 @@ impl LateLintPass<'_> for Cargo { }, Err(e) => { for lint in WITH_DEPS_LINTS { - span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}")); + span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}")); } }, } diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index 3f30a77fcfe..2769463c8a5 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -52,7 +52,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, - &format!("multiple versions for dependency `{name}`: {versions}"), + format!("multiple versions for dependency `{name}`: {versions}"), ); } } diff --git a/clippy_lints/src/cargo/wildcard_dependencies.rs b/clippy_lints/src/cargo/wildcard_dependencies.rs index 244e98eb666..0cf687d0192 100644 --- a/clippy_lints/src/cargo/wildcard_dependencies.rs +++ b/clippy_lints/src/cargo/wildcard_dependencies.rs @@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { cx, WILDCARD_DEPENDENCIES, DUMMY_SP, - &format!("wildcard dependency for `{}`", dep.name), + format!("wildcard dependency for `{}`", dep.name), ); } } diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs index 8bfb7383f14..2209ae3cad9 100644 --- a/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -33,7 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, AS_PTR_CAST_MUT, expr.span, - &format!("casting the result of `as_ptr` to *mut {ptrty}"), + format!("casting the result of `as_ptr` to *mut {ptrty}"), "replace with", format!("{recv}.as_mut_ptr()"), applicability, diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index c1663348321..d4d5ee37bcc 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -34,7 +34,7 @@ pub(super) fn check( cx, CAST_ABS_TO_UNSIGNED, span, - &format!("casting the result of `{cast_from}::abs()` to {cast_to}"), + format!("casting the result of `{cast_from}::abs()` to {cast_to}"), "replace with", format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()), Applicability::MachineApplicable, diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index 86f4332d05a..d52ad1c6f23 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -68,7 +68,7 @@ pub(super) fn check( cx, CAST_LOSSLESS, expr.span, - &message, + message, "try", format!("{cast_to_fmt}::from({sugg})"), app, diff --git a/clippy_lints/src/casts/cast_nan_to_int.rs b/clippy_lints/src/casts/cast_nan_to_int.rs index da756129db3..1743ce71add 100644 --- a/clippy_lints/src/casts/cast_nan_to_int.rs +++ b/clippy_lints/src/casts/cast_nan_to_int.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, CAST_NAN_TO_INT, expr.span, - &format!("casting a known NaN to {to_ty}"), + format!("casting a known NaN to {to_ty}"), None, "this always evaluates to 0", ); diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 32e45bd0a79..dbfa8e1ee91 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -142,7 +142,7 @@ pub(super) fn check( cx, CAST_ENUM_TRUNCATION, expr.span, - &format!( + format!( "casting `{cast_from}::{}` to `{cast_to}` will truncate the value{suffix}", variant.name, ), @@ -163,7 +163,7 @@ pub(super) fn check( _ => return, }; - span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| { + span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, msg, |diag| { diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ..."); if !cast_from.is_floating_point() { offer_suggestion(cx, expr, cast_expr, cast_to_span, diag); diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs index 2ddb0f00ecd..11274383595 100644 --- a/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/clippy_lints/src/casts/cast_possible_wrap.rs @@ -79,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca ), }; - span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, &message, |diag| { + span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, message, |diag| { if let EmitState::LintOnPtrSize(16) = should_lint { diag .note("`usize` and `isize` may be as small as 16 bits on some platforms") diff --git a/clippy_lints/src/casts/cast_precision_loss.rs b/clippy_lints/src/casts/cast_precision_loss.rs index 334e1646cd4..035666e4d4c 100644 --- a/clippy_lints/src/casts/cast_precision_loss.rs +++ b/clippy_lints/src/casts/cast_precision_loss.rs @@ -38,7 +38,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca cx, CAST_PRECISION_LOSS, expr.span, - &format!( + format!( "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \ but `{1}`'s mantissa is only {4} bits wide)", cast_from, diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs index f12f03fbe79..83fe324fc7e 100644 --- a/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -48,7 +48,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f cx, CAST_PTR_ALIGNMENT, expr.span, - &format!( + format!( "casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)", from_layout.align.abi.bytes(), to_layout.align.abi.bytes(), diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 90786175562..2b6e17dc103 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -47,7 +47,7 @@ pub(super) fn check<'cx>( cx, CAST_SIGN_LOSS, expr.span, - &format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"), + format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"), ); } } diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index a31943f0021..79dbc99bbf3 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv cx, CAST_SLICE_DIFFERENT_SIZES, expr.span, - &format!( + format!( "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count", start_ty.ty, end_ty.ty, ), 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 3db1e3e6d97..c70adc544d4 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -46,7 +46,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, CAST_SLICE_FROM_RAW_PARTS, span, - &format!("casting the result of `{func}` to {cast_to}"), + format!("casting the result of `{func}` to {cast_to}"), "replace with", format!("core::ptr::slice_{func}({ptr}, {len})"), applicability, diff --git a/clippy_lints/src/casts/fn_to_numeric_cast.rs b/clippy_lints/src/casts/fn_to_numeric_cast.rs index a26bfab4e7c..f263bec1576 100644 --- a/clippy_lints/src/casts/fn_to_numeric_cast.rs +++ b/clippy_lints/src/casts/fn_to_numeric_cast.rs @@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, FN_TO_NUMERIC_CAST, expr.span, - &format!("casting function pointer `{from_snippet}` to `{cast_to}`"), + format!("casting function pointer `{from_snippet}` to `{cast_to}`"), "try", format!("{from_snippet} as usize"), applicability, diff --git a/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/clippy_lints/src/casts/fn_to_numeric_cast_any.rs index 75654129408..826589bf303 100644 --- a/clippy_lints/src/casts/fn_to_numeric_cast_any.rs +++ b/clippy_lints/src/casts/fn_to_numeric_cast_any.rs @@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, FN_TO_NUMERIC_CAST_ANY, expr.span, - &format!("casting function pointer `{from_snippet}` to `{cast_to}`"), + format!("casting function pointer `{from_snippet}` to `{cast_to}`"), "did you mean to invoke the function?", format!("{from_snippet}() as {cast_to}"), applicability, diff --git a/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs index 556be1d1506..0e11bcfb8ec 100644 --- a/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs +++ b/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, FN_TO_NUMERIC_CAST_WITH_TRUNCATION, expr.span, - &format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"), + format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"), "try", format!("{from_snippet} as usize"), applicability, diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index ff069860a11..c807788b7bc 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>( PTR_CAST_CONSTNESS, expr.span, "`as` casting between raw pointers while changing only its constness", - &format!("try `pointer::cast_{constness}`, a safer alternative"), + format!("try `pointer::cast_{constness}`, a safer alternative"), format!("{}.cast_{constness}()", sugg.maybe_par()), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 08341ff32f3..d63f5ac6655 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -51,7 +51,7 @@ pub(super) fn check<'tcx>( cx, UNNECESSARY_CAST, expr.span, - &format!( + format!( "casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)" ), "try", @@ -166,7 +166,7 @@ pub(super) fn check<'tcx>( cx, UNNECESSARY_CAST, expr.span, - &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"), + format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"), "try", if needs_block { format!("{{ {cast_str} }}") @@ -209,7 +209,7 @@ fn lint_unnecessary_cast( cx, UNNECESSARY_CAST, expr.span, - &format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"), + format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"), "try", sugg, Applicability::MachineApplicable, diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 60f436dc5d2..4ac2da19145 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -121,7 +121,7 @@ impl CognitiveComplexity { cx, COGNITIVE_COMPLEXITY, fn_span, - &format!( + format!( "the function has a cognitive complexity of ({cc}/{})", self.limit.limit() ), diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index 98a6d9370c3..2b3f4854255 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { cx, DEFAULT_TRAIT_ACCESS, expr.span, - &format!("calling `{replacement}` is more clear than this expression"), + format!("calling `{replacement}` is more clear than this expression"), "try", replacement, Applicability::Unspecified, // First resolve the TODO above @@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { first_assign.unwrap().span, "field assignment outside of initializer for an instance created with Default::default()", Some(local.span), - &format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"), + format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"), ); self.reassigned_linted.insert(span); } diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index 61f68fdb66c..ac49e6f1a48 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { cx, DEFAULT_INSTEAD_OF_ITER_EMPTY, expr.span, - &format!("`{path}()` is the more idiomatic way"), + format!("`{path}()` is the more idiomatic way"), "try", sugg, applicability, diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index bfd89bfd2c7..3f87ed8df2b 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { item.span, "this union has the default representation", None, - &format!( + format!( "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout", cx.tcx.def_path_str(item.owner_id) ), diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 4a617ba34d5..871f529da6c 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -102,11 +102,11 @@ impl DisallowedMacros { DISALLOWED_MACROS, cx.tcx.local_def_id_to_hir_id(derive_src.def_id), mac.span, - &msg, + msg, add_note, ); } else { - span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, &msg, add_note); + span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, msg, add_note); } } } diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index 1868d3cd391..9de879604e2 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { None => return, }; let msg = format!("use of a disallowed method `{}`", conf.path()); - span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| { + span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, msg, |diag| { if let Some(reason) = conf.reason() { diag.note(reason); } diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs index 09dad5554ad..2afbf184117 100644 --- a/clippy_lints/src/disallowed_names.rs +++ b/clippy_lints/src/disallowed_names.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedNames { cx, DISALLOWED_NAMES, ident.span, - &format!("use of a disallowed/placeholder name `{}`", ident.name), + format!("use of a disallowed/placeholder name `{}`", ident.name), ); } } diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index 0c1bb2da7e8..def4b5932b4 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -98,7 +98,7 @@ impl EarlyLintPass for DisallowedScriptIdents { cx, DISALLOWED_SCRIPT_IDENTS, span, - &format!( + format!( "identifier `{symbol_str}` has a Unicode script that is not allowed by configuration: {}", script.full_name() ), diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs index 130f56b698f..4196309a22a 100644 --- a/clippy_lints/src/disallowed_types.rs +++ b/clippy_lints/src/disallowed_types.rs @@ -127,7 +127,7 @@ fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) { cx, DISALLOWED_TYPES, span, - &format!("`{name}` is not allowed according to config"), + format!("`{name}` is not allowed according to config"), |diag| { if let Some(reason) = conf.reason() { diag.note(reason); diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index bf6f54c1e72..119473c2454 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -129,9 +129,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { cx, lint, expr.span, - &msg, + msg, note_span, - &format!("argument has type `{arg_ty}`"), + format!("argument has type `{arg_ty}`"), ); } } diff --git a/clippy_lints/src/duplicate_mod.rs b/clippy_lints/src/duplicate_mod.rs index 471335c098f..ed27e38ef2d 100644 --- a/clippy_lints/src/duplicate_mod.rs +++ b/clippy_lints/src/duplicate_mod.rs @@ -119,7 +119,7 @@ impl EarlyLintPass for DuplicateMod { cx, DUPLICATE_MOD, multi_span, - &format!("file is loaded as a module multiple times: `{}`", local_path.display()), + format!("file is loaded as a module multiple times: `{}`", local_path.display()), None, "replace all but one `mod` item with `use` items", ); diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index b8a817e21b1..dd03df797de 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -197,7 +197,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix cx, lint.as_lint(), expr.span, - &format!( + format!( "usage of the {}`{ty}::{}`{}", if prefix == Prefix::From { "function " } else { "" }, lint.as_name(prefix), diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index dafbf6c8846..b7c9d3d0385 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { cx, MAP_ENTRY, expr.span, - &format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), + format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), "try", sugg, app, diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index c5f7212c4c0..62d5ce24d40 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -120,7 +120,7 @@ impl ExcessiveBools { cx, FN_PARAMS_EXCESSIVE_BOOLS, span, - &format!("more than {} bools in function parameters", self.max_fn_params_bools), + format!("more than {} bools in function parameters", self.max_fn_params_bools), None, "consider refactoring bools into two-variant enums", ); @@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { cx, STRUCT_EXCESSIVE_BOOLS, item.span, - &format!("more than {} bools in a struct", self.max_struct_bools), + format!("more than {} bools in a struct", self.max_struct_bools), None, "consider using a state machine or refactoring bools into two-variant enums", ); diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 2e9bec6a7b0..33bd5a5a9d3 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { cx, EXPLICIT_WRITE, expr.span, - &format!("use of `{used}.unwrap()`"), + format!("use of `{used}.unwrap()`"), "try", format!("{prefix}{sugg_mac}!({inputs_snippet})"), applicability, diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index 538d29eb43d..7484f772e08 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -110,11 +110,11 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> { .map_or(param.span, |bound_span| param.span.with_hi(bound_span.hi())) } - fn emit_help(&self, spans: Vec, msg: &str, help: &'static str) { + fn emit_help(&self, spans: Vec, msg: String, help: &'static str) { span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, None, help); } - fn emit_sugg(&self, spans: Vec, msg: &str, help: &'static str) { + fn emit_sugg(&self, spans: Vec, msg: String, help: &'static str) { let suggestions: Vec<(Span, String)> = spans.iter().copied().zip(std::iter::repeat(String::new())).collect(); span_lint_and_then(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, |diag| { diag.multipart_suggestion(help, suggestions, Applicability::MachineApplicable); @@ -167,7 +167,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> { .iter() .map(|(_, param)| self.get_bound_span(param)) .collect::>(); - self.emit_help(spans, &msg, help); + self.emit_help(spans, msg, help); } else { let spans = if explicit_params.len() == extra_params.len() { vec![self.generics.span] // Remove the entire list of generics @@ -196,7 +196,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> { }) .collect() }; - self.emit_sugg(spans, &msg, help); + self.emit_sugg(spans, msg, help); }; } } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 61f550ce0be..80db617c639 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { self.cx, FORMAT_IN_FORMAT_ARGS, self.macro_call.span, - &format!("`format!` in `{name}!` args"), + format!("`format!` in `{name}!` args"), |diag| { diag.help(format!( "combine the `format!(..)` arguments with the outer `{name}!(..)` call" @@ -431,7 +431,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { cx, TO_STRING_IN_FORMAT_ARGS, to_string_span.with_lo(receiver.span.hi()), - &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), "remove this", String::new(), Applicability::MachineApplicable, @@ -441,7 +441,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { cx, TO_STRING_IN_FORMAT_ARGS, value.span, - &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), "use this", format!( "{}{:*>n_needed_derefs$}{receiver_snippet}", diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index 93517076cda..0a52347940a 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { self.cx, RECURSIVE_FORMAT_IMPL, self.expr.span, - &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"), + format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"), ); } } @@ -235,7 +235,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { self.cx, PRINT_IN_FORMAT_IMPL, macro_call.span, - &format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name), + format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name), "replace with", if let Some(formatter_name) = self.format_trait_impl.formatter_name { format!("{replacement}!({formatter_name}, ..)") diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 5f8d787357d..34e93bdb9b9 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -151,12 +151,12 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { cx, SUSPICIOUS_ASSIGNMENT_FORMATTING, eqop_span, - &format!( + format!( "this looks like you are trying to use `.. {op}= ..`, but you \ really are doing `.. = ({op} ..)`" ), None, - &format!("to remove this lint, use either `{op}=` or `= {op}`"), + format!("to remove this lint, use either `{op}=` or `= {op}`"), ); } } @@ -187,12 +187,12 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) { cx, SUSPICIOUS_UNARY_OP_FORMATTING, eqop_span, - &format!( + format!( "by not having a space between `{binop_str}` and `{unop_str}` it looks like \ `{binop_str}{unop_str}` is a single operator" ), None, - &format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"), + format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"), ); } } @@ -239,9 +239,9 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { cx, SUSPICIOUS_ELSE_FORMATTING, else_span, - &format!("this is an `else {else_desc}` but the formatting might hide it"), + format!("this is an `else {else_desc}` but the formatting might hide it"), None, - &format!( + format!( "to remove this lint, remove the `else` or remove the new line between \ `else` and `{else_desc}`", ), @@ -309,9 +309,9 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { cx, SUSPICIOUS_ELSE_FORMATTING, else_span, - &format!("this looks like {looks_like} but the `else` is missing"), + format!("this looks like {looks_like} but the `else` is missing"), None, - &format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",), + format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",), ); } } diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs index c8d10dc4b92..b6d7cb87480 100644 --- a/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/clippy_lints/src/from_raw_with_void_ptr.rs @@ -52,7 +52,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr { cx, FROM_RAW_WITH_VOID_PTR, expr.span, - &msg, + msg, Some(arg.span), "cast this to a pointer of the appropriate type", ); diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 3aaf63ce340..d0d81c06950 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -142,7 +142,7 @@ fn check_must_use_candidate<'tcx>( item_span: Span, item_id: hir::OwnerId, fn_span: Span, - msg: &str, + msg: &'static str, ) { if has_mutable_arg(cx, body) || mutates_static(cx, body) diff --git a/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs index 1e08922a616..e72a2ad49d8 100644 --- a/clippy_lints/src/functions/too_many_arguments.rs +++ b/clippy_lints/src/functions/too_many_arguments.rs @@ -59,7 +59,7 @@ fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span, cx, TOO_MANY_ARGUMENTS, fn_span, - &format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"), + format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"), ); } } diff --git a/clippy_lints/src/functions/too_many_lines.rs b/clippy_lints/src/functions/too_many_lines.rs index 34f1bf3b2b1..586ca58d60d 100644 --- a/clippy_lints/src/functions/too_many_lines.rs +++ b/clippy_lints/src/functions/too_many_lines.rs @@ -77,7 +77,7 @@ pub(super) fn check_fn( cx, TOO_MANY_LINES, span, - &format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"), + format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"), ); } } diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index 8f48941c4a9..f5ba62ae432 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -117,9 +117,9 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { cx, IF_THEN_SOME_ELSE_NONE, expr.span, - &format!("this could be simplified with `bool::{method_name}`"), + format!("this could be simplified with `bool::{method_name}`"), None, - &help, + help, ); } } diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index a79bf66ae01..e1950d6218c 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { cx, IMPLICIT_HASHER, target.span(), - &format!( + format!( "impl for `{}` should be generalized over different hashers", target.type_name() ), @@ -187,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { cx, IMPLICIT_HASHER, target.span(), - &format!( + format!( "parameter of type `{}` should be generalized over different hashers", target.type_name() ), diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 79078055cc3..fb4ba175233 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -65,7 +65,7 @@ fn emit_lint( cx, IMPLIED_BOUNDS_IN_IMPLS, poly_trait.span, - &format!("this bound is already specified as the supertrait of `{implied_by}`"), + format!("this bound is already specified as the supertrait of `{implied_by}`"), |diag| { // If we suggest removing a bound, we may also need to extend the span // to include the `+` token that is ahead or behind, diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 23bcd19ddd3..35b4481bfee 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -104,7 +104,7 @@ impl IncompatibleMsrv { cx, INCOMPATIBLE_MSRV, span, - &format!( + format!( "current MSRV (Minimum Supported Rust Version) is `{}` but this item is stable since `{version}`", self.msrv ), diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index ca2ac60306b..157f6105984 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -132,20 +132,20 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) { cx, INHERENT_TO_STRING_SHADOW_DISPLAY, item.span, - &format!( + format!( "type `{self_type}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`" ), None, - &format!("remove the inherent method from type `{self_type}`"), + format!("remove the inherent method from type `{self_type}`"), ); } else { span_lint_and_help( cx, INHERENT_TO_STRING, item.span, - &format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"), + format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"), None, - &format!("implement trait `Display` for type `{self_type}` instead"), + format!("implement trait `Display` for type `{self_type}` instead"), ); } } diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 83ecaeef982..860258fd030 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -51,7 +51,7 @@ fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) { cx, INLINE_FN_WITHOUT_BODY, attr.span, - &format!("use of `#[inline]` on trait method `{name}` which has no body"), + format!("use of `#[inline]` on trait method `{name}` which has no body"), |diag| { diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable); }, diff --git a/clippy_lints/src/integer_division_remainder_used.rs b/clippy_lints/src/integer_division_remainder_used.rs index 36dc45ca788..a3577b765c0 100644 --- a/clippy_lints/src/integer_division_remainder_used.rs +++ b/clippy_lints/src/integer_division_remainder_used.rs @@ -43,7 +43,7 @@ impl LateLintPass<'_> for IntegerDivisionRemainderUsed { cx, INTEGER_DIVISION_REMAINDER_USED, expr.span.source_callsite(), - &format!("use of {} has been disallowed in this context", op.node.as_str()), + format!("use of {} has been disallowed in this context", op.node.as_str()), ); } } diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs index 7dcb80ac274..30f2285bdd2 100644 --- a/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/clippy_lints/src/invalid_upcast_comparisons.rs @@ -76,7 +76,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa cx, INVALID_UPCAST_COMPARISONS, span, - &format!( + format!( "because of the numeric bounds on `{}` prior to casting, this expression is always {}", snippet(cx, cast_val.span, "the expression"), if always { "true" } else { "false" }, diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 0b4c416d94d..6615122567d 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -240,9 +240,9 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: & cx, STRUCT_FIELD_NAMES, item.span, - &format!("all fields have the same {what}fix: `{value}`"), + format!("all fields have the same {what}fix: `{value}`"), None, - &format!("remove the {what}fixes"), + format!("remove the {what}fixes"), ); } } @@ -370,9 +370,9 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n cx, ENUM_VARIANT_NAMES, span, - &format!("all variants have the same {what}fix: `{value}`"), + format!("all variants have the same {what}fix: `{value}`"), None, - &format!( + format!( "remove the {what}fixes and use full paths to \ the variants instead of glob imports" ), diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index 32ae6be5687..1b5f1b49947 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -84,7 +84,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI cx, ITER_NOT_RETURNING_ITERATOR, sig.span, - &format!("this method is named `{name}` but its return type does not implement `Iterator`"), + format!("this method is named `{name}` but its return type does not implement `Iterator`"), ); } } diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index b5821d909f8..1dd9b1515a9 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -182,7 +182,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter { cx, INTO_ITER_WITHOUT_ITER, item.span, - &format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"), + format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"), |diag| { // The suggestion forwards to the `IntoIterator` impl and uses a form of UFCS // to avoid name ambiguities, as there might be an inherent into_iter method @@ -258,7 +258,7 @@ impl {self_ty_without_ref} {{ cx, ITER_WITHOUT_INTO_ITER, item.span, - &format!( + format!( "`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`", item.ident ), diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index eb7570e9b44..07488a512a3 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { cx, LARGE_FUTURES, expr.span, - &format!("large future with a size of {} bytes", size.bytes()), + format!("large future with a size of {} bytes", size.bytes()), "consider `Box::pin` on it", format!("Box::pin({})", snippet(cx, expr.span, "..")), Applicability::Unspecified, diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index 1b5981ecc28..0599afca09f 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -74,7 +74,7 @@ impl LateLintPass<'_> for LargeIncludeFile { expr.span, "attempted to include a large file", None, - &format!( + format!( "the configuration allows a maximum size of {} bytes", self.max_file_size ), diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index fd33ba91bfd..afcb6745947 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -58,12 +58,12 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { cx, LARGE_STACK_ARRAYS, expr.span, - &format!( + format!( "allocating a local array larger than {} bytes", self.maximum_allowed_size ), None, - &format!( + format!( "consider allocating on the heap with `vec!{}.into_boxed_slice()`", snippet(cx, expr.span, "[...]") ), diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 059ba981ef3..49408d7e243 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -174,7 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { cx, LARGE_STACK_FRAMES, fn_span, - &format!("this function may allocate {frame_size} on the stack"), + format!("this function may allocate {frame_size} on the stack"), |diag| { // Point out the largest individual contribution to this size, because // it is the most likely to be unintentionally large. diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 174b775f88b..ef52121ce3e 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -266,7 +266,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items cx, LEN_WITHOUT_IS_EMPTY, visited_trait.span, - &format!( + format!( "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method", visited_trait.ident.name ), @@ -484,7 +484,7 @@ fn check_for_is_empty( Some(_) => return, }; - span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, &msg, |db| { + span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, msg, |db| { if let Some(span) = is_empty_span { db.span_note(span, "`is_empty` defined here"); } @@ -542,8 +542,8 @@ fn check_len( cx, LEN_ZERO, span, - &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), - &format!("using `{op}is_empty` is clearer and more explicit"), + format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), + format!("using `{op}is_empty` is clearer and more explicit"), format!( "{op}{}.is_empty()", snippet_with_context(cx, receiver.span, span.ctxt(), "_", &mut applicability).0, @@ -566,7 +566,7 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex COMPARISON_TO_EMPTY, span, "comparison to empty slice", - &format!("using `{op}is_empty` is clearer and more explicit"), + format!("using `{op}is_empty` is clearer and more explicit"), format!("{op}{lit_str}.is_empty()"), applicability, ); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 2b73663d229..a60a40a2a47 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -216,7 +216,7 @@ fn check_fn_inner<'tcx>( None })) .collect_vec(), - &format!("the following explicit lifetimes could be elided: {lts}"), + format!("the following explicit lifetimes could be elided: {lts}"), |diag| { if sig.header.is_async() { // async functions have usages whose spans point at the lifetime declaration which messes up diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs index 29957e423b0..3d1c666dfea 100644 --- a/clippy_lints/src/lines_filter_map_ok.rs +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -70,7 +70,7 @@ impl LateLintPass<'_> for LinesFilterMapOk { cx, LINES_FILTER_MAP_OK, fm_span, - &format!("`{fm_method_str}()` will run forever if the iterator repeatedly produces an `Err`",), + format!("`{fm_method_str}()` will run forever if the iterator repeatedly produces an `Err`",), |diag| { diag.span_note( fm_receiver.span, diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs index 277062a8490..f0ee64d714e 100644 --- a/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/clippy_lints/src/loops/explicit_counter_loop.rs @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>( cx, EXPLICIT_COUNTER_LOOP, span, - &format!("the variable `{name}` is used as a loop counter"), + format!("the variable `{name}` is used as a loop counter"), "consider using", format!( "for ({name}, {}) in {}.enumerate()", @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( cx, EXPLICIT_COUNTER_LOOP, span, - &format!("the variable `{name}` is used as a loop counter"), + format!("the variable `{name}` is used as a loop counter"), |diag| { diag.span_suggestion( span, diff --git a/clippy_lints/src/loops/for_kv_map.rs b/clippy_lints/src/loops/for_kv_map.rs index 94c951fc10a..6922533fbe9 100644 --- a/clippy_lints/src/loops/for_kv_map.rs +++ b/clippy_lints/src/loops/for_kv_map.rs @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx cx, FOR_KV_MAP, arg_span, - &format!("you seem to want to iterate on a map's {kind}s"), + format!("you seem to want to iterate on a map's {kind}s"), |diag| { let map = sugg::Sugg::hir(cx, arg, "map"); multispan_sugg( diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs index 36de9021f49..dbc094a6d73 100644 --- a/clippy_lints/src/loops/manual_flatten.rs +++ b/clippy_lints/src/loops/manual_flatten.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( "...and remove the `if let` statement in the for loop" }; - span_lint_and_then(cx, MANUAL_FLATTEN, span, &msg, |diag| { + span_lint_and_then(cx, MANUAL_FLATTEN, span, msg, |diag| { diag.span_suggestion(arg.span, "try", sugg, applicability); diag.span_help(inner_expr.span, help_msg); }); diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index 04340d33330..de7ec81bc01 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -143,7 +143,7 @@ pub(super) fn check<'tcx>( cx, NEEDLESS_RANGE_LOOP, arg.span, - &format!("the loop variable `{}` is used to index `{indexed}`", ident.name), + format!("the loop variable `{}` is used to index `{indexed}`", ident.name), |diag| { multispan_sugg( diag, @@ -169,7 +169,7 @@ pub(super) fn check<'tcx>( cx, NEEDLESS_RANGE_LOOP, arg.span, - &format!("the loop variable `{}` is only used to index `{indexed}`", ident.name), + format!("the loop variable `{}` is only used to index `{indexed}`", ident.name), |diag| { multispan_sugg( diag, diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 0f35514b8ad..dd400a661a5 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( vec.span, "it looks like the same item is being pushed into this Vec", None, - &format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"), + format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"), ); } diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index a1ff787ebb5..108fdb69775 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -95,7 +95,7 @@ pub(super) fn check<'tcx>( cx, SINGLE_ELEMENT_LOOP, arg.span, - format!("this loops only once with `{pat_snip}` being `{range_expr}`").as_str(), + format!("this loops only once with `{pat_snip}` being `{range_expr}`"), "did you mean to iterate over the range instead?", sugg.to_string(), Applicability::Unspecified, diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs index a381b35cf2e..72807b4b284 100644 --- a/clippy_lints/src/main_recursion.rs +++ b/clippy_lints/src/main_recursion.rs @@ -51,7 +51,7 @@ impl LateLintPass<'_> for MainRecursion { cx, MAIN_RECURSION, func.span, - &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")), + format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")), None, "consider using another function for this recursion", ); diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index bcd02436002..45af9f07718 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -106,12 +106,12 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { cx, MANUAL_STRIP, strippings[0], - &format!("stripping a {kind_word} manually"), + format!("stripping a {kind_word} manually"), |diag| { diag.span_note(test_span, format!("the {kind_word} was tested here")); multispan_sugg( diag, - &format!("try using the `strip_{kind_word}` method"), + format!("try using the `strip_{kind_word}` method"), vec![( test_span, format!( diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index c9eab7109eb..9db04b615be 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -221,13 +221,13 @@ fn lint_map_unit_fn( binding = let_binding_name(cx, var_arg) ); - span_lint_and_then(cx, lint, expr.span, &msg, |diag| { + span_lint_and_then(cx, lint, expr.span, msg, |diag| { diag.span_suggestion(stmt.span, "try", suggestion, applicability); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); - span_lint_and_then(cx, lint, expr.span, &msg, |diag| { + span_lint_and_then(cx, lint, expr.span, msg, |diag| { if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) { let mut applicability = Applicability::MachineApplicable; let suggestion = format!( diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs index 62cedc8847b..2a5fc8b6609 100644 --- a/clippy_lints/src/match_result_ok.rs +++ b/clippy_lints/src/match_result_ok.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk { MATCH_RESULT_OK, expr.span.with_hi(let_expr.span.hi()), "matching on `Some` with `ok()` is redundant", - &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"), + format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"), sugg, applicability, ); diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 5fef5930fab..6746920edc5 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -97,7 +97,7 @@ fn check_arm<'tcx>( } else { String::new() }; - span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, &msg, |diag| { + span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, msg, |diag| { let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]); help_span.push_span_label(binding_span, "replace this binding"); help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}")); diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index 3e79cabd795..9edd6c95404 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee: cx, MANUAL_UNWRAP_OR, expr.span, - &format!("this pattern reimplements `{ty_name}::unwrap_or`"), + format!("this pattern reimplements `{ty_name}::unwrap_or`"), "replace with", format!("{suggestion}.unwrap_or({reindented_or_body})",), app, diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs index 3f737da92c0..a5079f46f5e 100644 --- a/clippy_lints/src/matches/match_as_ref.rs +++ b/clippy_lints/src/matches/match_as_ref.rs @@ -43,7 +43,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: cx, MATCH_AS_REF, expr.span, - &format!("use `{suggestion}()` instead"), + format!("use `{suggestion}()` instead"), "try", format!( "{}.{suggestion}(){cast}", diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index b062e81cefd..64cb7a06ce9 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -122,7 +122,7 @@ where cx, MATCH_LIKE_MATCHES_MACRO, expr.span, - &format!( + format!( "{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" } ), diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs index bd38648bcf1..322e9c3ebe5 100644 --- a/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -111,7 +111,7 @@ fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad MATCH_STR_CASE_MISMATCH, bad_case_span, "this `match` arm has a differing case than its expression", - &format!("consider changing the case of this arm to respect `{method_str}`"), + format!("consider changing the case of this arm to respect `{method_str}`"), format!("\"{suggestion}\""), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs index 8a4c0ab9062..d1f637ec78c 100644 --- a/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/clippy_lints/src/matches/match_wild_err_arm.rs @@ -43,7 +43,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' cx, MATCH_WILD_ERR_ARM, arm.pat.span, - &format!("`Err({ident_bind_name})` matches all errors"), + format!("`Err({ident_bind_name})` matches all errors"), None, "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable", ); diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index b5870d94d99..78973984fb0 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -72,7 +72,7 @@ fn find_match_true<'tcx>( pat: &'tcx Pat<'_>, scrutinee: &'tcx Expr<'_>, span: Span, - message: &str, + message: &'static str, ) { if let PatKind::Lit(lit) = pat.kind && let ExprKind::Lit(lit) = lit.kind @@ -98,7 +98,7 @@ fn find_match_true<'tcx>( span, message, "consider using the condition directly", - sugg.to_string(), + sugg.into_string(), applicability, ); } @@ -227,7 +227,7 @@ fn find_method_sugg_for_if_let<'tcx>( cx, REDUNDANT_PATTERN_MATCHING, let_pat.span, - &format!("redundant pattern matching, consider using `{good_method}`"), + format!("redundant pattern matching, consider using `{good_method}`"), |diag| { // if/while let ... = ... { ... } // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -304,7 +304,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op cx, REDUNDANT_PATTERN_MATCHING, span, - &format!("redundant pattern matching, consider using `{good_method}`"), + format!("redundant pattern matching, consider using `{good_method}`"), "try", sugg, Applicability::MachineApplicable, diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 1cdb7921f81..578aa7989e7 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -193,7 +193,7 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< cx, MEM_REPLACE_WITH_DEFAULT, expr_span, - &format!( + format!( "replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`" ), |diag| { diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 08bfa2e009b..fb440ce656e 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -84,7 +84,7 @@ pub(crate) trait BindInsteadOfMap { "{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME ); - span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, "try", note, app); + span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, "try", note, app); true } else { false @@ -114,7 +114,7 @@ pub(crate) trait BindInsteadOfMap { } else { return false; }; - span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| { + span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, |diag| { multispan_sugg_with_applicability( diag, "try", @@ -157,7 +157,7 @@ pub(crate) trait BindInsteadOfMap { cx, BIND_INSTEAD_OF_MAP, expr.span, - &msg, + msg, "use the expression directly", snippet(cx, recv.span, "..").into(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs index baafb7030aa..a82abc79f2a 100644 --- a/clippy_lints/src/methods/bytes_nth.rs +++ b/clippy_lints/src/methods/bytes_nth.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E cx, BYTES_NTH, parent.span, - &format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"), + format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"), "try", format!("{receiver}.as_bytes()[{n}]",), applicability, @@ -41,7 +41,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E cx, BYTES_NTH, expr.span, - &format!("called `.bytes().nth()` on a `{caller_type}`"), + format!("called `.bytes().nth()` on a `{caller_type}`"), "try", format!("{receiver}.as_bytes().get({n}).copied()"), applicability, diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs index c99cec067bf..4ae0aeea2d1 100644 --- a/clippy_lints/src/methods/chars_cmp.rs +++ b/clippy_lints/src/methods/chars_cmp.rs @@ -30,7 +30,7 @@ pub(super) fn check( cx, lint, info.expr.span, - &format!("you should use the `{suggest}` method"), + format!("you should use the `{suggest}` method"), "like this", format!( "{}{}.{suggest}({})", diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs index d07e45434a7..9c45ec2e56c 100644 --- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs +++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -23,7 +23,7 @@ pub(super) fn check( cx, lint, info.expr.span, - &format!("you should use the `{suggest}` method"), + format!("you should use the `{suggest}` method"), "like this", format!( "{}{}.{suggest}('{}')", diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index 506ec6ba1c9..5389861245a 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -43,7 +43,7 @@ fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) { cx, CLEAR_WITH_DRAIN, span.with_hi(expr.span.hi()), - &format!("`drain` used to clear a `{ty_name}`"), + format!("`drain` used to clear a `{ty_name}`"), "try", "clear()".to_string(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index fb5c0c544a9..4965b396b8c 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -94,7 +94,7 @@ pub(super) fn check( cx, CLONE_ON_COPY, expr.span, - &with_forced_trimmed_paths!(format!( + with_forced_trimmed_paths!(format!( "using `clone` on type `{ty}` which implements the `Copy` trait" )), help, diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index 3a8ca37610a..56171a13452 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -70,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re cx, DRAIN_COLLECT, expr.span, - &format!("you seem to be trying to move all elements into a new `{typename}`"), + format!("you seem to be trying to move all elements into a new `{typename}`"), "consider using `mem::take`", sugg, Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index 4d8fb217f7f..fba76852344 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -142,7 +142,7 @@ pub(super) fn check<'tcx>( cx, EXPECT_FUN_CALL, span_replace_word, - &format!("use of `{name}` followed by a function call"), + format!("use of `{name}` followed by a function call"), "try", format!("unwrap_or_else({closure_args} panic!({sugg}))"), applicability, @@ -160,7 +160,7 @@ pub(super) fn check<'tcx>( cx, EXPECT_FUN_CALL, span_replace_word, - &format!("use of `{name}` followed by a function call"), + format!("use of `{name}` followed by a function call"), "try", format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"), applicability, diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs index b05361ab212..eab536b88a5 100644 --- a/clippy_lints/src/methods/filetype_is_file.rs +++ b/clippy_lints/src/methods/filetype_is_file.rs @@ -34,5 +34,5 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr } let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files"); let help_msg = format!("use `{help_unary}FileType::is_dir()` instead"); - span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, None, &help_msg); + span_lint_and_help(cx, FILETYPE_IS_FILE, span, lint_msg, None, help_msg); } diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 83dcc90637e..581e3b308c3 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -386,7 +386,7 @@ pub(super) fn check( ) }, }; - span_lint_and_then(cx, lint, span, &msg, |diag| { + span_lint_and_then(cx, lint, span, msg, |diag| { diag.span_suggestion(span, "try", sugg, applicability); if let Some((note, span)) = note_and_span { diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs index 55fcf372894..f4465e654c2 100644 --- a/clippy_lints/src/methods/get_first.rs +++ b/clippy_lints/src/methods/get_first.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( cx, GET_FIRST, expr.span, - &format!("accessing first element with `{slice_name}.get(0)`"), + format!("accessing first element with `{slice_name}.get(0)`"), "try", format!("{slice_name}.first()"), app, @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( cx, GET_FIRST, expr.span, - &format!("accessing first element with `{slice_name}.get(0)`"), + format!("accessing first element with `{slice_name}.get(0)`"), "try", format!("{slice_name}.front()"), app, diff --git a/clippy_lints/src/methods/get_last_with_len.rs b/clippy_lints/src/methods/get_last_with_len.rs index 3bdc154df04..62037651134 100644 --- a/clippy_lints/src/methods/get_last_with_len.rs +++ b/clippy_lints/src/methods/get_last_with_len.rs @@ -44,7 +44,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: cx, GET_LAST_WITH_LEN, expr.span, - &format!("accessing last element with `{recv_snippet}.get({recv_snippet}.len() - 1)`"), + format!("accessing last element with `{recv_snippet}.get({recv_snippet}.len() - 1)`"), "try", format!("{recv_snippet}.{method}()"), applicability, diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index afdcb3b6549..455274a4428 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -70,7 +70,7 @@ pub(super) fn check<'tcx>( cx, GET_UNWRAP, span, - &format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"), + format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"), "try", format!( "{borrow_str}{}[{get_args_str}]", diff --git a/clippy_lints/src/methods/implicit_clone.rs b/clippy_lints/src/methods/implicit_clone.rs index 78a553eb8c0..c510cd915d0 100644 --- a/clippy_lints/src/methods/implicit_clone.rs +++ b/clippy_lints/src/methods/implicit_clone.rs @@ -27,7 +27,7 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv cx, IMPLICIT_CLONE, expr.span, - &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"), + format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"), "consider using", if ref_count > 1 { format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1)) diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index efc3ddd20b4..230a8eb2ec4 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -32,7 +32,7 @@ pub fn check( cx, INEFFICIENT_TO_STRING, expr.span, - &format!("calling `to_string` on `{arg_ty}`"), + format!("calling `to_string` on `{arg_ty}`"), |diag| { diag.help(format!( "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`" diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index 80160d17c82..bbc7ce8d78a 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -27,7 +27,7 @@ pub(super) fn check( cx, INTO_ITER_ON_REF, method_span, - &format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",), + format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",), "call directly", method_name.to_string(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index e963950960a..210e4ae0a7b 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -36,7 +36,7 @@ pub(super) fn check<'tcx>( cx, IS_DIGIT_ASCII_RADIX, expr.span, - &format!("use of `char::is_digit` with literal radix of {num}"), + format!("use of `char::is_digit` with literal radix of {num}"), "try", format!( "{}.{replacement}()", diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 7fe66062251..d921b7ea14f 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ cx, CONST_IS_EMPTY, expr.span, - &format!("this expression always evaluates to {init_is_empty:?}"), + format!("this expression always evaluates to {init_is_empty:?}"), ); } } diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs index dd741cd43f9..49de83885a1 100644 --- a/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/clippy_lints/src/methods/iter_cloned_collect.rs @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir: cx, ITER_CLONED_COLLECT, to_replace, - &format!( + format!( "called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ more readable" ), diff --git a/clippy_lints/src/methods/iter_count.rs b/clippy_lints/src/methods/iter_count.rs index bcddc7c786a..209cf2fcc0a 100644 --- a/clippy_lints/src/methods/iter_count.rs +++ b/clippy_lints/src/methods/iter_count.rs @@ -37,7 +37,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E cx, ITER_COUNT, expr.span, - &format!("called `.{iter_method}().count()` on a `{caller_type}`"), + format!("called `.{iter_method}().count()` on a `{caller_type}`"), "try", format!( "{}.len()", diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 6394f35f860..84fa4c03757 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -54,7 +54,7 @@ pub(super) fn check<'tcx>( cx, ITER_KV_MAP, expr.span, - &format!("iterating on a map's {replacement_kind}s"), + format!("iterating on a map's {replacement_kind}s"), "try", format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"), applicability, @@ -66,7 +66,7 @@ pub(super) fn check<'tcx>( cx, ITER_KV_MAP, expr.span, - &format!("iterating on a map's {replacement_kind}s"), + format!("iterating on a map's {replacement_kind}s"), "try", format!( "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})", diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index 5b0b70b4b96..e31fa2f777d 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( cx, ITER_NTH, expr.span, - &format!("called `.{iter_method}().nth()` on a {caller_type}"), + format!("called `.{iter_method}().nth()` on a {caller_type}"), |diag| { let get_method = if iter_method == "iter_mut" { "get_mut" } else { "get" }; diag.span_suggestion_verbose( diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 4c7c56e7174..2c789827f80 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -69,7 +69,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re cx, ITER_ON_SINGLE_ITEMS, expr.span, - &format!("`{method_name}` call on a collection with only one item"), + format!("`{method_name}` call on a collection with only one item"), "try", sugg, Applicability::MaybeIncorrect, @@ -79,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re cx, ITER_ON_EMPTY_COLLECTIONS, expr.span, - &format!("`{method_name}` call on an empty collection"), + format!("`{method_name}` call on an empty collection"), "try", format!("{top_crate}::iter::empty()"), Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs index 2ab721ace84..1378a07cbc4 100644 --- a/clippy_lints/src/methods/iter_with_drain.rs +++ b/clippy_lints/src/methods/iter_with_drain.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span cx, ITER_WITH_DRAIN, span.with_hi(expr.span.hi()), - &format!("`drain(..)` used on a `{ty_name}`"), + format!("`drain(..)` used on a `{ty_name}`"), "try", "into_iter()".to_string(), Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index bf437db7e72..9e3b313156e 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -50,7 +50,7 @@ pub fn check( super::MANUAL_SATURATING_ARITHMETIC, expr.span, "manual saturating arithmetic", - &format!("consider using `saturating_{arith}`"), + format!("consider using `saturating_{arith}`"), format!( "{}.saturating_{arith}({})", snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability), diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 9d020092ccb..0901268e9bd 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -161,7 +161,7 @@ fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool) { MAP_CLONE, replace, "you are explicitly cloning with `.map()`", - &format!("consider calling the dedicated `{replacement}` method"), + format!("consider calling the dedicated `{replacement}` method"), format!( "{}.{replacement}()", snippet_with_applicability(cx, root, "..", &mut applicability), @@ -184,7 +184,7 @@ fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_cop MAP_CLONE, replace, message, - &format!("consider calling the dedicated `{sugg_method}` method"), + format!("consider calling the dedicated `{sugg_method}` method"), format!( "{}.{sugg_method}()", snippet_with_applicability(cx, root, "..", &mut applicability), diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs index 26ef0d10fed..def8be2ef73 100644 --- a/clippy_lints/src/methods/map_flatten.rs +++ b/clippy_lints/src/methods/map_flatten.rs @@ -21,8 +21,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_ cx, MAP_FLATTEN, expr.span.with_lo(map_span.lo()), - &format!("called `map(..).flatten()` on `{caller_ty_name}`"), - &format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"), + format!("called `map(..).flatten()` on `{caller_ty_name}`"), + format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"), format!("{method_to_use}({closure_snippet})"), applicability, ); diff --git a/clippy_lints/src/methods/map_identity.rs b/clippy_lints/src/methods/map_identity.rs index 6da9a87f5ee..5dd7b1b02ad 100644 --- a/clippy_lints/src/methods/map_identity.rs +++ b/clippy_lints/src/methods/map_identity.rs @@ -29,7 +29,7 @@ pub(super) fn check( MAP_IDENTITY, sugg_span, "unnecessary map of the identity function", - &format!("remove the call to `{name}`"), + format!("remove the call to `{name}`"), String::new(), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3ad92a91ea7..2fb317c8c68 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4333,12 +4333,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods { cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, - &format!( + format!( "method `{}` can be confused for the standard trait method `{}::{}`", method_config.method_name, method_config.trait_name, method_config.method_name ), None, - &format!( + format!( "consider implementing the trait `{}` or choosing a less ambiguous method name", method_config.trait_name ), diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index 77484ab91a9..d425b505a76 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -151,7 +151,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S cx, NONSENSICAL_OPEN_OPTIONS, prev_span, - &format!("the method `{}` is called more than once", &option), + format!("the method `{}` is called more than once", &option), ); } } diff --git a/clippy_lints/src/methods/option_as_ref_cloned.rs b/clippy_lints/src/methods/option_as_ref_cloned.rs index d7fec360fa2..ba167f9d9c2 100644 --- a/clippy_lints/src/methods/option_as_ref_cloned.rs +++ b/clippy_lints/src/methods/option_as_ref_cloned.rs @@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, cloned_recv: &Expr<'_>, cloned_ident_s cx, OPTION_AS_REF_CLONED, as_ref_ident_span.to(cloned_ident_span), - &format!("cloning an `Option<_>` using `.{method}().cloned()`"), + format!("cloning an `Option<_>` using `.{method}().cloned()`"), "this can be written more concisely by cloning the `Option<_>` directly", "clone".into(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 88e2af15658..cb57689b0c4 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -104,8 +104,8 @@ pub(super) fn check( cx, OPTION_AS_REF_DEREF, expr.span, - &msg, - &suggestion, + msg, + suggestion, hint, Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index ab36f854fcb..efec9dd716d 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -97,7 +97,7 @@ pub(super) fn check<'tcx>( } else { "map_or(, )" }; - let msg = &format!("called `map().unwrap_or({arg})` on an `Option` value"); + let msg = format!("called `map().unwrap_or({arg})` on an `Option` value"); span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { let map_arg_span = map_arg.span; diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index 0602eeaa704..583e04fb4b1 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -97,7 +97,7 @@ pub(super) fn check<'tcx>( cx, UNWRAP_OR_DEFAULT, method_span.with_hi(span.hi()), - &format!("use of `{name}` to construct default value"), + format!("use of `{name}` to construct default value"), "try", format!("{sugg}()"), Applicability::MachineApplicable, @@ -167,7 +167,7 @@ pub(super) fn check<'tcx>( cx, OR_FUN_CALL, span_replace_word, - &format!("use of `{name}` followed by a function call"), + format!("use of `{name}` followed by a function call"), "try", format!("{name}_{suffix}({sugg})"), app, diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs index 1148628b084..28ca76832eb 100644 --- a/clippy_lints/src/methods/range_zip_with_len.rs +++ b/clippy_lints/src/methods/range_zip_with_len.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' cx, RANGE_ZIP_WITH_LEN, expr.span, - &format!( + format!( "it is more idiomatic to use `{}.iter().enumerate()`", snippet(cx, recv.span, "_") ), diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs index 0c3b881b086..ac5cc2f01e5 100644 --- a/clippy_lints/src/methods/search_is_some.rs +++ b/clippy_lints/src/methods/search_is_some.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( cx, SEARCH_IS_SOME, method_span.with_hi(expr.span.hi()), - &msg, + msg, "consider using", format!( "any({})", @@ -76,7 +76,7 @@ pub(super) fn check<'tcx>( cx, SEARCH_IS_SOME, expr.span, - &msg, + msg, "consider using", format!( "!{iter}.any({})", @@ -94,7 +94,7 @@ pub(super) fn check<'tcx>( "" } ); - span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, &hint); + span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, msg, None, hint); } } // lint if `find()` is called by `String` or `&str` @@ -117,7 +117,7 @@ pub(super) fn check<'tcx>( cx, SEARCH_IS_SOME, method_span.with_hi(expr.span.hi()), - &msg, + msg, "consider using", format!("contains({find_arg})"), applicability, @@ -131,7 +131,7 @@ pub(super) fn check<'tcx>( cx, SEARCH_IS_SOME, expr.span, - &msg, + msg, "consider using", format!("!{string}.contains({find_arg})"), applicability, diff --git a/clippy_lints/src/methods/stable_sort_primitive.rs b/clippy_lints/src/methods/stable_sort_primitive.rs index 0f4c97022db..aef14435d8a 100644 --- a/clippy_lints/src/methods/stable_sort_primitive.rs +++ b/clippy_lints/src/methods/stable_sort_primitive.rs @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx cx, STABLE_SORT_PRIMITIVE, e.span, - &format!("used `sort` on primitive type `{slice_type}`"), + format!("used `sort` on primitive type `{slice_type}`"), |diag| { let mut app = Applicability::MachineApplicable; let recv_snip = snippet_with_context(cx, recv.span, e.span.ctxt(), "..", &mut app).0; diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 55cd1a38ec9..955330237bf 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -53,7 +53,7 @@ fn lint_needless(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_ cx, NEEDLESS_SPLITN, expr.span, - &format!("unnecessary use of `{r}splitn`"), + format!("unnecessary use of `{r}splitn`"), "try", format!( "{}.{r}split({})", @@ -154,7 +154,7 @@ fn check_manual_split_once_indirect( let self_snip = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; let pat_snip = snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0; - span_lint_and_then(cx, MANUAL_SPLIT_ONCE, local.span, &msg, |diag| { + span_lint_and_then(cx, MANUAL_SPLIT_ONCE, local.span, msg, |diag| { diag.span_label(first.span, "first usage here"); diag.span_label(second.span, "second usage here"); diff --git a/clippy_lints/src/methods/suspicious_splitn.rs b/clippy_lints/src/methods/suspicious_splitn.rs index c45212581ee..ff5c1d1a401 100644 --- a/clippy_lints/src/methods/suspicious_splitn.rs +++ b/clippy_lints/src/methods/suspicious_splitn.rs @@ -37,6 +37,6 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se ) }; - span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, &msg, None, note_msg); + span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, msg, None, note_msg); } } diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs index 60864902a48..ce7aefed01f 100644 --- a/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/clippy_lints/src/methods/suspicious_to_owned.rs @@ -23,7 +23,7 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) - cx, SUSPICIOUS_TO_OWNED, expr.span, - &with_forced_trimmed_paths!(format!( + with_forced_trimmed_paths!(format!( "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned" )), |diag| { diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index 31e6ccb950a..6f9b38fcf83 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -55,7 +55,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) cx, TYPE_ID_ON_BOX, call_span, - &format!("calling `.type_id()` on `{ty_name}`"), + format!("calling `.type_id()` on `{ty_name}`"), |diag| { let derefs = recv_adjusts .iter() diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index fabf3fa0c0c..daf99d98614 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a UNNECESSARY_FIND_MAP }, expr.span, - &format!("this `.{name}` can be written more simply using `.{sugg}`"), + format!("this `.{name}` can be written more simply using `.{sugg}`"), ); } } diff --git a/clippy_lints/src/methods/unnecessary_get_then_check.rs b/clippy_lints/src/methods/unnecessary_get_then_check.rs index cc8053ef507..f6184222d8e 100644 --- a/clippy_lints/src/methods/unnecessary_get_then_check.rs +++ b/clippy_lints/src/methods/unnecessary_get_then_check.rs @@ -58,7 +58,7 @@ pub(super) fn check( cx, UNNECESSARY_GET_THEN_CHECK, both_calls_span, - &format!("unnecessary use of `{snippet}`"), + format!("unnecessary use of `{snippet}`"), "replace it with", suggestion, Applicability::MaybeIncorrect, @@ -70,7 +70,7 @@ pub(super) fn check( cx, UNNECESSARY_GET_THEN_CHECK, both_calls_span, - &format!("unnecessary use of `{snippet}`"), + format!("unnecessary use of `{snippet}`"), |diag| { diag.span_suggestion( full_span, diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 36497d59a5a..520dcb2d52d 100644 --- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -61,7 +61,7 @@ pub fn check_for_loop_iter( cx, UNNECESSARY_TO_OWNED, expr.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), |diag| { // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to // a `to_owned`-like function was removed, then the next suggestion may be diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 1b2bfbf4090..494d71fc053 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -63,7 +63,7 @@ pub(super) fn check( let help_message = format!("used `{method}()` on `{constructor}` value"); let suggestion_message = format!("remove the `{constructor}` and `{method}()`"); - span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { + span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, help_message, |diag| { let suggestions = match (constructor, method, ty) { ("None", "unwrap", _) => Some(vec![(expr.span, "panic!()".to_string())]), ("None", "expect", _) => Some(vec![ diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index c234e4f9b11..0762115d212 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -138,7 +138,7 @@ fn check_addr_of_expr( cx, UNNECESSARY_TO_OWNED, parent.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", format!( "{:&>width$}{receiver_snippet}", @@ -163,7 +163,7 @@ fn check_addr_of_expr( cx, UNNECESSARY_TO_OWNED, parent.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", receiver_snippet, Applicability::MachineApplicable, @@ -173,7 +173,7 @@ fn check_addr_of_expr( cx, UNNECESSARY_TO_OWNED, expr.span.with_lo(receiver.span.hi()), - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "remove this", String::new(), Applicability::MachineApplicable, @@ -188,7 +188,7 @@ fn check_addr_of_expr( cx, UNNECESSARY_TO_OWNED, parent.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", format!("{receiver_snippet}.as_ref()"), Applicability::MachineApplicable, @@ -232,7 +232,7 @@ fn check_into_iter_call_arg( cx, UNNECESSARY_TO_OWNED, parent.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", format!("{receiver_snippet}.iter().{cloned_or_copied}()"), Applicability::MaybeIncorrect, @@ -271,7 +271,7 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb cx, UNNECESSARY_TO_OWNED, parent.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", format!("{receiver_snippet}{as_ref}.split({arg_snippet})"), Applicability::MaybeIncorrect, @@ -353,7 +353,7 @@ fn check_other_call_arg<'tcx>( cx, UNNECESSARY_TO_OWNED, maybe_arg.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "use", format!("{:&>n_refs$}{receiver_snippet}", ""), Applicability::MachineApplicable, @@ -645,7 +645,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx cx, UNNECESSARY_TO_OWNED, arg.span, - &format!("unnecessary use of `{method_name}`"), + format!("unnecessary use of `{method_name}`"), "replace it with", if original_arg_ty.is_array() { format!("{snippet}.as_slice()") diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 7bd16b473ce..516b8984ad7 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -69,7 +69,7 @@ pub(super) fn check( cx, variant.lint(), expr.span, - &format!("used `{}()` on {kind} value", variant.method_name(is_err)), + format!("used `{}()` on {kind} value", variant.method_name(is_err)), |diag| { diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic")); diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index 474103fccd2..ae2b6e6347e 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -68,7 +68,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, cx, USELESS_ASREF, expr.span, - &format!("this call to `{call_name}` does nothing"), + format!("this call to `{call_name}` does nothing"), "try", snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(), applicability, @@ -159,7 +159,7 @@ fn lint_as_ref_clone(cx: &LateContext<'_>, span: Span, recvr: &hir::Expr<'_>, ca cx, USELESS_ASREF, span, - &format!("this call to `{call_name}.map(...)` does nothing"), + format!("this call to `{call_name}.map(...)` does nothing"), "try", format!( "{}.clone()", diff --git a/clippy_lints/src/methods/verbose_file_reads.rs b/clippy_lints/src/methods/verbose_file_reads.rs index 2fe5ae9a9ad..181b413a182 100644 --- a/clippy_lints/src/methods/verbose_file_reads.rs +++ b/clippy_lints/src/methods/verbose_file_reads.rs @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, - (msg, help): (&str, &str), + (msg, help): (&'static str, &'static str), ) { if is_trait_method(cx, expr, sym::IoRead) && matches!(recv.kind, ExprKind::Path(QPath::Resolved(None, _))) diff --git a/clippy_lints/src/methods/wrong_self_convention.rs b/clippy_lints/src/methods/wrong_self_convention.rs index 0a810a13f3f..28068c63473 100644 --- a/clippy_lints/src/methods/wrong_self_convention.rs +++ b/clippy_lints/src/methods/wrong_self_convention.rs @@ -137,7 +137,7 @@ pub(super) fn check<'tcx>( cx, WRONG_SELF_CONVENTION, first_arg_span, - &format!( + format!( "{suggestion} usually take {}", &self_kinds .iter() diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index 0016fb33517..c6b7f5b0ce2 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -181,7 +181,7 @@ fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str conf.min_ident_chars_threshold, )) }; - span_lint(cx, MIN_IDENT_CHARS, span, &help); + span_lint(cx, MIN_IDENT_CHARS, span, help); } /// Attempt to convert the node to an [`ItemKind::Use`] node. diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index ea6e662b4be..0c0d440a81b 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { cx, USED_UNDERSCORE_BINDING, expr.span, - &format!( + format!( "used binding `{name}` which is prefixed with an underscore. A leading \ underscore signals that a binding will not be used" ), diff --git a/clippy_lints/src/misc_early/builtin_type_shadow.rs b/clippy_lints/src/misc_early/builtin_type_shadow.rs index 9f6b0bdc7a4..662f7cd8500 100644 --- a/clippy_lints/src/misc_early/builtin_type_shadow.rs +++ b/clippy_lints/src/misc_early/builtin_type_shadow.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, param: &GenericParam) { cx, BUILTIN_TYPE_SHADOW, param.ident.span, - &format!("this generic shadows the built-in type `{}`", prim_ty.name()), + format!("this generic shadows the built-in type `{}`", prim_ty.name()), ); } } diff --git a/clippy_lints/src/misc_early/literal_suffix.rs b/clippy_lints/src/misc_early/literal_suffix.rs index eda4376f200..e0a5e401a50 100644 --- a/clippy_lints/src/misc_early/literal_suffix.rs +++ b/clippy_lints/src/misc_early/literal_suffix.rs @@ -16,7 +16,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi cx, SEPARATED_LITERAL_SUFFIX, lit_span, - &format!("{sugg_type} type suffix should not be separated by an underscore"), + format!("{sugg_type} type suffix should not be separated by an underscore"), "remove the underscore", format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]), Applicability::MachineApplicable, @@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi cx, UNSEPARATED_LITERAL_SUFFIX, lit_span, - &format!("{sugg_type} type suffix should be separated by an underscore"), + format!("{sugg_type} type suffix should be separated by an underscore"), "add an underscore", format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]), Applicability::MachineApplicable, diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index abe5b00e888..2f5499d7656 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -394,7 +394,7 @@ impl EarlyLintPass for MiscEarlyLints { cx, DUPLICATE_UNDERSCORE_ARGUMENT, *correspondence, - &format!( + format!( "`{arg_name}` already exists, having another argument having almost the same \ name makes code comprehension and documentation more difficult" ), diff --git a/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs index d7bb0616acb..d5b5b2bf2dd 100644 --- a/clippy_lints/src/misc_early/redundant_pattern.rs +++ b/clippy_lints/src/misc_early/redundant_pattern.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { cx, REDUNDANT_PATTERN, pat.span, - &format!( + format!( "the `{} @ _` pattern can be written as just `{}`", ident.name, ident.name, ), diff --git a/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/clippy_lints/src/misc_early/unneeded_field_pattern.rs index 676e5d40bb7..cb305cf5582 100644 --- a/clippy_lints/src/misc_early/unneeded_field_pattern.rs +++ b/clippy_lints/src/misc_early/unneeded_field_pattern.rs @@ -27,7 +27,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { pat.span, "all the struct fields are matched to a wildcard pattern, consider using `..`", None, - &format!("try with `{type_name} {{ .. }}` instead"), + format!("try with `{type_name} {{ .. }}` instead"), ); return; } @@ -63,7 +63,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { "you matched a field with a wildcard pattern, consider using `..` \ instead", None, - &format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")), + format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")), ); } } diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs index 0739b49fe19..0842a872824 100644 --- a/clippy_lints/src/mismatching_type_param_order.rs +++ b/clippy_lints/src/mismatching_type_param_order.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch { "try `{}`, or a name that does not conflict with `{type_name}`'s generic params", type_param_names[i] ); - span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, &msg, None, &help); + span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, msg, None, help); } } } diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index 39d4ea74b31..c29e46b941c 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -65,7 +65,7 @@ declare_clippy_lint! { } declare_lint_pass!(MissingAssertsForIndexing => [MISSING_ASSERTS_FOR_INDEXING]); -fn report_lint(cx: &LateContext<'_>, full_span: Span, msg: &str, indexes: &[Span], f: F) +fn report_lint(cx: &LateContext<'_>, full_span: Span, msg: &'static str, indexes: &[Span], f: F) where F: FnOnce(&mut Diag<'_, ()>), { diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 6878fb3349d..d9379ec89df 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -127,7 +127,7 @@ impl MissingDoc { cx, MISSING_DOCS_IN_PRIVATE_ITEMS, sp, - &format!("missing documentation for {article} {desc}"), + format!("missing documentation for {article} {desc}"), ); } } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 7393b39c8f6..c6a76478806 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -64,7 +64,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp cx, MISSING_INLINE_IN_PUBLIC_ITEMS, sp, - &format!("missing `#[inline]` for {desc}"), + format!("missing `#[inline]` for {desc}"), ); } } diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index 6bbf18d52d1..6f844bc646a 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { cx, MISSING_TRAIT_METHODS, source_map.guess_head_span(item.span), - &format!("missing trait method provided by default: `{}`", assoc.name), + format!("missing trait method provided by default: `{}`", assoc.name), Some(definition_span), "implement the method", ); diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 12c7c18afde..0a65c768c66 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { self.cx, MIXED_READ_WRITE_IN_EXPRESSION, expr.span, - &format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)), + format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)), Some(self.write_expr.span), "whether read occurs before this write depends on evaluation order", ); diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 0226b31dd19..6c031c08175 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -129,9 +129,9 @@ impl EarlyLintPass for ModStyle { cx, SELF_NAMED_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), - &format!("`mod.rs` files are required, found `{}`", path.display()), + format!("`mod.rs` files are required, found `{}`", path.display()), None, - &format!("move `{}` to `{}`", path.display(), correct.display(),), + format!("move `{}` to `{}`", path.display(), correct.display(),), ); } } @@ -169,9 +169,9 @@ fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &Source cx, MOD_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), - &format!("`mod.rs` files are not allowed, found `{}`", path.display()), + format!("`mod.rs` files are not allowed, found `{}`", path.display()), None, - &format!("move `{}` to `{}`", path.display(), mod_file.display()), + format!("move `{}` to `{}`", path.display(), mod_file.display()), ); } } diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 648d780ac09..0e138066780 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock { cx, MULTIPLE_UNSAFE_OPS_PER_BLOCK, block.span, - &format!( + format!( "this `unsafe` block contains {} unsafe operations, expected only one", unsafe_ops.len() ), diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 7447a2287d3..11ab36bb056 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -92,7 +92,7 @@ fn check_arguments<'tcx>( cx, UNNECESSARY_MUT_PASSED, argument.span, - &format!("the {fn_kind} `{name}` doesn't need a mutable reference"), + format!("the {fn_kind} `{name}` doesn't need a mutable reference"), ); } }, diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs index 2d7ce7b52ae..563ce2d82ea 100644 --- a/clippy_lints/src/mutable_debug_assertion.rs +++ b/clippy_lints/src/mutable_debug_assertion.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for DebugAssertWithMutCall { cx, DEBUG_ASSERT_WITH_MUT_CALL, span, - &format!("do not call a function with mutable arguments inside of `{macro_name}!`"), + format!("do not call a function with mutable arguments inside of `{macro_name}!`"), ); } } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index b882e00dbdf..0c7f7e44edf 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -92,9 +92,9 @@ impl<'tcx> LateLintPass<'tcx> for Mutex { behavior and not the internal type, consider using `Mutex<()>`" ); match *mutex_param.kind() { - ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), + ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), + ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg), + _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg), }; } } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 081d14c043c..f9ee4a3dc93 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -317,11 +317,11 @@ fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr fn check_comparison<'a, 'tcx>( cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, - left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, - left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, - right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, - right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, - no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>, + left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>, + left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>, + right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>, + right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>, + no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &'static str)>, ) { if let ExprKind::Binary(op, left_side, right_side) = e.kind { let (l_ty, r_ty) = ( @@ -391,7 +391,7 @@ fn check_comparison<'a, 'tcx>( binop_span, m, "try simplifying it as shown", - h(left_side, right_side).to_string(), + h(left_side, right_side).into_string(), applicability, ); }), @@ -406,7 +406,7 @@ fn suggest_bool_comparison<'a, 'tcx>( span: Span, expr: &Expr<'_>, mut app: Applicability, - message: &str, + message: &'static str, conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>, ) { let hint = Sugg::hir_with_context(cx, expr, span.ctxt(), "..", &mut app); @@ -416,7 +416,7 @@ fn suggest_bool_comparison<'a, 'tcx>( span, message, "try simplifying it as shown", - conv_hint(hint).to_string(), + conv_hint(hint).into_string(), app, ); } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 4710a69443b..d91329eadcb 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef { fn check_subpatterns<'tcx>( cx: &LateContext<'tcx>, - message: &str, + message: &'static str, ref_pat: &Pat<'_>, pat: &Pat<'_>, subpatterns: impl IntoIterator>, diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index ff72b5e69ef..8b4a12bb766 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -313,7 +313,7 @@ fn emit_warning(cx: &EarlyContext<'_>, data: &LintData<'_>, header: &str, typ: L expr.span, message, None, - &format!("{header}\n{snip}"), + format!("{header}\n{snip}"), ); } diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs index d7adf22ff32..37463cfec9a 100644 --- a/clippy_lints/src/needless_question_mark.rs +++ b/clippy_lints/src/needless_question_mark.rs @@ -131,7 +131,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { NEEDLESS_QUESTION_MARK, expr.span, "question mark operator is useless here", - &format!("try removing question mark and `{sugg_remove}`"), + format!("try removing question mark and `{sugg_remove}`"), format!("{}", snippet(cx, inner_expr.span, r#""...""#)), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 627b4968d9f..78dd1e05162 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -134,9 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { NEW_WITHOUT_DEFAULT, id.into(), impl_item.span, - &format!( - "you should consider adding a `Default` implementation for `{self_type_snip}`" - ), + format!("you should consider adding a `Default` implementation for `{self_type_snip}`"), |diag| { diag.suggest_prepend_item( cx, diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index b8c3c7fa65a..7b26235291a 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> { self.cx, MANY_SINGLE_CHAR_NAMES, span, - &format!("{num_single_char_names} bindings with single-character names in scope"), + format!("{num_single_char_names} bindings with single-character names in scope"), ); } } diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs index 793a3a9545c..d64190daecb 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { cx, NON_SEND_FIELDS_IN_SEND_TY, item.span, - &format!( + format!( "some fields in `{}` are not safe to be sent to another thread", snippet(cx, hir_impl.self_ty.span, "Unknown") ), diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs index 1c6069e9c65..88f2eabaccb 100644 --- a/clippy_lints/src/nonstandard_macro_braces.rs +++ b/clippy_lints/src/nonstandard_macro_braces.rs @@ -121,7 +121,7 @@ fn emit_help(cx: &EarlyContext<'_>, snip: &str, (open, close): (char, char), spa cx, NONSTANDARD_MACRO_BRACES, span, - &format!("use of irregular braces for `{macro_name}!` macro"), + format!("use of irregular braces for `{macro_name}!` macro"), "consider writing", format!("{macro_name}!{open}{macro_args}{close}"), Applicability::MachineApplicable, diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs index 8822dfeeddd..2fc039ae886 100644 --- a/clippy_lints/src/octal_escapes.rs +++ b/clippy_lints/src/octal_escapes.rs @@ -94,7 +94,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { cx, OCTAL_ESCAPES, span, - &format!( + format!( "octal-looking escape in {} literal", if is_string { "string" } else { "byte string" } ), diff --git a/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/clippy_lints/src/operators/absurd_extreme_comparisons.rs index f4863600ccc..9769da6d3e9 100644 --- a/clippy_lints/src/operators/absurd_extreme_comparisons.rs +++ b/clippy_lints/src/operators/absurd_extreme_comparisons.rs @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>( } ); - span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help); + span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, help); } } diff --git a/clippy_lints/src/operators/bit_mask.rs b/clippy_lints/src/operators/bit_mask.rs index 2e026c369ee..545e680ce0d 100644 --- a/clippy_lints/src/operators/bit_mask.rs +++ b/clippy_lints/src/operators/bit_mask.rs @@ -64,7 +64,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"), + format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"), ); } } else if mask_value == 0 { @@ -77,7 +77,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"), + format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"), ); } }, @@ -90,7 +90,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"), + format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"), ); } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); @@ -102,7 +102,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"), + format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"), ); } else { check_ineffective_lt(cx, span, mask_value, cmp_value, "|"); @@ -118,7 +118,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"), + format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"), ); } else if mask_value == 0 { span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero"); @@ -130,7 +130,7 @@ fn check_bit_mask( cx, BAD_BIT_MASK, span, - &format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"), + format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"), ); } else { check_ineffective_gt(cx, span, mask_value, cmp_value, "|"); @@ -149,7 +149,7 @@ fn check_ineffective_lt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op: cx, INEFFECTIVE_BIT_MASK, span, - &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"), + format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"), ); } } @@ -160,7 +160,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op: cx, INEFFECTIVE_BIT_MASK, span, - &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"), + format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"), ); } } diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs index e278cf9835a..7bf9b8ef866 100644 --- a/clippy_lints/src/operators/const_comparisons.rs +++ b/clippy_lints/src/operators/const_comparisons.rs @@ -89,7 +89,7 @@ pub(super) fn check<'tcx>( span, "left-hand side of `&&` operator has no effect", Some(left_cond.span.until(right_cond.span)), - &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"), + format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"), ); } else { span_lint_and_note( @@ -98,7 +98,7 @@ pub(super) fn check<'tcx>( span, "right-hand side of `&&` operator has no effect", Some(and_op.span.to(right_cond.span)), - &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"), + format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"), ); } // We could autofix this error but choose not to, @@ -124,7 +124,7 @@ pub(super) fn check<'tcx>( span, "boolean expression will never evaluate to 'true'", None, - ¬e, + note, ); }; } diff --git a/clippy_lints/src/operators/duration_subsec.rs b/clippy_lints/src/operators/duration_subsec.rs index f120be13836..ca3112ce5c4 100644 --- a/clippy_lints/src/operators/duration_subsec.rs +++ b/clippy_lints/src/operators/duration_subsec.rs @@ -31,7 +31,7 @@ pub(crate) fn check<'tcx>( cx, DURATION_SUBSEC, expr.span, - &format!("calling `{suggested_fn}()` is more concise than this calculation"), + format!("calling `{suggested_fn}()` is more concise than this calculation"), "try", format!( "{}.{suggested_fn}()", diff --git a/clippy_lints/src/operators/eq_op.rs b/clippy_lints/src/operators/eq_op.rs index 01dd418c38b..1421893274f 100644 --- a/clippy_lints/src/operators/eq_op.rs +++ b/clippy_lints/src/operators/eq_op.rs @@ -24,7 +24,7 @@ pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { cx, EQ_OP, lhs.span.to(rhs.span), - &format!("identical args used in this `{macro_name}!` macro call"), + format!("identical args used in this `{macro_name}!` macro call"), ); } } @@ -41,7 +41,7 @@ pub(crate) fn check<'tcx>( cx, EQ_OP, e.span, - &format!("equal expressions as operands to `{}`", op.as_str()), + format!("equal expressions as operands to `{}`", op.as_str()), |diag| { if let BinOpKind::Ne = op && cx.typeck_results().expr_ty(left).is_floating_point() diff --git a/clippy_lints/src/operators/modulo_arithmetic.rs b/clippy_lints/src/operators/modulo_arithmetic.rs index 2a933a11e12..c56518ac72a 100644 --- a/clippy_lints/src/operators/modulo_arithmetic.rs +++ b/clippy_lints/src/operators/modulo_arithmetic.rs @@ -113,7 +113,7 @@ fn check_const_operands<'tcx>( cx, MODULO_ARITHMETIC, expr.span, - &format!( + format!( "you are using modulo operator on constants with different signs: `{} % {}`", lhs_operand.string_representation.as_ref().unwrap(), rhs_operand.string_representation.as_ref().unwrap() diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs index a69989e400b..607930561e0 100644 --- a/clippy_lints/src/operators/ptr_eq.rs +++ b/clippy_lints/src/operators/ptr_eq.rs @@ -30,7 +30,7 @@ pub(super) fn check<'tcx>( cx, PTR_EQ, expr.span, - &format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), + format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), "try", format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"), Applicability::MachineApplicable, diff --git a/clippy_lints/src/operators/self_assignment.rs b/clippy_lints/src/operators/self_assignment.rs index 7c9d5320a3a..a932378fbb5 100644 --- a/clippy_lints/src/operators/self_assignment.rs +++ b/clippy_lints/src/operators/self_assignment.rs @@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, lhs: &'tcx cx, SELF_ASSIGNMENT, e.span, - &format!("self-assignment of `{rhs}` to `{lhs}`"), + format!("self-assignment of `{rhs}` to `{lhs}`"), ); } } diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 556c493d36c..3cbd03a58c5 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -304,7 +304,7 @@ impl<'tcx> LateLintPass<'tcx> for OptionIfLetElse { cx, OPTION_IF_LET_ELSE, expr.span, - format!("use Option::{} instead of an if let/else", det.method_sugg).as_str(), + format!("use Option::{} instead of an if let/else", det.method_sugg), "try", format!( "{}.{}({}, {})", diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index ec03ab0e41a..bb4a1de9f77 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -206,7 +206,7 @@ impl<'tcx> PassByRefOrValue { cx, TRIVIALLY_COPY_PASS_BY_REF, input.span, - &format!( + format!( "this argument ({size} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", self.ref_min_size ), @@ -236,7 +236,7 @@ impl<'tcx> PassByRefOrValue { cx, LARGE_TYPES_PASSED_BY_VALUE, input.span, - &format!( + format!( "this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", self.value_max_size ), diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index fbca4329342..582b9de43ae 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -138,7 +138,7 @@ fn apply_lint(cx: &LateContext<'_>, pat: &Pat<'_>, deref_possible: DerefPossible span, "type of pattern does not match the expression type", None, - &format!( + format!( "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings", match (deref_possible, level) { (DerefPossible::Possible, Level::Top) => "use `*` to dereference the match expression or ", diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 6f20b5ec150..d180d4fe327 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { ) .filter(|arg| arg.mutability() == Mutability::Not) { - span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, &arg.build_msg(), |diag| { + span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, arg.build_msg(), |diag| { diag.span_suggestion( arg.span, "change this to", @@ -237,7 +237,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { let results = check_ptr_arg_usage(cx, body, &lint_args); for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) { - span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, &args.build_msg(), |diag| { + span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, args.build_msg(), |diag| { diag.multipart_suggestion( "change this to", iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx)))) diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index ff8ec2ad57c..7c82895d609 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -64,13 +64,13 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast { cx, PTR_OFFSET_WITH_CAST, expr.span, - &msg, + msg, "try", sugg, Applicability::MachineApplicable, ); } else { - span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); + span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, msg); } } } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 6b54258dd61..186e548d373 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -242,7 +242,7 @@ fn check_possible_range_contains( cx, MANUAL_RANGE_CONTAINS, span, - &format!("manual `{range_type}::contains` implementation"), + format!("manual `{range_type}::contains` implementation"), "use", format!("({lo}{space}{range_op}{hi}).contains(&{name})"), applicability, @@ -272,7 +272,7 @@ fn check_possible_range_contains( cx, MANUAL_RANGE_CONTAINS, span, - &format!("manual `!{range_type}::contains` implementation"), + format!("manual `!{range_type}::contains` implementation"), "use", format!("!({lo}{space}{range_op}{hi}).contains(&{name})"), applicability, diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs index 6528a7b369f..8bc5d081a20 100644 --- a/clippy_lints/src/redundant_locals.rs +++ b/clippy_lints/src/redundant_locals.rs @@ -77,9 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { cx, REDUNDANT_LOCALS, local.span, - &format!("redundant redefinition of a binding `{ident}`"), + format!("redundant redefinition of a binding `{ident}`"), Some(binding_pat.span), - &format!("`{ident}` is initially defined here"), + format!("`{ident}` is initially defined here"), ); } } diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs index 0e43e4a7ee5..1b557730eca 100644 --- a/clippy_lints/src/redundant_pub_crate.rs +++ b/clippy_lints/src/redundant_pub_crate.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { cx, REDUNDANT_PUB_CRATE, span, - &format!("pub(crate) {descr} inside private module"), + format!("pub(crate) {descr} inside private module"), |diag| { diag.span_suggestion( item.vis_span, diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 07b604f2326..136e7db83bd 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -48,7 +48,7 @@ impl_lint_pass!(RedundantStaticLifetimes => [REDUNDANT_STATIC_LIFETIMES]); impl RedundantStaticLifetimes { // Recursively visit types - fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &str) { + fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &'static str) { match ty.kind { // Be careful of nested structures (arrays and tuples) TyKind::Array(ref ty, _) | TyKind::Slice(ref ty) => { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 687bad35a36..e925ec0271c 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -134,13 +134,13 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape vec![convert_span(primary)] }; - span_lint(cx, INVALID_REGEX, spans, &format!("regex syntax error: {kind}")); + span_lint(cx, INVALID_REGEX, spans, format!("regex syntax error: {kind}")); } else { span_lint_and_help( cx, INVALID_REGEX, base, - &error.to_string(), + error.to_string(), None, "consider using a raw string literal: `r\"..\"`", ); @@ -223,7 +223,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl); } }, - Err(e) => span_lint(cx, INVALID_REGEX, expr.span, &e.to_string()), + Err(e) => span_lint(cx, INVALID_REGEX, expr.span, e.to_string()), } } } diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs index fcb79f6d694..a358881bf80 100644 --- a/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/clippy_lints/src/repeat_vec_with_capacity.rs @@ -55,7 +55,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s cx, REPEAT_VEC_WITH_CAPACITY, span, - &format!("repeating `Vec::with_capacity` using `{kind}`, which does not retain capacity"), + format!("repeating `Vec::with_capacity` using `{kind}`, which does not retain capacity"), |diag| { diag.note(note); diag.span_suggestion_verbose(span, sugg_msg, sugg, Applicability::MaybeIncorrect); diff --git a/clippy_lints/src/self_named_constructors.rs b/clippy_lints/src/self_named_constructors.rs index 85a2b1a6735..23b47606f8a 100644 --- a/clippy_lints/src/self_named_constructors.rs +++ b/clippy_lints/src/self_named_constructors.rs @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { cx, SELF_NAMED_CONSTRUCTORS, impl_item.span, - &format!("constructor `{}` has the same name as the type", impl_item.ident.name), + format!("constructor `{}` has the same name as the type", impl_item.ident.name), ); } } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c74364d89d6..0fb7666dd9c 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -194,7 +194,7 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) cx, lint, span, - &msg, + msg, Some(cx.tcx.hir().span(shadowed)), "previous binding is here", ); diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs index 95b4a11a783..0a9a3c6307a 100644 --- a/clippy_lints/src/single_range_in_vec_init.rs +++ b/clippy_lints/src/single_range_in_vec_init.rs @@ -122,7 +122,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit { cx, SINGLE_RANGE_IN_VEC_INIT, span, - &format!("{suggested_type} of `Range` that is only one element"), + format!("{suggested_type} of `Range` that is only one element"), |diag| { if should_emit_every_value { diag.span_suggestion( diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index ff8e8fe7021..8a9f02b6dcb 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -196,7 +196,7 @@ impl SlowVectorInit { }; } - fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &str) { + fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &'static str) { let len_expr = Sugg::hir( cx, match vec_alloc.size_expr { diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index cf839941123..926c56332cc 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -128,8 +128,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { cx, lint, first_segment.ident.span, - &format!("used import from `{used_mod}` instead of `{replace_with}`"), - &format!("consider importing the item from `{replace_with}`"), + format!("used import from `{used_mod}` instead of `{replace_with}`"), + format!("consider importing the item from `{replace_with}`"), replace_with.to_string(), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 13ae1ff52dd..b3c729dacdd 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -495,8 +495,8 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { cx, TRIM_SPLIT_WHITESPACE, trim_span.with_hi(split_ws_span.lo()), - &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), - &format!("remove `{trim_fn_name}()`"), + format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), + format!("remove `{trim_fn_name}()`"), String::new(), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 8eab3f5874e..3f030b80331 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { cx, lint, binop.span, - &format!( + format!( "suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index be590aede15..78c99e0c0a3 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -103,7 +103,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa cx, MANUAL_SWAP, span, - &format!("this looks like you are swapping elements of `{slice}` manually"), + format!("this looks like you are swapping elements of `{slice}` manually"), "try", format!( "{}.swap({}, {});", @@ -126,7 +126,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa cx, MANUAL_SWAP, span, - &format!("this looks like you are swapping `{first}` and `{second}` manually"), + format!("this looks like you are swapping `{first}` and `{second}` manually"), |diag| { diag.span_suggestion( span, @@ -201,7 +201,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { cx, ALMOST_SWAPPED, span, - &format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"), + format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"), |diag| { diag.span_suggestion( span, diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs index cbdf31c9336..462084e96a8 100644 --- a/clippy_lints/src/trailing_empty_array.rs +++ b/clippy_lints/src/trailing_empty_array.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { item.span, "trailing zero-sized array in a struct which is not marked with a `repr` attribute", None, - &format!( + format!( "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute", cx.tcx.def_path_str(item.owner_id) ), diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 768623b5d03..9468d367a92 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -293,7 +293,7 @@ impl TraitBounds { p.span, "this type has already been used as a bound predicate", None, - &hint_string, + hint_string, ); } } @@ -420,7 +420,11 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef { ) } -fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -> Vec<(ComparableTraitRef, Span)> { +fn rollup_traits( + cx: &LateContext<'_>, + bounds: &[GenericBound<'_>], + msg: &'static str, +) -> Vec<(ComparableTraitRef, Span)> { let mut map = FxHashMap::default(); let mut repeated_res = false; diff --git a/clippy_lints/src/transmute/crosspointer_transmute.rs b/clippy_lints/src/transmute/crosspointer_transmute.rs index c4b9d82fc73..72f1529eb00 100644 --- a/clippy_lints/src/transmute/crosspointer_transmute.rs +++ b/clippy_lints/src/transmute/crosspointer_transmute.rs @@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty cx, CROSSPOINTER_TRANSMUTE, e.span, - &format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"), + format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"), ); true }, @@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty cx, CROSSPOINTER_TRANSMUTE, e.span, - &format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"), + format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"), ); true }, diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index aef520923e4..ab3bb5e1062 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_FLOAT_TO_INT, e.span, - &format!("transmute from a `{from_ty}` to a `{to_ty}`"), + format!("transmute from a `{from_ty}` to a `{to_ty}`"), |diag| { let mut sugg = sugg::Sugg::hir(cx, arg, ".."); diff --git a/clippy_lints/src/transmute/transmute_int_to_bool.rs b/clippy_lints/src/transmute/transmute_int_to_bool.rs index 58227c53de2..a7192809077 100644 --- a/clippy_lints/src/transmute/transmute_int_to_bool.rs +++ b/clippy_lints/src/transmute/transmute_int_to_bool.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_INT_TO_BOOL, e.span, - &format!("transmute from a `{from_ty}` to a `bool`"), + format!("transmute from a `{from_ty}` to a `bool`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); let zero = sugg::Sugg::NonParen(Cow::from("0")); diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs index 2a6c2481254..81d10a7d5bd 100644 --- a/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_INT_TO_CHAR, e.span, - &format!("transmute from a `{from_ty}` to a `char`"), + format!("transmute from a `{from_ty}` to a `char`"), |diag| { let Some(top_crate) = std_or_core(cx) else { return }; let arg = sugg::Sugg::hir(cx, arg, ".."); diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs index cc3422edbbf..d51888e3097 100644 --- a/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -22,7 +22,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_INT_TO_FLOAT, e.span, - &format!("transmute from a `{from_ty}` to a `{to_ty}`"), + format!("transmute from a `{from_ty}` to a `{to_ty}`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); let arg = if let ty::Int(int_ty) = from_ty.kind() { diff --git a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs index 97068efd43c..234021f0f47 100644 --- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs +++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs @@ -58,7 +58,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_INT_TO_NON_ZERO, e.span, - &format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"), + format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); diag.span_suggestion( diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs index 009d5a7c8ae..88b0ac5a368 100644 --- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_NUM_TO_BYTES, e.span, - &format!("transmute from a `{from_ty}` to a `{to_ty}`"), + format!("transmute from a `{from_ty}` to a `{to_ty}`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); diag.span_suggestion( diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 4ab3afbe714..65d89c1fe43 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_PTR_TO_REF, e.span, - &format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"), + format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); let (deref, cast) = if *mutbl == Mutability::Mut { diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 6c885ebdea1..5de2d7fc2e5 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -35,7 +35,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_BYTES_TO_STR, e.span, - &format!("transmute from a `{from_ty}` to a `{to_ty}`"), + format!("transmute from a `{from_ty}` to a `{to_ty}`"), "consider using", if const_context { format!("{top_crate}::str::from_utf8_unchecked{postfix}({snippet})") diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index a6f03c85b4f..275cab2af9b 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -71,7 +71,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_UNDEFINED_REPR, e.span, - &format!("transmute from `{from_ty_orig}` which has an undefined layout"), + format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty.peel_refs() { diag.note(format!("the contained type `{from_ty}` has an undefined layout")); @@ -85,7 +85,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_UNDEFINED_REPR, e.span, - &format!("transmute to `{to_ty_orig}` which has an undefined layout"), + format!("transmute to `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty.peel_refs() { diag.note(format!("the contained type `{to_ty}` has an undefined layout")); @@ -111,7 +111,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_UNDEFINED_REPR, e.span, - &format!( + format!( "transmute from `{from_ty_orig}` to `{to_ty_orig}`, both of which have an undefined layout" ), |diag| { @@ -140,7 +140,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_UNDEFINED_REPR, e.span, - &format!("transmute from `{from_ty_orig}` which has an undefined layout"), + format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty { diag.note(format!("the contained type `{from_ty}` has an undefined layout")); @@ -157,7 +157,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTE_UNDEFINED_REPR, e.span, - &format!("transmute into `{to_ty_orig}` which has an undefined layout"), + format!("transmute into `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty { diag.note(format!("the contained type `{to_ty}` has an undefined layout")); diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 043c9c88601..6f5ac625e35 100644 --- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -53,7 +53,7 @@ pub(super) fn check<'tcx>( cx, TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, e.span, - &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"), + format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"), "try", sugg, app, diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs index 891fefc17a6..35e93830766 100644 --- a/clippy_lints/src/transmute/unsound_collection_transmute.rs +++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty cx, UNSOUND_COLLECTION_TRANSMUTE, e.span, - &format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"), + format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"), ); true } else { diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs index 088c8fda87a..0d5fbff0605 100644 --- a/clippy_lints/src/transmute/useless_transmute.rs +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -21,7 +21,7 @@ pub(super) fn check<'tcx>( cx, USELESS_TRANSMUTE, e.span, - &format!("transmute from a type (`{from_ty}`) to itself"), + format!("transmute from a type (`{from_ty}`) to itself"), ); true }, diff --git a/clippy_lints/src/transmute/wrong_transmute.rs b/clippy_lints/src/transmute/wrong_transmute.rs index d1965565b92..53c479b54d5 100644 --- a/clippy_lints/src/transmute/wrong_transmute.rs +++ b/clippy_lints/src/transmute/wrong_transmute.rs @@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty cx, WRONG_TRANSMUTE, e.span, - &format!("transmute from a `{from_ty}` to a pointer"), + format!("transmute from a `{from_ty}` to a pointer"), ); true }, diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs index fc3420af020..9ac73394548 100644 --- a/clippy_lints/src/types/box_collection.rs +++ b/clippy_lints/src/types/box_collection.rs @@ -21,9 +21,9 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ cx, BOX_COLLECTION, hir_ty.span, - &format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"), + format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"), None, - &format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"), + format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"), ); true } else { diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index a0d609501a0..893faafc2c0 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: cx, REDUNDANT_ALLOCATION, hir_ty.span, - &format!("usage of `{outer_sym}<{generic_snippet}>`"), + format!("usage of `{outer_sym}<{generic_snippet}>`"), |diag| { diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability); diag.note(format!( @@ -73,7 +73,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: cx, REDUNDANT_ALLOCATION, hir_ty.span, - &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), + format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), |diag| { diag.span_suggestion( hir_ty.span, @@ -92,7 +92,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: cx, REDUNDANT_ALLOCATION, hir_ty.span, - &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), + format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), |diag| { diag.note(format!( "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation" diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 1dedb4510bd..8106694c43b 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { cx, UNNECESSARY_SAFETY_COMMENT, span, - &format!("{} has unnecessary safety comment", item.kind.descr()), + format!("{} has unnecessary safety comment", item.kind.descr()), Some(help_span), "consider removing the safety comment", ); @@ -268,7 +268,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { cx, UNNECESSARY_SAFETY_COMMENT, span, - &format!("{} has unnecessary safety comment", item.kind.descr()), + format!("{} has unnecessary safety comment", item.kind.descr()), Some(help_span), "consider removing the safety comment", ); diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index 729972de6e6..214b69dc925 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd { cx, UNIT_RETURN_EXPECTING_ORD, span, - &format!( + format!( "this closure returns \ the unit type which also implements {trait_name}" ), @@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd { cx, UNIT_RETURN_EXPECTING_ORD, span, - &format!( + format!( "this closure returns \ the unit type which also implements {trait_name}" ), diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index 7fd17e332e4..afc53e6f32d 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -69,7 +69,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp cx, UNIT_ARG, expr.span, - &format!("passing {singular}unit value{plural} to a function"), + format!("passing {singular}unit value{plural} to a function"), |db| { let mut or = ""; args_to_recover diff --git a/clippy_lints/src/unit_types/unit_cmp.rs b/clippy_lints/src/unit_types/unit_cmp.rs index d4342ec5169..6dcc1195a70 100644 --- a/clippy_lints/src/unit_types/unit_cmp.rs +++ b/clippy_lints/src/unit_types/unit_cmp.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { cx, UNIT_CMP, macro_call.span, - &format!("`{macro_name}` of unit values detected. This will always {result}"), + format!("`{macro_name}` of unit values detected. This will always {result}"), ); } return; @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { cx, UNIT_CMP, expr.span, - &format!( + format!( "{}-comparison of unit values detected. This will always be {result}", op.as_str() ), diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index c332cf076ae..bfcefb26153 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -88,7 +88,7 @@ impl UnnecessaryBoxReturns { cx, UNNECESSARY_BOX_RETURNS, return_ty_hir.span, - format!("boxed return of the sized type `{boxed_ty}`").as_str(), + format!("boxed return of the sized type `{boxed_ty}`"), |diagnostic| { diagnostic.span_suggestion( return_ty_hir.span, diff --git a/clippy_lints/src/unnecessary_map_on_constructor.rs b/clippy_lints/src/unnecessary_map_on_constructor.rs index 252e5e4dd7c..8f1eb5019f0 100644 --- a/clippy_lints/src/unnecessary_map_on_constructor.rs +++ b/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { cx, UNNECESSARY_MAP_ON_CONSTRUCTOR, expr.span, - &format!( + format!( "unnecessary {} on constructor {constructor_snippet}(_)", path.ident.name ), diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index 9c8b0ae1727..5c7fbbab988 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { ) }; - span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| { + span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg, |diag| { diag.span_suggestion( fn_decl.output.span(), return_type_sugg_msg, diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 3f2f765f751..51b3ea93b6d 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -65,7 +65,7 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, cx, UNSAFE_REMOVED_FROM_NAME, span, - &format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"), + format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"), ); } } diff --git a/clippy_lints/src/unused_rounding.rs b/clippy_lints/src/unused_rounding.rs index d5ca844b9e2..3e5afec541c 100644 --- a/clippy_lints/src/unused_rounding.rs +++ b/clippy_lints/src/unused_rounding.rs @@ -55,8 +55,8 @@ impl EarlyLintPass for UnusedRounding { cx, UNUSED_ROUNDING, expr.span, - &format!("used the `{method_name}` method with a whole number float"), - &format!("remove the `{method_name}` method call"), + format!("used the `{method_name}` method with a whole number float"), + format!("remove the `{method_name}` method call"), float, Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f2eb774b5cb..2622abd59cb 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { UNNECESSARY_UNWRAP, expr.hir_id, expr.span, - &format!( + format!( "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`", method_name.ident.name, unwrappable.check_name.ident.as_str(), @@ -373,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { PANICKING_UNWRAP, expr.hir_id, expr.span, - &format!("this call to `{}()` will always panic", method_name.ident.name), + format!("this call to `{}()` will always panic", method_name.ident.name), |diag| { diag.span_label(unwrappable.check.span, "because of this check"); }, diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs index d2a1d42f279..f376d349646 100644 --- a/clippy_lints/src/upper_case_acronyms.rs +++ b/clippy_lints/src/upper_case_acronyms.rs @@ -94,7 +94,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive UPPER_CASE_ACRONYMS, hir_id, span, - &format!("name `{ident}` contains a capitalized acronym"), + format!("name `{ident}` contains a capitalized acronym"), |diag| { diag.span_suggestion( span, diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index f7a455977fa..75541766156 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - &format!("useless conversion to the same type: `{b}`"), + format!("useless conversion to the same type: `{b}`"), "consider removing `.into()`", sugg.into_owned(), app, @@ -301,7 +301,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - &format!("useless conversion to the same type: `{b}`"), + format!("useless conversion to the same type: `{b}`"), "consider removing `.into_iter()`", sugg, Applicability::MachineApplicable, // snippet @@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - &format!("useless conversion to the same type: `{b}`"), + format!("useless conversion to the same type: `{b}`"), None, "consider removing `.try_into()`", ); @@ -346,9 +346,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - &format!("useless conversion to the same type: `{b}`"), + format!("useless conversion to the same type: `{b}`"), None, - &hint, + hint, ); } @@ -360,8 +360,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - &format!("useless conversion to the same type: `{b}`"), - &sugg_msg, + format!("useless conversion to the same type: `{b}`"), + sugg_msg, sugg.to_string(), app, ); diff --git a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs index 4822970e47e..5483e80f932 100644 --- a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs +++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation { ident.span, "non-standard lint formulation", None, - &format!("consider using `{}`", formulation.correction), + format!("consider using `{}`", formulation.correction), ); } return; diff --git a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs index df37619227c..9b6b6871818 100644 --- a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs +++ b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { path.ident.span, "usage of a compiler lint function", None, - &format!("please use the Clippy variant of this function: `{sugg}`"), + format!("please use the Clippy variant of this function: `{sugg}`"), ); } } diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 370ed430bcf..9be225759df 100644 --- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -181,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { cx, DEFAULT_LINT, item.span, - &format!("the lint `{}` has the default lint description", item.ident.name), + format!("the lint `{}` has the default lint description", item.ident.name), ); } @@ -191,7 +191,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { cx, DEFAULT_DEPRECATION_REASON, item.span, - &format!("the lint `{}` has the default deprecation reason", item.ident.name), + format!("the lint `{}` has the default deprecation reason", item.ident.name), ); } } @@ -247,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { cx, LINT_WITHOUT_LINT_PASS, lint_span, - &format!("the lint `{lint_name}` is not added to any `LintPass`"), + format!("the lint `{lint_name}` is not added to any `LintPass`"), ); } } diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index d6a541a1eff..5fb80059e03 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -822,7 +822,7 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s cx, METADATA_COLLECTOR, item.ident.span, - &format!("metadata collection error for `{}`: {message}", item.ident.name), + format!("metadata collection error for `{}`: {message}", item.ident.name), ); } 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 6d5240db832..777fe544b24 100644 --- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -51,8 +51,8 @@ impl LateLintPass<'_> for MsrvAttrImpl { cx, MISSING_MSRV_ATTR_IMPL, span, - &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"), - &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"), + format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"), + format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"), format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 5fb643854dc..2fa55c5ff52 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -78,9 +78,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath { cx, UNNECESSARY_DEF_PATH, span, - &format!("hardcoded path to a {msg}"), + format!("hardcoded path to a {msg}"), None, - &format!("convert all references to use `{sugg}`"), + format!("convert all references to use `{sugg}`"), ); } } diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs index 83369c66367..9818b98dd5b 100644 --- a/clippy_lints/src/visibility.rs +++ b/clippy_lints/src/visibility.rs @@ -89,7 +89,7 @@ impl EarlyLintPass for Visibility { cx, NEEDLESS_PUB_SELF, item.vis.span, - &format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }), + format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }), "remove it", String::new(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index be16d2e5cc3..26c6859233d 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -297,11 +297,11 @@ impl<'tcx> LateLintPass<'tcx> for Write { match diag_name { sym::print_macro | sym::println_macro if !allowed_in_tests => { if !is_build_script { - span_lint(cx, PRINT_STDOUT, macro_call.span, &format!("use of `{name}!`")); + span_lint(cx, PRINT_STDOUT, macro_call.span, format!("use of `{name}!`")); } }, sym::eprint_macro | sym::eprintln_macro if !allowed_in_tests => { - span_lint(cx, PRINT_STDERR, macro_call.span, &format!("use of `{name}!`")); + span_lint(cx, PRINT_STDERR, macro_call.span, format!("use of `{name}!`")); }, sym::write_macro | sym::writeln_macro => {}, _ => return, @@ -390,7 +390,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma cx, lint, macro_call.span, - &format!("using `{name}!()` with a format string that ends in a single newline"), + format!("using `{name}!()` with a format string that ends in a single newline"), |diag| { let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!'); let Some(format_snippet) = snippet_opt(cx, format_string_span) else { @@ -440,7 +440,7 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call cx, lint, macro_call.span, - &format!("empty string literal in `{name}!`"), + format!("empty string literal in `{name}!`"), |diag| { diag.span_suggestion( span, diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index d3623d6fda4..662242f6196 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { expr.span, "constant division of `0.0` with `0.0` will always result in NaN", None, - &format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",), + format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",), ); } } From 24d20b4eae2646e79a7aba6a691ef39127431882 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Mon, 1 Apr 2024 17:05:55 +0200 Subject: [PATCH 71/79] Set `RUSTC_ICE=0` in uitests and `cargo dev lint` --- clippy_dev/src/lint.rs | 4 ++++ tests/compile-test.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs index 906a9727810..f308f5dfdfd 100644 --- a/clippy_dev/src/lint.rs +++ b/clippy_dev/src/lint.rs @@ -20,6 +20,8 @@ pub fn run<'a>(path: &str, args: impl Iterator) { .args(["--edition", "2021"]) .arg(path) .args(args) + // Prevent rustc from creating `rustc-ice-*` files the console output is enough. + .env("RUSTC_ICE", "0") .status(), ); } else { @@ -32,6 +34,8 @@ pub fn run<'a>(path: &str, args: impl Iterator) { let status = Command::new(cargo_clippy_path()) .arg("clippy") .args(args) + // Prevent rustc from creating `rustc-ice-*` files the console output is enough. + .env("RUSTC_ICE", "0") .current_dir(path) .status(); diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a0c8bf9334c..32a31f5e082 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -146,6 +146,8 @@ fn base_config(test_dir: &str) -> (Config, Args) { ); config.program.args.extend(EXTERN_FLAGS.iter().map(OsString::from)); + // Prevent rustc from creating `rustc-ice-*` files the console output is enough. + config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); if let Some(host_libs) = option_env!("HOST_LIBS") { let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); From b456ed31e474c65bfc8f80c71dd0762b6a434857 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Tue, 2 Apr 2024 01:27:17 +0800 Subject: [PATCH 72/79] fix suggestion for [`len_zero`] with macros --- clippy_lints/src/len_zero.rs | 24 ++++++++++++++++++++--- tests/ui/len_zero.fixed | 37 ++++++++++++++++++++++++++++++++++++ tests/ui/len_zero.rs | 37 ++++++++++++++++++++++++++++++++++++ tests/ui/len_zero.stderr | 20 ++++++++++++++++++- 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index ef52121ce3e..5aa4e99121e 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::snippet_with_context; -use clippy_utils::sugg::Sugg; +use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::sugg::{has_enclosing_paren, Sugg}; use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -192,7 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind { // expr.span might contains parenthesis, see issue #10529 - let actual_span = left.span.with_hi(right.span.hi()); + let actual_span = span_without_enclosing_paren(cx, expr.span); match cmp { BinOpKind::Eq => { check_cmp(cx, actual_span, left, right, "", 0); // len == 0 @@ -218,6 +218,20 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } } +fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span { + let Some(snippet) = snippet_opt(cx, span) else { + return span; + }; + if has_enclosing_paren(snippet) { + let source_map = cx.tcx.sess.source_map(); + let left_paren = source_map.start_point(span); + let right_parent = source_map.end_point(span); + left_paren.between(right_parent) + } else { + span + } +} + fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool { item.ident.name == name @@ -495,6 +509,10 @@ fn check_for_is_empty( } fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { + if method.span.from_expansion() { + return; + } + if let (&ExprKind::MethodCall(method_path, receiver, args, _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index c16d7a26616..27319d9c20e 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -189,3 +189,40 @@ fn main() { fn test_slice(b: &[u8]) { if !b.is_empty() {} } + +// issue #11992 +fn binop_with_macros() { + macro_rules! len { + ($seq:ident) => { + $seq.len() + }; + } + + macro_rules! compare_to { + ($val:literal) => { + $val + }; + ($val:expr) => {{ $val }}; + } + + macro_rules! zero { + () => { + 0 + }; + } + + let has_is_empty = HasIsEmpty; + // Don't lint, suggesting changes might break macro compatibility. + (len!(has_is_empty) > 0).then(|| println!("This can happen.")); + // Don't lint, suggesting changes might break macro compatibility. + if len!(has_is_empty) == 0 {} + // Don't lint + if has_is_empty.len() == compare_to!(if true { 0 } else { 1 }) {} + // This is fine + if has_is_empty.len() == compare_to!(1) {} + + if has_is_empty.is_empty() {} + if has_is_empty.is_empty() {} + + (!has_is_empty.is_empty()).then(|| println!("This can happen.")); +} diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 5c49a5abf81..03c05bc6ed7 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -189,3 +189,40 @@ fn main() { fn test_slice(b: &[u8]) { if b.len() != 0 {} } + +// issue #11992 +fn binop_with_macros() { + macro_rules! len { + ($seq:ident) => { + $seq.len() + }; + } + + macro_rules! compare_to { + ($val:literal) => { + $val + }; + ($val:expr) => {{ $val }}; + } + + macro_rules! zero { + () => { + 0 + }; + } + + let has_is_empty = HasIsEmpty; + // Don't lint, suggesting changes might break macro compatibility. + (len!(has_is_empty) > 0).then(|| println!("This can happen.")); + // Don't lint, suggesting changes might break macro compatibility. + if len!(has_is_empty) == 0 {} + // Don't lint + if has_is_empty.len() == compare_to!(if true { 0 } else { 1 }) {} + // This is fine + if has_is_empty.len() == compare_to!(1) {} + + if has_is_empty.len() == compare_to!(0) {} + if has_is_empty.len() == zero!() {} + + (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen.")); +} diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index dd07a85d62c..5c849a2aca6 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -142,5 +142,23 @@ error: length comparison to zero LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()` -error: aborting due to 23 previous errors +error: length comparison to zero + --> tests/ui/len_zero.rs:224:8 + | +LL | if has_is_empty.len() == compare_to!(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + +error: length comparison to zero + --> tests/ui/len_zero.rs:225:8 + | +LL | if has_is_empty.len() == zero!() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + +error: length comparison to zero + --> tests/ui/len_zero.rs:227:6 + | +LL | (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen.")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + +error: aborting due to 26 previous errors From 989f04d0669ea04510d60f1727415c0dbed6d6b6 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:35:54 +0200 Subject: [PATCH 73/79] pause review rotation for y21 --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index d455d967e30..d8131044ff2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -19,7 +19,7 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" -users_on_vacation = [] +users_on_vacation = ["y21"] [assign.owners] "/.github" = ["@flip1995"] From e575f05a8b6895fdafd27f5fccca54b60876f318 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 2 Apr 2024 15:04:25 +0200 Subject: [PATCH 74/79] avoid an ICE in `ptr_as_ptr` when getting the def_id of a local --- clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- tests/ui/crashes/ice-12616.fixed | 7 +++++++ tests/ui/crashes/ice-12616.rs | 7 +++++++ tests/ui/crashes/ice-12616.stderr | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/ui/crashes/ice-12616.fixed create mode 100644 tests/ui/crashes/ice-12616.rs create mode 100644 tests/ui/crashes/ice-12616.stderr diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 35e36e9ef3f..16de9313685 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -62,8 +62,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { // we omit following `cast`: let omit_cast = if let ExprKind::Call(func, []) = cast_expr.kind && let ExprKind::Path(ref qpath @ QPath::Resolved(None, path)) = func.kind + && let Some(method_defid) = path.res.opt_def_id() { - let method_defid = path.res.def_id(); if cx.tcx.is_diagnostic_item(sym::ptr_null, method_defid) { OmitFollowedCastReason::Null(qpath) } else if cx.tcx.is_diagnostic_item(sym::ptr_null_mut, method_defid) { diff --git a/tests/ui/crashes/ice-12616.fixed b/tests/ui/crashes/ice-12616.fixed new file mode 100644 index 00000000000..a5a5b3d1e78 --- /dev/null +++ b/tests/ui/crashes/ice-12616.fixed @@ -0,0 +1,7 @@ +#![warn(clippy::ptr_as_ptr)] +#![allow(clippy::unnecessary_operation, clippy::unnecessary_cast)] + +fn main() { + let s = std::ptr::null::<()>; + s().cast::<()>(); +} diff --git a/tests/ui/crashes/ice-12616.rs b/tests/ui/crashes/ice-12616.rs new file mode 100644 index 00000000000..6ee9a5ec08f --- /dev/null +++ b/tests/ui/crashes/ice-12616.rs @@ -0,0 +1,7 @@ +#![warn(clippy::ptr_as_ptr)] +#![allow(clippy::unnecessary_operation, clippy::unnecessary_cast)] + +fn main() { + let s = std::ptr::null::<()>; + s() as *const (); +} diff --git a/tests/ui/crashes/ice-12616.stderr b/tests/ui/crashes/ice-12616.stderr new file mode 100644 index 00000000000..ef573f55cf3 --- /dev/null +++ b/tests/ui/crashes/ice-12616.stderr @@ -0,0 +1,19 @@ +error: `as` casting between raw pointers without changing its mutability + --> tests/ui/crashes/ice-12616.rs:6:5 + | +LL | s() as *const (); + | ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()` + | + = note: `-D clippy::ptr-as-ptr` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]` + +error: `as` casting between raw pointers without changing its mutability + --> tests/ui/crashes/ice-12616.rs:6:5 + | +LL | s() as *const (); + | ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + From 0478d26c8b32acb56df3d89cb21847974ff0f312 Mon Sep 17 00:00:00 2001 From: not-elm Date: Tue, 2 Apr 2024 22:24:17 +0900 Subject: [PATCH 75/79] FIX(12334): manual_swap auto fix Initialization expressions are now generated when index is bound to a variable. FIX: Check to see if variables are used after swap FIX: rename StmtKind::Local to StmtKind::Let --- clippy_lints/src/swap.rs | 174 +++++++++++++++++++++++++-- tests/ui/manual_swap_auto_fix.fixed | 57 +++++++++ tests/ui/manual_swap_auto_fix.rs | 72 +++++++++++ tests/ui/manual_swap_auto_fix.stderr | 88 ++++++++++++++ 4 files changed, 381 insertions(+), 10 deletions(-) create mode 100644 tests/ui/manual_swap_auto_fix.fixed create mode 100644 tests/ui/manual_swap_auto_fix.rs create mode 100644 tests/ui/manual_swap_auto_fix.stderr diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 78c99e0c0a3..422fb6dfc4d 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,8 +1,14 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::snippet_with_context; +use clippy_utils::source::{snippet_indent, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_type_diagnostic_item; + use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core}; +use itertools::Itertools; + +use rustc_hir::intravisit::{walk_expr, Visitor}; + +use crate::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -80,7 +86,17 @@ impl<'tcx> LateLintPass<'tcx> for Swap { } } -fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, span: Span, is_xor_based: bool) { +#[allow(clippy::too_many_arguments)] +fn generate_swap_warning<'tcx>( + block: &'tcx Block<'tcx>, + cx: &LateContext<'tcx>, + e1: &'tcx Expr<'tcx>, + e2: &'tcx Expr<'tcx>, + rhs1: &'tcx Expr<'tcx>, + rhs2: &'tcx Expr<'tcx>, + span: Span, + is_xor_based: bool, +) { let ctxt = span.ctxt(); let mut applicability = Applicability::MachineApplicable; @@ -99,6 +115,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa || is_type_diagnostic_item(cx, ty, sym::VecDeque) { let slice = Sugg::hir_with_applicability(cx, lhs1, "", &mut applicability); + span_lint_and_sugg( cx, MANUAL_SWAP, @@ -106,7 +123,17 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa format!("this looks like you are swapping elements of `{slice}` manually"), "try", format!( - "{}.swap({}, {});", + "{}{}.swap({}, {});", + IndexBinding { + block, + swap1_idx: idx1, + swap2_idx: idx2, + suggest_span: span, + cx, + ctxt, + applicability: &mut applicability, + } + .snippet_index_bindings(&[idx1, idx2, rhs1, rhs2]), slice.maybe_par(), snippet_with_context(cx, idx1.span, ctxt, "..", &mut applicability).0, snippet_with_context(cx, idx2.span, ctxt, "..", &mut applicability).0, @@ -142,7 +169,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa } /// Implementation of the `MANUAL_SWAP` lint. -fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { +fn check_manual_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if in_constant(cx, block.hir_id) { return; } @@ -160,10 +187,10 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { // bar() = t; && let StmtKind::Semi(second) = s3.kind && let ExprKind::Assign(lhs2, rhs2, _) = second.kind - && let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind - && rhs2.segments.len() == 1 + && let ExprKind::Path(QPath::Resolved(None, rhs2_path)) = rhs2.kind + && rhs2_path.segments.len() == 1 - && ident.name == rhs2.segments[0].ident.name + && ident.name == rhs2_path.segments[0].ident.name && eq_expr_value(cx, tmp_init, lhs1) && eq_expr_value(cx, rhs1, lhs2) @@ -174,7 +201,7 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { && second.span.ctxt() == ctxt { let span = s1.span.to(s3.span); - generate_swap_warning(cx, lhs1, lhs2, span, false); + generate_swap_warning(block, cx, lhs1, lhs2, rhs1, rhs2, span, false); } } } @@ -254,7 +281,7 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< } /// Implementation of the xor case for `MANUAL_SWAP` lint. -fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) { +fn check_xor_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { for [s1, s2, s3] in block.stmts.array_windows::<3>() { let ctxt = s1.span.ctxt(); if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt) @@ -268,7 +295,7 @@ fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) { && s3.span.ctxt() == ctxt { let span = s1.span.to(s3.span); - generate_swap_warning(cx, lhs0, rhs0, span, true); + generate_swap_warning(block, cx, lhs0, rhs0, rhs1, rhs2, span, true); }; } } @@ -294,3 +321,130 @@ fn extract_sides_of_xor_assign<'a, 'hir>( None } } + +struct IndexBinding<'a, 'tcx> { + block: &'a Block<'a>, + swap1_idx: &'a Expr<'a>, + swap2_idx: &'a Expr<'a>, + suggest_span: Span, + cx: &'a LateContext<'tcx>, + ctxt: SyntaxContext, + applicability: &'a mut Applicability, +} + +impl<'a, 'tcx> IndexBinding<'a, 'tcx> { + fn snippet_index_bindings(&mut self, exprs: &[&'tcx Expr<'tcx>]) -> String { + let mut bindings = FxHashSet::default(); + for expr in exprs { + bindings.insert(self.snippet_index_binding(expr)); + } + bindings.into_iter().join("") + } + + fn snippet_index_binding(&mut self, expr: &'tcx Expr<'tcx>) -> String { + match expr.kind { + ExprKind::Binary(_, lhs, rhs) => { + if matches!(lhs.kind, ExprKind::Lit(_)) && matches!(rhs.kind, ExprKind::Lit(_)) { + return String::new(); + } + let lhs_snippet = self.snippet_index_binding(lhs); + let rhs_snippet = self.snippet_index_binding(rhs); + format!("{lhs_snippet}{rhs_snippet}") + }, + ExprKind::Path(QPath::Resolved(_, path)) => { + let init = self.cx.expr_or_init(expr); + + let Some(first_segment) = path.segments.first() else { + return String::new(); + }; + if !self.suggest_span.contains(init.span) || !self.is_used_other_than_swapping(first_segment.ident) { + return String::new(); + } + + let init_str = snippet_with_context(self.cx, init.span, self.ctxt, "", self.applicability) + .0 + .to_string(); + let indent_str = snippet_indent(self.cx, init.span); + let indent_str = indent_str.as_deref().unwrap_or(""); + + format!("let {} = {init_str};\n{indent_str}", first_segment.ident) + }, + _ => String::new(), + } + } + + fn is_used_other_than_swapping(&mut self, idx_ident: Ident) -> bool { + if Self::is_used_slice_indexed(self.swap1_idx, idx_ident) + || Self::is_used_slice_indexed(self.swap2_idx, idx_ident) + { + return true; + } + self.is_used_after_swap(idx_ident) + } + + fn is_used_after_swap(&mut self, idx_ident: Ident) -> bool { + let mut v = IndexBindingVisitor { + found_used: false, + suggest_span: self.suggest_span, + idx: idx_ident, + }; + + for stmt in self.block.stmts { + match stmt.kind { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => v.visit_expr(expr), + StmtKind::Let(rustc_hir::Local { ref init, .. }) => { + if let Some(init) = init.as_ref() { + v.visit_expr(init); + } + }, + StmtKind::Item(_) => {}, + } + } + + v.found_used + } + + fn is_used_slice_indexed(swap_index: &Expr<'_>, idx_ident: Ident) -> bool { + match swap_index.kind { + ExprKind::Binary(_, lhs, rhs) => { + if matches!(lhs.kind, ExprKind::Lit(_)) && matches!(rhs.kind, ExprKind::Lit(_)) { + return false; + } + Self::is_used_slice_indexed(lhs, idx_ident) || Self::is_used_slice_indexed(rhs, idx_ident) + }, + ExprKind::Path(QPath::Resolved(_, path)) => { + path.segments.first().map_or(false, |idx| idx.ident == idx_ident) + }, + _ => false, + } + } +} + +struct IndexBindingVisitor { + idx: Ident, + suggest_span: Span, + found_used: bool, +} + +impl<'tcx> Visitor<'tcx> for IndexBindingVisitor { + fn visit_path_segment(&mut self, path_segment: &'tcx rustc_hir::PathSegment<'tcx>) -> Self::Result { + if path_segment.ident == self.idx { + self.found_used = true; + } + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result { + if expr.span.hi() <= self.suggest_span.hi() { + return; + } + + match expr.kind { + ExprKind::Path(QPath::Resolved(_, path)) => { + for segment in path.segments { + self.visit_path_segment(segment); + } + }, + _ => walk_expr(self, expr), + } + } +} diff --git a/tests/ui/manual_swap_auto_fix.fixed b/tests/ui/manual_swap_auto_fix.fixed new file mode 100644 index 00000000000..28466ff3f9b --- /dev/null +++ b/tests/ui/manual_swap_auto_fix.fixed @@ -0,0 +1,57 @@ +#![warn(clippy::manual_swap)] +#![no_main] + +fn swap1() { + let mut v = [3, 2, 1, 0]; + let index = v[0]; + v.swap(0, index); +} + +fn swap2() { + let mut v = [3, 2, 1, 0]; + let tmp = v[0]; + v.swap(0, 1); + // check not found in this scope. + let _ = tmp; +} + +fn swap3() { + let mut v = [3, 2]; + let i1 = 0; + let i2 = 1; + v.swap(i1, i2); +} + +fn swap4() { + let mut v = [3, 2, 1]; + let i1 = 0; + let i2 = 1; + v.swap(i1, i2 + 1); +} + +fn swap5() { + let mut v = [0, 1, 2, 3]; + let i1 = 0; + let i2 = 1; + v.swap(i1, i2 + 1); +} + +fn swap6() { + let mut v = [0, 1, 2, 3]; + let index = v[0]; + v.swap(0, index + 1); +} + +fn swap7() { + let mut v = [0, 1, 2, 3]; + let i1 = 0; + let i2 = 6; + v.swap(i1 * 3, i2 / 2); +} + +fn swap8() { + let mut v = [1, 2, 3, 4]; + let i1 = 1; + let i2 = 1; + v.swap(i1 + i2, i2); +} diff --git a/tests/ui/manual_swap_auto_fix.rs b/tests/ui/manual_swap_auto_fix.rs new file mode 100644 index 00000000000..702a9e67d3d --- /dev/null +++ b/tests/ui/manual_swap_auto_fix.rs @@ -0,0 +1,72 @@ +#![warn(clippy::manual_swap)] +#![no_main] + +fn swap1() { + let mut v = [3, 2, 1, 0]; + let index = v[0]; + //~^ ERROR: this looks like you are swapping elements of `v` manually + v[0] = v[index]; + v[index] = index; +} + +fn swap2() { + let mut v = [3, 2, 1, 0]; + let tmp = v[0]; + v[0] = v[1]; + v[1] = tmp; + // check not found in this scope. + let _ = tmp; +} + +fn swap3() { + let mut v = [3, 2]; + let i1 = 0; + let i2 = 1; + let temp = v[i1]; + v[i1] = v[i2]; + v[i2] = temp; +} + +fn swap4() { + let mut v = [3, 2, 1]; + let i1 = 0; + let i2 = 1; + let temp = v[i1]; + v[i1] = v[i2 + 1]; + v[i2 + 1] = temp; +} + +fn swap5() { + let mut v = [0, 1, 2, 3]; + let i1 = 0; + let i2 = 1; + let temp = v[i1]; + v[i1] = v[i2 + 1]; + v[i2 + 1] = temp; +} + +fn swap6() { + let mut v = [0, 1, 2, 3]; + let index = v[0]; + //~^ ERROR: this looks like you are swapping elements of `v` manually + v[0] = v[index + 1]; + v[index + 1] = index; +} + +fn swap7() { + let mut v = [0, 1, 2, 3]; + let i1 = 0; + let i2 = 6; + let tmp = v[i1 * 3]; + v[i1 * 3] = v[i2 / 2]; + v[i2 / 2] = tmp; +} + +fn swap8() { + let mut v = [1, 2, 3, 4]; + let i1 = 1; + let i2 = 1; + let tmp = v[i1 + i2]; + v[i1 + i2] = v[i2]; + v[i2] = tmp; +} diff --git a/tests/ui/manual_swap_auto_fix.stderr b/tests/ui/manual_swap_auto_fix.stderr new file mode 100644 index 00000000000..eecfcd3977b --- /dev/null +++ b/tests/ui/manual_swap_auto_fix.stderr @@ -0,0 +1,88 @@ +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:6:5 + | +LL | / let index = v[0]; +LL | | +LL | | v[0] = v[index]; +LL | | v[index] = index; + | |_____________________^ + | + = note: `-D clippy::manual-swap` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_swap)]` +help: try + | +LL ~ let index = v[0]; +LL + v.swap(0, index); + | + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:14:5 + | +LL | / let tmp = v[0]; +LL | | v[0] = v[1]; +LL | | v[1] = tmp; + | |_______________^ + | +help: try + | +LL ~ let tmp = v[0]; +LL + v.swap(0, 1); + | + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:25:5 + | +LL | / let temp = v[i1]; +LL | | v[i1] = v[i2]; +LL | | v[i2] = temp; + | |_________________^ help: try: `v.swap(i1, i2);` + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:34:5 + | +LL | / let temp = v[i1]; +LL | | v[i1] = v[i2 + 1]; +LL | | v[i2 + 1] = temp; + | |_____________________^ help: try: `v.swap(i1, i2 + 1);` + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:43:5 + | +LL | / let temp = v[i1]; +LL | | v[i1] = v[i2 + 1]; +LL | | v[i2 + 1] = temp; + | |_____________________^ help: try: `v.swap(i1, i2 + 1);` + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:50:5 + | +LL | / let index = v[0]; +LL | | +LL | | v[0] = v[index + 1]; +LL | | v[index + 1] = index; + | |_________________________^ + | +help: try + | +LL ~ let index = v[0]; +LL + v.swap(0, index + 1); + | + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:60:5 + | +LL | / let tmp = v[i1 * 3]; +LL | | v[i1 * 3] = v[i2 / 2]; +LL | | v[i2 / 2] = tmp; + | |____________________^ help: try: `v.swap(i1 * 3, i2 / 2);` + +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:69:5 + | +LL | / let tmp = v[i1 + i2]; +LL | | v[i1 + i2] = v[i2]; +LL | | v[i2] = tmp; + | |________________^ help: try: `v.swap(i1 + i2, i2);` + +error: aborting due to 8 previous errors + From 53e31dc45cecb671c664dd13685cfa9dc832b336 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 3 Apr 2024 15:17:00 +0200 Subject: [PATCH 76/79] rename `expose_addr` to `expose_provenance` --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 12b08005997..325c9bee057 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -149,7 +149,7 @@ fn check_rvalue<'tcx>( Err((span, "unsizing casts are not allowed in const fn".into())) } }, - Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { + Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => { Err((span, "casting pointers to ints is unstable in const fn".into())) }, Rvalue::Cast(CastKind::DynStar, _, _) => { From b6486fae5c9ce3610aa325a3c86d23871e05c1e8 Mon Sep 17 00:00:00 2001 From: Francisco Salgueiro Date: Wed, 3 Apr 2024 17:07:12 +0100 Subject: [PATCH 77/79] add missing links in development guide --- book/src/development/defining_lints.md | 9 ++++----- book/src/development/lint_passes.md | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/book/src/development/defining_lints.md b/book/src/development/defining_lints.md index 54f77b00190..806ed0845f0 100644 --- a/book/src/development/defining_lints.md +++ b/book/src/development/defining_lints.md @@ -62,9 +62,8 @@ $ cargo dev new_lint --name=lint_name --pass=late --category=pedantic There are two things to note here: 1. `--pass`: We set `--pass=late` in this command to do a late lint pass. The - alternative is an `early` lint pass. We will discuss this difference in a - later chapter. - + alternative is an `early` lint pass. We will discuss this difference in the + [Lint Passes] chapter. 2. `--category`: If not provided, the `category` of this new lint will default to `nursery`. @@ -194,8 +193,7 @@ store.register_late_pass(|_| Box::new(foo_functions::FooFunctions)); As you might have guessed, where there's something late, there is something early: in Clippy there is a `register_early_pass` method as well. More on early -vs. late passes in a later chapter. - +vs. late passes in the [Lint Passes] chapter. Without a call to one of `register_early_pass` or `register_late_pass`, the lint pass in question will not be run. @@ -203,3 +201,4 @@ pass in question will not be run. [all_lints]: https://rust-lang.github.io/rust-clippy/master/ [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints +[Lint Passes]: lint_passes.md diff --git a/book/src/development/lint_passes.md b/book/src/development/lint_passes.md index 621fc20972e..dde9e1a273b 100644 --- a/book/src/development/lint_passes.md +++ b/book/src/development/lint_passes.md @@ -50,7 +50,7 @@ questions already, but the parser is okay with it. This is what we mean when we say `EarlyLintPass` deals with only syntax on the AST level. Alternatively, think of the `foo_functions` lint we mentioned in -define new lints chapter. +the [Define New Lints](defining_lints.md) chapter. We want the `foo_functions` lint to detect functions with `foo` as their name. Writing a lint that only checks for the name of a function means that we only From 571118f4b018aad8b15e8f80aa905f0209a27aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 2 Apr 2024 10:41:58 +0200 Subject: [PATCH 78/79] Do not suggest `assigning_clones` in `Clone` impl --- clippy_lints/src/assigning_clones.rs | 17 +++++++++++++++++ tests/ui/assigning_clones.fixed | 13 +++++++++++++ tests/ui/assigning_clones.rs | 13 +++++++++++++ tests/ui/assigning_clones.stderr | 12 ++++++------ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index d7d2dbee433..e1e7d406cd0 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -181,6 +181,23 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC return false; } + // If the call expression is inside an impl block that contains the method invoked by the + // call expression, we bail out to avoid suggesting something that could result in endless + // recursion. + if let Some(local_block_id) = impl_block.as_local() + && let Some(block) = cx.tcx.hir_node_by_def_id(local_block_id).as_owner() + { + let impl_block_owner = block.def_id(); + if cx + .tcx + .hir() + .parent_id_iter(lhs.hir_id) + .any(|parent| parent.owner == impl_block_owner) + { + return false; + } + } + // Find the function for which we want to check that it is implemented. let provided_fn = match call.target { TargetTrait::Clone => cx.tcx.get_diagnostic_item(sym::Clone).and_then(|clone| { diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed index 160f3b94663..8387c7d6156 100644 --- a/tests/ui/assigning_clones.fixed +++ b/tests/ui/assigning_clones.fixed @@ -153,6 +153,19 @@ fn clone_inside_macro() { clone_inside!(a, b); } +// Make sure that we don't suggest the lint when we call clone inside a Clone impl +// https://github.com/rust-lang/rust-clippy/issues/12600 +pub struct AvoidRecursiveCloneFrom; + +impl Clone for AvoidRecursiveCloneFrom { + fn clone(&self) -> Self { + Self + } + fn clone_from(&mut self, source: &Self) { + *self = source.clone(); + } +} + // ToOwned fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { ref_str.clone_into(mut_string); diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs index 14ba1d4db9a..6f4da9f652c 100644 --- a/tests/ui/assigning_clones.rs +++ b/tests/ui/assigning_clones.rs @@ -153,6 +153,19 @@ fn clone_inside_macro() { clone_inside!(a, b); } +// Make sure that we don't suggest the lint when we call clone inside a Clone impl +// https://github.com/rust-lang/rust-clippy/issues/12600 +pub struct AvoidRecursiveCloneFrom; + +impl Clone for AvoidRecursiveCloneFrom { + fn clone(&self) -> Self { + Self + } + fn clone_from(&mut self, source: &Self) { + *self = source.clone(); + } +} + // ToOwned fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { *mut_string = ref_str.to_owned(); diff --git a/tests/ui/assigning_clones.stderr b/tests/ui/assigning_clones.stderr index ba59f067431..793927bd1cb 100644 --- a/tests/ui/assigning_clones.stderr +++ b/tests/ui/assigning_clones.stderr @@ -86,37 +86,37 @@ LL | a = c.to_owned(); | ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:158:5 + --> tests/ui/assigning_clones.rs:171:5 | LL | *mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:162:5 + --> tests/ui/assigning_clones.rs:175:5 | LL | mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:183:5 + --> tests/ui/assigning_clones.rs:196:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:187:5 + --> tests/ui/assigning_clones.rs:200:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:191:5 + --> tests/ui/assigning_clones.rs:204:5 | LL | *mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:195:5 + --> tests/ui/assigning_clones.rs:208:5 | LL | mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)` From bb023e90d8dfbdee714aa33cfa44b91753a99a03 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 4 Apr 2024 19:48:53 +0200 Subject: [PATCH 79/79] Bump nightly version -> 2024-04-04 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index a63e66f3214..b2fe5c8bee7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-03-21" +channel = "nightly-2024-04-04" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]