From c5a9adc2bef3afcaf8bcdb260e218a82911a034e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:20:10 +0200 Subject: [PATCH 01/80] new lint: `type_id_on_box` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 35 ++++++++++++ clippy_lints/src/methods/type_id_on_box.rs | 64 ++++++++++++++++++++++ tests/ui/type_id_on_box.fixed | 20 +++++++ tests/ui/type_id_on_box.rs | 20 +++++++ tests/ui/type_id_on_box.stderr | 25 +++++++++ 7 files changed, 166 insertions(+) create mode 100644 clippy_lints/src/methods/type_id_on_box.rs create mode 100644 tests/ui/type_id_on_box.fixed create mode 100644 tests/ui/type_id_on_box.rs create mode 100644 tests/ui/type_id_on_box.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 269be545b0ab1..f82a373925909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5230,6 +5230,7 @@ Released 2018-09-13 [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity +[`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_id_on_box [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction [`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 7690e8f724707..0a2db21ca95c2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -403,6 +403,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::SUSPICIOUS_MAP_INFO, crate::methods::SUSPICIOUS_SPLITN_INFO, crate::methods::SUSPICIOUS_TO_OWNED_INFO, + crate::methods::TYPE_ID_ON_BOX_INFO, crate::methods::UNINIT_ASSUMED_INIT_INFO, crate::methods::UNIT_HASH_INFO, crate::methods::UNNECESSARY_FILTER_MAP_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 99c984ba65a8d..e98fe99eac73b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -87,6 +87,7 @@ mod suspicious_command_arg_space; mod suspicious_map; mod suspicious_splitn; mod suspicious_to_owned; +mod type_id_on_box; mod uninit_assumed_init; mod unit_hash; mod unnecessary_filter_map; @@ -2922,6 +2923,37 @@ declare_clippy_lint! { "use of sort() when sort_unstable() is equivalent" } +declare_clippy_lint! { + /// ### What it does + /// Looks for calls to ` as Any>::type_id`. + /// + /// ### 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!). + /// + /// ### Example + /// ```rust,ignore + /// use std::any::{Any, TypeId}; + /// + /// let any_box: Box = Box::new(42_i32); + /// assert_eq!(any_box.type_id(), TypeId::of::()); // ⚠️ this fails! + /// ``` + /// Use instead: + /// ```rust + /// use std::any::{Any, TypeId}; + /// + /// let any_box: Box = Box::new(42_i32); + /// assert_eq!((*any_box).type_id(), TypeId::of::()); + /// // ^ dereference first, to call `type_id` on `dyn Any` + /// ``` + #[clippy::version = "1.47.0"] + pub TYPE_ID_ON_BOX, + suspicious, + "calling `.type_id()` on `Box`" +} + declare_clippy_lint! { /// ### What it does /// Detects `().hash(_)`. @@ -3878,6 +3910,9 @@ impl Methods { ("to_os_string" | "to_path_buf" | "to_vec", []) => { implicit_clone::check(cx, name, expr, recv); }, + ("type_id", []) => { + type_id_on_box::check(cx, recv, expr.span); + } ("unwrap", []) => { match method_call(recv) { Some(("get", recv, [get_arg], _, _)) => { diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs new file mode 100644 index 0000000000000..8ccbd0d8d1bd4 --- /dev/null +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -0,0 +1,64 @@ +use crate::methods::TYPE_ID_ON_BOX; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::Adjustment; +use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, ExistentialPredicate}; +use rustc_span::{sym, Span}; + +fn is_dyn_trait(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { + 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, + }) + } else { + false + } +} + +pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) { + let recv_adjusts = cx.typeck_results().expr_adjustments(receiver); + + if let Some(Adjustment { target: recv_ty, .. }) = recv_adjusts.last() + && let ty::Ref(_, ty, _) = recv_ty.kind() + && let ty::Adt(adt, substs) = ty.kind() + && adt.is_box() + && is_dyn_trait(cx, substs.type_at(0)) + { + span_lint_and_then( + cx, + TYPE_ID_ON_BOX, + call_span, + "calling `.type_id()` on a `Box`", + |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( + "if this is intentional, use `TypeId::of::>()` instead, \ + which makes it more clear" + ) + .span_suggestion( + receiver.span, + "consider dereferencing first", + format!("({sugg})"), + Applicability::MaybeIncorrect, + ); + }, + ); + } +} diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed new file mode 100644 index 0000000000000..fc177afacd4d8 --- /dev/null +++ b/tests/ui/type_id_on_box.fixed @@ -0,0 +1,20 @@ +//@run-rustfix + +#![warn(clippy::type_id_on_box)] + +use std::any::{Any, TypeId}; + +fn existential() -> impl Any { + Box::new(1) as Box +} + +fn main() { + let any_box: Box = Box::new(0usize); + let _ = (*any_box).type_id(); + let _ = TypeId::of::>(); // don't lint, user probably explicitly wants to do this + let _ = (*any_box).type_id(); + let any_box: &Box = &(Box::new(0usize) as Box); + let _ = (**any_box).type_id(); // 2 derefs are needed here + let b = existential(); + let _ = b.type_id(); // don't lint +} diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs new file mode 100644 index 0000000000000..36cf631a092e9 --- /dev/null +++ b/tests/ui/type_id_on_box.rs @@ -0,0 +1,20 @@ +//@run-rustfix + +#![warn(clippy::type_id_on_box)] + +use std::any::{Any, TypeId}; + +fn existential() -> impl Any { + Box::new(1) as Box +} + +fn main() { + let any_box: Box = Box::new(0usize); + let _ = any_box.type_id(); + let _ = TypeId::of::>(); // don't lint, user probably explicitly wants to do this + let _ = (*any_box).type_id(); + let any_box: &Box = &(Box::new(0usize) as Box); + let _ = any_box.type_id(); // 2 derefs are needed here + let b = existential(); + let _ = b.type_id(); // don't lint +} diff --git a/tests/ui/type_id_on_box.stderr b/tests/ui/type_id_on_box.stderr new file mode 100644 index 0000000000000..47e0e814daf6d --- /dev/null +++ b/tests/ui/type_id_on_box.stderr @@ -0,0 +1,25 @@ +error: calling `.type_id()` on a `Box` + --> $DIR/type_id_on_box.rs:13: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: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + = note: `-D clippy::type-id-on-box` implied by `-D warnings` + +error: calling `.type_id()` on a `Box` + --> $DIR/type_id_on_box.rs:17:13 + | +LL | let _ = any_box.type_id(); // 2 derefs are needed here + | -------^^^^^^^^^^ + | | + | 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: if this is intentional, use `TypeId::of::>()` instead, which makes it more clear + +error: aborting due to 2 previous errors + From 9ab1e8e95c45cbe9cdf657bded08a7d874e48fbd Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:27:20 +0200 Subject: [PATCH 02/80] that was definitely not the right version --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e98fe99eac73b..255a8cc0a95ad 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2948,7 +2948,7 @@ declare_clippy_lint! { /// assert_eq!((*any_box).type_id(), TypeId::of::()); /// // ^ dereference first, to call `type_id` on `dyn Any` /// ``` - #[clippy::version = "1.47.0"] + #[clippy::version = "1.72.0"] pub TYPE_ID_ON_BOX, suspicious, "calling `.type_id()` on `Box`" From 26ac76c15f4a12b2debde692dfff02a08d516f6e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:36:08 +0200 Subject: [PATCH 03/80] add it to the methods lint pass --- clippy_lints/src/methods/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 255a8cc0a95ad..6c0e15d16d761 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3389,6 +3389,7 @@ impl_lint_pass!(Methods => [ STRING_EXTEND_CHARS, ITER_CLONED_COLLECT, ITER_WITH_DRAIN, + TYPE_ID_ON_BOX, USELESS_ASREF, UNNECESSARY_FOLD, UNNECESSARY_FILTER_MAP, From b0dfecd8c13aaf51946ce43db8a6ed398b9a5bf5 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 19 Jun 2023 00:36:16 +0200 Subject: [PATCH 04/80] add a few more test cases --- tests/ui/type_id_on_box.fixed | 26 +++++++++++++++++++++++--- tests/ui/type_id_on_box.rs | 26 +++++++++++++++++++++++--- tests/ui/type_id_on_box.stderr | 19 +++++++++++++++---- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed index fc177afacd4d8..615d809c8975c 100644 --- a/tests/ui/type_id_on_box.fixed +++ b/tests/ui/type_id_on_box.fixed @@ -3,6 +3,19 @@ #![warn(clippy::type_id_on_box)] use std::any::{Any, TypeId}; +use std::ops::Deref; + +type SomeBox = Box; + +struct BadBox(Box); + +impl Deref for BadBox { + type Target = Box; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} fn existential() -> impl Any { Box::new(1) as Box @@ -11,10 +24,17 @@ fn existential() -> impl Any { fn main() { let any_box: Box = Box::new(0usize); let _ = (*any_box).type_id(); - let _ = TypeId::of::>(); // don't lint, user probably explicitly wants to do this + let _ = TypeId::of::>(); // Don't lint. We explicitly say "do this instead" if this is intentional let _ = (*any_box).type_id(); let any_box: &Box = &(Box::new(0usize) as Box); - let _ = (**any_box).type_id(); // 2 derefs are needed here + let _ = (**any_box).type_id(); // 2 derefs are needed here to get to the `dyn Any` + let b = existential(); - let _ = b.type_id(); // don't lint + let _ = b.type_id(); // Don't lint. + + let b: SomeBox = Box::new(0usize); + let _ = (*b).type_id(); + + let b = BadBox(Box::new(0usize)); + let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! } diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs index 36cf631a092e9..74b6c74ae5f6f 100644 --- a/tests/ui/type_id_on_box.rs +++ b/tests/ui/type_id_on_box.rs @@ -3,6 +3,19 @@ #![warn(clippy::type_id_on_box)] use std::any::{Any, TypeId}; +use std::ops::Deref; + +type SomeBox = Box; + +struct BadBox(Box); + +impl Deref for BadBox { + type Target = Box; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} fn existential() -> impl Any { Box::new(1) as Box @@ -11,10 +24,17 @@ fn existential() -> impl Any { fn main() { let any_box: Box = Box::new(0usize); let _ = any_box.type_id(); - let _ = TypeId::of::>(); // don't lint, user probably explicitly wants to do this + let _ = TypeId::of::>(); // Don't lint. We explicitly say "do this instead" if this is intentional let _ = (*any_box).type_id(); let any_box: &Box = &(Box::new(0usize) as Box); - let _ = any_box.type_id(); // 2 derefs are needed here + let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any` + let b = existential(); - let _ = b.type_id(); // don't lint + let _ = b.type_id(); // Don't lint. + + let b: SomeBox = Box::new(0usize); + let _ = b.type_id(); + + let b = BadBox(Box::new(0usize)); + let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! } diff --git a/tests/ui/type_id_on_box.stderr b/tests/ui/type_id_on_box.stderr index 47e0e814daf6d..1525328c0d03c 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 a `Box` - --> $DIR/type_id_on_box.rs:13:13 + --> $DIR/type_id_on_box.rs:26:13 | LL | let _ = any_box.type_id(); | -------^^^^^^^^^^ @@ -11,9 +11,9 @@ LL | let _ = any_box.type_id(); = note: `-D clippy::type-id-on-box` implied by `-D warnings` error: calling `.type_id()` on a `Box` - --> $DIR/type_id_on_box.rs:17:13 + --> $DIR/type_id_on_box.rs:30:13 | -LL | let _ = any_box.type_id(); // 2 derefs are needed here +LL | let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any` | -------^^^^^^^^^^ | | | help: consider dereferencing first: `(**any_box)` @@ -21,5 +21,16 @@ LL | let _ = any_box.type_id(); // 2 derefs are needed here = 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 +error: calling `.type_id()` on a `Box` + --> $DIR/type_id_on_box.rs:36: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: aborting due to 3 previous errors From 1b6738ba39bf5ecd4d32f95a53966662baabc1e0 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 20 Jun 2023 17:33:32 +0200 Subject: [PATCH 05/80] s/is_dyn_trait/is_dyn_any --- clippy_lints/src/methods/type_id_on_box.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index 8ccbd0d8d1bd4..88adba504aa58 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::{self, ExistentialPredicate}; use rustc_span::{sym, Span}; -fn is_dyn_trait(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { +fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { 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), @@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) && let ty::Ref(_, ty, _) = recv_ty.kind() && let ty::Adt(adt, substs) = ty.kind() && adt.is_box() - && is_dyn_trait(cx, substs.type_at(0)) + && is_dyn_any(cx, substs.type_at(0)) { span_lint_and_then( cx, From 7bd8ab77e5c84f783760cecb3b9ead277d8c7e60 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 16 Jun 2023 16:02:11 +0000 Subject: [PATCH 06/80] Make simd_shuffle_indices use valtrees --- clippy_lints/src/non_copy_const.rs | 64 +++++++++++++++++++++++------- tests/ui/crashes/ice-9445.stderr | 12 ++++++ 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 tests/ui/crashes/ice-9445.stderr diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 58590df1fedf8..ac49ccdb5011b 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -15,12 +15,14 @@ use rustc_hir::{ }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, Lint}; -use rustc_middle::mir; -use rustc_middle::mir::interpret::{ConstValue, ErrorHandled}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::adjustment::Adjust; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, InnerSpan, Span}; +use rustc_target::abi::VariantIdx; +use rustc_middle::mir::interpret::EvalToValTreeResult; +use rustc_middle::mir::interpret::GlobalId; // FIXME: this is a correctness problem but there's no suitable // warn-by-default category. @@ -141,21 +143,35 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { fn is_value_unfrozen_raw<'tcx>( cx: &LateContext<'tcx>, - result: Result, ErrorHandled>, + result: Result>, ErrorHandled>, ty: Ty<'tcx>, ) -> bool { - fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool { - match val.ty().kind() { + fn inner<'tcx>(cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool { + match *ty.kind() { // the fact that we have to dig into every structs to search enums // leads us to the point checking `UnsafeCell` directly is the only option. ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true, // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the // contained value. ty::Adt(def, ..) if def.is_union() => false, - ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => { - let val = cx.tcx.destructure_mir_constant(cx.param_env, val); - val.fields.iter().any(|field| inner(cx, *field)) + ty::Array(ty, _) => { + val.unwrap_branch().iter().any(|field| inner(cx, *field, ty)) }, + ty::Adt(def, _) if def.is_union() => false, + ty::Adt(def, substs) if def.is_enum() => { + let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap(); + let variant_index = + VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap()); + fields.iter().copied().zip( + def.variants()[variant_index] + .fields + .iter() + .map(|field| field.ty(cx.tcx, substs))).any(|(field, ty)| inner(cx, field, ty)) + } + ty::Adt(def, substs) => { + val.unwrap_branch().iter().zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, substs))).any(|(field, ty)| inner(cx, *field, ty)) + } + ty::Tuple(tys) => val.unwrap_branch().iter().zip(tys).any(|(field, ty)| inner(cx, *field, ty)), _ => false, } } @@ -184,24 +200,44 @@ fn is_value_unfrozen_raw<'tcx>( // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none). err == ErrorHandled::TooGeneric }, - |val| inner(cx, mir::ConstantKind::from_value(val, ty)), + |val| val.map_or(true, |val| inner(cx, val, ty)), ) } fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool { - let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id()); + let def_id = body_id.hir_id.owner.to_def_id(); + let substs = ty::InternalSubsts::identity_for_item(cx.tcx, def_id); + let instance = ty::Instance::new(def_id, substs); + let cid = rustc_middle::mir::interpret::GlobalId { instance, 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, None); is_value_unfrozen_raw(cx, result, ty) } fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let substs = cx.typeck_results().node_substs(hir_id); - let result = cx - .tcx - .const_eval_resolve(cx.param_env, mir::UnevaluatedConst::new(def_id, substs), None); + let result = const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, substs), None); is_value_unfrozen_raw(cx, result, ty) } + +pub fn const_eval_resolve<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ct: ty::UnevaluatedConst<'tcx>, + span: Option, +) -> EvalToValTreeResult<'tcx> { + match ty::Instance::resolve(tcx, param_env, ct.def, ct.substs) { + Ok(Some(instance)) => { + let cid = GlobalId { instance, promoted: None }; + tcx.const_eval_global_id_for_typeck(param_env, cid, span) + } + Ok(None) => Err(ErrorHandled::TooGeneric), + Err(err) => Err(ErrorHandled::Reported(err.into())), + } +} + #[derive(Copy, Clone)] enum Source { Item { item: Span }, diff --git a/tests/ui/crashes/ice-9445.stderr b/tests/ui/crashes/ice-9445.stderr new file mode 100644 index 0000000000000..a59d098e5ac0a --- /dev/null +++ b/tests/ui/crashes/ice-9445.stderr @@ -0,0 +1,12 @@ +error: a `const` item should never be interior mutable + --> $DIR/ice-9445.rs:1:1 + | +LL | const UNINIT: core::mem::MaybeUninit> = core::mem::MaybeUninit::uninit(); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | make this a static item (maybe with lazy_static) + | + = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings` + +error: aborting due to previous error + From d69c4f553c69fb0e64c281f85eb5822bcdfb4739 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sat, 10 Jun 2023 11:21:28 +0200 Subject: [PATCH 07/80] Add `SPEEDTEST` --- book/src/development/speedtest.md | 24 ++++++++++++++++ tests/compile-test.rs | 46 +++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 book/src/development/speedtest.md diff --git a/book/src/development/speedtest.md b/book/src/development/speedtest.md new file mode 100644 index 0000000000000..0db718e6ad674 --- /dev/null +++ b/book/src/development/speedtest.md @@ -0,0 +1,24 @@ +# Speedtest +`SPEEDTEST` is the tool we use to measure lint's performance, it works by executing the same test several times. + +It's useful for measuring changes to current lints and deciding if the performance changes too much. `SPEEDTEST` is +accessed by the `SPEEDTEST` (and `SPEEDTEST_*`) environment variables. + +## Checking Speedtest + +To do a simple speed test of a lint (e.g. `allow_attributes`), use this command. + +```sh +$ SPEEDTEST=ui TESTNAME="allow_attributes" cargo uitest -- --nocapture +``` + +This will test all `ui` tests (`SPEEDTEST=ui`) whose names start with `allow_attributes`. By default, `SPEEDTEST` will +iterate your test 1000 times. But you can change this with `SPEEDTEST_ITERATIONS`. + +```sh +$ SPEEDTEST=toml SPEEDTEST_ITERATIONS=100 TESTNAME="semicolon_block" cargo uitest -- --nocapture +``` + +> **WARNING**: Be sure to use `-- --nocapture` at the end of the command to see the average test time. If you don't +> use `-- --nocapture` (e.g. `SPEEDTEST=ui` `TESTNAME="let_underscore_untyped" cargo uitest -- --nocapture`), this +> will not show up. diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c5e8622bc85c5..c45339ba0b5f0 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -213,12 +213,46 @@ fn run_ui_cargo() { fn main() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); - run_ui(); - run_ui_toml(); - run_ui_cargo(); - run_internal_tests(); - rustfix_coverage_known_exceptions_accuracy(); - ui_cargo_toml_metadata(); + // The SPEEDTEST_* env variables can be used to check Clippy's performance on your PR. It runs the + // affected test 1000 times and gets the average. + if let Ok(speedtest) = std::env::var("SPEEDTEST") { + println!("----------- STARTING SPEEDTEST -----------"); + let f; + match speedtest.as_str() { + "ui" => f = run_ui as fn(), + "cargo" => f = run_ui_cargo as fn(), + "toml" => f = run_ui_toml as fn(), + "internal" => f = run_internal_tests as fn(), + "rustfix-coverage-known-exceptions-accuracy" => f = rustfix_coverage_known_exceptions_accuracy as fn(), + "ui-cargo-toml-metadata" => f = ui_cargo_toml_metadata() as fn(), + + _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"), + } + + let iterations; + if let Ok(iterations_str) = std::env::var("SPEEDTEST_ITERATIONS") { + iterations = iterations_str + .parse::() + .unwrap_or_else(|_| panic!("Couldn't parse `{}`, please use a valid u64", iterations_str)); + } else { + iterations = 1000; + } + + let mut sum = 0; + for _ in 0..iterations { + let start = std::time::Instant::now(); + f(); + sum += start.elapsed().as_millis(); + } + println!("average {} time: {} millis.", speedtest.to_uppercase(), sum / 1000); + } else { + run_ui(); + run_ui_toml(); + run_ui_cargo(); + run_internal_tests(); + rustfix_coverage_known_exceptions_accuracy(); + ui_cargo_toml_metadata(); + } } const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ From 0cd8bbc8674a38dab07ce55b36339ac403f70daa Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sat, 10 Jun 2023 22:43:51 +0200 Subject: [PATCH 08/80] Fix dogfood --- tests/compile-test.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c45339ba0b5f0..50f8cf26fde51 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -223,17 +223,17 @@ fn main() { "cargo" => f = run_ui_cargo as fn(), "toml" => f = run_ui_toml as fn(), "internal" => f = run_internal_tests as fn(), - "rustfix-coverage-known-exceptions-accuracy" => f = rustfix_coverage_known_exceptions_accuracy as fn(), - "ui-cargo-toml-metadata" => f = ui_cargo_toml_metadata() as fn(), + "rustfix-coverage-known-exceptions-accuracy" => f = rustfix_coverage_known_exceptions_accuracy as fn(), + "ui-cargo-toml-metadata" => f = ui_cargo_toml_metadata as fn(), _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"), - } + }; let iterations; if let Ok(iterations_str) = std::env::var("SPEEDTEST_ITERATIONS") { iterations = iterations_str .parse::() - .unwrap_or_else(|_| panic!("Couldn't parse `{}`, please use a valid u64", iterations_str)); + .unwrap_or_else(|_| panic!("Couldn't parse `{iterations_str}`, please use a valid u64")); } else { iterations = 1000; } @@ -250,8 +250,8 @@ fn main() { run_ui_toml(); run_ui_cargo(); run_internal_tests(); - rustfix_coverage_known_exceptions_accuracy(); - ui_cargo_toml_metadata(); + rustfix_coverage_known_exceptions_accuracy(); + ui_cargo_toml_metadata(); } } From 57923c3720fad870b1edeed1dbe74f990b431288 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Wed, 28 Jun 2023 16:03:59 +0200 Subject: [PATCH 09/80] Finally fix dogfood --- tests/compile-test.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 50f8cf26fde51..bda3662acd044 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -217,14 +217,13 @@ fn main() { // affected test 1000 times and gets the average. if let Ok(speedtest) = std::env::var("SPEEDTEST") { println!("----------- STARTING SPEEDTEST -----------"); - let f; - match speedtest.as_str() { - "ui" => f = run_ui as fn(), - "cargo" => f = run_ui_cargo as fn(), - "toml" => f = run_ui_toml as fn(), - "internal" => f = run_internal_tests as fn(), - "rustfix-coverage-known-exceptions-accuracy" => f = rustfix_coverage_known_exceptions_accuracy as fn(), - "ui-cargo-toml-metadata" => f = ui_cargo_toml_metadata as fn(), + let f = match speedtest.as_str() { + "ui" => run_ui as fn(), + "cargo" => run_ui_cargo as fn(), + "toml" => run_ui_toml as fn(), + "internal" => run_internal_tests as fn(), + "rustfix-coverage-known-exceptions-accuracy" => rustfix_coverage_known_exceptions_accuracy as fn(), + "ui-cargo-toml-metadata" => ui_cargo_toml_metadata as fn(), _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"), }; From 4340a8a0f25a6de5bba1de69fb00068967830dbd Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Wed, 28 Jun 2023 21:58:14 +0000 Subject: [PATCH 10/80] Use depinfo to discover UI test dependencies --- Cargo.toml | 11 ++++ clippy_test_deps/Cargo.toml | 23 ------- clippy_test_deps/src/lib.rs | 14 ----- tests/compile-test.rs | 118 +++++++++++++++++++++++++++++++++--- 4 files changed, 120 insertions(+), 46 deletions(-) delete mode 100644 clippy_test_deps/Cargo.toml delete mode 100644 clippy_test_deps/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 76c804f935e29..e7a5dbe030d14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,17 @@ walkdir = "2.3" filetime = "0.2" itertools = "0.10.1" +# UI test dependencies +clippy_utils = { path = "clippy_utils" } +derive-new = "0.5" +if_chain = "1.0" +quote = "1.0" +serde = { version = "1.0.125", features = ["derive"] } +syn = { version = "2.0", features = ["full"] } +futures = "0.3" +parking_lot = "0.12" +tokio = { version = "1", features = ["io-util"] } + [build-dependencies] rustc_tools_util = "0.3.0" diff --git a/clippy_test_deps/Cargo.toml b/clippy_test_deps/Cargo.toml deleted file mode 100644 index 362c08e0d7790..0000000000000 --- a/clippy_test_deps/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "clippy_test_deps" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clippy_utils = { path = "../clippy_utils" } -derive-new = "0.5" -if_chain = "1.0" -itertools = "0.10.1" -quote = "1.0" -serde = { version = "1.0.125", features = ["derive"] } -syn = { version = "2.0", features = ["full"] } -futures = "0.3" -parking_lot = "0.12" -tokio = { version = "1", features = ["io-util"] } -regex = "1.5" -clippy_lints = { path = "../clippy_lints" } - -[features] -internal = ["clippy_lints/internal"] diff --git a/clippy_test_deps/src/lib.rs b/clippy_test_deps/src/lib.rs deleted file mode 100644 index 7d12d9af8195b..0000000000000 --- a/clippy_test_deps/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/tests/compile-test.rs b/tests/compile-test.rs index dce6f2fc27269..62cfea6bec745 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,17 +3,108 @@ #![feature(is_sorted)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] +#![allow(unused_extern_crates)] use compiletest::{status_emitter, CommandBuilder}; use ui_test as compiletest; use ui_test::Mode as TestMode; +use std::collections::BTreeMap; use std::env::{self, remove_var, set_var, var_os}; use std::ffi::{OsStr, OsString}; use std::fs; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use test_utils::IS_RUSTC_TEST_SUITE; +// Test dependencies may need an `extern crate` here to ensure that they show up +// in the depinfo file (otherwise cargo thinks they are unused) +extern crate clippy_lints; +extern crate clippy_utils; +extern crate derive_new; +extern crate futures; +extern crate if_chain; +extern crate itertools; +extern crate parking_lot; +extern crate quote; +extern crate syn; +extern crate tokio; + +/// All crates used in UI tests are listed here +static TEST_DEPENDENCIES: &[&str] = &[ + "clippy_lints", + "clippy_utils", + "derive_new", + "futures", + "if_chain", + "itertools", + "parking_lot", + "quote", + "regex", + "serde_derive", + "serde", + "syn", + "tokio", +]; + +/// Produces a string with an `--extern` flag for all UI test crate +/// dependencies. +/// +/// The dependency files are located by parsing the depinfo file for this test +/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test +/// dependencies must be added to Cargo.toml at the project root. Test +/// dependencies that are not *directly* used by this test module require an +/// `extern crate` declaration. +static EXTERN_FLAGS: LazyLock> = LazyLock::new(|| { + let current_exe_depinfo = { + let mut path = env::current_exe().unwrap(); + path.set_extension("d"); + fs::read_to_string(path).unwrap() + }; + let mut crates = BTreeMap::<&str, &str>::new(); + for line in current_exe_depinfo.lines() { + // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:` + let parse_name_path = || { + if line.starts_with(char::is_whitespace) { + return None; + } + let path_str = line.strip_suffix(':')?; + let path = Path::new(path_str); + if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") { + return None; + } + let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?; + // the "lib" prefix is not present for dll files + let name = name.strip_prefix("lib").unwrap_or(name); + Some((name, path_str)) + }; + if let Some((name, path)) = parse_name_path() { + if TEST_DEPENDENCIES.contains(&name) { + // A dependency may be listed twice if it is available in sysroot, + // and the sysroot dependencies are listed first. As of the writing, + // this only seems to apply to if_chain. + crates.insert(name, path); + } + } + } + let not_found: Vec<&str> = TEST_DEPENDENCIES + .iter() + .copied() + .filter(|n| !crates.contains_key(n)) + .collect(); + assert!( + not_found.is_empty(), + "dependencies not found in depinfo: {not_found:?}\n\ + help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\ + help: Try adding to dev-dependencies in Cargo.toml\n\ + help: Be sure to also add `extern crate ...;` to tests/compile-test.rs", + ); + crates + .into_iter() + .map(|(name, path)| format!("--extern={name}={path}")) + .collect() +}); + mod test_utils; // whether to run internal tests or not @@ -29,7 +120,6 @@ fn base_config(test_dir: &str) -> compiletest::Config { } else { compiletest::OutputConflictHandling::Error("cargo test -- -- --bless".into()) }, - dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()), target: None, out_dir: "target/ui_test".into(), ..compiletest::Config::rustc(Path::new("tests").join(test_dir)) @@ -44,10 +134,23 @@ fn base_config(test_dir: &str) -> compiletest::Config { let deps_path = current_exe_path.parent().unwrap(); let profile_path = deps_path.parent().unwrap(); - config.program.args.push("--emit=metadata".into()); - config.program.args.push("-Aunused".into()); - config.program.args.push("-Zui-testing".into()); - config.program.args.push("-Dwarnings".into()); + config.program.args.extend( + [ + "--emit=metadata", + "-Aunused", + "-Zui-testing", + "-Dwarnings", + &format!("-Ldependency={}", deps_path.display()), + ] + .map(OsString::from), + ); + + config.program.args.extend(EXTERN_FLAGS.iter().map(OsString::from)); + + if let Some(host_libs) = option_env!("HOST_LIBS") { + let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); + config.program.args.push(dep.into()); + } // Normalize away slashes in windows paths. config.stderr_filter(r"\\", "/"); @@ -105,9 +208,7 @@ fn run_internal_tests() { if !RUN_INTERNAL_TESTS { return; } - let mut config = base_config("ui-internal"); - config.dependency_builder.args.push("--features".into()); - config.dependency_builder.args.push("internal".into()); + let config = base_config("ui-internal"); compiletest::run_tests(config).unwrap(); } @@ -165,7 +266,6 @@ fn run_ui_cargo() { .push(("RUSTFLAGS".into(), Some("-Dwarnings".into()))); // We need to do this while we still have a rustc in the `program` field. config.fill_host_and_target().unwrap(); - config.dependencies_crate_manifest_path = None; config.program.program.set_file_name(if cfg!(windows) { "cargo-clippy.exe" } else { From 86391abc704555610af8ba33d910bdd16a877ddb Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 11 Jun 2023 06:35:29 +0200 Subject: [PATCH 11/80] Don't lint manual_let_else in cases where the question mark operator would work Also, lint question_mark for `let...else` clauses that can be simplified to use `?`. This lint isn't perfect as it doesn't support the unstable try blocks. --- clippy_lints/src/manual_let_else.rs | 48 ++++++++++++++- clippy_lints/src/question_mark.rs | 33 +++++++++- tests/ui/manual_let_else_question_mark.fixed | 56 +++++++++++++++++ tests/ui/manual_let_else_question_mark.rs | 61 +++++++++++++++++++ tests/ui/manual_let_else_question_mark.stderr | 49 +++++++++++++++ 5 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 tests/ui/manual_let_else_question_mark.fixed create mode 100644 tests/ui/manual_let_else_question_mark.rs create mode 100644 tests/ui/manual_let_else_question_mark.stderr diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 59e421c162202..dcfc365a34831 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,14 +1,15 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::peel_blocks; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; +use clippy_utils::{is_refutable, is_res_lang_ctor, peel_blocks}; use if_chain::if_chain; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -85,6 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then); if let Some(if_else) = if_else; if expr_diverges(cx, if_else); + if pat_and_expr_can_be_question_mark(cx, let_pat, if_else).is_none(); then { emit_manual_let_else(cx, stmt.span, if_let_expr, &ident_map, let_pat, if_else); } @@ -167,6 +169,50 @@ fn emit_manual_let_else( ); } +/// Returns whether the given let pattern and else body can be turned into a question mark +/// +/// For this example: +/// ```ignore +/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(a) +/// else_body: return None +/// ``` + +/// And for this example: +/// ```ignore +/// let Some(FooBar { a, b }) = ex else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(FooBar { a, b }) +/// else_body: return None +/// ``` + +/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because +/// the question mark operator is applicable here. Callers have to check whether we are in a +/// constant or not. +pub fn pat_and_expr_can_be_question_mark<'a, 'hir>( + cx: &LateContext<'_>, + pat: &'a Pat<'hir>, + else_body: &Expr<'_>, +) -> Option<&'a Pat<'hir>> { + if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind && + is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) && + !is_refutable(cx, inner_pat) && + let else_body = peel_blocks(else_body) && + let ExprKind::Ret(Some(ret_val)) = else_body.kind && + let ExprKind::Path(ret_path) = ret_val.kind && + is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone) + { + Some(inner_pat) + } else { + None + } +} + /// Replaces the locals in the pattern /// /// For this example: diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index e3d940ad2a44c..b1eeedc26bdb8 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,3 +1,4 @@ +use crate::manual_let_else::pat_and_expr_can_be_question_mark; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; @@ -10,7 +11,9 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; -use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath}; +use rustc_hir::{ + BindingAnnotation, Block, ByRef, Expr, ExprKind, Local, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::declare_tool_lint; @@ -78,6 +81,29 @@ enum IfBlockType<'hir> { ), } +fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { + if let StmtKind::Local(Local { pat, init: Some(init_expr), els: Some(els), .. }) = stmt.kind && + let Block { stmts: &[], expr: Some(els), .. } = els && + let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, els) + { + let mut applicability = Applicability::MaybeIncorrect; + let init_expr_str = snippet_with_applicability(cx, init_expr.span, "..", &mut applicability); + let receiver_str = snippet_with_applicability(cx, inner_pat.span, "..", &mut applicability); + let sugg = format!( + "let {receiver_str} = {init_expr_str}?;", + ); + span_lint_and_sugg( + cx, + QUESTION_MARK, + stmt.span, + "this `let...else` may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } +} + fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_>) -> bool { match *if_block { IfBlockType::IfIs(caller, caller_ty, call_sym, if_then, _) => { @@ -259,6 +285,11 @@ fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool { } impl<'tcx> LateLintPass<'tcx> for QuestionMark { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { + if !in_constant(cx, stmt.hir_id) { + check_let_some_else_return_none(cx, stmt); + } + } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !in_constant(cx, expr.hir_id) { self.check_is_none_or_err_and_early_return(cx, expr); diff --git a/tests/ui/manual_let_else_question_mark.fixed b/tests/ui/manual_let_else_question_mark.fixed new file mode 100644 index 0000000000000..617f127b9a868 --- /dev/null +++ b/tests/ui/manual_let_else_question_mark.fixed @@ -0,0 +1,56 @@ +//@run-rustfix +#![allow(unused_braces, unused_variables, dead_code)] +#![allow( + clippy::collapsible_else_if, + clippy::unused_unit, + clippy::let_unit_value, + clippy::match_single_binding, + clippy::never_loop +)] +#![warn(clippy::manual_let_else, clippy::question_mark)] + +enum Variant { + A(usize, usize), + B(usize), + C, +} + +fn g() -> Option<(u8, u8)> { + None +} + +fn e() -> Variant { + Variant::A(0, 0) +} + +fn main() {} + +fn foo() -> Option<()> { + // Fire here, normal case + let v = g()?; + + // Don't fire here, the pattern is refutable + let Variant::A(v, w) = e() else { return None }; + + // Fire here, the pattern is irrefutable + let (v, w) = g()?; + + // Don't fire manual_let_else in this instance: question mark can be used instead. + let v = g()?; + + // Do fire manual_let_else in this instance: question mark cannot be used here due to the return + // body. + let Some(v) = g() else { + return Some(()); + }; + + // Here we could also fire the question_mark lint, but we don't (as it's a match and not an if let). + // So we still emit manual_let_else here. For the *resulting* code, we *do* emit the question_mark + // lint, so for rustfix reasons, we allow the question_mark lint here. + #[allow(clippy::question_mark)] + { + let Some(v) = g() else { return None }; + } + + Some(()) +} diff --git a/tests/ui/manual_let_else_question_mark.rs b/tests/ui/manual_let_else_question_mark.rs new file mode 100644 index 0000000000000..3cf1eca867349 --- /dev/null +++ b/tests/ui/manual_let_else_question_mark.rs @@ -0,0 +1,61 @@ +//@run-rustfix +#![allow(unused_braces, unused_variables, dead_code)] +#![allow( + clippy::collapsible_else_if, + clippy::unused_unit, + clippy::let_unit_value, + clippy::match_single_binding, + clippy::never_loop +)] +#![warn(clippy::manual_let_else, clippy::question_mark)] + +enum Variant { + A(usize, usize), + B(usize), + C, +} + +fn g() -> Option<(u8, u8)> { + None +} + +fn e() -> Variant { + Variant::A(0, 0) +} + +fn main() {} + +fn foo() -> Option<()> { + // Fire here, normal case + let Some(v) = g() else { return None }; + + // Don't fire here, the pattern is refutable + let Variant::A(v, w) = e() else { return None }; + + // Fire here, the pattern is irrefutable + let Some((v, w)) = g() else { return None }; + + // Don't fire manual_let_else in this instance: question mark can be used instead. + let v = if let Some(v_some) = g() { v_some } else { return None }; + + // Do fire manual_let_else in this instance: question mark cannot be used here due to the return + // body. + let v = if let Some(v_some) = g() { + v_some + } else { + return Some(()); + }; + + // Here we could also fire the question_mark lint, but we don't (as it's a match and not an if let). + // So we still emit manual_let_else here. For the *resulting* code, we *do* emit the question_mark + // lint, so for rustfix reasons, we allow the question_mark lint here. + #[allow(clippy::question_mark)] + { + let v = match g() { + Some(v_some) => v_some, + _ => return None, + }; + } + + Some(()) +} diff --git a/tests/ui/manual_let_else_question_mark.stderr b/tests/ui/manual_let_else_question_mark.stderr new file mode 100644 index 0000000000000..31052acf75cd7 --- /dev/null +++ b/tests/ui/manual_let_else_question_mark.stderr @@ -0,0 +1,49 @@ +error: this `let...else` may be rewritten with the `?` operator + --> $DIR/manual_let_else_question_mark.rs:30:5 + | +LL | let Some(v) = g() else { return None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `let v = g()?;` + | + = note: `-D clippy::question-mark` implied by `-D warnings` + +error: this `let...else` may be rewritten with the `?` operator + --> $DIR/manual_let_else_question_mark.rs:36:5 + | +LL | let Some((v, w)) = g() else { return None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `let (v, w) = g()?;` + +error: this block may be rewritten with the `?` operator + --> $DIR/manual_let_else_question_mark.rs:39:13 + | +LL | let v = if let Some(v_some) = g() { v_some } else { return None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `g()?` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_question_mark.rs:43:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | v_some +LL | | } else { +LL | | return Some(()); +LL | | }; + | |______^ + | + = note: `-D clippy::manual-let-else` implied by `-D warnings` +help: consider writing + | +LL ~ let Some(v) = g() else { +LL + return Some(()); +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_question_mark.rs:54:9 + | +LL | / let v = match g() { +LL | | Some(v_some) => v_some, +LL | | _ => return None, +LL | | }; + | |__________^ help: consider writing: `let Some(v) = g() else { return None };` + +error: aborting due to 5 previous errors + From c6be62159ff6c100786a86b6a5687ded883ace5f Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 11 Jun 2023 07:11:47 +0200 Subject: [PATCH 12/80] Fix the now stricter lint in manual_rem_euclid.rs --- clippy_lints/src/manual_rem_euclid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index aafee92713fe1..0e89ca132ef9f 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -119,7 +119,7 @@ fn check_for_either_unsigned_int_constant<'a>( } fn check_for_unsigned_int_constant<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option { - let Some(int_const) = constant_full_int(cx, cx.typeck_results(), expr) else { return None }; + let int_const = constant_full_int(cx, cx.typeck_results(), expr)?; match int_const { FullInt::S(s) => s.try_into().ok(), FullInt::U(u) => Some(u), From 20dfaba0351d81748f2c1bbbb8a5e1d8bd77c3cb Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 30 Jun 2023 18:41:10 +0200 Subject: [PATCH 13/80] Put into one pass --- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/manual_let_else.rs | 77 +++-------------------------- clippy_lints/src/question_mark.rs | 72 ++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 78 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5ab28b5c70c11..771f13bda15f1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -662,7 +662,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv()))); let matches_for_let_else = conf.matches_for_let_else; - store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv(), matches_for_let_else))); store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv()))); @@ -771,7 +770,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher)); store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|_| Box::::default()); + store.register_late_pass(move |_| Box::new(question_mark::QuestionMark::new(msrv(), matches_for_let_else))); store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl)); diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index dcfc365a34831..363018f138195 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,19 +1,19 @@ +use crate::question_mark::{pat_and_expr_can_be_question_mark, QuestionMark}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs; +use clippy_utils::peel_blocks; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; -use clippy_utils::{is_refutable, is_res_lang_ctor, peel_blocks}; use if_chain::if_chain; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::declare_tool_lint; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use serde::Deserialize; @@ -51,25 +51,8 @@ declare_clippy_lint! { "manual implementation of a let...else statement" } -pub struct ManualLetElse { - msrv: Msrv, - matches_behaviour: MatchLintBehaviour, -} - -impl ManualLetElse { - #[must_use] - pub fn new(msrv: Msrv, matches_behaviour: MatchLintBehaviour) -> Self { - Self { - msrv, - matches_behaviour, - } - } -} - -impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]); - -impl<'tcx> LateLintPass<'tcx> for ManualLetElse { - fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) { +impl<'tcx> QuestionMark { + pub(crate) fn check_manual_let_else(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) { if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) { return; } @@ -130,8 +113,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { } }; } - - extract_msrv_attr!(LateContext); } fn emit_manual_let_else( @@ -169,50 +150,6 @@ fn emit_manual_let_else( ); } -/// Returns whether the given let pattern and else body can be turned into a question mark -/// -/// For this example: -/// ```ignore -/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None }; -/// ``` -/// We get as parameters: -/// ```ignore -/// pat: Some(a) -/// else_body: return None -/// ``` - -/// And for this example: -/// ```ignore -/// let Some(FooBar { a, b }) = ex else { return None }; -/// ``` -/// We get as parameters: -/// ```ignore -/// pat: Some(FooBar { a, b }) -/// else_body: return None -/// ``` - -/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because -/// the question mark operator is applicable here. Callers have to check whether we are in a -/// constant or not. -pub fn pat_and_expr_can_be_question_mark<'a, 'hir>( - cx: &LateContext<'_>, - pat: &'a Pat<'hir>, - else_body: &Expr<'_>, -) -> Option<&'a Pat<'hir>> { - if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind && - is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) && - !is_refutable(cx, inner_pat) && - let else_body = peel_blocks(else_body) && - let ExprKind::Ret(Some(ret_val)) = else_body.kind && - let ExprKind::Path(ret_path) = ret_val.kind && - is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone) - { - Some(inner_pat) - } else { - None - } -} - /// Replaces the locals in the pattern /// /// For this example: diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b1eeedc26bdb8..d473b6fd5c435 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,10 +1,11 @@ -use crate::manual_let_else::pat_and_expr_can_be_question_mark; +use crate::manual_let_else::{MatchLintBehaviour, MANUAL_LET_ELSE}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ - eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id, - peel_blocks, peel_blocks_with_stmt, + eq_expr_value, get_parent_node, in_constant, is_else_clause, is_refutable, is_res_lang_ctor, path_to_local, + path_to_local_id, peel_blocks, peel_blocks_with_stmt, }; use clippy_utils::{higher, is_path_lang_item}; use if_chain::if_chain; @@ -12,7 +13,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, Local, Node, Pat, PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -45,8 +46,9 @@ declare_clippy_lint! { "checks for expressions that could be replaced by the question mark operator" } -#[derive(Default)] pub struct QuestionMark { + pub(crate) msrv: Msrv, + pub(crate) matches_behaviour: MatchLintBehaviour, /// Keeps track of how many try blocks we are in at any point during linting. /// This allows us to answer the question "are we inside of a try block" /// very quickly, without having to walk up the parent chain, by simply checking @@ -54,7 +56,19 @@ pub struct QuestionMark { /// As for why we need this in the first place: try_block_depth_stack: Vec, } -impl_lint_pass!(QuestionMark => [QUESTION_MARK]); + +impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]); + +impl QuestionMark { + #[must_use] + pub fn new(msrv: Msrv, matches_behaviour: MatchLintBehaviour) -> Self { + Self { + msrv, + matches_behaviour, + try_block_depth_stack: Vec::new(), + } + } +} enum IfBlockType<'hir> { /// An `if x.is_xxx() { a } else { b } ` expression. @@ -81,6 +95,50 @@ enum IfBlockType<'hir> { ), } +/// Returns whether the given let pattern and else body can be turned into a question mark +/// +/// For this example: +/// ```ignore +/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(a) +/// else_body: return None +/// ``` + +/// And for this example: +/// ```ignore +/// let Some(FooBar { a, b }) = ex else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(FooBar { a, b }) +/// else_body: return None +/// ``` + +/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because +/// the question mark operator is applicable here. Callers have to check whether we are in a +/// constant or not. +pub(crate) fn pat_and_expr_can_be_question_mark<'a, 'hir>( + cx: &LateContext<'_>, + pat: &'a Pat<'hir>, + else_body: &Expr<'_>, +) -> Option<&'a Pat<'hir>> { + if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind && + is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) && + !is_refutable(cx, inner_pat) && + let else_body = peel_blocks(else_body) && + let ExprKind::Ret(Some(ret_val)) = else_body.kind && + let ExprKind::Path(ret_path) = ret_val.kind && + is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone) + { + Some(inner_pat) + } else { + None + } +} + fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { if let StmtKind::Local(Local { pat, init: Some(init_expr), els: Some(els), .. }) = stmt.kind && let Block { stmts: &[], expr: Some(els), .. } = els && @@ -289,6 +347,7 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { if !in_constant(cx, stmt.hir_id) { check_let_some_else_return_none(cx, stmt); } + self.check_manual_let_else(cx, stmt); } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !in_constant(cx, expr.hir_id) { @@ -322,4 +381,5 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { .expect("blocks are always part of bodies and must have a depth") -= 1; } } + extract_msrv_attr!(LateContext); } From 2f7f1393c9623e7d36297b0cd7534a43cc8bb091 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 30 Jun 2023 21:34:28 +0000 Subject: [PATCH 14/80] Use `cargo build --tests` in CI --- .github/workflows/clippy.yml | 2 +- .github/workflows/clippy_bors.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index c582c28cd3cf1..410ff53a251b2 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -50,7 +50,7 @@ jobs: echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV - name: Build - run: cargo build --features deny-warnings,internal + run: cargo build --tests --features deny-warnings,internal - name: Test run: cargo test --features deny-warnings,internal diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index d5ab313ba0e6f..4eb11a3ac8572 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -106,7 +106,7 @@ jobs: echo "$SYSROOT/bin" >> $GITHUB_PATH - name: Build - run: cargo build --features deny-warnings,internal + run: cargo build --tests --features deny-warnings,internal - name: Test if: runner.os == 'Linux' From 420f3d11e8cc0f6353f65f578c21ffef3c369314 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 1 Jul 2023 07:08:01 -0400 Subject: [PATCH 15/80] "try this" -> "try" --- clippy_lints/src/dereference.rs | 8 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/init_numbered_fields.rs | 2 +- clippy_lints/src/loops/missing_spin_loop.rs | 2 +- clippy_lints/src/map_unit_fn.rs | 6 +- .../matches/infallible_destructuring_match.rs | 2 +- clippy_lints/src/matches/manual_filter.rs | 2 +- clippy_lints/src/matches/manual_map.rs | 2 +- clippy_lints/src/matches/match_as_ref.rs | 2 +- .../src/matches/match_like_matches.rs | 2 +- .../src/matches/match_on_vec_items.rs | 2 +- clippy_lints/src/matches/match_wild_enum.rs | 4 +- .../src/matches/redundant_pattern_match.rs | 4 +- clippy_lints/src/matches/single_match.rs | 2 +- clippy_lints/src/matches/try_err.rs | 2 +- .../src/methods/bind_instead_of_map.rs | 4 +- clippy_lints/src/methods/clone_on_ref_ptr.rs | 2 +- clippy_lints/src/methods/expect_fun_call.rs | 4 +- clippy_lints/src/methods/extend_with_drain.rs | 2 +- clippy_lints/src/methods/filter_map_next.rs | 2 +- clippy_lints/src/methods/filter_next.rs | 2 +- clippy_lints/src/methods/get_unwrap.rs | 2 +- .../src/methods/iter_overeager_cloned.rs | 2 +- clippy_lints/src/methods/iter_with_drain.rs | 2 +- clippy_lints/src/methods/manual_str_repeat.rs | 2 +- .../src/methods/map_collect_result_unit.rs | 2 +- clippy_lints/src/methods/map_unwrap_or.rs | 2 +- .../src/methods/needless_option_as_deref.rs | 2 +- clippy_lints/src/methods/or_fun_call.rs | 4 +- clippy_lints/src/methods/or_then_unwrap.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 4 +- .../src/methods/string_extend_chars.rs | 2 +- clippy_lints/src/methods/useless_asref.rs | 2 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/strlen_on_c_strings.rs | 2 +- clippy_lints/src/to_digit_is_some.rs | 2 +- clippy_lints/src/write.rs | 2 +- tests/lint_message_convention.rs | 6 +- .../uninlined_format_args.stderr | 2 +- tests/ui-toml/unwrap_used/unwrap_used.stderr | 30 +++---- tests/ui/bind_instead_of_map.stderr | 2 +- tests/ui/bind_instead_of_map_multipart.stderr | 10 +-- tests/ui/crashes/ice-7169.stderr | 2 +- tests/ui/crashes/ice-8250.stderr | 2 +- tests/ui/deref_addrof.stderr | 20 ++--- tests/ui/deref_addrof_double_trigger.stderr | 6 +- tests/ui/entry.stderr | 20 ++--- tests/ui/entry_btree.stderr | 2 +- tests/ui/entry_with_else.stderr | 14 ++-- tests/ui/expect_fun_call.stderr | 30 +++---- tests/ui/explicit_auto_deref.stderr | 78 +++++++++---------- tests/ui/explicit_deref_methods.stderr | 24 +++--- tests/ui/explicit_write.stderr | 26 +++---- tests/ui/extend_with_drain.stderr | 8 +- tests/ui/filter_map_next_fixable.stderr | 4 +- tests/ui/get_unwrap.stderr | 34 ++++---- .../ui/infallible_destructuring_match.stderr | 8 +- tests/ui/iter_overeager_cloned.stderr | 14 ++-- tests/ui/iter_with_drain.stderr | 12 +-- tests/ui/manual_filter.stderr | 30 +++---- tests/ui/manual_map_option.stderr | 42 +++++----- tests/ui/manual_map_option_2.stderr | 10 +-- tests/ui/manual_split_once.stderr | 28 +++---- tests/ui/manual_str_repeat.stderr | 20 ++--- tests/ui/map_collect_result_unit.stderr | 4 +- tests/ui/map_unwrap_or.stderr | 2 +- tests/ui/map_unwrap_or_fixable.stderr | 4 +- tests/ui/match_as_ref.stderr | 6 +- tests/ui/match_expr_like_matches_macro.stderr | 28 +++---- tests/ui/match_on_vec_items.stderr | 16 ++-- tests/ui/match_ref_pats.stderr | 4 +- tests/ui/match_same_arms2.stderr | 2 +- .../match_wildcard_for_single_variants.stderr | 20 ++--- tests/ui/methods_fixable.stderr | 2 +- tests/ui/missing_spin_loop.stderr | 12 +-- tests/ui/missing_spin_loop_no_std.stderr | 2 +- tests/ui/needless_borrow_pat.stderr | 24 +++--- tests/ui/needless_option_as_deref.stderr | 6 +- tests/ui/needless_splitn.stderr | 26 +++---- tests/ui/numbered_fields.stderr | 4 +- tests/ui/option_map_unit_fn_fixable.stderr | 38 ++++----- tests/ui/or_fun_call.stderr | 56 ++++++------- tests/ui/or_then_unwrap.stderr | 6 +- tests/ui/print_literal.stderr | 24 +++--- ...dundant_pattern_matching_drop_order.stderr | 44 +++++------ .../redundant_pattern_matching_ipaddr.stderr | 36 ++++----- .../redundant_pattern_matching_option.stderr | 56 ++++++------- .../ui/redundant_pattern_matching_poll.stderr | 36 ++++----- .../redundant_pattern_matching_result.stderr | 56 ++++++------- tests/ui/ref_binding_to_reference.stderr | 14 ++-- tests/ui/result_map_unit_fn_fixable.stderr | 36 ++++----- tests/ui/result_map_unit_fn_unfixable.stderr | 12 +-- tests/ui/single_match.stderr | 36 ++++----- tests/ui/single_match_else.stderr | 18 ++--- tests/ui/string_extend.stderr | 8 +- tests/ui/strlen_on_c_strings.stderr | 14 ++-- tests/ui/to_digit_is_some.stderr | 4 +- tests/ui/try_err.stderr | 22 +++--- tests/ui/unnecessary_clone.stderr | 12 +-- tests/ui/unwrap_or.stderr | 4 +- tests/ui/useless_asref.stderr | 22 +++--- tests/ui/wildcard_enum_match_arm.stderr | 12 +-- tests/ui/write_literal.stderr | 24 +++--- tests/ui/write_literal_2.stderr | 28 +++---- 105 files changed, 682 insertions(+), 680 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 73556c1053ecd..20378849c2254 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -589,7 +589,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { pat.spans, "this pattern creates a reference to a reference", |diag| { - diag.multipart_suggestion("try this", replacements, app); + diag.multipart_suggestion("try", replacements, app); }, ); } @@ -1531,7 +1531,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data Mutability::Not => "explicit `deref` method call", Mutability::Mut => "explicit `deref_mut` method call", }, - "try this", + "try", format!("{addr_of_str}{deref_str}{expr_str}"), app, ); @@ -1593,7 +1593,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data } else { format!("{prefix}{snip}") }; - diag.span_suggestion(data.span, "try this", sugg, app); + diag.span_suggestion(data.span, "try", sugg, app); }, ); }, @@ -1620,7 +1620,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data |diag| { let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0; - diag.span_suggestion(data.span, "try this", snip.into_owned(), app); + diag.span_suggestion(data.span, "try", snip.into_owned(), app); }, ); }, diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index ee5a875ade7b5..86e94a62a7844 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { MAP_ENTRY, expr.span, &format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), - "try this", + "try", sugg, app, ); diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 315df6c714ffc..4b9ca8c917e52 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { EXPLICIT_WRITE, expr.span, &format!("use of `{used}.unwrap()`"), - "try this", + "try", format!("{prefix}{sugg_mac}!({inputs_snippet})"), applicability, ); diff --git a/clippy_lints/src/init_numbered_fields.rs b/clippy_lints/src/init_numbered_fields.rs index 7e1548531f10c..f95d2c2edb1ef 100644 --- a/clippy_lints/src/init_numbered_fields.rs +++ b/clippy_lints/src/init_numbered_fields.rs @@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for NumberedFields { INIT_NUMBERED_FIELDS, e.span, "used a field initializer for a tuple struct", - "try this instead", + "try", snippet, appl, ); diff --git a/clippy_lints/src/loops/missing_spin_loop.rs b/clippy_lints/src/loops/missing_spin_loop.rs index 8412875b11b7e..f3bfe9e927d5f 100644 --- a/clippy_lints/src/loops/missing_spin_loop.rs +++ b/clippy_lints/src/loops/missing_spin_loop.rs @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &' MISSING_SPIN_LOOP, body.span, "busy-waiting loop should at least have a spin loop hint", - "try this", + "try", (if is_no_std_crate(cx) { "{ core::hint::spin_loop() }" } else { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index edcab6968cbe0..1b3a47e4acd93 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -226,7 +226,7 @@ fn lint_map_unit_fn( ); span_lint_and_then(cx, lint, expr.span, &msg, |diag| { - diag.span_suggestion(stmt.span, "try this", suggestion, applicability); + 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); @@ -241,7 +241,7 @@ fn lint_map_unit_fn( snippet_with_applicability(cx, var_arg.span, "_", &mut applicability), snippet_with_context(cx, reduced_expr_span, var_arg.span.ctxt(), "_", &mut applicability).0, ); - diag.span_suggestion(stmt.span, "try this", suggestion, applicability); + diag.span_suggestion(stmt.span, "try", suggestion, applicability); } else { let suggestion = format!( "if let {0}({1}) = {2} {{ ... }}", @@ -249,7 +249,7 @@ fn lint_map_unit_fn( snippet(cx, binding.pat.span, "_"), snippet(cx, var_arg.span, "_"), ); - diag.span_suggestion(stmt.span, "try this", suggestion, Applicability::HasPlaceholders); + diag.span_suggestion(stmt.span, "try", suggestion, Applicability::HasPlaceholders); } }); } diff --git a/clippy_lints/src/matches/infallible_destructuring_match.rs b/clippy_lints/src/matches/infallible_destructuring_match.rs index d18c92caba2a6..3329f93b73c4a 100644 --- a/clippy_lints/src/matches/infallible_destructuring_match.rs +++ b/clippy_lints/src/matches/infallible_destructuring_match.rs @@ -28,7 +28,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool { local.span, "you seem to be trying to use `match` to destructure a single infallible pattern. \ Consider using `let`", - "try this", + "try", format!( "let {}({}{}) = {};", snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), diff --git a/clippy_lints/src/matches/manual_filter.rs b/clippy_lints/src/matches/manual_filter.rs index f6bf0e7aa1ad9..e0181a4757c04 100644 --- a/clippy_lints/src/matches/manual_filter.rs +++ b/clippy_lints/src/matches/manual_filter.rs @@ -143,7 +143,7 @@ fn check<'tcx>( MANUAL_FILTER, expr.span, "manual implementation of `Option::filter`", - "try this", + "try", if sugg_info.needs_brackets { format!( "{{ {}{}.filter({body_str}) }}", diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs index aaba239677fff..ed3d8b09fdcda 100644 --- a/clippy_lints/src/matches/manual_map.rs +++ b/clippy_lints/src/matches/manual_map.rs @@ -58,7 +58,7 @@ fn check<'tcx>( MANUAL_MAP, expr.span, "manual implementation of `Option::map`", - "try this", + "try", if sugg_info.needs_brackets { format!( "{{ {}{}.map({}) }}", diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs index 2818f030b7a63..a6392b7aaec27 100644 --- a/clippy_lints/src/matches/match_as_ref.rs +++ b/clippy_lints/src/matches/match_as_ref.rs @@ -46,7 +46,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: MATCH_AS_REF, expr.span, &format!("use `{suggestion}()` instead"), - "try this", + "try", format!( "{}.{suggestion}(){cast}", snippet_with_applicability(cx, ex.span, "_", &mut applicability), diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index 0064619ef89d1..69f6c59beb35d 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -139,7 +139,7 @@ where MATCH_LIKE_MATCHES_MACRO, expr.span, &format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }), - "try this", + "try", format!( "{}matches!({}, {pat_and_guard})", if b0 { "" } else { "!" }, diff --git a/clippy_lints/src/matches/match_on_vec_items.rs b/clippy_lints/src/matches/match_on_vec_items.rs index 2917f85c45f53..89dcac4d8494c 100644 --- a/clippy_lints/src/matches/match_on_vec_items.rs +++ b/clippy_lints/src/matches/match_on_vec_items.rs @@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) { MATCH_ON_VEC_ITEMS, scrutinee.span, "indexing into a vector may panic", - "try this", + "try", format!( "{}.get({})", snippet(cx, vec.span, ".."), diff --git a/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs index 3126b590180e6..8d22ceb47f859 100644 --- a/clippy_lints/src/matches/match_wild_enum.rs +++ b/clippy_lints/src/matches/match_wild_enum.rs @@ -143,7 +143,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { MATCH_WILDCARD_FOR_SINGLE_VARIANTS, wildcard_span, "wildcard matches only a single variant and will also match any future added variants", - "try this", + "try", format_suggestion(x), Applicability::MaybeIncorrect, ), @@ -161,7 +161,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { WILDCARD_ENUM_MATCH_ARM, wildcard_span, message, - "try this", + "try", suggestions.join(" | "), Applicability::MaybeIncorrect, ); diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index 479cfd835126c..43d2ab9f60e38 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -175,7 +175,7 @@ fn find_sugg_for_if_let<'tcx>( .maybe_par() .to_string(); - diag.span_suggestion(span, "try this", format!("{keyword} {sugg}.{good_method}"), app); + diag.span_suggestion(span, "try", format!("{keyword} {sugg}.{good_method}"), app); if needs_drop { diag.note("this will change drop order of the result, as well as all temporaries"); @@ -200,7 +200,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op REDUNDANT_PATTERN_MATCHING, span, &format!("redundant pattern matching, consider using `{good_method}`"), - "try this", + "try", format!("{}.{good_method}", snippet(cx, result_expr.span, "_")), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 35627d6c6491a..6b05c6bfffdc5 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -136,7 +136,7 @@ fn report_single_pattern( } }; - span_lint_and_sugg(cx, lint, expr.span, msg, "try this", sugg, app); + span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app); } fn check_opt_like<'a>( diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index 3a7f1e034f310..99a748489b470 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -70,7 +70,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine TRY_ERR, expr.span, "returning an `Err(_)` with the `?` operator", - "try this", + "try", suggestion, applicability, ); diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 00853348840ed..883a5505827e1 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -87,7 +87,7 @@ pub(crate) trait BindInsteadOfMap { BIND_INSTEAD_OF_MAP, expr.span, &msg, - "try this", + "try", note, app, ); @@ -124,7 +124,7 @@ pub(crate) trait BindInsteadOfMap { span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| { multispan_sugg_with_applicability( diag, - "try this", + "try", Applicability::MachineApplicable, std::iter::once((span, Self::GOOD_METHOD_NAME.into())).chain( suggs diff --git a/clippy_lints/src/methods/clone_on_ref_ptr.rs b/clippy_lints/src/methods/clone_on_ref_ptr.rs index 5e8ad0861f33d..ddf3c9f27df29 100644 --- a/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -42,7 +42,7 @@ pub(super) fn check( CLONE_ON_REF_PTR, expr.span, "using `.clone()` on a ref-counted pointer", - "try this", + "try", format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)), app, ); diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index 92d21bb893262..862a7cec77510 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -144,7 +144,7 @@ pub(super) fn check<'tcx>( EXPECT_FUN_CALL, span_replace_word, &format!("use of `{name}` followed by a function call"), - "try this", + "try", format!("unwrap_or_else({closure_args} panic!({sugg}))"), applicability, ); @@ -162,7 +162,7 @@ pub(super) fn check<'tcx>( EXPECT_FUN_CALL, span_replace_word, &format!("use of `{name}` followed by a function call"), - "try this", + "try", format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"), applicability, ); diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 37b28463527cc..495b266529bdc 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: EXTEND_WITH_DRAIN, expr.span, "use of `extend` instead of `append` for adding the full range of a second vector", - "try this", + "try", format!( "{}.append({}{})", snippet_with_applicability(cx, recv.span, "..", &mut applicability), diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index 175e04f8ac061..3f89e59314874 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( FILTER_MAP_NEXT, expr.span, msg, - "try this", + "try", format!("{iter_snippet}.find_map({filter_snippet})"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs index edcec0fc1015e..ad71b49461904 100644 --- a/clippy_lints/src/methods/filter_next.rs +++ b/clippy_lints/src/methods/filter_next.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( FILTER_NEXT, expr.span, msg, - "try this", + "try", format!("{iter_snippet}.find({filter_snippet})"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index e35fb12ed7910..a8f090d1de173 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -71,7 +71,7 @@ pub(super) fn check<'tcx>( GET_UNWRAP, span, &format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"), - "try this", + "try", format!( "{borrow_str}{}[{get_args_str}]", snippet_with_applicability(cx, recv.span, "..", &mut applicability) diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs index b4210d875104b..9f7ec19aa598a 100644 --- a/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -51,7 +51,7 @@ pub(super) fn check<'tcx>( if let Some(mut snip) = snippet_opt(cx, method_span) { snip.push_str(trailing_clone); let replace_span = expr.span.with_lo(cloned_recv.span.hi()); - diag.span_suggestion(replace_span, "try this", snip, Applicability::MachineApplicable); + diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable); } } ); diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs index f6772c5c6b369..2ab721ace8487 100644 --- a/clippy_lints/src/methods/iter_with_drain.rs +++ b/clippy_lints/src/methods/iter_with_drain.rs @@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span ITER_WITH_DRAIN, span.with_hi(expr.span.hi()), &format!("`drain(..)` used on a `{ty_name}`"), - "try this", + "try", "into_iter()".to_string(), Applicability::MaybeIncorrect, ); diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index a08f7254053fe..ab13d30d84529 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -88,7 +88,7 @@ pub(super) fn check( MANUAL_STR_REPEAT, collect_expr.span, "manual implementation of `str::repeat` using iterators", - "try this", + "try", format!("{val_str}.repeat({count_snip})"), app ) diff --git a/clippy_lints/src/methods/map_collect_result_unit.rs b/clippy_lints/src/methods/map_collect_result_unit.rs index a0300d278709d..36c7ddc973cff 100644 --- a/clippy_lints/src/methods/map_collect_result_unit.rs +++ b/clippy_lints/src/methods/map_collect_result_unit.rs @@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr MAP_COLLECT_RESULT_UNIT, expr.span, "`.map().collect()` can be replaced with `.try_for_each()`", - "try this", + "try", format!( "{}.try_for_each({})", snippet(cx, iter.span, ".."), diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 3122f72ee9155..2c60e85fa908d 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -63,7 +63,7 @@ pub(super) fn check<'tcx>( MAP_UNWRAP_OR, expr.span, msg, - "try this", + "try", format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/needless_option_as_deref.rs b/clippy_lints/src/methods/needless_option_as_deref.rs index 7030baf19ff5c..c18bfa1b80263 100644 --- a/clippy_lints/src/methods/needless_option_as_deref.rs +++ b/clippy_lints/src/methods/needless_option_as_deref.rs @@ -29,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name NEEDLESS_OPTION_AS_DEREF, expr.span, "derefed type is same as origin", - "try this", + "try", snippet_opt(cx, recv.span).unwrap(), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index 7ce28ea93e01a..9165c1248f0aa 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( OR_FUN_CALL, method_span.with_hi(span.hi()), &format!("use of `{name}` followed by a call to `{path}`"), - "try this", + "try", format!("{sugg}()"), Applicability::MachineApplicable, ); @@ -139,7 +139,7 @@ pub(super) fn check<'tcx>( OR_FUN_CALL, span_replace_word, &format!("use of `{name}` followed by a function call"), - "try this", + "try", format!("{name}_{suffix}({sugg})"), app, ); diff --git a/clippy_lints/src/methods/or_then_unwrap.rs b/clippy_lints/src/methods/or_then_unwrap.rs index 55ba6e262df7e..d65082173b3fc 100644 --- a/clippy_lints/src/methods/or_then_unwrap.rs +++ b/clippy_lints/src/methods/or_then_unwrap.rs @@ -50,7 +50,7 @@ pub(super) fn check<'tcx>( OR_THEN_UNWRAP, unwrap_expr.span.with_lo(or_span.lo()), title, - "try this", + "try", suggestion, applicability, ); diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 88a3c2620a406..41986551da472 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -55,7 +55,7 @@ fn lint_needless(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_ NEEDLESS_SPLITN, expr.span, &format!("unnecessary use of `{r}splitn`"), - "try this", + "try", format!( "{}.{r}split({})", snippet_with_context(cx, self_arg.span, expr.span.ctxt(), "..", &mut app).0, @@ -110,7 +110,7 @@ fn check_manual_split_once( IterUsageKind::Nth(_) => return, }; - span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app); + span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try", sugg, app); } /// checks for diff --git a/clippy_lints/src/methods/string_extend_chars.rs b/clippy_lints/src/methods/string_extend_chars.rs index 2c20c6d752d70..c7885f689d75b 100644 --- a/clippy_lints/src/methods/string_extend_chars.rs +++ b/clippy_lints/src/methods/string_extend_chars.rs @@ -34,7 +34,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr STRING_EXTEND_CHARS, expr.span, "calling `.extend(_.chars())`", - "try this", + "try", format!( "{}.push_str({ref_str}{})", snippet_with_applicability(cx, recv.span, "..", &mut applicability), diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index c1139d84e2f47..b5f810eddf4a0 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -37,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, USELESS_ASREF, expr.span, &format!("this call to `{call_name}` does nothing"), - "try this", + "try", snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(), applicability, ); diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index a642e2da3ba12..db870ec4c5b6d 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -94,7 +94,7 @@ impl EarlyLintPass for DerefAddrOf { DEREF_ADDROF, e.span, "immediately dereferencing a reference", - "try this", + "try", sugg.to_string(), applicability, ); diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index 2f2e84fa35a12..b3db5e9a42214 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { STRLEN_ON_C_STRINGS, span, "using `libc::strlen` on a `CString` or `CStr` value", - "try this", + "try", format!("{val_name}.{method_name}().len()"), app, ); diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs index 2512500a6be73..f1b703fde0e62 100644 --- a/clippy_lints/src/to_digit_is_some.rs +++ b/clippy_lints/src/to_digit_is_some.rs @@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { TO_DIGIT_IS_SOME, expr.span, "use of `.to_digit(..).is_some()`", - "try this", + "try", if is_method_call { format!("{char_arg_snip}.is_digit({radix_snip})") } else { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index f194dc5d4b2ef..8f1363b6074ad 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -522,7 +522,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { { let replacement = replacement.replace('{', "{{").replace('}', "}}"); diag.multipart_suggestion( - "try this", + "try", vec![(*placeholder_span, replacement), (removal_span, String::new())], Applicability::MachineApplicable, ); diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs index 15e5cdd6992cc..98019c7552767 100644 --- a/tests/lint_message_convention.rs +++ b/tests/lint_message_convention.rs @@ -18,18 +18,20 @@ impl Message { fn new(path: PathBuf) -> Self { // we don't want the first letter after "error: ", "help: " ... to be capitalized // also no punctuation (except for "?" ?) at the end of a line + // Prefer "try" over "try this". static REGEX_SET: LazyLock = LazyLock::new(|| { RegexSet::new([ "error: [A-Z]", "help: [A-Z]", "warning: [A-Z]", "note: [A-Z]", - "try this: [A-Z]", + "try: [A-Z]", "error: .*[.!]$", "help: .*[.!]$", "warning: .*[.!]$", "note: .*[.!]$", - "try this: .*[.!]$", + "try: .*[.!]$", + "try this", ]) .unwrap() }); diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr index 6ec79a618de14..eb1180e60b807 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr @@ -30,7 +30,7 @@ LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^ | = note: `-D clippy::print-literal` implied by `-D warnings` -help: try this +help: try | LL - println!("Hello {} is {:.*}", "x", local_i32, local_f64); LL + println!("Hello x is {:.*}", local_i32, local_f64); diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index eb66a5cf50ba9..aed29a51c1dd5 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -2,7 +2,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/unwrap_used.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` | = note: `-D clippy::get-unwrap` implied by `-D warnings` @@ -19,7 +19,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:41:17 @@ -33,7 +33,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:42:17 @@ -47,7 +47,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:43:17 @@ -61,7 +61,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more --> $DIR/unwrap_used.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:44:17 @@ -75,7 +75,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more --> $DIR/unwrap_used.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:45:17 @@ -89,7 +89,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/unwrap_used.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:49:22 @@ -103,7 +103,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor --> $DIR/unwrap_used.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:54:10 @@ -117,7 +117,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor --> $DIR/unwrap_used.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:55:10 @@ -131,7 +131,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more --> $DIR/unwrap_used.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:56:10 @@ -145,7 +145,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and --> $DIR/unwrap_used.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:57:10 @@ -159,7 +159,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc --> $DIR/unwrap_used.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:69:17 @@ -173,7 +173,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more --> $DIR/unwrap_used.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:70:17 @@ -187,13 +187,13 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/unwrap_used.rs:77:13 | LL | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/unwrap_used.rs:95:17 | LL | let _ = Box::new([0]).get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&Box::new([0])[1]` error: aborting due to 28 previous errors diff --git a/tests/ui/bind_instead_of_map.stderr b/tests/ui/bind_instead_of_map.stderr index b6a81d21bb200..f17fee7460dc2 100644 --- a/tests/ui/bind_instead_of_map.stderr +++ b/tests/ui/bind_instead_of_map.stderr @@ -14,7 +14,7 @@ error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed --> $DIR/bind_instead_of_map.rs:10:13 | LL | let _ = x.and_then(|o| Some(o + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.map(|o| o + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map(|o| o + 1)` error: using `Result.and_then(Ok)`, which is a no-op --> $DIR/bind_instead_of_map.rs:16:13 diff --git a/tests/ui/bind_instead_of_map_multipart.stderr b/tests/ui/bind_instead_of_map_multipart.stderr index 0152a93feee42..cedbca785610a 100644 --- a/tests/ui/bind_instead_of_map_multipart.stderr +++ b/tests/ui/bind_instead_of_map_multipart.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(clippy::bind_instead_of_map)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: try this +help: try | LL | let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); | ~~~ ~ ~~~~~~~ @@ -20,7 +20,7 @@ error: using `Result.and_then(|x| Ok(y))`, which is more succinctly expressed as LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try | LL | let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); | ~~~ ~ ~~~~~~~ @@ -31,7 +31,7 @@ error: using `Result.or_else(|x| Err(y))`, which is more succinctly expressed as LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try | LL | let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() }); | ~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~ @@ -48,7 +48,7 @@ LL | | } LL | | }); | |______^ | -help: try this +help: try | LL ~ Some("42").map(|s| { LL | if { @@ -82,7 +82,7 @@ error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try | LL | let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) }); | ~~~ ~~~~ ~~~~~~~~ diff --git a/tests/ui/crashes/ice-7169.stderr b/tests/ui/crashes/ice-7169.stderr index 84e0af3f0d0a9..0cd02851640e6 100644 --- a/tests/ui/crashes/ice-7169.stderr +++ b/tests/ui/crashes/ice-7169.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/ice-7169.rs:10:12 | LL | if let Ok(_) = Ok::<_, ()>(A::::default()) {} - | -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::::default()).is_ok()` + | -------^^^^^-------------------------------------- help: try: `if Ok::<_, ()>(A::::default()).is_ok()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` diff --git a/tests/ui/crashes/ice-8250.stderr b/tests/ui/crashes/ice-8250.stderr index 8ed8f3b3a0642..e6f3644ef34f2 100644 --- a/tests/ui/crashes/ice-8250.stderr +++ b/tests/ui/crashes/ice-8250.stderr @@ -2,7 +2,7 @@ error: unnecessary use of `splitn` --> $DIR/ice-8250.rs:2:13 | LL | let _ = s[1..].splitn(2, '.').next()?; - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split('.')` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `s[1..].split('.')` | = note: `-D clippy::needless-splitn` implied by `-D warnings` diff --git a/tests/ui/deref_addrof.stderr b/tests/ui/deref_addrof.stderr index e0287522fc56f..9dd1e246b3e45 100644 --- a/tests/ui/deref_addrof.stderr +++ b/tests/ui/deref_addrof.stderr @@ -2,7 +2,7 @@ error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:24:13 | LL | let b = *&a; - | ^^^ help: try this: `a` + | ^^^ help: try: `a` | = note: `-D clippy::deref-addrof` implied by `-D warnings` @@ -10,49 +10,49 @@ error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:26:13 | LL | let b = *&get_number(); - | ^^^^^^^^^^^^^^ help: try this: `get_number()` + | ^^^^^^^^^^^^^^ help: try: `get_number()` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:31:13 | LL | let b = *&bytes[1..2][0]; - | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` + | ^^^^^^^^^^^^^^^^ help: try: `bytes[1..2][0]` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:35:13 | LL | let b = *&(a); - | ^^^^^ help: try this: `(a)` + | ^^^^^ help: try: `(a)` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:37:13 | LL | let b = *(&a); - | ^^^^^ help: try this: `a` + | ^^^^^ help: try: `a` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:40:13 | LL | let b = *((&a)); - | ^^^^^^^ help: try this: `a` + | ^^^^^^^ help: try: `a` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:42:13 | LL | let b = *&&a; - | ^^^^ help: try this: `&a` + | ^^^^ help: try: `&a` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:44:14 | LL | let b = **&aref; - | ^^^^^^ help: try this: `aref` + | ^^^^^^ help: try: `aref` error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:54:17 | LL | inline!(*& $(@expr self)) - | ^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)` + | ^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` | = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -60,7 +60,7 @@ error: immediately dereferencing a reference --> $DIR/deref_addrof.rs:58:17 | LL | inline!(*&mut $(@expr self)) - | ^^^^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)` + | ^^^^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` | = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/deref_addrof_double_trigger.stderr b/tests/ui/deref_addrof_double_trigger.stderr index 2c55a4ed6acdb..6fa5069b6b4bd 100644 --- a/tests/ui/deref_addrof_double_trigger.stderr +++ b/tests/ui/deref_addrof_double_trigger.stderr @@ -2,7 +2,7 @@ error: immediately dereferencing a reference --> $DIR/deref_addrof_double_trigger.rs:10:14 | LL | let b = **&&a; - | ^^^^ help: try this: `&a` + | ^^^^ help: try: `&a` | = note: `-D clippy::deref-addrof` implied by `-D warnings` @@ -10,13 +10,13 @@ error: immediately dereferencing a reference --> $DIR/deref_addrof_double_trigger.rs:14:17 | LL | let y = *&mut x; - | ^^^^^^^ help: try this: `x` + | ^^^^^^^ help: try: `x` error: immediately dereferencing a reference --> $DIR/deref_addrof_double_trigger.rs:21:18 | LL | let y = **&mut &mut x; - | ^^^^^^^^^^^^ help: try this: `&mut x` + | ^^^^^^^^^^^^ help: try: `&mut x` error: aborting due to 3 previous errors diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 2c4c49d2522ca..e8a003e9cf674 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -4,7 +4,7 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` LL | / if !m.contains_key(&k) { LL | | m.insert(k, v); LL | | } - | |_____^ help: try this: `m.entry(k).or_insert(v);` + | |_____^ help: try: `m.entry(k).or_insert(v);` | = note: `-D clippy::map-entry` implied by `-D warnings` @@ -20,7 +20,7 @@ LL | | } LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + if true { @@ -43,7 +43,7 @@ LL | | }; LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + if true { @@ -66,7 +66,7 @@ LL | | } LL | | } | |_____^ | -help: try this +help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { LL + if true { @@ -87,7 +87,7 @@ LL | | m.insert(k, v); LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + foo(); @@ -107,7 +107,7 @@ LL | | }; LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + match 0 { @@ -133,7 +133,7 @@ LL | | }; LL | | } | |_____^ | -help: try this +help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { LL + match 0 { @@ -157,7 +157,7 @@ LL | | } LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + foo(); @@ -192,7 +192,7 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` LL | / if !m.contains_key(&m!(k)) { LL | | m.insert(m!(k), m!(v)); LL | | } - | |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));` + | |_____^ help: try: `m.entry(m!(k)).or_insert_with(|| m!(v));` error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:152:5 @@ -204,7 +204,7 @@ LL | | m.insert(k, v); LL | | } | |_____^ | -help: try this +help: try | LL ~ m.entry(k).or_insert_with(|| { LL + let x = (String::new(), String::new()); diff --git a/tests/ui/entry_btree.stderr b/tests/ui/entry_btree.stderr index 5c6fcdf1a28c0..8f41581d6b6d9 100644 --- a/tests/ui/entry_btree.stderr +++ b/tests/ui/entry_btree.stderr @@ -8,7 +8,7 @@ LL | | } | |_____^ | = note: `-D clippy::map-entry` implied by `-D warnings` -help: try this +help: try | LL ~ if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) { LL + e.insert(v); diff --git a/tests/ui/entry_with_else.stderr b/tests/ui/entry_with_else.stderr index e0f6671b460ed..0d0eb964937e6 100644 --- a/tests/ui/entry_with_else.stderr +++ b/tests/ui/entry_with_else.stderr @@ -9,7 +9,7 @@ LL | | } | |_____^ | = note: `-D clippy::map-entry` implied by `-D warnings` -help: try this +help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Vacant(e) => { @@ -31,7 +31,7 @@ LL | | m.insert(k, v2); LL | | } | |_____^ | -help: try this +help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Occupied(mut e) => { @@ -53,7 +53,7 @@ LL | | foo(); LL | | } | |_____^ | -help: try this +help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { LL + e.insert(v); @@ -72,7 +72,7 @@ LL | | m.insert(k, v); LL | | } | |_____^ | -help: try this +help: try | LL ~ if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { LL + e.insert(v); @@ -91,7 +91,7 @@ LL | | m.insert(k, v2); LL | | } | |_____^ | -help: try this +help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Vacant(e) => { @@ -113,7 +113,7 @@ LL | | m.insert(k, v) LL | | }; | |_____^ | -help: try this +help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Occupied(mut e) => { @@ -137,7 +137,7 @@ LL | | None LL | | }; | |_____^ | -help: try this +help: try | LL ~ if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { LL + foo(); diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 36fb0e5de1567..a621f681d9810 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -2,7 +2,7 @@ error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:38:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` | = note: `-D clippy::expect-fun-call` implied by `-D warnings` @@ -10,85 +10,85 @@ error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:41:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:44:37 | LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:54:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:57:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:69:17 | LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:90:21 | LL | Some("foo").expect(&get_string()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:91:21 | LL | Some("foo").expect(get_string().as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:92:21 | LL | Some("foo").expect(get_string().as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:94:21 | LL | Some("foo").expect(get_static_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:95:21 | LL | Some("foo").expect(get_non_static_str(&0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:99:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:105:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:109:20 | LL | format_capture.expect(&format!("{error_code}")); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}"))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))` error: use of `expect` followed by a function call --> $DIR/expect_fun_call.rs:112:30 | LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` error: aborting due to 15 previous errors diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr index 91863abcc5d24..afc311e3f7cdd 100644 --- a/tests/ui/explicit_auto_deref.stderr +++ b/tests/ui/explicit_auto_deref.stderr @@ -2,7 +2,7 @@ error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:70:19 | LL | let _: &str = &*s; - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` | = note: `-D clippy::explicit-auto-deref` implied by `-D warnings` @@ -10,229 +10,229 @@ error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:71:19 | LL | let _: &str = &*{ String::new() }; - | ^^^^^^^^^^^^^^^^^^^ help: try this: `&{ String::new() }` + | ^^^^^^^^^^^^^^^^^^^ help: try: `&{ String::new() }` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:72:19 | LL | let _: &str = &mut *{ String::new() }; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut { String::new() }` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut { String::new() }` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:76:11 | LL | f_str(&*s); - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:80:13 | LL | f_str_t(&*s, &*s); // Don't lint second param. - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:83:24 | LL | let _: &Box = &**b; - | ^^^^ help: try this: `&b` + | ^^^^ help: try: `&b` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:89:7 | LL | c(&*s); - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:95:9 | LL | &**x - | ^^^^ help: try this: `x` + | ^^^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:99:11 | LL | { &**x } - | ^^^^ help: try this: `x` + | ^^^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:103:9 | LL | &**{ x } - | ^^^^^^^^ help: try this: `{ x }` + | ^^^^^^^^ help: try: `{ x }` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:107:9 | LL | &***x - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:124:12 | LL | f1(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:125:12 | LL | f2(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:126:12 | LL | f3(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:127:27 | LL | f4.callable_str()(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:128:12 | LL | f5(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:129:12 | LL | f6(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:130:27 | LL | f7.callable_str()(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:131:25 | LL | f8.callable_t()(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:132:12 | LL | f9(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:133:13 | LL | f10(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:134:26 | LL | f11.callable_t()(&*x); - | ^^^ help: try this: `&x` + | ^^^ help: try: `&x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:138:16 | LL | let _ = S1(&*s); - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:143:21 | LL | let _ = S2 { s: &*s }; - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:159:30 | LL | let _ = Self::S1(&**s); - | ^^^^ help: try this: `s` + | ^^^^ help: try: `s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:160:35 | LL | let _ = Self::S2 { s: &**s }; - | ^^^^ help: try this: `s` + | ^^^^ help: try: `s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:163:20 | LL | let _ = E1::S1(&*s); - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:164:25 | LL | let _ = E1::S2 { s: &*s }; - | ^^^ help: try this: `&s` + | ^^^ help: try: `&s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:182:13 | LL | let _ = (*b).foo; - | ^^^^ help: try this: `b` + | ^^^^ help: try: `b` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:183:13 | LL | let _ = (**b).foo; - | ^^^^^ help: try this: `b` + | ^^^^^ help: try: `b` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:198:19 | LL | let _ = f_str(*ref_str); - | ^^^^^^^^ help: try this: `ref_str` + | ^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:200:19 | LL | let _ = f_str(**ref_ref_str); - | ^^^^^^^^^^^^^ help: try this: `ref_ref_str` + | ^^^^^^^^^^^^^ help: try: `ref_ref_str` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:210:13 | LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references - | ^^^^^^^^ help: try this: `ref_str` + | ^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:211:12 | LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference - | ^^^^^^^^^^ help: try this: `ref_str` + | ^^^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:220:41 | LL | let _ = || -> &'static str { return *s }; - | ^^ help: try this: `s` + | ^^ help: try: `s` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:239:9 | LL | &**x - | ^^^^ help: try this: `x` + | ^^^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:262:8 | LL | c1(*x); - | ^^ help: try this: `x` + | ^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:265:20 | LL | return *x; - | ^^ help: try this: `x` + | ^^ help: try: `x` error: deref which would be done by auto-deref --> $DIR/explicit_auto_deref.rs:267:9 | LL | *x - | ^^ help: try this: `x` + | ^^ help: try: `x` error: aborting due to 39 previous errors diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index d025035b78942..362e559b21a57 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -2,7 +2,7 @@ error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:54:19 | LL | let b: &str = a.deref(); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` | = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` @@ -10,67 +10,67 @@ error: explicit `deref_mut` method call --> $DIR/explicit_deref_methods.rs:56:23 | LL | let b: &mut str = a.deref_mut(); - | ^^^^^^^^^^^^^ help: try this: `&mut **a` + | ^^^^^^^^^^^^^ help: try: `&mut **a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:59:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:59:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:61:20 | LL | println!("{}", a.deref()); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:64:11 | LL | match a.deref() { - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:68:28 | LL | let b: String = concat(a.deref()); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:70:13 | LL | let b = just_return(a).deref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:72:28 | LL | let b: String = concat(just_return(a).deref()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:74:19 | LL | let b: &str = a.deref().deref(); - | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` + | ^^^^^^^^^^^^^^^^^ help: try: `&**a` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:77:13 | LL | let b = opt_a.unwrap().deref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()` error: explicit `deref` method call --> $DIR/explicit_deref_methods.rs:114:31 | LL | let b: &str = expr_deref!(a.deref()); - | ^^^^^^^^^ help: try this: `&*a` + | ^^^^^^^^^ help: try: `&*a` error: aborting due to 12 previous errors diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 457e9c6271809..b3aa7274c6d00 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -2,7 +2,7 @@ error: use of `write!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:24:9 | LL | write!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `print!("test")` | = note: `-D clippy::explicit-write` implied by `-D warnings` @@ -10,73 +10,73 @@ error: use of `write!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:25:9 | LL | write!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:26:9 | LL | writeln!(std::io::stdout(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:27:9 | LL | writeln!(std::io::stderr(), "test").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` --> $DIR/explicit_write.rs:28:9 | LL | std::io::stdout().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` --> $DIR/explicit_write.rs:29:9 | LL | std::io::stderr().write_fmt(format_args!("test")).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` --> $DIR/explicit_write.rs:32:9 | LL | writeln!(std::io::stdout(), "test/ntest").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:33:9 | LL | writeln!(std::io::stderr(), "test/ntest").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test/ntest")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:36:9 | LL | writeln!(std::io::stderr(), "with {}", value).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {}", value)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {}", value)` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:37:9 | LL | writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {} {}", 2, value)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {} {}", 2, value)` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:38:9 | LL | writeln!(std::io::stderr(), "with {value}").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {value}")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {value}")` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:39:9 | LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("macro arg {}", one!())` error: use of `writeln!(stderr(), ...).unwrap()` --> $DIR/explicit_write.rs:41:9 | LL | writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("{:w$}", value, w = width)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("{:w$}", value, w = width)` error: aborting due to 13 previous errors diff --git a/tests/ui/extend_with_drain.stderr b/tests/ui/extend_with_drain.stderr index da14ddb25b373..eb2dd304d3707 100644 --- a/tests/ui/extend_with_drain.stderr +++ b/tests/ui/extend_with_drain.stderr @@ -2,7 +2,7 @@ error: use of `extend` instead of `append` for adding the full range of a second --> $DIR/extend_with_drain.rs:9:5 | LL | vec2.extend(vec1.drain(..)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec2.append(&mut vec1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec2.append(&mut vec1)` | = note: `-D clippy::extend-with-drain` implied by `-D warnings` @@ -10,19 +10,19 @@ error: use of `extend` instead of `append` for adding the full range of a second --> $DIR/extend_with_drain.rs:14:5 | LL | vec4.extend(vec3.drain(..)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec4.append(&mut vec3)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec4.append(&mut vec3)` error: use of `extend` instead of `append` for adding the full range of a second vector --> $DIR/extend_with_drain.rs:18:5 | LL | vec11.extend(return_vector().drain(..)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec11.append(&mut return_vector())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec11.append(&mut return_vector())` error: use of `extend` instead of `append` for adding the full range of a second vector --> $DIR/extend_with_drain.rs:49:5 | LL | y.extend(ref_x.drain(..)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `y.append(ref_x)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `y.append(ref_x)` error: aborting due to 4 previous errors diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr index a9fc6abe88fac..26d9c5e19da7f 100644 --- a/tests/ui/filter_map_next_fixable.stderr +++ b/tests/ui/filter_map_next_fixable.stderr @@ -2,7 +2,7 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly --> $DIR/filter_map_next_fixable.rs:9:32 | LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` | = note: `-D clippy::filter-map-next` implied by `-D warnings` @@ -10,7 +10,7 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly --> $DIR/filter_map_next_fixable.rs:22:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` error: aborting due to 2 previous errors diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index fd961420dc41d..e705bebac57a4 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -2,7 +2,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` | note: the lint level is defined here --> $DIR/get_unwrap.rs:10:9 @@ -23,7 +23,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:41:17 @@ -37,7 +37,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:42:17 @@ -51,7 +51,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:43:17 @@ -65,7 +65,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:44:17 @@ -79,7 +79,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:45:17 @@ -93,7 +93,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:49:22 @@ -107,7 +107,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor --> $DIR/get_unwrap.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:54:10 @@ -121,7 +121,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor --> $DIR/get_unwrap.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:55:10 @@ -135,7 +135,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more --> $DIR/get_unwrap.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:56:10 @@ -149,7 +149,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and --> $DIR/get_unwrap.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:57:10 @@ -163,7 +163,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc --> $DIR/get_unwrap.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:69:17 @@ -177,7 +177,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more --> $DIR/get_unwrap.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value --> $DIR/get_unwrap.rs:70:17 @@ -191,25 +191,25 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co --> $DIR/get_unwrap.rs:80:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:83:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:86:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise --> $DIR/get_unwrap.rs:103:33 | LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` error: aborting due to 30 previous errors diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index f8a50f0223d63..004260a1d648e 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -4,7 +4,7 @@ error: you seem to be trying to use `match` to destructure a single infallible p LL | / let data = match wrapper { LL | | SingleVariantEnum::Variant(i) => i, LL | | }; - | |______^ help: try this: `let SingleVariantEnum::Variant(data) = wrapper;` + | |______^ help: try: `let SingleVariantEnum::Variant(data) = wrapper;` | = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` @@ -14,7 +14,7 @@ error: you seem to be trying to use `match` to destructure a single infallible p LL | / let data = match wrapper { LL | | TupleStruct(i) => i, LL | | }; - | |______^ help: try this: `let TupleStruct(data) = wrapper;` + | |______^ help: try: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` --> $DIR/infallible_destructuring_match.rs:85:5 @@ -22,7 +22,7 @@ error: you seem to be trying to use `match` to destructure a single infallible p LL | / let data = match wrapper { LL | | TupleStructWithNonCopy(ref n) => n, LL | | }; - | |______^ help: try this: `let TupleStructWithNonCopy(ref data) = wrapper;` + | |______^ help: try: `let TupleStructWithNonCopy(ref data) = wrapper;` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` --> $DIR/infallible_destructuring_match.rs:104:5 @@ -30,7 +30,7 @@ error: you seem to be trying to use `match` to destructure a single infallible p LL | / let data = match wrapper { LL | | Ok(i) => i, LL | | }; - | |______^ help: try this: `let Ok(data) = wrapper;` + | |______^ help: try: `let Ok(data) = wrapper;` error: aborting due to 4 previous errors diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr index dcae7cecd33e9..eaac48be88094 100644 --- a/tests/ui/iter_overeager_cloned.stderr +++ b/tests/ui/iter_overeager_cloned.stderr @@ -4,7 +4,7 @@ error: unnecessarily eager cloning of iterator items LL | let _: Option = vec.iter().cloned().last(); | ^^^^^^^^^^---------------- | | - | help: try this: `.last().cloned()` + | help: try: `.last().cloned()` | = note: `-D clippy::iter-overeager-cloned` implied by `-D warnings` @@ -14,7 +14,7 @@ error: unnecessarily eager cloning of iterator items LL | let _: Option = vec.iter().chain(vec.iter()).cloned().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------- | | - | help: try this: `.next().cloned()` + | help: try: `.next().cloned()` error: unneeded cloning of iterator items --> $DIR/iter_overeager_cloned.rs:12:20 @@ -22,7 +22,7 @@ error: unneeded cloning of iterator items LL | let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------- | | - | help: try this: `.count()` + | help: try: `.count()` | = note: `-D clippy::redundant-clone` implied by `-D warnings` @@ -32,7 +32,7 @@ error: unnecessarily eager cloning of iterator items LL | let _: Vec<_> = vec.iter().cloned().take(2).collect(); | ^^^^^^^^^^----------------- | | - | help: try this: `.take(2).cloned()` + | help: try: `.take(2).cloned()` error: unnecessarily eager cloning of iterator items --> $DIR/iter_overeager_cloned.rs:16:21 @@ -40,7 +40,7 @@ error: unnecessarily eager cloning of iterator items LL | let _: Vec<_> = vec.iter().cloned().skip(2).collect(); | ^^^^^^^^^^----------------- | | - | help: try this: `.skip(2).cloned()` + | help: try: `.skip(2).cloned()` error: unnecessarily eager cloning of iterator items --> $DIR/iter_overeager_cloned.rs:18:13 @@ -48,7 +48,7 @@ error: unnecessarily eager cloning of iterator items LL | let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------- | | - | help: try this: `.nth(2).cloned()` + | help: try: `.nth(2).cloned()` error: unnecessarily eager cloning of iterator items --> $DIR/iter_overeager_cloned.rs:20:13 @@ -60,7 +60,7 @@ LL | | .cloned() LL | | .flatten(); | |__________________^ | -help: try this +help: try | LL ~ .iter() LL ~ .flatten().cloned(); diff --git a/tests/ui/iter_with_drain.stderr b/tests/ui/iter_with_drain.stderr index aa394439fa624..bfaed29a099c5 100644 --- a/tests/ui/iter_with_drain.stderr +++ b/tests/ui/iter_with_drain.stderr @@ -2,7 +2,7 @@ error: `drain(..)` used on a `Vec` --> $DIR/iter_with_drain.rs:11:34 | LL | let mut a: BinaryHeap<_> = a.drain(..).collect(); - | ^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^ help: try: `into_iter()` | = note: `-D clippy::iter-with-drain` implied by `-D warnings` @@ -10,31 +10,31 @@ error: `drain(..)` used on a `VecDeque` --> $DIR/iter_with_drain.rs:14:27 | LL | let mut a: Vec<_> = a.drain(..).collect(); - | ^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` --> $DIR/iter_with_drain.rs:15:34 | LL | let mut a: HashMap<_, _> = a.drain(..).map(|x| (x.clone(), x)).collect(); - | ^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` --> $DIR/iter_with_drain.rs:21:34 | LL | let mut a: BinaryHeap<_> = a.drain(0..).collect(); - | ^^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `VecDeque` --> $DIR/iter_with_drain.rs:24:27 | LL | let mut a: Vec<_> = a.drain(..a.len()).collect(); - | ^^^^^^^^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` --> $DIR/iter_with_drain.rs:25:34 | LL | let mut a: HashMap<_, _> = a.drain(0..a.len()).map(|x| (x.clone(), x)).collect(); - | ^^^^^^^^^^^^^^^^^ help: try this: `into_iter()` + | ^^^^^^^^^^^^^^^^^ help: try: `into_iter()` error: aborting due to 6 previous errors diff --git a/tests/ui/manual_filter.stderr b/tests/ui/manual_filter.stderr index 53dea9229306b..f62d3e960594b 100644 --- a/tests/ui/manual_filter.stderr +++ b/tests/ui/manual_filter.stderr @@ -8,7 +8,7 @@ LL | | if x > 0 { ... | LL | | }, LL | | }; - | |_____^ help: try this: `Some(0).filter(|&x| x <= 0)` + | |_____^ help: try: `Some(0).filter(|&x| x <= 0)` | = note: `-D clippy::manual-filter` implied by `-D warnings` @@ -22,7 +22,7 @@ LL | | None ... | LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(1).filter(|&x| x <= 0)` + | |_____^ help: try: `Some(1).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:29:5 @@ -34,7 +34,7 @@ LL | | None ... | LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(2).filter(|&x| x <= 0)` + | |_____^ help: try: `Some(2).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:40:5 @@ -46,7 +46,7 @@ LL | | Some(x) ... | LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(3).filter(|&x| x > 0)` + | |_____^ help: try: `Some(3).filter(|&x| x > 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:52:5 @@ -58,7 +58,7 @@ LL | | Some(x) => { ... | LL | | }, LL | | }; - | |_____^ help: try this: `y.filter(|&x| x <= 0)` + | |_____^ help: try: `y.filter(|&x| x <= 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:64:5 @@ -70,7 +70,7 @@ LL | | Some(x) ... | LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(5).filter(|&x| x > 0)` + | |_____^ help: try: `Some(5).filter(|&x| x > 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:75:5 @@ -82,7 +82,7 @@ LL | | Some(x) ... | LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(6).as_ref().filter(|&x| x > &0)` + | |_____^ help: try: `Some(6).as_ref().filter(|&x| x > &0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:87:5 @@ -94,7 +94,7 @@ LL | | Some(x) ... | LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(String::new()).filter(|x| external_cond)` + | |_____^ help: try: `Some(String::new()).filter(|x| external_cond)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:98:5 @@ -104,7 +104,7 @@ LL | | if external_cond { Some(x) } else { None } LL | | } else { LL | | None LL | | }; - | |_____^ help: try this: `Some(7).filter(|&x| external_cond)` + | |_____^ help: try: `Some(7).filter(|&x| external_cond)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:104:5 @@ -116,7 +116,7 @@ LL | | Some(x) ... | LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(8).filter(|&x| x != 0)` + | |_____^ help: try: `Some(8).filter(|&x| x != 0)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:115:5 @@ -128,7 +128,7 @@ LL | | Some(x) ... | LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(9).filter(|&x| x > 10 && x < 100)` + | |_____^ help: try: `Some(9).filter(|&x| x > 10 && x < 100)` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:141:5 @@ -142,7 +142,7 @@ LL | | None => None, LL | | }; | |_____^ | -help: try this +help: try | LL ~ Some(11).filter(|&x| { LL + println!("foo"); @@ -161,7 +161,7 @@ LL | | Some(x) ... | LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(14).filter(|&x| unsafe { f(x) })` + | |_____^ help: try: `Some(14).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:195:13 @@ -173,7 +173,7 @@ LL | | if f(x) { Some(x) } else { None } LL | | }, LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(15).filter(|&x| unsafe { f(x) })` + | |_____^ help: try: `Some(15).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` --> $DIR/manual_filter.rs:205:12 @@ -185,7 +185,7 @@ LL | | if x % 2 == 0 { Some(x) } else { None } LL | | } else { LL | | None LL | | }; - | |_____^ help: try this: `{ Some(16).filter(|&x| x % 2 == 0) }` + | |_____^ help: try: `{ Some(16).filter(|&x| x % 2 == 0) }` error: aborting due to 15 previous errors diff --git a/tests/ui/manual_map_option.stderr b/tests/ui/manual_map_option.stderr index cdc2c0e62a9b9..3f9caad4e89ed 100644 --- a/tests/ui/manual_map_option.stderr +++ b/tests/ui/manual_map_option.stderr @@ -5,7 +5,7 @@ LL | / match Some(0) { LL | | Some(_) => Some(2), LL | | None:: => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|_| 2)` + | |_____^ help: try: `Some(0).map(|_| 2)` | = note: `-D clippy::manual-map` implied by `-D warnings` @@ -16,7 +16,7 @@ LL | / match Some(0) { LL | | Some(x) => Some(x + 1), LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| x + 1)` + | |_____^ help: try: `Some(0).map(|x| x + 1)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:25:5 @@ -25,7 +25,7 @@ LL | / match Some("") { LL | | Some(x) => Some(x.is_empty()), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some("").map(|x| x.is_empty())` + | |_____^ help: try: `Some("").map(|x| x.is_empty())` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:30:5 @@ -35,7 +35,7 @@ LL | | Some(!x) LL | | } else { LL | | None LL | | }; - | |_____^ help: try this: `Some(0).map(|x| !x)` + | |_____^ help: try: `Some(0).map(|x| !x)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:37:5 @@ -44,7 +44,7 @@ LL | / match Some(0) { LL | | Some(x) => { Some(std::convert::identity(x)) } LL | | None => { None } LL | | }; - | |_____^ help: try this: `Some(0).map(std::convert::identity)` + | |_____^ help: try: `Some(0).map(std::convert::identity)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:42:5 @@ -53,7 +53,7 @@ LL | / match Some(&String::new()) { LL | | Some(x) => Some(str::len(x)), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))` + | |_____^ help: try: `Some(&String::new()).map(|x| str::len(x))` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:52:5 @@ -62,7 +62,7 @@ LL | / match &Some([0, 1]) { LL | | Some(x) => Some(x[0]), LL | | &None => None, LL | | }; - | |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])` + | |_____^ help: try: `Some([0, 1]).as_ref().map(|x| x[0])` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:57:5 @@ -71,7 +71,7 @@ LL | / match &Some(0) { LL | | &Some(x) => Some(x * 2), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| x * 2)` + | |_____^ help: try: `Some(0).map(|x| x * 2)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:62:5 @@ -80,7 +80,7 @@ LL | / match Some(String::new()) { LL | | Some(ref x) => Some(x.is_empty()), LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())` + | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:67:5 @@ -89,7 +89,7 @@ LL | / match &&Some(String::new()) { LL | | Some(x) => Some(x.len()), LL | | _ => None, LL | | }; - | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())` + | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:72:5 @@ -98,7 +98,7 @@ LL | / match &&Some(0) { LL | | &&Some(x) => Some(x + x), LL | | &&_ => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| x + x)` + | |_____^ help: try: `Some(0).map(|x| x + x)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:85:9 @@ -107,7 +107,7 @@ LL | / match &mut Some(String::new()) { LL | | Some(x) => Some(x.push_str("")), LL | | None => None, LL | | }; - | |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))` + | |_________^ help: try: `Some(String::new()).as_mut().map(|x| x.push_str(""))` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:91:5 @@ -116,7 +116,7 @@ LL | / match &mut Some(String::new()) { LL | | Some(ref x) => Some(x.len()), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())` + | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:96:5 @@ -125,7 +125,7 @@ LL | / match &mut &Some(String::new()) { LL | | Some(x) => Some(x.is_empty()), LL | | &mut _ => None, LL | | }; - | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())` + | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:101:5 @@ -134,7 +134,7 @@ LL | / match Some((0, 1, 2)) { LL | | Some((x, y, z)) => Some(x + y + z), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)` + | |_____^ help: try: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:106:5 @@ -143,7 +143,7 @@ LL | / match Some([1, 2, 3]) { LL | | Some([first, ..]) => Some(first), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)` + | |_____^ help: try: `Some([1, 2, 3]).map(|[first, ..]| first)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:111:5 @@ -152,7 +152,7 @@ LL | / match &Some((String::new(), "test")) { LL | | Some((x, y)) => Some((y, x)), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))` + | |_____^ help: try: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:169:5 @@ -161,7 +161,7 @@ LL | / match Some(0) { LL | | Some(x) => Some(vec![x]), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| vec![x])` + | |_____^ help: try: `Some(0).map(|x| vec![x])` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:174:5 @@ -170,7 +170,7 @@ LL | / match option_env!("") { LL | | Some(x) => Some(String::from(x)), LL | | None => None, LL | | }; - | |_____^ help: try this: `option_env!("").map(String::from)` + | |_____^ help: try: `option_env!("").map(String::from)` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:194:12 @@ -181,7 +181,7 @@ LL | | Some(x + 1) LL | | } else { LL | | None LL | | }; - | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }` + | |_____^ help: try: `{ Some(0).map(|x| x + 1) }` error: manual implementation of `Option::map` --> $DIR/manual_map_option.rs:202:12 @@ -192,7 +192,7 @@ LL | | Some(x + 1) LL | | } else { LL | | None LL | | }; - | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }` + | |_____^ help: try: `{ Some(0).map(|x| x + 1) }` error: aborting due to 21 previous errors diff --git a/tests/ui/manual_map_option_2.stderr b/tests/ui/manual_map_option_2.stderr index d35b6252fb870..8c78fcffca8c5 100644 --- a/tests/ui/manual_map_option_2.stderr +++ b/tests/ui/manual_map_option_2.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____^ | = note: `-D clippy::manual-map` implied by `-D warnings` -help: try this +help: try | LL ~ let _ = Some(0).map(|x| { LL + let y = (String::new(), String::new()); @@ -32,7 +32,7 @@ LL | | None => None, LL | | }; | |_____^ | -help: try this +help: try | LL ~ let _ = s.as_ref().map(|x| { LL + if let Some(ref s) = s { (x.clone(), s) } else { panic!() } @@ -47,7 +47,7 @@ LL | let _ = match Some(0) { LL | | Some(x) => Some(f(x)), LL | | None => None, LL | | }; - | |_________^ help: try this: `Some(0).map(|x| f(x))` + | |_________^ help: try: `Some(0).map(|x| f(x))` error: manual implementation of `Option::map` --> $DIR/manual_map_option_2.rs:67:13 @@ -57,7 +57,7 @@ LL | let _ = match Some(0) { LL | | Some(x) => unsafe { Some(f(x)) }, LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| unsafe { f(x) })` + | |_____^ help: try: `Some(0).map(|x| unsafe { f(x) })` error: manual implementation of `Option::map` --> $DIR/manual_map_option_2.rs:71:13 @@ -67,7 +67,7 @@ LL | let _ = match Some(0) { LL | | Some(x) => Some(unsafe { f(x) }), LL | | None => None, LL | | }; - | |_____^ help: try this: `Some(0).map(|x| unsafe { f(x) })` + | |_____^ help: try: `Some(0).map(|x| unsafe { f(x) })` error: aborting due to 5 previous errors diff --git a/tests/ui/manual_split_once.stderr b/tests/ui/manual_split_once.stderr index 78da5a16cc52b..f454f95b41dce 100644 --- a/tests/ui/manual_split_once.stderr +++ b/tests/ui/manual_split_once.stderr @@ -2,7 +2,7 @@ error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:13:13 | LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1` | = note: `-D clippy::manual-split-once` implied by `-D warnings` @@ -10,73 +10,73 @@ error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:14:13 | LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:15:18 | LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=')` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:18:13 | LL | let _ = s.splitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:21:13 | LL | let _ = s.splitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:24:13 | LL | let _ = s.splitn(2, '=').skip(1).next().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:27:17 | LL | let _ = s.splitn(2, '=').nth(1)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:28:17 | LL | let _ = s.splitn(2, '=').skip(1).next()?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:29:17 | LL | let _ = s.rsplitn(2, '=').nth(1)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:30:17 | LL | let _ = s.rsplitn(2, '=').skip(1).next()?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:38:13 | LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().0` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').unwrap().0` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:39:18 | LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:40:13 | LL | let _ = s.rsplitn(2, '=').nth(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=').map(|x| x.0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=').map(|x| x.0)` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:44:5 @@ -182,7 +182,7 @@ error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:141:13 | LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` --> $DIR/manual_split_once.rs:143:5 diff --git a/tests/ui/manual_str_repeat.stderr b/tests/ui/manual_str_repeat.stderr index bdfee7cab261e..331bb6ea575b3 100644 --- a/tests/ui/manual_str_repeat.stderr +++ b/tests/ui/manual_str_repeat.stderr @@ -2,7 +2,7 @@ error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:9:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)` | = note: `-D clippy::manual-str-repeat` implied by `-D warnings` @@ -10,55 +10,55 @@ error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:10:21 | LL | let _: String = std::iter::repeat('x').take(10).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"x".repeat(10)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"x".repeat(10)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:11:21 | LL | let _: String = std::iter::repeat('/'').take(10).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"'".repeat(10)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"'".repeat(10)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:12:21 | LL | let _: String = std::iter::repeat('"').take(10).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"/"".repeat(10)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"/"".repeat(10)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:16:13 | LL | let _ = repeat(x).take(count + 2).collect::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count + 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count + 2)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:25:21 | LL | let _: String = repeat(*x).take(count).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(*x).repeat(count)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*x).repeat(count)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:34:21 | LL | let _: String = repeat(x).take(count).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:46:21 | LL | let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Cow::Borrowed("test").repeat(count)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Cow::Borrowed("test").repeat(count)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:49:21 | LL | let _: String = repeat(x).take(count).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators --> $DIR/manual_str_repeat.rs:64:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)` error: aborting due to 10 previous errors diff --git a/tests/ui/map_collect_result_unit.stderr b/tests/ui/map_collect_result_unit.stderr index 8b06e13baa6b4..596e51e5741ee 100644 --- a/tests/ui/map_collect_result_unit.stderr +++ b/tests/ui/map_collect_result_unit.stderr @@ -2,7 +2,7 @@ error: `.map().collect()` can be replaced with `.try_for_each()` --> $DIR/map_collect_result_unit.rs:6:17 | LL | let _ = (0..3).map(|t| Err(t + 1)).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(0..3).try_for_each(|t| Err(t + 1))` | = note: `-D clippy::map-collect-result-unit` implied by `-D warnings` @@ -10,7 +10,7 @@ error: `.map().collect()` can be replaced with `.try_for_each()` --> $DIR/map_collect_result_unit.rs:7:32 | LL | let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(0..3).try_for_each(|t| Err(t + 1))` error: aborting due to 2 previous errors diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index 9f4a4a9ae6bf4..5b3c61acf7477 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -162,7 +162,7 @@ error: called `map().unwrap_or_else()` on a `Result` value. This can be do --> $DIR/map_unwrap_or.rs:99:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead --> $DIR/map_unwrap_or.rs:106:13 diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 1837bc2ca3b8b..71dc009f2ce61 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -5,7 +5,7 @@ LL | let _ = opt.map(|x| x + 1) | _____________^ LL | | // Should lint even though this call is on a separate line. LL | | .unwrap_or_else(|| 0); - | |_____________________________^ help: try this: `opt.map_or_else(|| 0, |x| x + 1)` + | |_____________________________^ help: try: `opt.map_or_else(|| 0, |x| x + 1)` | = note: `-D clippy::map-unwrap-or` implied by `-D warnings` @@ -16,7 +16,7 @@ LL | let _ = res.map(|x| x + 1) | _____________^ LL | | // should lint even though this call is on a separate line LL | | .unwrap_or_else(|_e| 0); - | |_______________________________^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` + | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` error: aborting due to 2 previous errors diff --git a/tests/ui/match_as_ref.stderr b/tests/ui/match_as_ref.stderr index c3b62849cb33f..252abf74bca30 100644 --- a/tests/ui/match_as_ref.stderr +++ b/tests/ui/match_as_ref.stderr @@ -6,7 +6,7 @@ LL | let borrowed: Option<&()> = match owned { LL | | None => None, LL | | Some(ref v) => Some(v), LL | | }; - | |_____^ help: try this: `owned.as_ref()` + | |_____^ help: try: `owned.as_ref()` | = note: `-D clippy::match-as-ref` implied by `-D warnings` @@ -18,7 +18,7 @@ LL | let borrow_mut: Option<&mut ()> = match mut_owned { LL | | None => None, LL | | Some(ref mut v) => Some(v), LL | | }; - | |_____^ help: try this: `mut_owned.as_mut()` + | |_____^ help: try: `mut_owned.as_mut()` error: use `as_ref()` instead --> $DIR/match_as_ref.rs:30:13 @@ -27,7 +27,7 @@ LL | / match self.source { LL | | Some(ref s) => Some(s), LL | | None => None, LL | | } - | |_____________^ help: try this: `self.source.as_ref().map(|x| x as _)` + | |_____________^ help: try: `self.source.as_ref().map(|x| x as _)` error: aborting due to 3 previous errors diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr index b72fe10b74804..c8c1e5da05fe0 100644 --- a/tests/ui/match_expr_like_matches_macro.stderr +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -6,7 +6,7 @@ LL | let _y = match x { LL | | Some(0) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `matches!(x, Some(0))` + | |_____^ help: try: `matches!(x, Some(0))` | = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` @@ -18,7 +18,7 @@ LL | let _w = match x { LL | | Some(_) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `x.is_some()` + | |_____^ help: try: `x.is_some()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -30,7 +30,7 @@ LL | let _z = match x { LL | | Some(_) => false, LL | | None => true, LL | | }; - | |_____^ help: try this: `x.is_none()` + | |_____^ help: try: `x.is_none()` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:33:15 @@ -40,13 +40,13 @@ LL | let _zz = match x { LL | | Some(r) if r == 0 => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)` + | |_____^ help: try: `!matches!(x, Some(r) if r == 0)` error: if let .. else expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:39:16 | LL | let _zzz = if let Some(5) = x { true } else { false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(x, Some(5))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:63:20 @@ -57,7 +57,7 @@ LL | | E::A(_) => true, LL | | E::B(_) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` + | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:73:20 @@ -70,7 +70,7 @@ LL | | } LL | | E::B(_) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` + | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:83:20 @@ -81,7 +81,7 @@ LL | | E::B(_) => false, LL | | E::C => false, LL | | _ => true, LL | | }; - | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)` + | |_________^ help: try: `!matches!(x, E::B(_) | E::C)` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:143:18 @@ -91,7 +91,7 @@ LL | let _z = match &z { LL | | Some(3) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(z, Some(3))` + | |_________^ help: try: `matches!(z, Some(3))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:152:18 @@ -101,7 +101,7 @@ LL | let _z = match &z { LL | | Some(3) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(&z, Some(3))` + | |_________^ help: try: `matches!(&z, Some(3))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:169:21 @@ -111,7 +111,7 @@ LL | let _ = match &z { LL | | AnEnum::X => true, LL | | _ => false, LL | | }; - | |_____________^ help: try this: `matches!(&z, AnEnum::X)` + | |_____________^ help: try: `matches!(&z, AnEnum::X)` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:183:20 @@ -121,7 +121,7 @@ LL | let _res = match &val { LL | | &Some(ref _a) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(&val, &Some(ref _a))` + | |_________^ help: try: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:195:20 @@ -131,7 +131,7 @@ LL | let _res = match &val { LL | | &Some(ref _a) => true, LL | | _ => false, LL | | }; - | |_________^ help: try this: `matches!(&val, &Some(ref _a))` + | |_________^ help: try: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:253:14 @@ -141,7 +141,7 @@ LL | let _y = match Some(5) { LL | | Some(0) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `matches!(Some(5), Some(0))` + | |_____^ help: try: `matches!(Some(5), Some(0))` error: aborting due to 14 previous errors diff --git a/tests/ui/match_on_vec_items.stderr b/tests/ui/match_on_vec_items.stderr index 9b1f052867e0f..fc4a3ce19463f 100644 --- a/tests/ui/match_on_vec_items.stderr +++ b/tests/ui/match_on_vec_items.stderr @@ -2,7 +2,7 @@ error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:10:11 | LL | match arr[idx] { - | ^^^^^^^^ help: try this: `arr.get(idx)` + | ^^^^^^^^ help: try: `arr.get(idx)` | = note: `-D clippy::match-on-vec-items` implied by `-D warnings` @@ -10,43 +10,43 @@ error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:17:11 | LL | match arr[range] { - | ^^^^^^^^^^ help: try this: `arr.get(range)` + | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:30:11 | LL | match arr[idx] { - | ^^^^^^^^ help: try this: `arr.get(idx)` + | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:37:11 | LL | match arr[range] { - | ^^^^^^^^^^ help: try this: `arr.get(range)` + | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:50:11 | LL | match arr[idx] { - | ^^^^^^^^ help: try this: `arr.get(idx)` + | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:57:11 | LL | match arr[range] { - | ^^^^^^^^^^ help: try this: `arr.get(range)` + | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:70:11 | LL | match arr[idx] { - | ^^^^^^^^ help: try this: `arr.get(idx)` + | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic --> $DIR/match_on_vec_items.rs:77:11 | LL | match arr[range] { - | ^^^^^^^^^^ help: try this: `arr.get(range)` + | ^^^^^^^^^^ help: try: `arr.get(range)` error: aborting due to 8 previous errors diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr index 7d9646c842ee8..1294e0fe56fd4 100644 --- a/tests/ui/match_ref_pats.stderr +++ b/tests/ui/match_ref_pats.stderr @@ -35,7 +35,7 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/match_ref_pats.rs:38:12 | LL | if let &None = a { - | -------^^^^^---- help: try this: `if a.is_none()` + | -------^^^^^---- help: try: `if a.is_none()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -43,7 +43,7 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/match_ref_pats.rs:43:12 | LL | if let &None = &b { - | -------^^^^^----- help: try this: `if b.is_none()` + | -------^^^^^----- help: try: `if b.is_none()` error: you don't need to add `&` to all patterns --> $DIR/match_ref_pats.rs:103:9 diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 7f0c70745ac0b..a734818757385 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -144,7 +144,7 @@ LL | | E::A => false, LL | | E::B => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `!matches!(x, E::A | E::B)` + | |_____^ help: try: `!matches!(x, E::A | E::B)` | = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` diff --git a/tests/ui/match_wildcard_for_single_variants.stderr b/tests/ui/match_wildcard_for_single_variants.stderr index 105b4c4b41d1e..40ff4fbd31606 100644 --- a/tests/ui/match_wildcard_for_single_variants.stderr +++ b/tests/ui/match_wildcard_for_single_variants.stderr @@ -2,7 +2,7 @@ error: wildcard matches only a single variant and will also match any future add --> $DIR/match_wildcard_for_single_variants.rs:24:13 | LL | _ => (), - | ^ help: try this: `Self::Rgb(..)` + | ^ help: try: `Self::Rgb(..)` | = note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings` @@ -10,55 +10,55 @@ error: wildcard matches only a single variant and will also match any future add --> $DIR/match_wildcard_for_single_variants.rs:34:9 | LL | _ => {}, - | ^ help: try this: `Foo::C` + | ^ help: try: `Foo::C` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:44:9 | LL | _ => {}, - | ^ help: try this: `Color::Blue` + | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:52:9 | LL | _ => {}, - | ^ help: try this: `Color::Blue` + | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:58:9 | LL | _ => {}, - | ^ help: try this: `Color::Blue` + | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:75:9 | LL | &_ => (), - | ^^ help: try this: `Color::Blue` + | ^^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:84:9 | LL | _ => (), - | ^ help: try this: `C::Blue` + | ^ help: try: `C::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:91:9 | LL | _ => (), - | ^ help: try this: `Color::Blue` + | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:126:13 | LL | _ => (), - | ^ help: try this: `Enum::__Private` + | ^ help: try: `Enum::__Private` error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:153:13 | LL | _ => 2, - | ^ help: try this: `Foo::B` + | ^ help: try: `Foo::B` error: aborting due to 10 previous errors diff --git a/tests/ui/methods_fixable.stderr b/tests/ui/methods_fixable.stderr index 187714c75fb95..6f45d100d2822 100644 --- a/tests/ui/methods_fixable.stderr +++ b/tests/ui/methods_fixable.stderr @@ -2,7 +2,7 @@ error: called `filter(..).next()` on an `Iterator`. This is more succinctly expr --> $DIR/methods_fixable.rs:11:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `v.iter().find(|&x| *x < 0)` | = note: `-D clippy::filter-next` implied by `-D warnings` diff --git a/tests/ui/missing_spin_loop.stderr b/tests/ui/missing_spin_loop.stderr index 485da00dc6407..5795c2c219067 100644 --- a/tests/ui/missing_spin_loop.stderr +++ b/tests/ui/missing_spin_loop.stderr @@ -2,7 +2,7 @@ error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:11:37 | LL | while b.load(Ordering::Acquire) {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` | = note: `-D clippy::missing-spin-loop` implied by `-D warnings` @@ -10,31 +10,31 @@ error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:13:37 | LL | while !b.load(Ordering::SeqCst) {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:15:46 | LL | while b.load(Ordering::Acquire) == false {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:17:49 | LL | while { true == b.load(Ordering::Acquire) } {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:19:93 | LL | while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop.rs:21:94 | LL | while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {} - | ^^ help: try this: `{ std::hint::spin_loop() }` + | ^^ help: try: `{ std::hint::spin_loop() }` error: aborting due to 6 previous errors diff --git a/tests/ui/missing_spin_loop_no_std.stderr b/tests/ui/missing_spin_loop_no_std.stderr index 2b3b6873c3c41..3322a7aae5f6a 100644 --- a/tests/ui/missing_spin_loop_no_std.stderr +++ b/tests/ui/missing_spin_loop_no_std.stderr @@ -2,7 +2,7 @@ error: busy-waiting loop should at least have a spin loop hint --> $DIR/missing_spin_loop_no_std.rs:13:37 | LL | while b.load(Ordering::Acquire) {} - | ^^ help: try this: `{ core::hint::spin_loop() }` + | ^^ help: try: `{ core::hint::spin_loop() }` | = note: `-D clippy::missing-spin-loop` implied by `-D warnings` diff --git a/tests/ui/needless_borrow_pat.stderr b/tests/ui/needless_borrow_pat.stderr index db3b52b8850e1..2d9b8f1590213 100644 --- a/tests/ui/needless_borrow_pat.stderr +++ b/tests/ui/needless_borrow_pat.stderr @@ -2,7 +2,7 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:59:14 | LL | Some(ref x) => x, - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` | = note: `-D clippy::needless-borrow` implied by `-D warnings` @@ -12,7 +12,7 @@ error: this pattern creates a reference to a reference LL | Some(ref x) => *x, | ^^^^^ | -help: try this +help: try | LL | Some(x) => x, | ~ ~ @@ -23,7 +23,7 @@ error: this pattern creates a reference to a reference LL | Some(ref x) => { | ^^^^^ | -help: try this +help: try | LL ~ Some(x) => { LL | f1(x); @@ -34,13 +34,13 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:81:14 | LL | Some(ref x) => m1!(x), - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:86:15 | LL | let _ = |&ref x: &&String| { - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:91:10 @@ -48,7 +48,7 @@ error: this pattern creates a reference to a reference LL | let (ref y,) = (&x,); | ^^^^^ | -help: try this +help: try | LL ~ let (y,) = (&x,); LL ~ let _: &String = y; @@ -58,7 +58,7 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:101:14 | LL | Some(ref x) => x.0, - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:111:14 @@ -66,7 +66,7 @@ error: this pattern creates a reference to a reference LL | E::A(ref x) | E::B(ref x) => *x, | ^^^^^ ^^^^^ | -help: try this +help: try | LL | E::A(x) | E::B(x) => x, | ~ ~ ~ @@ -75,7 +75,7 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:117:21 | LL | if let Some(ref x) = Some(&String::new()); - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:125:12 @@ -83,7 +83,7 @@ error: this pattern creates a reference to a reference LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ | -help: try this +help: try | LL ~ fn f2<'a>(&x: &&'a String) -> &'a String { LL | let _: &String = x; @@ -94,7 +94,7 @@ error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:132:11 | LL | fn f(&ref x: &&String) { - | ^^^^^ help: try this: `x` + | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference --> $DIR/needless_borrow_pat.rs:140:11 @@ -102,7 +102,7 @@ error: this pattern creates a reference to a reference LL | fn f(&ref x: &&String) { | ^^^^^ | -help: try this +help: try | LL ~ fn f(&x: &&String) { LL ~ let _: &String = x; diff --git a/tests/ui/needless_option_as_deref.stderr b/tests/ui/needless_option_as_deref.stderr index 20d28a968c917..4c0d502a20313 100644 --- a/tests/ui/needless_option_as_deref.stderr +++ b/tests/ui/needless_option_as_deref.stderr @@ -2,7 +2,7 @@ error: derefed type is same as origin --> $DIR/needless_option_as_deref.rs:9:29 | LL | let _: Option<&usize> = Some(&1).as_deref(); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)` + | ^^^^^^^^^^^^^^^^^^^ help: try: `Some(&1)` | = note: `-D clippy::needless-option-as-deref` implied by `-D warnings` @@ -10,13 +10,13 @@ error: derefed type is same as origin --> $DIR/needless_option_as_deref.rs:10:33 | LL | let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(&mut 1)` error: derefed type is same as origin --> $DIR/needless_option_as_deref.rs:14:13 | LL | let _ = x.as_deref_mut(); - | ^^^^^^^^^^^^^^^^ help: try this: `x` + | ^^^^^^^^^^^^^^^^ help: try: `x` error: aborting due to 3 previous errors diff --git a/tests/ui/needless_splitn.stderr b/tests/ui/needless_splitn.stderr index f607d8e1ab5f4..0005f758104a9 100644 --- a/tests/ui/needless_splitn.stderr +++ b/tests/ui/needless_splitn.stderr @@ -2,7 +2,7 @@ error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:14:13 | LL | let _ = str.splitn(2, '=').next(); - | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` | = note: `-D clippy::needless-splitn` implied by `-D warnings` @@ -10,73 +10,73 @@ error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:15:13 | LL | let _ = str.splitn(2, '=').nth(0); - | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:18:18 | LL | let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); - | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `rsplitn` --> $DIR/needless_splitn.rs:21:13 | LL | let _ = str.rsplitn(2, '=').next(); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `rsplitn` --> $DIR/needless_splitn.rs:22:13 | LL | let _ = str.rsplitn(2, '=').nth(0); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `rsplitn` --> $DIR/needless_splitn.rs:25:18 | LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:27:13 | LL | let _ = str.splitn(5, '=').next(); - | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:28:13 | LL | let _ = str.splitn(5, '=').nth(3); - | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:34:13 | LL | let _ = s.splitn(2, '=').next()?; - | ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')` + | ^^^^^^^^^^^^^^^^ help: try: `s.split('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:35:13 | LL | let _ = s.splitn(2, '=').nth(0)?; - | ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')` + | ^^^^^^^^^^^^^^^^ help: try: `s.split('=')` error: unnecessary use of `rsplitn` --> $DIR/needless_splitn.rs:36:13 | LL | let _ = s.rsplitn(2, '=').next()?; - | ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')` + | ^^^^^^^^^^^^^^^^^ help: try: `s.rsplit('=')` error: unnecessary use of `rsplitn` --> $DIR/needless_splitn.rs:37:13 | LL | let _ = s.rsplitn(2, '=').nth(0)?; - | ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')` + | ^^^^^^^^^^^^^^^^^ help: try: `s.rsplit('=')` error: unnecessary use of `splitn` --> $DIR/needless_splitn.rs:45:13 | LL | let _ = "key=value".splitn(2, '=').nth(0).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split('=')` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split('=')` error: aborting due to 13 previous errors diff --git a/tests/ui/numbered_fields.stderr b/tests/ui/numbered_fields.stderr index 60c0d7898063f..26f7ad9048b87 100644 --- a/tests/ui/numbered_fields.stderr +++ b/tests/ui/numbered_fields.stderr @@ -7,7 +7,7 @@ LL | | 0: 1u32, LL | | 1: 42, LL | | 2: 23u8, LL | | }; - | |_____^ help: try this instead: `TupleStruct(1u32, 42, 23u8)` + | |_____^ help: try: `TupleStruct(1u32, 42, 23u8)` | = note: `-D clippy::init-numbered-fields` implied by `-D warnings` @@ -20,7 +20,7 @@ LL | | 0: 1u32, LL | | 2: 2u8, LL | | 1: 3u32, LL | | }; - | |_____^ help: try this instead: `TupleStruct(1u32, 3u32, 2u8)` + | |_____^ help: try: `TupleStruct(1u32, 3u32, 2u8)` error: aborting due to 2 previous errors diff --git a/tests/ui/option_map_unit_fn_fixable.stderr b/tests/ui/option_map_unit_fn_fixable.stderr index 0305387b9f8ae..5be5f10b0177a 100644 --- a/tests/ui/option_map_unit_fn_fixable.stderr +++ b/tests/ui/option_map_unit_fn_fixable.stderr @@ -4,7 +4,7 @@ error: called `map(f)` on an `Option` value where `f` is a function that returns LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }` + | help: try: `if let Some(x_field) = x.field { do_nothing(x_field) }` | = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` @@ -14,7 +14,7 @@ error: called `map(f)` on an `Option` value where `f` is a function that returns LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }` + | help: try: `if let Some(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:42:5 @@ -22,7 +22,7 @@ error: called `map(f)` on an `Option` value where `f` is a function that returns LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(x_field) = x.field { diverge(x_field) }` + | help: try: `if let Some(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:48:5 @@ -30,7 +30,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` + | help: try: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:50:5 @@ -38,7 +38,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` + | help: try: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:53:5 @@ -46,7 +46,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:55:5 @@ -54,7 +54,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:57:5 @@ -62,7 +62,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + | help: try: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:59:5 @@ -70,7 +70,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` + | help: try: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:62:5 @@ -78,7 +78,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + | help: try: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:64:5 @@ -86,7 +86,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` + | help: try: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:66:5 @@ -94,7 +94,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + | help: try: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:68:5 @@ -102,7 +102,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` + | help: try: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:73:5 @@ -110,7 +110,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` + | help: try: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:75:5 @@ -118,7 +118,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + | help: try: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:77:5 @@ -126,7 +126,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` + | help: try: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:80:5 @@ -134,7 +134,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:82:5 @@ -142,7 +142,7 @@ error: called `map(f)` on an `Option` value where `f` is a function that returns LL | option().map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(a) = option() { do_nothing(a) }` + | help: try: `if let Some(a) = option() { do_nothing(a) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:84:5 @@ -150,7 +150,7 @@ error: called `map(f)` on an `Option` value where `f` is a closure that returns LL | option().map(|value| println!("{:?}", value)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Some(value) = option() { println!("{:?}", value) }` + | help: try: `if let Some(value) = option() { println!("{:?}", value) }` error: aborting due to 19 previous errors diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 0b5c686bec0d9..3965ae52aed1f 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -2,7 +2,7 @@ error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:54:22 | LL | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` + | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(make)` | = note: `-D clippy::or-fun-call` implied by `-D warnings` @@ -10,163 +10,163 @@ error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:57:14 | LL | with_new.unwrap_or(Vec::new()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:60:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:63:14 | LL | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` + | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:66:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` --> $DIR/or_fun_call.rs:69:24 | LL | with_default_trait.unwrap_or(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` --> $DIR/or_fun_call.rs:72:23 | LL | with_default_type.unwrap_or(u64::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:75:18 | LL | self_default.unwrap_or(::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(::default)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(::default)` error: use of `unwrap_or` followed by a call to `default` --> $DIR/or_fun_call.rs:78:18 | LL | real_default.unwrap_or(::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:81:14 | LL | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:84:21 | LL | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a call to `new` --> $DIR/or_fun_call.rs:87:19 | LL | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` --> $DIR/or_fun_call.rs:90:23 | LL | map_vec.entry(42).or_insert(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` + | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` --> $DIR/or_fun_call.rs:93:21 | LL | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` --> $DIR/or_fun_call.rs:96:25 | LL | btree_vec.entry(42).or_insert(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` + | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:99:21 | LL | let _ = stringy.unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:107:21 | LL | let _ = Some(1).unwrap_or(map[&1]); - | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` + | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:109:21 | LL | let _ = Some(1).unwrap_or(map[&1]); - | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` + | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: use of `or` followed by a function call --> $DIR/or_fun_call.rs:133:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:172:14 | LL | None.unwrap_or(ptr_to_ref(s)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:178:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:180:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:194:14 | LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:207:14 | LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:219:14 | LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:230:10 | LL | .unwrap_or(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `map_or` followed by a function call --> $DIR/or_fun_call.rs:255:25 | LL | let _ = Some(4).map_or(g(), |v| v); - | ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)` + | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)` error: use of `map_or` followed by a function call --> $DIR/or_fun_call.rs:256:25 | LL | let _ = Some(4).map_or(g(), f); - | ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)` + | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` error: aborting due to 28 previous errors diff --git a/tests/ui/or_then_unwrap.stderr b/tests/ui/or_then_unwrap.stderr index da88154c59f71..2a1a52407dc37 100644 --- a/tests/ui/or_then_unwrap.stderr +++ b/tests/ui/or_then_unwrap.stderr @@ -2,7 +2,7 @@ error: found `.or(Some(…)).unwrap()` --> $DIR/or_then_unwrap.rs:24:20 | LL | let _ = option.or(Some("fallback")).unwrap(); // should trigger lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or("fallback")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` | = note: `-D clippy::or-then-unwrap` implied by `-D warnings` @@ -10,13 +10,13 @@ error: found `.or(Ok(…)).unwrap()` --> $DIR/or_then_unwrap.rs:27:20 | LL | let _ = result.or::<&str>(Ok("fallback")).unwrap(); // should trigger lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or("fallback")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` error: found `.or(Some(…)).unwrap()` --> $DIR/or_then_unwrap.rs:31:31 | LL | let _ = option.map(|v| v).or(Some("fallback")).unwrap().to_string().chars(); // should trigger lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or("fallback")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` error: aborting due to 3 previous errors diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index 6404dacdafa56..71c8d188f1678 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -5,7 +5,7 @@ LL | print!("Hello {}", "world"); | ^^^^^^^ | = note: `-D clippy::print-literal` implied by `-D warnings` -help: try this +help: try | LL - print!("Hello {}", "world"); LL + print!("Hello world"); @@ -17,7 +17,7 @@ error: literal with an empty format string LL | println!("Hello {} {}", world, "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("Hello {} {}", world, "world"); LL + println!("Hello {} world", world); @@ -29,7 +29,7 @@ error: literal with an empty format string LL | println!("Hello {}", "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("Hello {}", "world"); LL + println!("Hello world"); @@ -41,7 +41,7 @@ error: literal with an empty format string LL | println!("{} {:.4}", "a literal", 5); | ^^^^^^^^^^^ | -help: try this +help: try | LL - println!("{} {:.4}", "a literal", 5); LL + println!("a literal {:.4}", 5); @@ -53,7 +53,7 @@ error: literal with an empty format string LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{0} {1}", "hello", "world"); LL + println!("hello {1}", "world"); @@ -65,7 +65,7 @@ error: literal with an empty format string LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{0} {1}", "hello", "world"); LL + println!("{0} world", "hello"); @@ -77,7 +77,7 @@ error: literal with an empty format string LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{1} {0}", "hello", "world"); LL + println!("world {0}", "hello"); @@ -89,7 +89,7 @@ error: literal with an empty format string LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{1} {0}", "hello", "world"); LL + println!("{1} hello", "world"); @@ -101,7 +101,7 @@ error: literal with an empty format string LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{foo} {bar}", foo = "hello", bar = "world"); LL + println!("hello {bar}", bar = "world"); @@ -113,7 +113,7 @@ error: literal with an empty format string LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{foo} {bar}", foo = "hello", bar = "world"); LL + println!("{foo} world", foo = "hello"); @@ -125,7 +125,7 @@ error: literal with an empty format string LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{bar} {foo}", foo = "hello", bar = "world"); LL + println!("world {foo}", foo = "hello"); @@ -137,7 +137,7 @@ error: literal with an empty format string LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - println!("{bar} {foo}", foo = "hello", bar = "world"); LL + println!("{bar} hello", bar = "world"); diff --git a/tests/ui/redundant_pattern_matching_drop_order.stderr b/tests/ui/redundant_pattern_matching_drop_order.stderr index e9ea3f2e6886c..28f33f0c95d70 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.stderr +++ b/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_drop_order.rs:17:12 | LL | if let Ok(_) = m.lock() {} - | -------^^^^^----------- help: try this: `if m.lock().is_ok()` + | -------^^^^^----------- help: try: `if m.lock().is_ok()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -12,7 +12,7 @@ error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 | LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} - | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()` + | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>(m.lock().unwrap().0).is_err()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -21,7 +21,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_drop_order.rs:21:16 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} - | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -30,7 +30,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_drop_order.rs:23:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { - | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -39,31 +39,31 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_drop_order.rs:26:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} - | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_drop_order.rs:27:12 | LL | if let Err(_) = Err::, _>(()) {} - | -------^^^^^^------------------------------------------ help: try this: `if Err::, _>(()).is_err()` + | -------^^^^^^------------------------------------------ help: try: `if Err::, _>(()).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 | LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} - | -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()` + | -------^^^^^----------------------------- help: try: `if Ok::<_, ()>(String::new()).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_drop_order.rs:30:12 | LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} - | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()` + | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>((String::new(), ())).is_err()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_drop_order.rs:33:12 | LL | if let Some(_) = Some(m.lock()) {} - | -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()` + | -------^^^^^^^----------------- help: try: `if Some(m.lock()).is_some()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -72,7 +72,7 @@ error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 | LL | if let Some(_) = Some(m.lock().unwrap().0) {} - | -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()` + | -------^^^^^^^---------------------------- help: try: `if Some(m.lock().unwrap().0).is_some()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -81,7 +81,7 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_drop_order.rs:37:16 | LL | if let None = None::> {} - | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` + | -------^^^^------------------------------------ help: try: `if None::>.is_none()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -90,7 +90,7 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_drop_order.rs:39:12 | LL | if let None = None::> { - | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` + | -------^^^^------------------------------------ help: try: `if None::>.is_none()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -99,25 +99,25 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_drop_order.rs:43:12 | LL | if let None = None::> {} - | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` + | -------^^^^------------------------------------ help: try: `if None::>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 | LL | if let Some(_) = Some(String::new()) {} - | -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()` + | -------^^^^^^^---------------------- help: try: `if Some(String::new()).is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_drop_order.rs:46:12 | LL | if let Some(_) = Some((String::new(), ())) {} - | -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()` + | -------^^^^^^^---------------------------- help: try: `if Some((String::new(), ())).is_some()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_drop_order.rs:49:12 | LL | if let Ready(_) = Ready(m.lock()) {} - | -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()` + | -------^^^^^^^^------------------ help: try: `if Ready(m.lock()).is_ready()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -126,7 +126,7 @@ error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 | LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} - | -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()` + | -------^^^^^^^^----------------------------- help: try: `if Ready(m.lock().unwrap().0).is_ready()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -135,7 +135,7 @@ error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_drop_order.rs:53:16 | LL | if let Pending = Pending::> {} - | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` + | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -144,7 +144,7 @@ error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_drop_order.rs:55:12 | LL | if let Pending = Pending::> { - | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` + | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` | = note: this will change drop order of the result, as well as all temporaries = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important @@ -153,19 +153,19 @@ error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_drop_order.rs:59:12 | LL | if let Pending = Pending::> {} - | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` + | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_drop_order.rs:61:12 | LL | if let Ready(_) = Ready(String::new()) {} - | -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()` + | -------^^^^^^^^----------------------- help: try: `if Ready(String::new()).is_ready()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_drop_order.rs:62:12 | LL | if let Ready(_) = Ready((String::new(), ())) {} - | -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()` + | -------^^^^^^^^----------------------------- help: try: `if Ready((String::new(), ())).is_ready()` error: aborting due to 22 previous errors diff --git a/tests/ui/redundant_pattern_matching_ipaddr.stderr b/tests/ui/redundant_pattern_matching_ipaddr.stderr index 6d1fb29646329..f34dc70983300 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 | LL | if let V4(_) = &ipaddr {} - | -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()` + | -------^^^^^---------- help: try: `if ipaddr.is_ipv4()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -10,25 +10,25 @@ error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} - | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:22:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} - | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} - | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:26:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} - | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:36:5 @@ -37,7 +37,7 @@ LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; - | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:41:5 @@ -46,7 +46,7 @@ LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; - | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` + | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:46:5 @@ -55,7 +55,7 @@ LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; - | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:51:5 @@ -64,49 +64,49 @@ LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; - | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` + | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:56:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { - | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:64:20 | LL | let _ = if let V4(_) = gen_ipaddr() { - | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()` + | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:66:19 | LL | } else if let V6(_) = gen_ipaddr() { - | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()` + | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} - | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:80:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} - | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} - | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:84:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} - | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` --> $DIR/redundant_pattern_matching_ipaddr.rs:86:5 @@ -115,7 +115,7 @@ LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; - | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` + | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` --> $DIR/redundant_pattern_matching_ipaddr.rs:91:5 @@ -124,7 +124,7 @@ LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; - | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` + | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: aborting due to 18 previous errors diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 717b603c496e3..097ca827a4260 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:15:12 | LL | if let None = None::<()> {} - | -------^^^^------------- help: try this: `if None::<()>.is_none()` + | -------^^^^------------- help: try: `if None::<()>.is_none()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -10,37 +10,37 @@ error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:17:12 | LL | if let Some(_) = Some(42) {} - | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` + | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:19:12 | LL | if let Some(_) = Some(42) { - | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` + | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:25:15 | LL | while let Some(_) = Some(42) {} - | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` + | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:27:15 | LL | while let None = Some(42) {} - | ----------^^^^----------- help: try this: `while Some(42).is_none()` + | ----------^^^^----------- help: try: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:29:15 | LL | while let None = None::<()> {} - | ----------^^^^------------- help: try this: `while None::<()>.is_none()` + | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:32:15 | LL | while let Some(_) = v.pop() { - | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` + | ----------^^^^^^^---------- help: try: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:40:5 @@ -49,7 +49,7 @@ LL | / match Some(42) { LL | | Some(_) => true, LL | | None => false, LL | | }; - | |_____^ help: try this: `Some(42).is_some()` + | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:45:5 @@ -58,7 +58,7 @@ LL | / match None::<()> { LL | | Some(_) => false, LL | | None => true, LL | | }; - | |_____^ help: try this: `None::<()>.is_none()` + | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:50:13 @@ -68,55 +68,55 @@ LL | let _ = match None::<()> { LL | | Some(_) => false, LL | | None => true, LL | | }; - | |_____^ help: try this: `None::<()>.is_none()` + | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:56:20 | LL | let _ = if let Some(_) = opt { true } else { false }; - | -------^^^^^^^------ help: try this: `if opt.is_some()` + | -------^^^^^^^------ help: try: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:62:20 | LL | let _ = if let Some(_) = gen_opt() { - | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` + | -------^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:64:19 | LL | } else if let None = gen_opt() { - | -------^^^^------------ help: try this: `if gen_opt().is_none()` + | -------^^^^------------ help: try: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:70:12 | LL | if let Some(..) = gen_opt() {} - | -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()` + | -------^^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:85:12 | LL | if let Some(_) = Some(42) {} - | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` + | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:87:12 | LL | if let None = None::<()> {} - | -------^^^^------------- help: try this: `if None::<()>.is_none()` + | -------^^^^------------- help: try: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:89:15 | LL | while let Some(_) = Some(42) {} - | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` + | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:91:15 | LL | while let None = None::<()> {} - | ----------^^^^------------- help: try this: `while None::<()>.is_none()` + | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:93:5 @@ -125,7 +125,7 @@ LL | / match Some(42) { LL | | Some(_) => true, LL | | None => false, LL | | }; - | |_____^ help: try this: `Some(42).is_some()` + | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:98:5 @@ -134,19 +134,19 @@ LL | / match None::<()> { LL | | Some(_) => false, LL | | None => true, LL | | }; - | |_____^ help: try this: `None::<()>.is_none()` + | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:106:12 | LL | if let None = *(&None::<()>) {} - | -------^^^^----------------- help: try this: `if (&None::<()>).is_none()` + | -------^^^^----------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:107:12 | LL | if let None = *&None::<()> {} - | -------^^^^--------------- help: try this: `if (&None::<()>).is_none()` + | -------^^^^--------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:113:5 @@ -155,7 +155,7 @@ LL | / match x { LL | | Some(_) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `x.is_some()` + | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:118:5 @@ -164,7 +164,7 @@ LL | / match x { LL | | None => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `x.is_none()` + | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:123:5 @@ -173,7 +173,7 @@ LL | / match x { LL | | Some(_) => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `x.is_none()` + | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:128:5 @@ -182,19 +182,19 @@ LL | / match x { LL | | None => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `x.is_some()` + | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_option.rs:143:13 | LL | let _ = matches!(x, Some(_)); - | ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` --> $DIR/redundant_pattern_matching_option.rs:145:13 | LL | let _ = matches!(x, None); - | ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()` + | ^^^^^^^^^^^^^^^^^ help: try: `x.is_none()` error: aborting due to 28 previous errors diff --git a/tests/ui/redundant_pattern_matching_poll.stderr b/tests/ui/redundant_pattern_matching_poll.stderr index b89fde35fcfa6..28d3606c4fb65 100644 --- a/tests/ui/redundant_pattern_matching_poll.stderr +++ b/tests/ui/redundant_pattern_matching_poll.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:17:12 | LL | if let Pending = Pending::<()> {} - | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` + | -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -10,31 +10,31 @@ error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:19:12 | LL | if let Ready(_) = Ready(42) {} - | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:21:12 | LL | if let Ready(_) = Ready(42) { - | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:27:15 | LL | while let Ready(_) = Ready(42) {} - | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` + | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:29:15 | LL | while let Pending = Ready(42) {} - | ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()` + | ----------^^^^^^^------------ help: try: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:31:15 | LL | while let Pending = Pending::<()> {} - | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` + | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:37:5 @@ -43,7 +43,7 @@ LL | / match Ready(42) { LL | | Ready(_) => true, LL | | Pending => false, LL | | }; - | |_____^ help: try this: `Ready(42).is_ready()` + | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:42:5 @@ -52,7 +52,7 @@ LL | / match Pending::<()> { LL | | Ready(_) => false, LL | | Pending => true, LL | | }; - | |_____^ help: try this: `Pending::<()>.is_pending()` + | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:47:13 @@ -62,49 +62,49 @@ LL | let _ = match Pending::<()> { LL | | Ready(_) => false, LL | | Pending => true, LL | | }; - | |_____^ help: try this: `Pending::<()>.is_pending()` + | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:53:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; - | -------^^^^^^^^------- help: try this: `if poll.is_ready()` + | -------^^^^^^^^------- help: try: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:57:20 | LL | let _ = if let Ready(_) = gen_poll() { - | -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()` + | -------^^^^^^^^------------- help: try: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:59:19 | LL | } else if let Pending = gen_poll() { - | -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()` + | -------^^^^^^^------------- help: try: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:75:12 | LL | if let Ready(_) = Ready(42) {} - | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:77:12 | LL | if let Pending = Pending::<()> {} - | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` + | -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:79:15 | LL | while let Ready(_) = Ready(42) {} - | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` + | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:81:15 | LL | while let Pending = Pending::<()> {} - | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` + | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` --> $DIR/redundant_pattern_matching_poll.rs:83:5 @@ -113,7 +113,7 @@ LL | / match Ready(42) { LL | | Ready(_) => true, LL | | Pending => false, LL | | }; - | |_____^ help: try this: `Ready(42).is_ready()` + | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` --> $DIR/redundant_pattern_matching_poll.rs:88:5 @@ -122,7 +122,7 @@ LL | / match Pending::<()> { LL | | Ready(_) => false, LL | | Pending => true, LL | | }; - | |_____^ help: try this: `Pending::<()>.is_pending()` + | |_____^ help: try: `Pending::<()>.is_pending()` error: aborting due to 18 previous errors diff --git a/tests/ui/redundant_pattern_matching_result.stderr b/tests/ui/redundant_pattern_matching_result.stderr index f6ce666bb4ffc..2b1ce9f54652b 100644 --- a/tests/ui/redundant_pattern_matching_result.stderr +++ b/tests/ui/redundant_pattern_matching_result.stderr @@ -2,7 +2,7 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:16:12 | LL | if let Ok(_) = &result {} - | -------^^^^^---------- help: try this: `if result.is_ok()` + | -------^^^^^---------- help: try: `if result.is_ok()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` @@ -10,25 +10,25 @@ error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:18:12 | LL | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + | -------^^^^^--------------------- help: try: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:20:12 | LL | if let Err(_) = Err::(42) {} - | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` + | -------^^^^^^---------------------- help: try: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:22:15 | LL | while let Ok(_) = Ok::(10) {} - | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` + | ----------^^^^^--------------------- help: try: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:24:15 | LL | while let Err(_) = Ok::(10) {} - | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` + | ----------^^^^^^--------------------- help: try: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:34:5 @@ -37,7 +37,7 @@ LL | / match Ok::(42) { LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; - | |_____^ help: try this: `Ok::(42).is_ok()` + | |_____^ help: try: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:39:5 @@ -46,7 +46,7 @@ LL | / match Ok::(42) { LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; - | |_____^ help: try this: `Ok::(42).is_err()` + | |_____^ help: try: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:44:5 @@ -55,7 +55,7 @@ LL | / match Err::(42) { LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; - | |_____^ help: try this: `Err::(42).is_err()` + | |_____^ help: try: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:49:5 @@ -64,73 +64,73 @@ LL | / match Err::(42) { LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; - | |_____^ help: try this: `Err::(42).is_ok()` + | |_____^ help: try: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:54:20 | LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; - | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` + | -------^^^^^--------------------- help: try: `if Ok::(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:62:20 | LL | let _ = if let Ok(_) = gen_res() { - | -------^^^^^------------ help: try this: `if gen_res().is_ok()` + | -------^^^^^------------ help: try: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:64:19 | LL | } else if let Err(_) = gen_res() { - | -------^^^^^^------------ help: try this: `if gen_res().is_err()` + | -------^^^^^^------------ help: try: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_result.rs:87:19 | LL | while let Some(_) = r#try!(result_opt()) {} - | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` + | ----------^^^^^^^----------------------- help: try: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_result.rs:88:16 | LL | if let Some(_) = r#try!(result_opt()) {} - | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` + | -------^^^^^^^----------------------- help: try: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_result.rs:94:12 | LL | if let Some(_) = m!() {} - | -------^^^^^^^------- help: try this: `if m!().is_some()` + | -------^^^^^^^------- help: try: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` --> $DIR/redundant_pattern_matching_result.rs:95:15 | LL | while let Some(_) = m!() {} - | ----------^^^^^^^------- help: try this: `while m!().is_some()` + | ----------^^^^^^^------- help: try: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:113:12 | LL | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + | -------^^^^^--------------------- help: try: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:115:12 | LL | if let Err(_) = Err::(42) {} - | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` + | -------^^^^^^---------------------- help: try: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:117:15 | LL | while let Ok(_) = Ok::(10) {} - | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` + | ----------^^^^^--------------------- help: try: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:119:15 | LL | while let Err(_) = Ok::(10) {} - | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` + | ----------^^^^^^--------------------- help: try: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:121:5 @@ -139,7 +139,7 @@ LL | / match Ok::(42) { LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; - | |_____^ help: try this: `Ok::(42).is_ok()` + | |_____^ help: try: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:126:5 @@ -148,7 +148,7 @@ LL | / match Err::(42) { LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; - | |_____^ help: try this: `Err::(42).is_err()` + | |_____^ help: try: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:136:5 @@ -157,7 +157,7 @@ LL | / match x { LL | | Ok(_) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `x.is_ok()` + | |_____^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:141:5 @@ -166,7 +166,7 @@ LL | / match x { LL | | Ok(_) => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `x.is_err()` + | |_____^ help: try: `x.is_err()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:146:5 @@ -175,7 +175,7 @@ LL | / match x { LL | | Err(_) => true, LL | | _ => false, LL | | }; - | |_____^ help: try this: `x.is_err()` + | |_____^ help: try: `x.is_err()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:151:5 @@ -184,19 +184,19 @@ LL | / match x { LL | | Err(_) => false, LL | | _ => true, LL | | }; - | |_____^ help: try this: `x.is_ok()` + | |_____^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_ok()` --> $DIR/redundant_pattern_matching_result.rs:172:13 | LL | let _ = matches!(x, Ok(_)); - | ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()` + | ^^^^^^^^^^^^^^^^^^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` --> $DIR/redundant_pattern_matching_result.rs:174:13 | LL | let _ = matches!(x, Err(_)); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()` + | ^^^^^^^^^^^^^^^^^^^ help: try: `x.is_err()` error: aborting due to 28 previous errors diff --git a/tests/ui/ref_binding_to_reference.stderr b/tests/ui/ref_binding_to_reference.stderr index eb36cd516a246..016feb103df6e 100644 --- a/tests/ui/ref_binding_to_reference.stderr +++ b/tests/ui/ref_binding_to_reference.stderr @@ -5,7 +5,7 @@ LL | Some(ref x) => x, | ^^^^^ | = note: `-D clippy::ref-binding-to-reference` implied by `-D warnings` -help: try this +help: try | LL | Some(x) => &x, | ~ ~~ @@ -16,7 +16,7 @@ error: this pattern creates a reference to a reference LL | Some(ref x) => { | ^^^^^ | -help: try this +help: try | LL ~ Some(x) => { LL | f1(x); @@ -30,7 +30,7 @@ error: this pattern creates a reference to a reference LL | Some(ref x) => m2!(x), | ^^^^^ | -help: try this +help: try | LL | Some(x) => m2!(&x), | ~ ~~ @@ -41,7 +41,7 @@ error: this pattern creates a reference to a reference LL | let _ = |&ref x: &&String| { | ^^^^^ | -help: try this +help: try | LL ~ let _ = |&x: &&String| { LL ~ let _: &&String = &x; @@ -53,7 +53,7 @@ error: this pattern creates a reference to a reference LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ | -help: try this +help: try | LL ~ fn f2<'a>(&x: &&'a String) -> &'a String { LL ~ let _: &&String = &x; @@ -66,7 +66,7 @@ error: this pattern creates a reference to a reference LL | fn f(&ref x: &&String) { | ^^^^^ | -help: try this +help: try | LL ~ fn f(&x: &&String) { LL ~ let _: &&String = &x; @@ -78,7 +78,7 @@ error: this pattern creates a reference to a reference LL | fn f(&ref x: &&String) { | ^^^^^ | -help: try this +help: try | LL ~ fn f(&x: &&String) { LL ~ let _: &&String = &x; diff --git a/tests/ui/result_map_unit_fn_fixable.stderr b/tests/ui/result_map_unit_fn_fixable.stderr index 782febd526441..ad941fa8bcc0b 100644 --- a/tests/ui/result_map_unit_fn_fixable.stderr +++ b/tests/ui/result_map_unit_fn_fixable.stderr @@ -4,7 +4,7 @@ error: called `map(f)` on an `Result` value where `f` is a function that returns LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(x_field) = x.field { do_nothing(x_field) }` + | help: try: `if let Ok(x_field) = x.field { do_nothing(x_field) }` | = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` @@ -14,7 +14,7 @@ error: called `map(f)` on an `Result` value where `f` is a function that returns LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(x_field) = x.field { do_nothing(x_field) }` + | help: try: `if let Ok(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:39:5 @@ -22,7 +22,7 @@ error: called `map(f)` on an `Result` value where `f` is a function that returns LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(x_field) = x.field { diverge(x_field) }` + | help: try: `if let Ok(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:45:5 @@ -30,7 +30,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` + | help: try: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:47:5 @@ -38,7 +38,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` + | help: try: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:50:5 @@ -46,7 +46,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:52:5 @@ -54,7 +54,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:54:5 @@ -62,7 +62,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + | help: try: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:56:5 @@ -70,7 +70,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` + | help: try: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:59:5 @@ -78,7 +78,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` + | help: try: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:61:5 @@ -86,7 +86,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` + | help: try: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:63:5 @@ -94,7 +94,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + | help: try: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:65:5 @@ -102,7 +102,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` + | help: try: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:70:5 @@ -110,7 +110,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` + | help: try: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:72:5 @@ -118,7 +118,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + | help: try: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:74:5 @@ -126,7 +126,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` + | help: try: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:77:5 @@ -134,7 +134,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` + | help: try: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_fixable.rs:79:5 @@ -142,7 +142,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| println!("{:?}", value)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { println!("{:?}", value) }` + | help: try: `if let Ok(value) = x.field { println!("{:?}", value) }` error: aborting due to 18 previous errors diff --git a/tests/ui/result_map_unit_fn_unfixable.stderr b/tests/ui/result_map_unit_fn_unfixable.stderr index d0e534f635682..75ec1ba80245e 100644 --- a/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/tests/ui/result_map_unit_fn_unfixable.stderr @@ -4,7 +4,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { ... }` + | help: try: `if let Ok(value) = x.field { ... }` | = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` @@ -14,7 +14,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { ... }` + | help: try: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_unfixable.rs:29:5 @@ -23,7 +23,7 @@ LL | // x.field.map(|value| { LL | || do_nothing(value); LL | || do_nothing(value) LL | || }); - | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | ||______^- help: try: `if let Ok(value) = x.field { ... }` | |______| | @@ -33,7 +33,7 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(value) = x.field { ... }` + | help: try: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` --> $DIR/result_map_unit_fn_unfixable.rs:37:5 @@ -41,7 +41,7 @@ error: called `map(f)` on an `Result` value where `f` is a function that returns LL | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(a) = "12".parse::() { diverge(a) }` + | help: try: `if let Ok(a) = "12".parse::() { diverge(a) }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` --> $DIR/result_map_unit_fn_unfixable.rs:43:5 @@ -49,7 +49,7 @@ error: called `map(f)` on an `Result` value where `f` is a function that returns LL | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- | | - | help: try this: `if let Ok(_y) = y { do_nothing(_y) }` + | help: try: `if let Ok(_y) = y { do_nothing(_y) }` error: aborting due to 6 previous errors diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index ef90151324043..76f7e78958985 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -10,7 +10,7 @@ LL | | }; | |_____^ | = note: `-D clippy::single-match` implied by `-D warnings` -help: try this +help: try | LL ~ if let Some(y) = x { LL + println!("{:?}", y); @@ -27,7 +27,7 @@ LL | | // is expanded before we can do anything. LL | | Some(y) => println!("{:?}", y), LL | | _ => (), LL | | } - | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` + | |_____^ 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` --> $DIR/single_match.rs:31:5 @@ -36,7 +36,7 @@ LL | / match z { LL | | (2..=3, 7..=9) => dummy(), LL | | _ => {}, LL | | }; - | |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }` + | |_____^ 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` --> $DIR/single_match.rs:60:5 @@ -45,7 +45,7 @@ LL | / match x { LL | | Some(y) => dummy(), LL | | None => (), LL | | }; - | |_____^ help: try this: `if let Some(y) = x { dummy() }` + | |_____^ 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` --> $DIR/single_match.rs:65:5 @@ -54,7 +54,7 @@ LL | / match y { LL | | Ok(y) => dummy(), LL | | Err(..) => (), LL | | }; - | |_____^ help: try this: `if let Ok(y) = y { dummy() }` + | |_____^ 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` --> $DIR/single_match.rs:72:5 @@ -63,7 +63,7 @@ LL | / match c { LL | | Cow::Borrowed(..) => dummy(), LL | | Cow::Owned(..) => (), LL | | }; - | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` + | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` --> $DIR/single_match.rs:93:5 @@ -72,7 +72,7 @@ LL | / match x { LL | | "test" => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if x == "test" { println!() }` + | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` --> $DIR/single_match.rs:106:5 @@ -81,7 +81,7 @@ LL | / match x { LL | | Foo::A => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if x == Foo::A { println!() }` + | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` --> $DIR/single_match.rs:112:5 @@ -90,7 +90,7 @@ LL | / match x { LL | | FOO_C => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if x == FOO_C { println!() }` + | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` --> $DIR/single_match.rs:117:5 @@ -99,7 +99,7 @@ LL | / match &&x { LL | | Foo::A => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if x == Foo::A { println!() }` + | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` --> $DIR/single_match.rs:123:5 @@ -108,7 +108,7 @@ LL | / match &x { LL | | Foo::A => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if x == &Foo::A { println!() }` + | |_____^ 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` --> $DIR/single_match.rs:140:5 @@ -117,7 +117,7 @@ LL | / match x { LL | | Bar::A => println!(), LL | | _ => (), LL | | } - | |_____^ help: try this: `if let Bar::A = x { println!() }` + | |_____^ 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` --> $DIR/single_match.rs:148:5 @@ -126,7 +126,7 @@ LL | / match x { LL | | None => println!(), LL | | _ => (), LL | | }; - | |_____^ help: try this: `if let None = x { println!() }` + | |_____^ 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` --> $DIR/single_match.rs:170:5 @@ -135,7 +135,7 @@ LL | / match x { LL | | (Some(_), _) => {}, LL | | (None, _) => {}, LL | | } - | |_____^ help: try this: `if let (Some(_), _) = x {}` + | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:176:5 @@ -144,7 +144,7 @@ LL | / match x { LL | | (Some(E::V), _) => todo!(), LL | | (_, _) => {}, LL | | } - | |_____^ help: try this: `if let (Some(E::V), _) = x { todo!() }` + | |_____^ 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` --> $DIR/single_match.rs:182:5 @@ -153,7 +153,7 @@ LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, LL | | (..) => {}, LL | | } - | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` + | |_____^ 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` --> $DIR/single_match.rs:254:5 @@ -167,7 +167,7 @@ LL | | _ => {}, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { unsafe { LL + let r = &v as *const i32; @@ -187,7 +187,7 @@ LL | | _ => {}, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { LL + unsafe { diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 228236f3bb8e8..5e7d4062efea0 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____^ | = note: `-D clippy::single-match-else` implied by `-D warnings` -help: try this +help: try | LL ~ let _ = if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { LL + let x = 5; @@ -32,7 +32,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(a) = Some(1) { println!("${:?}", a) } else { LL + println!("else block"); @@ -52,7 +52,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(a) = Some(1) { println!("${:?}", a) } else { LL + println!("else block"); @@ -72,7 +72,7 @@ LL | | } LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { LL + println!("else block"); @@ -92,7 +92,7 @@ LL | | } LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else { LL + println!("else block"); @@ -112,7 +112,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { unsafe { LL + let r = &v as *const i32; @@ -135,7 +135,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { LL + println!("Some"); @@ -159,7 +159,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { unsafe { LL + let r = &v as *const i32; @@ -183,7 +183,7 @@ LL | | }, LL | | } | |_____^ | -help: try this +help: try | LL ~ if let Some(v) = bar { LL + unsafe { diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index b35c77fd96113..34b43290147e2 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -2,7 +2,7 @@ error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:18:5 | LL | s.extend(abc.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str(abc)` | = note: `-D clippy::string-extend-chars` implied by `-D warnings` @@ -10,19 +10,19 @@ error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:21:5 | LL | s.extend("abc".chars()); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str("abc")` error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:24:5 | LL | s.extend(def.chars()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str(&def)` error: calling `.extend(_.chars())` --> $DIR/string_extend.rs:34:5 | LL | s.extend(abc[0..2].chars()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&abc[0..2])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str(&abc[0..2])` error: aborting due to 4 previous errors diff --git a/tests/ui/strlen_on_c_strings.stderr b/tests/ui/strlen_on_c_strings.stderr index 296268a5f1df7..fcd17f6894040 100644 --- a/tests/ui/strlen_on_c_strings.stderr +++ b/tests/ui/strlen_on_c_strings.stderr @@ -2,7 +2,7 @@ error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:15:13 | LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `cstring.as_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstring.as_bytes().len()` | = note: `-D clippy::strlen-on-c-strings` implied by `-D warnings` @@ -10,37 +10,37 @@ error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:19:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:21:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:24:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(*pcstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:29:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unsafe_identity(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:30:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value --> $DIR/strlen_on_c_strings.rs:33:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `f(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` error: aborting due to 7 previous errors diff --git a/tests/ui/to_digit_is_some.stderr b/tests/ui/to_digit_is_some.stderr index 10a1b393a3906..c4718825dc26f 100644 --- a/tests/ui/to_digit_is_some.stderr +++ b/tests/ui/to_digit_is_some.stderr @@ -2,7 +2,7 @@ error: use of `.to_digit(..).is_some()` --> $DIR/to_digit_is_some.rs:9:13 | LL | let _ = d.to_digit(8).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `d.is_digit(8)` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d.is_digit(8)` | = note: `-D clippy::to-digit-is-some` implied by `-D warnings` @@ -10,7 +10,7 @@ error: use of `.to_digit(..).is_some()` --> $DIR/to_digit_is_some.rs:10:13 | LL | let _ = char::to_digit(c, 8).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `char::is_digit(c, 8)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `char::is_digit(c, 8)` error: aborting due to 2 previous errors diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr index 4ad0e2e56a4d3..79f7b70224a19 100644 --- a/tests/ui/try_err.stderr +++ b/tests/ui/try_err.stderr @@ -2,7 +2,7 @@ error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:19:9 | LL | Err(err)?; - | ^^^^^^^^^ help: try this: `return Err(err)` + | ^^^^^^^^^ help: try: `return Err(err)` | note: the lint level is defined here --> $DIR/try_err.rs:4:9 @@ -14,25 +14,25 @@ error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:29:9 | LL | Err(err)?; - | ^^^^^^^^^ help: try this: `return Err(err.into())` + | ^^^^^^^^^ help: try: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:49:17 | LL | Err(err)?; - | ^^^^^^^^^ help: try this: `return Err(err)` + | ^^^^^^^^^ help: try: `return Err(err)` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:68:17 | LL | Err(err)?; - | ^^^^^^^^^ help: try this: `return Err(err.into())` + | ^^^^^^^^^ help: try: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:88:23 | LL | Err(_) => Err(1)?, - | ^^^^^^^ help: try this: `return Err(1)` + | ^^^^^^^ help: try: `return Err(1)` | = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -40,7 +40,7 @@ error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:95:23 | LL | Err(_) => Err(inline!(1))?, - | ^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(1))` + | ^^^^^^^^^^^^^^^^ help: try: `return Err(inline!(1))` | = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -48,31 +48,31 @@ error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:122:9 | LL | Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:129:9 | LL | Err(io::ErrorKind::WriteZero)? - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:131:9 | LL | Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:139:9 | LL | Err(io::ErrorKind::NotFound)? - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` error: returning an `Err(_)` with the `?` operator --> $DIR/try_err.rs:148:16 | LL | return Err(42)?; - | ^^^^^^^^ help: try this: `Err(42)` + | ^^^^^^^^ help: try: `Err(42)` error: aborting due to 11 previous errors diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 5686ab6b4531e..23639f6d41a04 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -2,7 +2,7 @@ error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:23:5 | LL | rc.clone(); - | ^^^^^^^^^^ help: try this: `Rc::::clone(&rc)` + | ^^^^^^^^^^ help: try: `Rc::::clone(&rc)` | = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` @@ -10,25 +10,25 @@ error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:26:5 | LL | arc.clone(); - | ^^^^^^^^^^^ help: try this: `Arc::::clone(&arc)` + | ^^^^^^^^^^^ help: try: `Arc::::clone(&arc)` error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:29:5 | LL | rcweak.clone(); - | ^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&rcweak)` + | ^^^^^^^^^^^^^^ help: try: `Weak::::clone(&rcweak)` error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:32:5 | LL | arc_weak.clone(); - | ^^^^^^^^^^^^^^^^ help: try this: `Weak::::clone(&arc_weak)` + | ^^^^^^^^^^^^^^^^ help: try: `Weak::::clone(&arc_weak)` error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:36:33 | LL | let _: Arc = x.clone(); - | ^^^^^^^^^ help: try this: `Arc::::clone(&x)` + | ^^^^^^^^^ help: try: `Arc::::clone(&x)` error: using `clone` on type `T` which implements the `Copy` trait --> $DIR/unnecessary_clone.rs:40:5 @@ -54,7 +54,7 @@ error: using `.clone()` on a ref-counted pointer --> $DIR/unnecessary_clone.rs:95:14 | LL | Some(try_opt!(Some(rc)).clone()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::::clone(&try_opt!(Some(rc)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Rc::::clone(&try_opt!(Some(rc)))` error: aborting due to 9 previous errors diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index cf720eaaf052e..e384bbbb01557 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -2,7 +2,7 @@ error: use of `unwrap_or` followed by a function call --> $DIR/unwrap_or.rs:5:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| "Fail".to_string())` | = note: `-D clippy::or-fun-call` implied by `-D warnings` @@ -10,7 +10,7 @@ error: use of `unwrap_or` followed by a function call --> $DIR/unwrap_or.rs:9:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| "Fail".to_string())` error: aborting due to 2 previous errors diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 67ce8b64e0e3d..1f51831b2e958 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -2,7 +2,7 @@ error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:43:18 | LL | foo_rstr(rstr.as_ref()); - | ^^^^^^^^^^^^^ help: try this: `rstr` + | ^^^^^^^^^^^^^ help: try: `rstr` | note: the lint level is defined here --> $DIR/useless_asref.rs:2:9 @@ -14,61 +14,61 @@ error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:45:20 | LL | foo_rslice(rslice.as_ref()); - | ^^^^^^^^^^^^^^^ help: try this: `rslice` + | ^^^^^^^^^^^^^^^ help: try: `rslice` error: this call to `as_mut` does nothing --> $DIR/useless_asref.rs:49:21 | LL | foo_mrslice(mrslice.as_mut()); - | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` + | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:51:20 | LL | foo_rslice(mrslice.as_ref()); - | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` + | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:58:20 | LL | foo_rslice(rrrrrslice.as_ref()); - | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` + | ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:60:18 | LL | foo_rstr(rrrrrstr.as_ref()); - | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` + | ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr` error: this call to `as_mut` does nothing --> $DIR/useless_asref.rs:65:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:67:20 | LL | foo_rslice(mrrrrrslice.as_ref()); - | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:71:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)` error: this call to `as_mut` does nothing --> $DIR/useless_asref.rs:121:13 | LL | foo_mrt(mrt.as_mut()); - | ^^^^^^^^^^^^ help: try this: `mrt` + | ^^^^^^^^^^^^ help: try: `mrt` error: this call to `as_ref` does nothing --> $DIR/useless_asref.rs:123:12 | LL | foo_rt(mrt.as_ref()); - | ^^^^^^^^^^^^ help: try this: `mrt` + | ^^^^^^^^^^^^ help: try: `mrt` error: aborting due to 11 previous errors diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr index 30d29aa4e77a1..5b88ae4ab665e 100644 --- a/tests/ui/wildcard_enum_match_arm.stderr +++ b/tests/ui/wildcard_enum_match_arm.stderr @@ -2,7 +2,7 @@ error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:40:9 | LL | _ => eprintln!("Not red"), - | ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` + | ^ help: try: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` | note: the lint level is defined here --> $DIR/wildcard_enum_match_arm.rs:3:9 @@ -14,31 +14,31 @@ error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:44:9 | LL | _not_red => eprintln!("Not red"), - | ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` + | ^^^^^^^^ help: try: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:48:9 | LL | not_red => format!("{:?}", not_red), - | ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` + | ^^^^^^^ help: try: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:64:9 | LL | _ => "No red", - | ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` + | ^ help: try: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` error: wildcard matches known variants and will also match future added variants --> $DIR/wildcard_enum_match_arm.rs:81:9 | LL | _ => {}, - | ^ help: try this: `ErrorKind::PermissionDenied | _` + | ^ help: try: `ErrorKind::PermissionDenied | _` error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:99:13 | LL | _ => (), - | ^ help: try this: `Enum::B | Enum::__Private` + | ^ help: try: `Enum::B | Enum::__Private` error: aborting due to 6 previous errors diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 1e306ae28a263..8b72c8bd28231 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -5,7 +5,7 @@ LL | write!(v, "Hello {}", "world"); | ^^^^^^^ | = note: `-D clippy::write-literal` implied by `-D warnings` -help: try this +help: try | LL - write!(v, "Hello {}", "world"); LL + write!(v, "Hello world"); @@ -17,7 +17,7 @@ error: literal with an empty format string LL | writeln!(v, "Hello {} {}", world, "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "Hello {} {}", world, "world"); LL + writeln!(v, "Hello {} world", world); @@ -29,7 +29,7 @@ error: literal with an empty format string LL | writeln!(v, "Hello {}", "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "Hello {}", "world"); LL + writeln!(v, "Hello world"); @@ -41,7 +41,7 @@ error: literal with an empty format string LL | writeln!(v, "{} {:.4}", "a literal", 5); | ^^^^^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{} {:.4}", "a literal", 5); LL + writeln!(v, "a literal {:.4}", 5); @@ -53,7 +53,7 @@ error: literal with an empty format string LL | writeln!(v, "{0} {1}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{0} {1}", "hello", "world"); LL + writeln!(v, "hello {1}", "world"); @@ -65,7 +65,7 @@ error: literal with an empty format string LL | writeln!(v, "{0} {1}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{0} {1}", "hello", "world"); LL + writeln!(v, "{0} world", "hello"); @@ -77,7 +77,7 @@ error: literal with an empty format string LL | writeln!(v, "{1} {0}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{1} {0}", "hello", "world"); LL + writeln!(v, "world {0}", "hello"); @@ -89,7 +89,7 @@ error: literal with an empty format string LL | writeln!(v, "{1} {0}", "hello", "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{1} {0}", "hello", "world"); LL + writeln!(v, "{1} hello", "world"); @@ -101,7 +101,7 @@ error: literal with an empty format string LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); LL + writeln!(v, "hello {bar}", bar = "world"); @@ -113,7 +113,7 @@ error: literal with an empty format string LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); LL + writeln!(v, "{foo} world", foo = "hello"); @@ -125,7 +125,7 @@ error: literal with an empty format string LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); LL + writeln!(v, "world {foo}", foo = "hello"); @@ -137,7 +137,7 @@ error: literal with an empty format string LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^ | -help: try this +help: try | LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); LL + writeln!(v, "{bar} hello", bar = "world"); diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index 18591250aad9e..c30ec385b35ae 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -13,7 +13,7 @@ LL | writeln!(v, "{}", "{hello}"); | ^^^^^^^^^ | = note: `-D clippy::write-literal` implied by `-D warnings` -help: try this +help: try | LL - writeln!(v, "{}", "{hello}"); LL + writeln!(v, "{{hello}}"); @@ -25,7 +25,7 @@ error: literal with an empty format string LL | writeln!(v, r"{}", r"{hello}"); | ^^^^^^^^^^ | -help: try this +help: try | LL - writeln!(v, r"{}", r"{hello}"); LL + writeln!(v, r"{{hello}}"); @@ -37,7 +37,7 @@ error: literal with an empty format string LL | writeln!(v, "{}", '/''); | ^^^^ | -help: try this +help: try | LL - writeln!(v, "{}", '/''); LL + writeln!(v, "'"); @@ -49,7 +49,7 @@ error: literal with an empty format string LL | writeln!(v, "{}", '"'); | ^^^ | -help: try this +help: try | LL - writeln!(v, "{}", '"'); LL + writeln!(v, "/""); @@ -67,7 +67,7 @@ error: literal with an empty format string LL | writeln!(v, r"{}", '/''); | ^^^^ | -help: try this +help: try | LL - writeln!(v, r"{}", '/''); LL + writeln!(v, r"'"); @@ -80,7 +80,7 @@ LL | / "hello / LL | | world!" | |_______________^ | -help: try this +help: try | LL ~ "some hello / LL ~ world!" @@ -92,7 +92,7 @@ error: literal with an empty format string LL | "1", "2", "3", | ^^^ | -help: try this +help: try | LL ~ "some 1/ LL ~ {} // {}", "2", "3", @@ -104,7 +104,7 @@ error: literal with an empty format string LL | "1", "2", "3", | ^^^ | -help: try this +help: try | LL ~ 2 // {}", LL ~ "1", "3", @@ -116,7 +116,7 @@ error: literal with an empty format string LL | "1", "2", "3", | ^^^ | -help: try this +help: try | LL ~ {} // 3", LL ~ "1", "2", @@ -128,7 +128,7 @@ error: literal with an empty format string LL | writeln!(v, "{}", "//"); | ^^^^ | -help: try this +help: try | LL - writeln!(v, "{}", "//"); LL + writeln!(v, "//"); @@ -140,7 +140,7 @@ error: literal with an empty format string LL | writeln!(v, r"{}", "//"); | ^^^^ | -help: try this +help: try | LL - writeln!(v, r"{}", "//"); LL + writeln!(v, r"/"); @@ -152,7 +152,7 @@ error: literal with an empty format string LL | writeln!(v, r#"{}"#, "//"); | ^^^^ | -help: try this +help: try | LL - writeln!(v, r#"{}"#, "//"); LL + writeln!(v, r#"/"#); @@ -164,7 +164,7 @@ error: literal with an empty format string LL | writeln!(v, "{}", r"/"); | ^^^^ | -help: try this +help: try | LL - writeln!(v, "{}", r"/"); LL + writeln!(v, "//"); @@ -176,7 +176,7 @@ error: literal with an empty format string LL | writeln!(v, "{}", "/r"); | ^^^^ | -help: try this +help: try | LL - writeln!(v, "{}", "/r"); LL + writeln!(v, "/r"); From 885a18207fb66fc736496a4c9cb8c010881c1ab5 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 1 Jul 2023 19:33:08 -0500 Subject: [PATCH 16/80] Fix typos --- book/src/lint_configuration.md | 2 +- clippy_lints/src/methods/map_unwrap_or.rs | 3 ++- clippy_lints/src/min_ident_chars.rs | 2 +- clippy_lints/src/needless_else.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_utils/src/attrs.rs | 4 ++-- clippy_utils/src/check_proc_macro.rs | 2 +- clippy_utils/src/comparisons.rs | 4 ++-- clippy_utils/src/consts.rs | 2 +- clippy_utils/src/eager_or_lazy.rs | 2 +- clippy_utils/src/higher.rs | 8 ++++---- clippy_utils/src/lib.rs | 5 +++-- clippy_utils/src/sugg.rs | 2 +- tests/ui/needless_else.stderr | 2 +- 14 files changed, 22 insertions(+), 20 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index ae0b51403167e..1ade6e3f4813f 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -174,7 +174,7 @@ The maximum amount of nesting a block can reside in ## `disallowed-names` The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value -`".."` can be used as part of the list to indicate, that the configured values should be appended to the +`".."` can be used as part of the list to indicate that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. **Default Value:** `["foo", "baz", "quux"]` (`Vec`) diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 3122f72ee9155..72156bbd1b096 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -11,7 +11,8 @@ use rustc_span::symbol::sym; use super::MAP_UNWRAP_OR; /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s -/// Return true if lint triggered +/// +/// Returns true if the lint was emitted pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index d49bb0ca6e291..23593e0d4d97b 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -25,7 +25,7 @@ declare_clippy_lint! { /// ### Example /// ```rust,ignore /// for m in movies { - /// let title = m.t; + /// let title = m.t; /// } /// ``` /// Use instead: diff --git a/clippy_lints/src/needless_else.rs b/clippy_lints/src/needless_else.rs index 4ff1bf7ffc0de..23d4a7b9586d1 100644 --- a/clippy_lints/src/needless_else.rs +++ b/clippy_lints/src/needless_else.rs @@ -51,7 +51,7 @@ impl EarlyLintPass for NeedlessElse { cx, NEEDLESS_ELSE, span, - "this else branch is empty", + "this `else` branch is empty", "you can remove it", String::new(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 890639646228d..59e997588296f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -319,7 +319,7 @@ define_Conf! { /// Lint: DISALLOWED_NAMES. /// /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value - /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the + /// `".."` can be used as part of the list to indicate that the configured values should be appended to the /// default configuration of Clippy. By default, any configuration will replace the default value. (disallowed_names: Vec = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()), /// Lint: SEMICOLON_INSIDE_BLOCK. diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 49cb9718ef66e..e4cc86f680053 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -143,13 +143,13 @@ pub fn get_unique_attr<'a>( unique_attr } -/// Return true if the attributes contain any of `proc_macro`, +/// Returns true if the attributes contain any of `proc_macro`, /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool { attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr) } -/// Return true if the attributes contain `#[doc(hidden)]` +/// Returns true if the attributes contain `#[doc(hidden)]` pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { attrs .iter() diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index c6d0b654f57b6..62792d60652ba 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -339,7 +339,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), - // NOTE: This is missing `TraitObject`. It always return true then. + // NOTE: This is missing `TraitObject`. It will always return true then. _ => (Pat::Str(""), Pat::Str("")), } } diff --git a/clippy_utils/src/comparisons.rs b/clippy_utils/src/comparisons.rs index 7a18d5e818fb1..5e6bf22784422 100644 --- a/clippy_utils/src/comparisons.rs +++ b/clippy_utils/src/comparisons.rs @@ -1,11 +1,11 @@ -//! Utility functions about comparison operators. +//! Utility functions for comparison operators. #![deny(clippy::missing_docs_in_private_items)] use rustc_hir::{BinOpKind, Expr}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] -/// Represent a normalized comparison operator. +/// Represents a normalized comparison operator. pub enum Rel { /// `<` Lt, diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 068820801dfe0..87d85d742ce41 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -267,7 +267,7 @@ pub fn constant_with_source<'tcx>( res.map(|x| (x, ctxt.source)) } -/// Attempts to evaluate an expression only if it's value is not dependent on other items. +/// Attempts to evaluate an expression only if its value is not dependent on other items. pub fn constant_simple<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 4a845ca63b49f..eda739bceb5c5 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -1,7 +1,7 @@ //! Utilities for evaluating whether eagerly evaluated expressions can be made lazy and vice versa. //! //! Things to consider: -//! - has the expression side-effects? +//! - does the expression have side-effects? //! - is the expression computationally expensive? //! //! See lints: diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index a61e4c380886d..357ac40b45594 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -13,7 +13,7 @@ use rustc_lint::LateContext; use rustc_span::{sym, symbol, Span}; /// The essential nodes of a desugared for loop as well as the entire span: -/// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, 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>, @@ -264,7 +264,7 @@ impl<'a> Range<'a> { } } -/// Represent the pre-expansion arguments of a `vec!` invocation. +/// 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>), @@ -398,7 +398,7 @@ impl<'hir> WhileLet<'hir> { } } -/// Converts a hir binary operator to the corresponding `ast` type. +/// Converts a `hir` binary operator to the corresponding `ast` type. #[must_use] pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind { match op { @@ -436,7 +436,7 @@ pub enum VecInitKind { WithExprCapacity(HirId), } -/// Checks if given expression is an initialization of `Vec` and returns its kind. +/// Checks if the given expression is an initialization of `Vec` and returns its kind. pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option { if let ExprKind::Call(func, args) = expr.kind { match func.kind { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 727b59f1f432a..272228cebd070 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -823,7 +823,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath< false } -/// Return true if the expr is equal to `Default::default` when evaluated. +/// 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_chain! { if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind; @@ -2527,7 +2527,8 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool { }); } -/// Return all the comments a given span contains +/// Returns all the comments a given span contains +/// /// Comments are returned wrapped with their relevant delimiters pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String { let snippet = sm.span_to_snippet(span).unwrap_or_default(); diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index cf781e18cd66e..de3aad6475725 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -395,7 +395,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { } } -/// Return `true` if `sugg` is enclosed in parenthesis. +/// Returns `true` if `sugg` is enclosed in parenthesis. pub fn has_enclosing_paren(sugg: impl AsRef) -> bool { let mut chars = sugg.as_ref().chars(); if chars.next() == Some('(') { diff --git a/tests/ui/needless_else.stderr b/tests/ui/needless_else.stderr index ea69308516449..49cd78501eac2 100644 --- a/tests/ui/needless_else.stderr +++ b/tests/ui/needless_else.stderr @@ -1,4 +1,4 @@ -error: this else branch is empty +error: this `else` branch is empty --> $DIR/needless_else.rs:24:7 | LL | } else { From cb3ecf7b792fdc4b00e61935b9e40ca836752492 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 14:35:19 +0200 Subject: [PATCH 17/80] Merge commit '37f4c1725d3fd7e9c3ffd8783246bc5589debc53' into clippyup --- .cargo/config.toml | 2 + .github/workflows/clippy.yml | 1 - .github/workflows/clippy_bors.yml | 1 - .github/workflows/clippy_dev.yml | 1 - CHANGELOG.md | 200 +++- Cargo.toml | 19 +- book/src/development/adding_lints.md | 19 +- book/src/development/basics.md | 2 +- .../infrastructure/changelog_update.md | 22 + book/src/lint_configuration.md | 591 ++++++---- clippy_dev/src/bless.rs | 60 - clippy_dev/src/fmt.rs | 1 + clippy_dev/src/lib.rs | 7 +- clippy_dev/src/main.rs | 10 +- clippy_dev/src/new_lint.rs | 15 +- clippy_lints/Cargo.toml | 3 +- clippy_lints/src/allow_attributes.rs | 7 +- clippy_lints/src/arc_with_non_send_sync.rs | 72 ++ clippy_lints/src/as_conversions.rs | 11 +- clippy_lints/src/attrs.rs | 68 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/casts/borrow_as_ptr.rs | 10 + clippy_lints/src/casts/cast_possible_wrap.rs | 95 +- clippy_lints/src/casts/mod.rs | 13 +- clippy_lints/src/casts/ptr_cast_constness.rs | 13 +- clippy_lints/src/casts/unnecessary_cast.rs | 140 ++- clippy_lints/src/declared_lints.rs | 28 +- .../src/default_constructed_unit_structs.rs | 2 +- clippy_lints/src/default_numeric_fallback.rs | 2 +- clippy_lints/src/dereference.rs | 41 +- clippy_lints/src/derivable_impls.rs | 39 +- clippy_lints/src/derive.rs | 7 +- clippy_lints/src/doc.rs | 11 +- clippy_lints/src/drop_forget_ref.rs | 52 +- clippy_lints/src/endian_bytes.rs | 216 ++++ clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 31 +- clippy_lints/src/eta_reduction.rs | 8 + clippy_lints/src/excessive_nesting.rs | 181 +++ .../src/extra_unused_type_parameters.rs | 2 + clippy_lints/src/float_literal.rs | 11 +- clippy_lints/src/floating_point_arithmetic.rs | 2 +- clippy_lints/src/format_push_string.rs | 23 +- clippy_lints/src/formatting.rs | 6 + clippy_lints/src/from_over_into.rs | 8 +- clippy_lints/src/incorrect_impls.rs | 124 ++ clippy_lints/src/items_after_test_module.rs | 3 +- clippy_lints/src/large_stack_frames.rs | 162 +++ clippy_lints/src/let_with_type_underscore.rs | 12 +- clippy_lints/src/lib.rs | 121 +- clippy_lints/src/lifetimes.rs | 17 +- .../src/loops/explicit_into_iter_loop.rs | 69 +- clippy_lints/src/loops/explicit_iter_loop.rs | 256 +++- clippy_lints/src/loops/manual_memcpy.rs | 4 +- clippy_lints/src/loops/mod.rs | 95 +- clippy_lints/src/loops/never_loop.rs | 92 +- clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/macro_use.rs | 2 +- clippy_lints/src/manual_let_else.rs | 247 ++-- clippy_lints/src/manual_range_patterns.rs | 123 ++ clippy_lints/src/matches/match_same_arms.rs | 29 +- .../src/matches/match_wild_err_arm.rs | 2 +- clippy_lints/src/matches/mod.rs | 10 +- clippy_lints/src/matches/overlapping_arms.rs | 4 +- .../matches/significant_drop_in_scrutinee.rs | 2 +- clippy_lints/src/matches/single_match.rs | 24 +- clippy_lints/src/matches/try_err.rs | 2 +- clippy_lints/src/mem_forget.rs | 46 - clippy_lints/src/methods/drain_collect.rs | 85 ++ clippy_lints/src/methods/get_unwrap.rs | 33 +- clippy_lints/src/methods/iter_nth.rs | 4 +- clippy_lints/src/methods/iter_nth_zero.rs | 35 +- clippy_lints/src/methods/manual_try_fold.rs | 55 + clippy_lints/src/methods/mod.rs | 174 ++- clippy_lints/src/methods/needless_collect.rs | 2 +- .../src/methods/option_map_unwrap_or.rs | 115 +- clippy_lints/src/methods/str_splitn.rs | 2 +- clippy_lints/src/methods/unnecessary_fold.rs | 211 +++- .../src/methods/unnecessary_literal_unwrap.rs | 95 ++ .../src/methods/unnecessary_to_owned.rs | 5 + clippy_lints/src/min_ident_chars.rs | 153 +++ clippy_lints/src/minmax.rs | 8 +- .../src/misc_early/mixed_case_hex_literals.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 37 + .../misc_early/redundant_at_rest_pattern.rs | 26 + .../src/mismatching_type_param_order.rs | 2 +- clippy_lints/src/missing_fields_in_debug.rs | 5 + .../src/mixed_read_write_in_expression.rs | 12 +- clippy_lints/src/module_style.rs | 10 +- clippy_lints/src/needless_if.rs | 75 ++ clippy_lints/src/needless_pass_by_value.rs | 33 +- clippy_lints/src/no_effect.rs | 47 +- clippy_lints/src/non_copy_const.rs | 18 +- clippy_lints/src/operators/eq_op.rs | 9 +- clippy_lints/src/operators/float_cmp.rs | 2 +- clippy_lints/src/option_if_let_else.rs | 3 + clippy_lints/src/ptr.rs | 105 +- clippy_lints/src/question_mark.rs | 250 ++-- clippy_lints/src/ranges.rs | 6 +- clippy_lints/src/raw_strings.rs | 143 +++ clippy_lints/src/redundant_clone.rs | 17 +- clippy_lints/src/redundant_closure_call.rs | 163 ++- .../src/redundant_type_annotations.rs | 210 ++++ clippy_lints/src/returns.rs | 8 +- .../src/significant_drop_tightening.rs | 587 +++++----- clippy_lints/src/single_call_fn.rs | 133 +++ clippy_lints/src/single_range_in_vec_init.rs | 147 +++ clippy_lints/src/trait_bounds.rs | 43 +- clippy_lints/src/tuple_array_conversions.rs | 235 ++++ .../src/undocumented_unsafe_blocks.rs | 126 +- clippy_lints/src/unused_async.rs | 3 +- clippy_lints/src/upper_case_acronyms.rs | 2 +- clippy_lints/src/useless_conversion.rs | 121 +- clippy_lints/src/utils/conf.rs | 47 +- clippy_lints/src/utils/internal_lints.rs | 1 + .../almost_standard_lint_formulation.rs | 87 ++ .../interning_defined_symbol.rs | 2 +- .../internal_lints/metadata_collector.rs | 28 +- clippy_lints/src/utils/mod.rs | 12 +- clippy_lints/src/vec.rs | 156 ++- clippy_lints/src/visibility.rs | 131 +++ clippy_test_deps/Cargo.toml | 23 + clippy_test_deps/src/lib.rs | 14 + clippy_utils/src/check_proc_macro.rs | 122 +- clippy_utils/src/consts.rs | 147 ++- clippy_utils/src/eager_or_lazy.rs | 23 +- clippy_utils/src/lib.rs | 23 +- clippy_utils/src/macros.rs | 14 +- clippy_utils/src/msrvs.rs | 6 +- clippy_utils/src/numeric_literal.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 82 +- clippy_utils/src/sugg.rs | 2 +- clippy_utils/src/ty.rs | 58 +- clippy_utils/src/usage.rs | 2 +- declare_clippy_lint/src/lib.rs | 4 +- lintcheck/src/main.rs | 2 +- rust-toolchain | 2 +- rustfmt.toml | 1 + src/driver.rs | 2 +- src/main.rs | 8 +- tests/compile-test.rs | 442 +++---- tests/headers.rs | 29 + tests/lint_message_convention.rs | 30 +- tests/missing-test-files.rs | 6 +- .../fail/{src/main.stderr => Cargo.stderr} | 7 +- .../{src/main.stderr => Cargo.stderr} | 7 +- .../{src/main.stderr => Cargo.stderr} | 7 +- .../fail_both_diff/Cargo.stderr | 21 + .../fail_both_diff/src/main.stderr | 22 - .../fail_both_same/Cargo.stderr | 19 + .../fail_cargo/Cargo.stderr | 19 + .../fail_cargo/src/main.stderr | 20 - .../fail_clippy/Cargo.stderr | 19 + .../fail_clippy/src/main.stderr | 20 - .../Cargo.stderr} | 15 +- .../fail_file_attr/src/main.stderr | 20 - .../{src/main.stderr => Cargo.stderr} | 2 - .../ui-cargo/duplicate_mod/fail/Cargo.stderr | 52 + .../duplicate_mod/fail/src/main.stderr | 53 - tests/ui-cargo/feature_name/fail/Cargo.stderr | 43 + .../feature_name/fail/src/main.stderr | 44 - .../module_style/fail_mod/Cargo.stderr | 18 + .../module_style/fail_mod/src/main.stderr | 19 - .../module_style/fail_mod_remap/Cargo.stderr | 10 + .../fail_mod_remap/src/main.stderr | 11 - .../module_style/fail_no_mod/Cargo.stderr | 10 + .../module_style/fail_no_mod/src/main.stderr | 11 - .../multiple_config_files/warn/Cargo.stderr | 2 + .../warn/src/main.stderr | 4 - .../multiple_crate_versions/fail/Cargo.stderr | 5 + .../fail/src/main.stderr | 6 - tests/ui-cargo/update-all-references.sh | 2 +- .../wildcard_dependencies/fail/Cargo.stderr | 5 + .../fail/src/main.stderr | 6 - tests/ui-internal/check_formulation.rs | 54 + tests/ui-internal/check_formulation.stderr | 19 + tests/ui-internal/custom_ice_message.stderr | 6 +- tests/ui-internal/if_chain_style.rs | 7 +- tests/ui-internal/if_chain_style.stderr | 20 +- .../uninlined_format_args.fixed | 1 + .../uninlined_format_args.rs | 1 + .../uninlined_format_args.stderr | 12 +- .../arithmetic_side_effects_allowed.rs | 1 + .../arithmetic_side_effects_allowed.stderr | 18 +- tests/ui-toml/bad_toml/conf_bad_toml.rs | 2 + tests/ui-toml/bad_toml/conf_bad_toml.stderr | 2 +- tests/ui-toml/bad_toml_type/conf_bad_type.rs | 2 + .../bad_toml_type/conf_bad_type.stderr | 2 +- .../conf_deprecated_key.stderr | 4 +- .../duplicated_keys/duplicated_keys.rs | 2 + .../duplicated_keys/duplicated_keys.stderr | 2 +- .../duplicated_keys.stderr | 4 +- .../duplicated_keys.stderr | 4 +- .../auxiliary/proc_macros.rs | 472 ++++++++ tests/ui-toml/excessive_nesting/clippy.toml | 1 + .../excessive_nesting/excessive_nesting.rs | 197 ++++ .../excessive_nesting.stderr | 314 +++++ tests/ui-toml/expect_used/expect_used.rs | 1 + tests/ui-toml/expect_used/expect_used.stderr | 4 +- .../invalid_min_rust_version.rs | 2 + .../ui-toml/lint_decimal_readability/test.rs | 2 +- .../lint_decimal_readability/test.stderr | 10 +- .../index_refutable_slice.rs | 1 + .../min_ident_chars/auxiliary/extern_types.rs | 3 + tests/ui-toml/min_ident_chars/clippy.toml | 2 + .../min_ident_chars/min_ident_chars.rs | 19 + .../min_ident_chars/min_ident_chars.stderr | 46 + .../min_rust_version/min_rust_version.rs | 4 +- tests/ui-toml/module_inception/clippy.toml | 1 + .../module_inception/module_inception.rs | 34 + .../module_inception/module_inception.stderr | 20 + .../auxiliary/proc_macro_derive.rs | 5 - .../conf_nonstandard_macro_braces.fixed | 2 +- .../conf_nonstandard_macro_braces.rs | 2 +- tests/ui-toml/suppress_lint_in_const/test.rs | 10 +- .../suppress_lint_in_const/test.stderr | 18 +- .../conf_disallowed_methods.rs | 2 + .../conf_disallowed_methods.stderr | 28 +- tests/ui-toml/toml_trivially_copy/test.rs | 2 +- tests/ui-toml/toml_trivially_copy/test.stderr | 6 +- .../toml_unknown_key/conf_unknown_key.rs | 2 +- .../toml_unknown_key/conf_unknown_key.stderr | 20 +- .../auxiliary/proc_macro_unsafe.rs | 13 + .../undocumented_unsafe_blocks/clippy.toml | 2 + .../undocumented_unsafe_blocks.rs | 567 +++++++++ .../undocumented_unsafe_blocks.stderr | 314 +++++ tests/ui-toml/unwrap_used/unwrap_used.rs | 9 +- tests/ui-toml/unwrap_used/unwrap_used.stderr | 62 +- tests/ui-toml/update-all-references.sh | 2 +- tests/ui/allow_attributes.fixed | 20 +- tests/ui/allow_attributes.rs | 20 +- tests/ui/allow_attributes.stderr | 4 +- tests/ui/allow_attributes_false_positive.rs | 5 - tests/ui/allow_attributes_without_reason.rs | 32 +- .../ui/allow_attributes_without_reason.stderr | 28 +- tests/ui/almost_complete_range.fixed | 2 +- tests/ui/almost_complete_range.rs | 2 +- tests/ui/arc_with_non_send_sync.rs | 17 + tests/ui/arc_with_non_send_sync.stderr | 11 + tests/ui/arithmetic_side_effects.rs | 17 +- tests/ui/as_conversions.rs | 13 +- tests/ui/as_conversions.stderr | 6 +- tests/ui/as_ptr_cast_mut.rs | 2 +- tests/ui/asm_syntax.rs | 4 +- tests/ui/assertions_on_result_states.fixed | 1 + tests/ui/assertions_on_result_states.rs | 1 + tests/ui/assertions_on_result_states.stderr | 14 +- tests/ui/assign_ops.fixed | 2 +- tests/ui/assign_ops.rs | 2 +- tests/ui/auxiliary/extern_fake_libc.rs | 10 + tests/ui/auxiliary/macro_rules.rs | 8 +- tests/ui/auxiliary/macro_use_helper.rs | 2 + tests/ui/auxiliary/proc_macro_attr.rs | 4 - tests/ui/auxiliary/proc_macro_derive.rs | 114 +- .../proc_macro_suspicious_else_formatting.rs | 5 - tests/ui/auxiliary/proc_macro_unsafe.rs | 5 - tests/ui/auxiliary/proc_macros.rs | 6 +- tests/ui/blocks_in_if_conditions.fixed | 2 +- tests/ui/blocks_in_if_conditions.rs | 2 +- tests/ui/blocks_in_if_conditions_closure.rs | 7 +- .../ui/blocks_in_if_conditions_closure.stderr | 4 +- tests/ui/bool_comparison.fixed | 1 + tests/ui/bool_comparison.rs | 1 + tests/ui/bool_comparison.stderr | 44 +- tests/ui/borrow_as_ptr.fixed | 9 + tests/ui/borrow_as_ptr.rs | 9 + tests/ui/borrow_as_ptr.stderr | 4 +- tests/ui/borrow_deref_ref.fixed | 2 +- tests/ui/borrow_deref_ref.rs | 2 +- .../ui/borrow_interior_mutable_const/enums.rs | 26 +- .../enums.stderr | 24 +- .../borrow_interior_mutable_const/others.rs | 30 +- .../others.stderr | 34 +- .../borrow_interior_mutable_const/traits.rs | 32 +- .../traits.stderr | 36 +- tests/ui/builtin_type_shadow.rs | 2 +- tests/ui/bytecount.rs | 2 +- tests/ui/cast.rs | 8 + tests/ui/cast.stderr | 118 +- tests/ui/cast_slice_different_sizes.rs | 2 +- tests/ui/cfg_features.rs | 12 + tests/ui/cfg_features.stderr | 28 + .../ui/checked_unwrap/complex_conditionals.rs | 6 +- .../complex_conditionals.stderr | 40 +- .../complex_conditionals_nested.rs | 6 +- .../complex_conditionals_nested.stderr | 4 +- .../ui/checked_unwrap/simple_conditionals.rs | 6 +- .../checked_unwrap/simple_conditionals.stderr | 34 +- tests/ui/clone_on_copy_impl.rs | 2 + tests/ui/cloned_instead_of_copied.fixed | 1 + tests/ui/cloned_instead_of_copied.rs | 1 + tests/ui/cloned_instead_of_copied.stderr | 16 +- .../ui/cmp_owned/asymmetric_partial_eq.fixed | 7 +- tests/ui/cmp_owned/asymmetric_partial_eq.rs | 7 +- .../ui/cmp_owned/asymmetric_partial_eq.stderr | 12 +- tests/ui/cmp_owned/with_suggestion.fixed | 2 +- tests/ui/cognitive_complexity.stderr | 10 +- tests/ui/collapsible_else_if.fixed | 2 +- tests/ui/collapsible_else_if.rs | 2 +- tests/ui/collapsible_if.fixed | 1 + tests/ui/collapsible_if.rs | 1 + tests/ui/collapsible_if.stderr | 18 +- tests/ui/collection_is_never_read.rs | 2 +- tests/ui/comparison_to_empty.fixed | 1 + tests/ui/comparison_to_empty.rs | 1 + tests/ui/comparison_to_empty.stderr | 8 +- .../ui/crashes/auxiliary/proc_macro_crash.rs | 8 - tests/ui/crashes/ice-10148.rs | 2 +- tests/ui/crashes/ice-10645.rs | 2 +- tests/ui/crashes/ice-10645.stderr | 4 +- tests/ui/crashes/ice-10912.rs | 4 + tests/ui/crashes/ice-10912.stderr | 16 + tests/ui/crashes/ice-1782.rs | 1 + tests/ui/crashes/ice-2774.stderr | 4 +- tests/ui/crashes/ice-3462.rs | 2 +- tests/ui/crashes/ice-3741.rs | 2 +- tests/ui/crashes/ice-4968.rs | 2 - tests/ui/crashes/ice-5497.rs | 2 +- tests/ui/crashes/ice-5579.rs | 2 + tests/ui/crashes/ice-6250.stderr | 11 +- tests/ui/crashes/ice-6251.stderr | 10 +- tests/ui/crashes/ice-6255.rs | 2 +- tests/ui/crashes/ice-6256.rs | 4 +- tests/ui/crashes/ice-6256.stderr | 2 +- tests/ui/crashes/ice-7169.rs | 2 + tests/ui/crashes/ice-7169.stderr | 2 +- tests/ui/crashes/ice-7410.rs | 4 +- tests/ui/crashes/ice-96721.rs | 2 +- tests/ui/crashes/ice-96721.stderr | 2 +- .../needless_lifetimes_impl_trait.stderr | 4 +- .../entrypoint_recursion.rs | 2 +- .../entrypoint_recursion.stderr | 11 - .../no_std_main_recursion.rs | 2 +- tests/ui/dbg_macro.rs | 1 - tests/ui/dbg_macro.stderr | 36 +- .../declare_interior_mutable_const/enums.rs | 27 +- .../enums.stderr | 43 +- .../declare_interior_mutable_const/others.rs | 16 +- .../others.stderr | 8 +- .../declare_interior_mutable_const/traits.rs | 22 +- .../traits.stderr | 22 +- tests/ui/def_id_nocore.rs | 2 +- tests/ui/default_numeric_fallback_f64.fixed | 2 +- tests/ui/default_numeric_fallback_f64.rs | 2 +- tests/ui/default_numeric_fallback_i32.fixed | 2 +- tests/ui/default_numeric_fallback_i32.rs | 2 +- tests/ui/default_trait_access.fixed | 2 +- tests/ui/default_trait_access.rs | 2 +- tests/ui/deref_addrof.fixed | 4 +- tests/ui/deref_addrof.rs | 4 +- tests/ui/deref_addrof_macro.rs | 2 +- tests/ui/derivable_impls.fixed | 21 + tests/ui/derivable_impls.rs | 21 + tests/ui/derive.rs | 2 +- tests/ui/disallowed_names.rs | 1 + tests/ui/disallowed_names.stderr | 28 +- tests/ui/diverging_sub_expression.rs | 16 + tests/ui/diverging_sub_expression.stderr | 46 +- tests/ui/doc/doc-fixable.fixed | 1 + tests/ui/doc/doc-fixable.rs | 1 + tests/ui/doc/doc-fixable.stderr | 32 +- tests/ui/doc/needless_doctest_main.rs | 20 + tests/ui/doc_unsafe.rs | 2 +- tests/ui/double_comparison.fixed | 1 + tests/ui/double_comparison.rs | 1 + tests/ui/double_comparison.stderr | 16 +- tests/ui/drain_collect.fixed | 77 ++ tests/ui/drain_collect.rs | 77 ++ tests/ui/drain_collect.stderr | 68 ++ tests/ui/else_if_without_else.rs | 4 +- tests/ui/else_if_without_else.stderr | 4 +- tests/ui/empty_line_after_doc_comments.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/empty_loop.rs | 2 +- tests/ui/empty_loop_no_std.rs | 2 +- tests/ui/endian_bytes.rs | 127 ++ tests/ui/endian_bytes.stderr | 1031 +++++++++++++++++ tests/ui/enum_clike_unportable_variant.rs | 2 +- tests/ui/eprint_with_newline.rs | 2 +- tests/ui/eprint_with_newline.stderr | 12 +- tests/ui/eq_op.rs | 4 +- tests/ui/eq_op.stderr | 20 +- tests/ui/eq_op_macros.rs | 1 + tests/ui/eq_op_macros.stderr | 24 +- tests/ui/equatable_if_let.fixed | 11 +- tests/ui/equatable_if_let.rs | 11 +- tests/ui/equatable_if_let.stderr | 28 +- tests/ui/err_expect.fixed | 2 +- tests/ui/err_expect.rs | 2 +- tests/ui/eta.fixed | 9 +- tests/ui/eta.rs | 9 +- tests/ui/eta.stderr | 52 +- tests/ui/excessive_precision.fixed | 15 +- tests/ui/excessive_precision.rs | 15 +- tests/ui/excessive_precision.stderr | 30 +- tests/ui/expect.rs | 1 + tests/ui/expect.stderr | 6 +- tests/ui/expect_fun_call.fixed | 6 +- tests/ui/expect_fun_call.rs | 6 +- tests/ui/expect_fun_call.stderr | 30 +- tests/ui/expect_tool_lint_rfc_2383.rs | 2 +- tests/ui/explicit_counter_loop.rs | 50 +- tests/ui/explicit_counter_loop.stderr | 10 +- tests/ui/explicit_deref_methods.fixed | 33 +- tests/ui/explicit_deref_methods.rs | 33 +- tests/ui/explicit_deref_methods.stderr | 24 +- tests/ui/explicit_into_iter_loop.fixed | 69 ++ tests/ui/explicit_into_iter_loop.rs | 69 ++ tests/ui/explicit_into_iter_loop.stderr | 40 + tests/ui/explicit_iter_loop.fixed | 154 +++ tests/ui/explicit_iter_loop.rs | 154 +++ tests/ui/explicit_iter_loop.stderr | 142 +++ tests/ui/extra_unused_lifetimes.rs | 2 +- tests/ui/extra_unused_type_parameters.fixed | 12 + tests/ui/extra_unused_type_parameters.rs | 12 + tests/ui/extra_unused_type_parameters.stderr | 16 +- tests/ui/field_reassign_with_default.rs | 4 +- tests/ui/filetype_is_file.rs | 1 + tests/ui/filetype_is_file.stderr | 6 +- tests/ui/find_map.rs | 1 + tests/ui/fn_null_check.rs | 1 + tests/ui/fn_null_check.stderr | 10 +- tests/ui/for_loop_fixable.fixed | 309 ----- tests/ui/for_loop_fixable.rs | 309 ----- tests/ui/for_loop_fixable.stderr | 96 -- tests/ui/for_loop_unfixable.rs | 16 - tests/ui/for_loop_unfixable.stderr | 10 - tests/ui/format.fixed | 4 +- tests/ui/format.rs | 4 +- tests/ui/format.stderr | 30 +- tests/ui/format_push_string.rs | 29 + tests/ui/format_push_string.stderr | 37 +- tests/ui/from_iter_instead_of_collect.fixed | 1 + tests/ui/from_iter_instead_of_collect.rs | 1 + tests/ui/from_iter_instead_of_collect.stderr | 30 +- tests/ui/from_over_into.fixed | 9 + tests/ui/from_over_into.rs | 9 + tests/ui/from_over_into.stderr | 18 +- tests/ui/from_over_into_unfixable.rs | 16 +- tests/ui/from_over_into_unfixable.stderr | 10 +- tests/ui/from_raw_with_void_ptr.rs | 1 + tests/ui/from_raw_with_void_ptr.stderr | 20 +- tests/ui/get_first.fixed | 1 + tests/ui/get_first.rs | 1 + tests/ui/get_first.stderr | 6 +- tests/ui/get_last_with_len.fixed | 2 +- tests/ui/get_last_with_len.rs | 2 +- tests/ui/get_unwrap.fixed | 46 +- tests/ui/get_unwrap.rs | 46 +- tests/ui/get_unwrap.stderr | 80 +- tests/ui/if_same_then_else.rs | 10 +- tests/ui/if_same_then_else.stderr | 24 +- tests/ui/if_same_then_else2.rs | 12 +- tests/ui/if_same_then_else2.stderr | 37 +- tests/ui/ifs_same_cond.rs | 14 +- tests/ui/ifs_same_cond.stderr | 16 +- tests/ui/implicit_hasher.rs | 2 +- .../ui/inconsistent_struct_constructor.fixed | 2 +- tests/ui/inconsistent_struct_constructor.rs | 2 +- .../incorrect_clone_impl_on_copy_type.fixed | 97 ++ tests/ui/incorrect_clone_impl_on_copy_type.rs | 107 ++ .../incorrect_clone_impl_on_copy_type.stderr | 40 + tests/ui/indexing_slicing_index.rs | 7 +- tests/ui/indexing_slicing_index.stderr | 26 +- tests/ui/indexing_slicing_slice.rs | 2 +- tests/ui/into_iter_on_ref.fixed | 54 +- tests/ui/into_iter_on_ref.rs | 54 +- tests/ui/into_iter_on_ref.stderr | 54 +- tests/ui/issue-3145.rs | 2 +- tests/ui/issue-3145.stderr | 2 +- tests/ui/issue_4266.stderr | 8 +- .../block_module.stderr | 17 +- tests/ui/iter_cloned_collect.fixed | 1 + tests/ui/iter_cloned_collect.rs | 1 + tests/ui/iter_cloned_collect.stderr | 10 +- tests/ui/iter_count.fixed | 3 +- tests/ui/iter_count.rs | 3 +- tests/ui/iter_count.stderr | 50 +- tests/ui/iter_next_loop.rs | 16 + tests/ui/iter_next_loop.stderr | 9 + tests/ui/iter_next_slice.fixed | 1 + tests/ui/iter_next_slice.rs | 1 + tests/ui/iter_next_slice.stderr | 8 +- tests/ui/iter_nth.rs | 1 + tests/ui/iter_nth.stderr | 22 +- tests/ui/iter_nth_zero.fixed | 15 + tests/ui/iter_nth_zero.rs | 15 + tests/ui/iter_overeager_cloned.fixed | 2 +- tests/ui/iter_overeager_cloned.rs | 2 +- tests/ui/iter_skip_next.fixed | 1 + tests/ui/iter_skip_next.rs | 1 + tests/ui/iter_skip_next.stderr | 14 +- tests/ui/iter_with_drain.fixed | 2 +- tests/ui/iter_with_drain.rs | 2 +- tests/ui/iterator_step_by_zero.rs | 1 + tests/ui/iterator_step_by_zero.stderr | 14 +- tests/ui/large_enum_variant.rs | 2 +- tests/ui/large_futures.rs | 1 + tests/ui/large_futures.stderr | 16 +- tests/ui/large_stack_frames.rs | 44 + tests/ui/large_stack_frames.stderr | 37 + tests/ui/len_zero.fixed | 2 +- tests/ui/len_zero.rs | 2 +- tests/ui/let_underscore_untyped.rs | 2 +- tests/ui/let_with_type_underscore.rs | 25 +- tests/ui/let_with_type_underscore.stderr | 38 +- tests/ui/lossy_float_literal.fixed | 4 + tests/ui/lossy_float_literal.rs | 4 + tests/ui/lossy_float_literal.stderr | 22 +- tests/ui/macro_use_imports.fixed | 2 +- tests/ui/macro_use_imports.rs | 2 +- tests/ui/macro_use_imports.stderr | 16 +- tests/ui/macro_use_imports_expect.rs | 2 +- tests/ui/manual_assert.edition2018.fixed | 2 +- tests/ui/manual_assert.edition2021.fixed | 2 +- tests/ui/manual_assert.rs | 2 +- tests/ui/manual_async_fn.fixed | 2 +- tests/ui/manual_async_fn.rs | 2 +- tests/ui/manual_filter.fixed | 2 +- tests/ui/manual_filter.rs | 2 +- tests/ui/manual_filter_map.fixed | 1 + tests/ui/manual_filter_map.rs | 1 + tests/ui/manual_filter_map.stderr | 54 +- tests/ui/manual_find_map.fixed | 1 + tests/ui/manual_find_map.rs | 1 + tests/ui/manual_find_map.stderr | 60 +- tests/ui/manual_let_else.rs | 50 +- tests/ui/manual_let_else.stderr | 107 +- tests/ui/manual_let_else_match.rs | 11 +- tests/ui/manual_let_else_match.stderr | 27 +- .../ui/manual_memcpy/without_loop_counters.rs | 1 + .../without_loop_counters.stderr | 26 +- tests/ui/manual_range_patterns.fixed | 35 + tests/ui/manual_range_patterns.rs | 35 + tests/ui/manual_range_patterns.stderr | 51 + tests/ui/manual_rem_euclid.fixed | 2 +- tests/ui/manual_rem_euclid.rs | 2 +- tests/ui/manual_slice_size_calculation.fixed | 2 +- tests/ui/manual_slice_size_calculation.rs | 2 +- tests/ui/manual_try_fold.rs | 100 ++ tests/ui/manual_try_fold.stderr | 28 + tests/ui/manual_unwrap_or.fixed | 2 +- tests/ui/manual_unwrap_or.rs | 2 +- tests/ui/map_clone.fixed | 3 +- tests/ui/map_clone.rs | 3 +- tests/ui/map_clone.stderr | 12 +- tests/ui/map_unwrap_or.rs | 47 + tests/ui/map_unwrap_or.stderr | 44 +- tests/ui/match_on_vec_items.rs | 1 + tests/ui/match_on_vec_items.stderr | 16 +- tests/ui/match_overlapping_arm.rs | 2 +- tests/ui/match_same_arms.rs | 20 +- tests/ui/match_same_arms.stderr | 24 +- tests/ui/match_same_arms2.rs | 23 +- tests/ui/match_same_arms2.stderr | 33 +- tests/ui/match_same_arms_non_exhaustive.rs | 58 + .../ui/match_same_arms_non_exhaustive.stderr | 29 + tests/ui/match_single_binding.fixed | 3 +- tests/ui/match_single_binding.rs | 3 +- tests/ui/match_single_binding.stderr | 48 +- tests/ui/mem_forget.rs | 3 + tests/ui/mem_forget.stderr | 15 +- tests/ui/mem_replace_macro.rs | 2 +- tests/ui/methods.rs | 1 + tests/ui/methods.stderr | 4 +- tests/ui/methods_fixable.fixed | 1 + tests/ui/methods_fixable.rs | 1 + tests/ui/methods_fixable.stderr | 2 +- tests/ui/min_ident_chars.rs | 84 ++ tests/ui/min_ident_chars.stderr | 178 +++ tests/ui/missing_assert_message.rs | 11 +- tests/ui/missing_assert_message.stderr | 32 +- .../ui/missing_const_for_fn/cant_be_const.rs | 45 +- .../ui/missing_const_for_fn/could_be_const.rs | 13 + .../could_be_const.stderr | 30 +- tests/ui/missing_doc.rs | 2 +- tests/ui/missing_doc_impl.rs | 2 +- tests/ui/missing_inline_proc_macro.rs | 1 - tests/ui/missing_panics_doc.rs | 80 +- tests/ui/missing_panics_doc.stderr | 110 +- tests/ui/mistyped_literal_suffix.fixed | 2 +- tests/ui/mistyped_literal_suffix.rs | 2 +- tests/ui/module_inception.rs | 12 + tests/ui/module_inception.stderr | 22 +- tests/ui/multiple_unsafe_ops_per_block.rs | 2 +- tests/ui/must_use_unit.fixed | 2 +- tests/ui/must_use_unit.rs | 2 +- tests/ui/mut_mut.rs | 2 +- .../needless_arbitrary_self_type_unfixable.rs | 2 +- tests/ui/needless_bool/fixable.fixed | 1 + tests/ui/needless_bool/fixable.rs | 1 + tests/ui/needless_bool/fixable.stderr | 42 +- tests/ui/needless_borrow.fixed | 3 +- tests/ui/needless_borrow.rs | 3 +- tests/ui/needless_borrow.stderr | 72 +- tests/ui/needless_borrowed_ref.fixed | 3 +- tests/ui/needless_borrowed_ref.rs | 3 +- tests/ui/needless_borrowed_ref.stderr | 34 +- tests/ui/needless_collect.fixed | 7 +- tests/ui/needless_collect.rs | 7 +- tests/ui/needless_collect_indirect.rs | 3 +- tests/ui/needless_collect_indirect.stderr | 32 +- tests/ui/needless_if.fixed | 93 ++ tests/ui/needless_if.rs | 94 ++ tests/ui/needless_if.stderr | 65 ++ tests/ui/needless_late_init.fixed | 5 +- tests/ui/needless_late_init.rs | 5 +- tests/ui/needless_late_init.stderr | 32 +- tests/ui/needless_lifetimes.fixed | 2 +- tests/ui/needless_lifetimes.rs | 2 +- tests/ui/needless_lifetimes.stderr | 184 +-- tests/ui/needless_option_as_deref.fixed | 1 + tests/ui/needless_option_as_deref.rs | 1 + tests/ui/needless_option_as_deref.stderr | 6 +- tests/ui/needless_pass_by_value_proc_macro.rs | 1 - tests/ui/needless_pub_self.fixed | 33 + tests/ui/needless_pub_self.rs | 33 + tests/ui/needless_pub_self.stderr | 22 + tests/ui/needless_range_loop.rs | 64 +- tests/ui/needless_range_loop.stderr | 28 +- tests/ui/needless_range_loop2.rs | 1 + tests/ui/needless_range_loop2.stderr | 16 +- tests/ui/needless_raw_string.fixed | 16 + tests/ui/needless_raw_string.rs | 16 + tests/ui/needless_raw_string.stderr | 22 + tests/ui/needless_raw_string_hashes.fixed | 19 + tests/ui/needless_raw_string_hashes.rs | 19 + tests/ui/needless_raw_string_hashes.stderr | 58 + tests/ui/never_loop.rs | 38 + tests/ui/never_loop.stderr | 46 +- tests/ui/no_effect.rs | 3 +- tests/ui/no_effect.stderr | 58 +- tests/ui/no_effect_return.rs | 81 ++ tests/ui/no_effect_return.stderr | 70 ++ tests/ui/non_expressive_names.rs | 12 +- tests/ui/non_expressive_names.stderr | 6 +- tests/ui/non_octal_unix_permissions.fixed | 2 +- tests/ui/non_octal_unix_permissions.rs | 2 +- tests/ui/nonminimal_bool.rs | 3 +- tests/ui/nonminimal_bool.stderr | 26 +- tests/ui/nonminimal_bool_methods.fixed | 2 +- tests/ui/nonminimal_bool_methods.rs | 2 +- tests/ui/octal_escapes.stderr | 6 +- tests/ui/ok_expect.rs | 2 + tests/ui/ok_expect.stderr | 10 +- tests/ui/option_as_ref_deref.fixed | 2 +- tests/ui/option_as_ref_deref.rs | 2 +- tests/ui/option_env_unwrap.rs | 2 +- tests/ui/option_if_let_else.fixed | 16 + tests/ui/option_if_let_else.rs | 22 + tests/ui/option_if_let_else.stderr | 20 +- tests/ui/or_fun_call.fixed | 8 +- tests/ui/or_fun_call.rs | 8 +- tests/ui/or_fun_call.stderr | 56 +- tests/ui/or_then_unwrap.fixed | 2 +- tests/ui/or_then_unwrap.rs | 2 +- tests/ui/overflow_check_conditional.rs | 1 + tests/ui/overflow_check_conditional.stderr | 16 +- tests/ui/partialeq_to_none.fixed | 2 +- tests/ui/partialeq_to_none.rs | 2 +- tests/ui/patterns.fixed | 11 + tests/ui/patterns.rs | 11 + tests/ui/patterns.stderr | 6 +- tests/ui/print_with_newline.fixed | 58 + tests/ui/print_with_newline.rs | 2 +- tests/ui/print_with_newline.stderr | 12 +- tests/ui/proc_macro.rs | 1 - tests/ui/proc_macro.stderr | 2 +- tests/ui/ptr_arg.rs | 33 +- tests/ui/ptr_arg.stderr | 60 +- tests/ui/ptr_as_ptr.fixed | 2 +- tests/ui/ptr_as_ptr.rs | 2 +- tests/ui/ptr_cast_constness.fixed | 21 +- tests/ui/ptr_cast_constness.rs | 31 +- tests/ui/ptr_cast_constness.stderr | 46 +- tests/ui/ptr_offset_with_cast.fixed | 2 +- tests/ui/ptr_offset_with_cast.rs | 2 +- tests/ui/pub_with_shorthand.fixed | 38 + tests/ui/pub_with_shorthand.rs | 38 + tests/ui/pub_with_shorthand.stderr | 28 + tests/ui/pub_without_shorthand.fixed | 38 + tests/ui/pub_without_shorthand.rs | 38 + tests/ui/pub_without_shorthand.stderr | 22 + tests/ui/question_mark.fixed | 22 + tests/ui/question_mark.rs | 26 + tests/ui/question_mark.stderr | 42 +- tests/ui/range.rs | 1 + tests/ui/range.stderr | 2 +- tests/ui/rc_clone_in_vec_init/arc.rs | 1 + tests/ui/rc_clone_in_vec_init/arc.stderr | 8 +- tests/ui/rc_clone_in_vec_init/rc.rs | 1 + tests/ui/rc_clone_in_vec_init/rc.stderr | 8 +- tests/ui/rc_clone_in_vec_init/weak.rs | 1 + tests/ui/rc_clone_in_vec_init/weak.stderr | 16 +- tests/ui/redundant_at_rest_pattern.fixed | 27 + tests/ui/redundant_at_rest_pattern.rs | 27 + tests/ui/redundant_at_rest_pattern.stderr | 40 + tests/ui/redundant_clone.fixed | 8 +- tests/ui/redundant_clone.rs | 8 +- tests/ui/redundant_clone.stderr | 60 +- tests/ui/redundant_closure_call_fixable.fixed | 47 + tests/ui/redundant_closure_call_fixable.rs | 47 + .../ui/redundant_closure_call_fixable.stderr | 62 +- ...edundant_pattern_matching_drop_order.fixed | 7 +- .../redundant_pattern_matching_drop_order.rs | 7 +- ...dundant_pattern_matching_drop_order.stderr | 44 +- .../redundant_pattern_matching_ipaddr.fixed | 1 + tests/ui/redundant_pattern_matching_ipaddr.rs | 1 + .../redundant_pattern_matching_ipaddr.stderr | 36 +- .../redundant_pattern_matching_option.fixed | 1 + tests/ui/redundant_pattern_matching_option.rs | 1 + .../redundant_pattern_matching_option.stderr | 56 +- .../ui/redundant_pattern_matching_poll.fixed | 1 + tests/ui/redundant_pattern_matching_poll.rs | 1 + .../ui/redundant_pattern_matching_poll.stderr | 36 +- .../redundant_pattern_matching_result.fixed | 1 + tests/ui/redundant_pattern_matching_result.rs | 1 + .../redundant_pattern_matching_result.stderr | 56 +- tests/ui/redundant_pub_crate.fixed | 8 +- tests/ui/redundant_pub_crate.rs | 8 +- tests/ui/redundant_static_lifetimes.fixed | 22 +- tests/ui/redundant_static_lifetimes.rs | 22 +- tests/ui/redundant_static_lifetimes.stderr | 24 +- .../ui/redundant_static_lifetimes_multiple.rs | 6 +- ...redundant_static_lifetimes_multiple.stderr | 12 +- tests/ui/redundant_type_annotations.rs | 176 +++ tests/ui/redundant_type_annotations.stderr | 106 ++ tests/ui/regex.rs | 7 +- tests/ui/regex.stderr | 52 +- tests/ui/rename.fixed | 6 +- tests/ui/rename.rs | 6 +- tests/ui/rename.stderr | 114 +- tests/ui/same_functions_in_if_condition.rs | 12 +- .../ui/same_functions_in_if_condition.stderr | 4 +- tests/ui/search_is_some.rs | 1 + tests/ui/search_is_some.stderr | 16 +- tests/ui/search_is_some_fixable_none.fixed | 2 +- tests/ui/search_is_some_fixable_none.rs | 2 +- tests/ui/search_is_some_fixable_some.fixed | 2 +- tests/ui/search_is_some_fixable_some.rs | 2 +- tests/ui/self_assignment.rs | 1 + tests/ui/self_assignment.stderr | 22 +- tests/ui/shadow.rs | 4 +- tests/ui/significant_drop_in_scrutinee.fixed | 627 ++++++++++ tests/ui/significant_drop_tightening.fixed | 12 + tests/ui/significant_drop_tightening.rs | 12 + tests/ui/significant_drop_tightening.stderr | 6 +- tests/ui/single_call_fn.rs | 74 ++ tests/ui/single_call_fn.stderr | 55 + tests/ui/single_char_add_str.fixed | 1 + tests/ui/single_char_add_str.rs | 1 + tests/ui/single_char_add_str.stderr | 30 +- tests/ui/single_char_pattern.fixed | 2 +- tests/ui/single_char_pattern.rs | 2 +- tests/ui/single_char_pattern.stderr | 4 +- tests/ui/single_element_loop.fixed | 2 + tests/ui/single_element_loop.rs | 2 + tests/ui/single_element_loop.stderr | 14 +- tests/ui/single_match.fixed | 47 +- tests/ui/single_match.rs | 47 +- tests/ui/single_match.stderr | 36 +- tests/ui/single_match_else.fixed | 2 +- tests/ui/single_match_else.rs | 2 +- tests/ui/single_range_in_vec_init.rs | 58 + tests/ui/single_range_in_vec_init.stderr | 145 +++ tests/ui/skip_while_next.rs | 2 +- tests/ui/stable_sort_primitive.fixed | 1 + tests/ui/stable_sort_primitive.rs | 1 + tests/ui/stable_sort_primitive.stderr | 14 +- tests/ui/starts_ends_with.fixed | 2 +- tests/ui/starts_ends_with.rs | 2 +- tests/ui/string_add.rs | 2 +- tests/ui/string_lit_as_bytes.fixed | 2 +- tests/ui/string_lit_as_bytes.rs | 2 +- tests/ui/suspicious_else_formatting.rs | 16 +- tests/ui/suspicious_else_formatting.stderr | 18 +- tests/ui/suspicious_unary_op_formatting.rs | 1 + .../ui/suspicious_unary_op_formatting.stderr | 8 +- tests/ui/swap.fixed | 3 +- tests/ui/swap.rs | 3 +- tests/ui/swap.stderr | 34 +- tests/ui/tests_outside_test_module.rs | 1 - tests/ui/tests_outside_test_module.stderr | 2 +- ...to_string_in_format_args_incremental.fixed | 9 + .../to_string_in_format_args_incremental.rs | 9 + ...o_string_in_format_args_incremental.stderr | 10 + tests/ui/toplevel_ref_arg.fixed | 4 +- tests/ui/toplevel_ref_arg.rs | 4 +- tests/ui/toplevel_ref_arg_non_rustfix.rs | 2 +- tests/ui/transmute_ptr_to_ptr.rs | 2 +- tests/ui/transmute_ptr_to_ref.fixed | 5 +- tests/ui/transmute_ptr_to_ref.rs | 5 +- tests/ui/transmute_ptr_to_ref.stderr | 48 +- tests/ui/try_err.fixed | 2 +- tests/ui/try_err.rs | 2 +- tests/ui/tuple_array_conversions.rs | 73 ++ tests/ui/tuple_array_conversions.stderr | 83 ++ tests/ui/type_complexity.rs | 2 +- tests/ui/type_repetition_in_bounds.rs | 39 + tests/ui/type_repetition_in_bounds.stderr | 18 +- tests/ui/undocumented_unsafe_blocks.rs | 24 +- tests/ui/undocumented_unsafe_blocks.stderr | 26 +- tests/ui/unicode.fixed | 1 - tests/ui/unicode.rs | 1 - tests/ui/unicode.stderr | 20 +- tests/ui/uninlined_format_args.fixed | 9 +- tests/ui/uninlined_format_args.rs | 9 +- tests/ui/uninlined_format_args.stderr | 142 +-- tests/ui/unit_arg.rs | 2 +- tests/ui/unit_cmp.rs | 3 +- tests/ui/unit_cmp.stderr | 12 +- tests/ui/unit_return_expecting_ord.rs | 1 + tests/ui/unit_return_expecting_ord.stderr | 12 +- tests/ui/unnecessary_cast.fixed | 81 +- tests/ui/unnecessary_cast.rs | 81 +- tests/ui/unnecessary_cast.stderr | 110 +- tests/ui/unnecessary_fold.fixed | 24 + tests/ui/unnecessary_fold.rs | 24 + tests/ui/unnecessary_fold.stderr | 56 +- tests/ui/unnecessary_join.fixed | 2 +- tests/ui/unnecessary_join.rs | 2 +- tests/ui/unnecessary_lazy_eval.fixed | 30 +- tests/ui/unnecessary_lazy_eval.rs | 30 +- tests/ui/unnecessary_lazy_eval.stderr | 102 +- tests/ui/unnecessary_lazy_eval_unfixable.rs | 1 + .../ui/unnecessary_lazy_eval_unfixable.stderr | 6 +- tests/ui/unnecessary_literal_unwrap.fixed | 78 ++ tests/ui/unnecessary_literal_unwrap.rs | 78 ++ tests/ui/unnecessary_literal_unwrap.stderr | 413 +++++++ .../unnecessary_literal_unwrap_unfixable.rs | 116 ++ ...nnecessary_literal_unwrap_unfixable.stderr | 603 ++++++++++ tests/ui/unnecessary_safety_comment.rs | 2 +- tests/ui/unnecessary_sort_by.fixed | 2 +- tests/ui/unnecessary_sort_by.rs | 2 +- .../unnecessary_struct_initialization.fixed | 2 +- tests/ui/unnecessary_struct_initialization.rs | 2 +- tests/ui/unnecessary_to_owned.fixed | 35 +- tests/ui/unnecessary_to_owned.rs | 35 +- tests/ui/unnecessary_unsafety_doc.rs | 2 +- tests/ui/unneeded_field_pattern.rs | 14 +- tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unneeded_wildcard_pattern.fixed | 9 + tests/ui/unneeded_wildcard_pattern.rs | 9 + tests/ui/unneeded_wildcard_pattern.stderr | 30 +- tests/ui/unnested_or_patterns.fixed | 8 +- tests/ui/unnested_or_patterns.rs | 8 +- tests/ui/unnested_or_patterns.stderr | 34 +- tests/ui/unnested_or_patterns2.fixed | 7 +- tests/ui/unnested_or_patterns2.rs | 7 +- tests/ui/unnested_or_patterns2.stderr | 16 +- tests/ui/unseparated_prefix_literals.fixed | 2 +- tests/ui/unseparated_prefix_literals.rs | 2 +- tests/ui/unused_async.rs | 14 + tests/ui/unused_async.stderr | 8 +- tests/ui/unwrap.rs | 1 + tests/ui/unwrap.stderr | 6 +- tests/ui/unwrap_expect_used.rs | 1 + tests/ui/unwrap_expect_used.stderr | 12 +- tests/ui/unwrap_or.rs | 1 + tests/ui/unwrap_or.stderr | 4 +- tests/ui/unwrap_or_else_default.fixed | 2 +- tests/ui/unwrap_or_else_default.rs | 2 +- tests/ui/update-all-references.sh | 2 +- tests/ui/use_self.fixed | 2 +- tests/ui/use_self.rs | 2 +- tests/ui/used_underscore_binding.rs | 2 +- tests/ui/useless_attribute.fixed | 2 +- tests/ui/useless_attribute.rs | 2 +- tests/ui/useless_conversion.fixed | 31 +- tests/ui/useless_conversion.rs | 31 +- tests/ui/useless_conversion.stderr | 62 +- tests/ui/useless_conversion_try.rs | 1 + tests/ui/useless_conversion_try.stderr | 18 +- tests/ui/vec.fixed | 82 +- tests/ui/vec.rs | 82 +- tests/ui/vec.stderr | 56 +- tests/ui/while_let_on_iterator.fixed | 4 +- tests/ui/while_let_on_iterator.rs | 4 +- tests/ui/while_let_on_iterator.stderr | 52 +- tests/ui/wildcard_imports.fixed | 2 +- tests/ui/wildcard_imports.rs | 2 +- tests/ui/wildcard_imports.stderr | 4 +- tests/ui/write_literal_2.rs | 2 +- tests/ui/write_literal_2.stderr | 32 +- tests/ui/write_with_newline.fixed | 63 + tests/ui/write_with_newline.stderr | 12 +- tests/workspace.rs | 40 + tests/workspace_test/Cargo.toml | 2 +- .../pass_mod_with_dep_in_subdir/Cargo.toml | 10 + .../dep_no_mod/Cargo.toml | 9 + .../dep_no_mod/src/foo.rs | 2 + .../dep_no_mod/src/foo/hello.rs | 1 + .../dep_no_mod/src/lib.rs | 5 + .../src/bad/mod.rs | 1 + .../pass_mod_with_dep_in_subdir/src/main.rs | 13 + .../src/more/foo.rs | 1 + .../src/more/inner/mod.rs | 1 + .../src/more/mod.rs | 2 + .../pass_no_mod_with_dep_in_subdir/Cargo.toml | 10 + .../dep_with_mod/Cargo.toml | 9 + .../dep_with_mod/src/lib.rs | 7 + .../dep_with_mod/src/with_mod/inner.rs | 1 + .../dep_with_mod/src/with_mod/inner/stuff.rs | 3 + .../src/with_mod/inner/stuff/most.rs | 1 + .../dep_with_mod/src/with_mod/mod.rs | 3 + .../src/good.rs | 1 + .../src/main.rs | 9 + util/etc/vscode-tasks.json | 4 +- util/gh-pages/index.html | 9 +- util/gh-pages/script.js | 204 +++- util/gh-pages/versions.html | 9 +- util/versions.py | 25 +- 912 files changed, 21798 insertions(+), 5828 deletions(-) delete mode 100644 clippy_dev/src/bless.rs create mode 100644 clippy_lints/src/arc_with_non_send_sync.rs create mode 100644 clippy_lints/src/endian_bytes.rs create mode 100644 clippy_lints/src/excessive_nesting.rs create mode 100644 clippy_lints/src/incorrect_impls.rs create mode 100644 clippy_lints/src/large_stack_frames.rs create mode 100644 clippy_lints/src/manual_range_patterns.rs delete mode 100644 clippy_lints/src/mem_forget.rs create mode 100644 clippy_lints/src/methods/drain_collect.rs create mode 100644 clippy_lints/src/methods/manual_try_fold.rs create mode 100644 clippy_lints/src/methods/unnecessary_literal_unwrap.rs create mode 100644 clippy_lints/src/min_ident_chars.rs create mode 100644 clippy_lints/src/misc_early/redundant_at_rest_pattern.rs create mode 100644 clippy_lints/src/needless_if.rs create mode 100644 clippy_lints/src/raw_strings.rs create mode 100644 clippy_lints/src/redundant_type_annotations.rs create mode 100644 clippy_lints/src/single_call_fn.rs create mode 100644 clippy_lints/src/single_range_in_vec_init.rs create mode 100644 clippy_lints/src/tuple_array_conversions.rs create mode 100644 clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs create mode 100644 clippy_lints/src/visibility.rs create mode 100644 clippy_test_deps/Cargo.toml create mode 100644 clippy_test_deps/src/lib.rs create mode 100644 tests/headers.rs rename tests/ui-cargo/cargo_common_metadata/fail/{src/main.stderr => Cargo.stderr} (74%) rename tests/ui-cargo/cargo_common_metadata/fail_publish/{src/main.stderr => Cargo.stderr} (74%) rename tests/ui-cargo/cargo_common_metadata/fail_publish_true/{src/main.stderr => Cargo.stderr} (74%) create mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr rename tests/ui-cargo/cargo_rust_version/{fail_both_same/src/main.stderr => fail_file_attr/Cargo.stderr} (56%) delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr rename tests/ui-cargo/cargo_rust_version/warn_both_diff/{src/main.stderr => Cargo.stderr} (77%) create mode 100644 tests/ui-cargo/duplicate_mod/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/duplicate_mod/fail/src/main.stderr create mode 100644 tests/ui-cargo/feature_name/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/feature_name/fail/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_mod/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_mod/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_no_mod/src/main.stderr create mode 100644 tests/ui-cargo/multiple_config_files/warn/Cargo.stderr delete mode 100644 tests/ui-cargo/multiple_config_files/warn/src/main.stderr create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr create mode 100644 tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr create mode 100644 tests/ui-internal/check_formulation.rs create mode 100644 tests/ui-internal/check_formulation.stderr create mode 100644 tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs create mode 100644 tests/ui-toml/excessive_nesting/clippy.toml create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.rs create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.stderr create mode 100644 tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs create mode 100644 tests/ui-toml/min_ident_chars/clippy.toml create mode 100644 tests/ui-toml/min_ident_chars/min_ident_chars.rs create mode 100644 tests/ui-toml/min_ident_chars/min_ident_chars.stderr create mode 100644 tests/ui-toml/module_inception/clippy.toml create mode 100644 tests/ui-toml/module_inception/module_inception.rs create mode 100644 tests/ui-toml/module_inception/module_inception.stderr create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/clippy.toml create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr delete mode 100644 tests/ui/allow_attributes_false_positive.rs create mode 100644 tests/ui/arc_with_non_send_sync.rs create mode 100644 tests/ui/arc_with_non_send_sync.stderr create mode 100644 tests/ui/auxiliary/extern_fake_libc.rs create mode 100644 tests/ui/cfg_features.rs create mode 100644 tests/ui/cfg_features.stderr create mode 100644 tests/ui/crashes/ice-10912.rs create mode 100644 tests/ui/crashes/ice-10912.stderr delete mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.stderr create mode 100644 tests/ui/doc/needless_doctest_main.rs create mode 100644 tests/ui/drain_collect.fixed create mode 100644 tests/ui/drain_collect.rs create mode 100644 tests/ui/drain_collect.stderr create mode 100644 tests/ui/endian_bytes.rs create mode 100644 tests/ui/endian_bytes.stderr create mode 100644 tests/ui/explicit_into_iter_loop.fixed create mode 100644 tests/ui/explicit_into_iter_loop.rs create mode 100644 tests/ui/explicit_into_iter_loop.stderr create mode 100644 tests/ui/explicit_iter_loop.fixed create mode 100644 tests/ui/explicit_iter_loop.rs create mode 100644 tests/ui/explicit_iter_loop.stderr delete mode 100644 tests/ui/for_loop_fixable.fixed delete mode 100644 tests/ui/for_loop_fixable.rs delete mode 100644 tests/ui/for_loop_fixable.stderr delete mode 100644 tests/ui/for_loop_unfixable.rs delete mode 100644 tests/ui/for_loop_unfixable.stderr create mode 100644 tests/ui/incorrect_clone_impl_on_copy_type.fixed create mode 100644 tests/ui/incorrect_clone_impl_on_copy_type.rs create mode 100644 tests/ui/incorrect_clone_impl_on_copy_type.stderr create mode 100644 tests/ui/iter_next_loop.rs create mode 100644 tests/ui/iter_next_loop.stderr create mode 100644 tests/ui/large_stack_frames.rs create mode 100644 tests/ui/large_stack_frames.stderr create mode 100644 tests/ui/manual_range_patterns.fixed create mode 100644 tests/ui/manual_range_patterns.rs create mode 100644 tests/ui/manual_range_patterns.stderr create mode 100644 tests/ui/manual_try_fold.rs create mode 100644 tests/ui/manual_try_fold.stderr create mode 100644 tests/ui/match_same_arms_non_exhaustive.rs create mode 100644 tests/ui/match_same_arms_non_exhaustive.stderr create mode 100644 tests/ui/min_ident_chars.rs create mode 100644 tests/ui/min_ident_chars.stderr create mode 100644 tests/ui/needless_if.fixed create mode 100644 tests/ui/needless_if.rs create mode 100644 tests/ui/needless_if.stderr create mode 100644 tests/ui/needless_pub_self.fixed create mode 100644 tests/ui/needless_pub_self.rs create mode 100644 tests/ui/needless_pub_self.stderr create mode 100644 tests/ui/needless_raw_string.fixed create mode 100644 tests/ui/needless_raw_string.rs create mode 100644 tests/ui/needless_raw_string.stderr create mode 100644 tests/ui/needless_raw_string_hashes.fixed create mode 100644 tests/ui/needless_raw_string_hashes.rs create mode 100644 tests/ui/needless_raw_string_hashes.stderr create mode 100644 tests/ui/no_effect_return.rs create mode 100644 tests/ui/no_effect_return.stderr create mode 100644 tests/ui/print_with_newline.fixed create mode 100644 tests/ui/pub_with_shorthand.fixed create mode 100644 tests/ui/pub_with_shorthand.rs create mode 100644 tests/ui/pub_with_shorthand.stderr create mode 100644 tests/ui/pub_without_shorthand.fixed create mode 100644 tests/ui/pub_without_shorthand.rs create mode 100644 tests/ui/pub_without_shorthand.stderr create mode 100644 tests/ui/redundant_at_rest_pattern.fixed create mode 100644 tests/ui/redundant_at_rest_pattern.rs create mode 100644 tests/ui/redundant_at_rest_pattern.stderr create mode 100644 tests/ui/redundant_type_annotations.rs create mode 100644 tests/ui/redundant_type_annotations.stderr create mode 100644 tests/ui/significant_drop_in_scrutinee.fixed create mode 100644 tests/ui/single_call_fn.rs create mode 100644 tests/ui/single_call_fn.stderr create mode 100644 tests/ui/single_range_in_vec_init.rs create mode 100644 tests/ui/single_range_in_vec_init.stderr create mode 100644 tests/ui/to_string_in_format_args_incremental.fixed create mode 100644 tests/ui/to_string_in_format_args_incremental.rs create mode 100644 tests/ui/to_string_in_format_args_incremental.stderr create mode 100644 tests/ui/tuple_array_conversions.rs create mode 100644 tests/ui/tuple_array_conversions.stderr create mode 100644 tests/ui/unnecessary_literal_unwrap.fixed create mode 100644 tests/ui/unnecessary_literal_unwrap.rs create mode 100644 tests/ui/unnecessary_literal_unwrap.stderr create mode 100644 tests/ui/unnecessary_literal_unwrap_unfixable.rs create mode 100644 tests/ui/unnecessary_literal_unwrap_unfixable.stderr create mode 100644 tests/ui/write_with_newline.fixed create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 4d80d3ce63dac..48a63e4856815 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,7 @@ [alias] uitest = "test --test compile-test" +uibless = "test --test compile-test -- -- --bless" +bless = "test -- -- --bless" dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " collect-metadata = "test --test dogfood --features internal -- run_metadata_collection_lint --ignored" diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index a9d42159c4bac..c582c28cd3cf1 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -25,7 +25,6 @@ env: CARGO_TARGET_DIR: '${{ github.workspace }}/target' NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true jobs: base: diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 30a156c925b07..d5ab313ba0e6f 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -11,7 +11,6 @@ env: CARGO_TARGET_DIR: '${{ github.workspace }}/target' NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true defaults: run: diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index 514706d64c8c0..0f0e3f2db925c 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -16,7 +16,6 @@ on: env: RUST_BACKTRACE: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true jobs: clippy_dev: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b609b47d8192..14d822083d8ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,9 @@ document. ## Rust 1.70 -Current beta, released 2023-06-01 +Current stable, released 2023-06-01 -[149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23) +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -95,7 +95,7 @@ Current beta, released 2023-06-01 [#10375](https://github.com/rust-lang/rust-clippy/pull/10375) * [`mem_replace_option_with_none`]: No longer lints on field expressions [#10594](https://github.com/rust-lang/rust-clippy/pull/10594) -* [`items_after_statements`]: No longer lints on times from macros +* [`items_after_statements`]: No longer lints on items from macros [#10542](https://github.com/rust-lang/rust-clippy/pull/10542) * [`print_literal`], [`write_literal`]: No longer lint strings coming from the `file!()` macro [#10573](https://github.com/rust-lang/rust-clippy/pull/10573) @@ -135,9 +135,9 @@ Current beta, released 2023-06-01 ## Rust 1.69 -Current stable, released 2023-04-20 +Released 2023-04-20 -[7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0) +[**View 86 PRs merged since 1.68**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-03-09..2023-04-20+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -252,7 +252,7 @@ Current stable, released 2023-04-20 Released 2023-03-09 -[d822110d...7f27e2e7](https://github.com/rust-lang/rust-clippy/compare/d822110d...7f27e2e7) +[**View 85 PRs merged since 1.67**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-01-26..2023-03-09+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -399,7 +399,7 @@ Released 2023-03-09 Released 2023-01-26 -[4f142aa1...d822110d](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...d822110d) +[**View 68 PRs merged since 1.66**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-12-15..2023-01-26+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -590,7 +590,8 @@ Released 2023-01-26 Released 2022-12-15 -[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1) +[**View 93 PRs merged since 1.65**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-11-03..2022-12-15+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -761,7 +762,8 @@ Released 2022-12-15 Released 2022-11-03 -[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523) +[**View 129 PRs merged since 1.64**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-09-22..2022-11-03+base%3Amaster+sort%3Amerged-desc+) + ### Important Changes @@ -905,7 +907,8 @@ Released 2022-11-03 Released 2022-09-22 -[d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc) +[**View 92 PRs merged since 1.63**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-08-11..2022-09-22+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1055,7 +1058,8 @@ Released 2022-09-22 Released 2022-08-11 -[7c21f91b...d7b5cbf0](https://github.com/rust-lang/rust-clippy/compare/7c21f91b...d7b5cbf0) +[**View 100 PRs merged since 1.62**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-06-30..2022-08-11+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1201,7 +1205,8 @@ Released 2022-08-11 Released 2022-06-30 -[d0cf3481...7c21f91b](https://github.com/rust-lang/rust-clippy/compare/d0cf3481...7c21f91b) +[**View 104 PRs merged since 1.61**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-05-19..2022-06-30+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1358,7 +1363,8 @@ Released 2022-06-30 Released 2022-05-19 -[57b3c4b...d0cf3481](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...d0cf3481) +[**View 93 PRs merged since 1.60**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-04-07..2022-05-19+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1459,7 +1465,8 @@ Released 2022-05-19 Released 2022-04-07 -[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b) +[**View 75 PRs merged since 1.59**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-02-24..2022-04-07+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1591,7 +1598,8 @@ Released 2022-04-07 Released 2022-02-24 -[e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589) +[**View 63 PRs merged since 1.58**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-01-13..2022-02-24+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1755,7 +1763,8 @@ Released 2022-02-24 Released 2022-01-13 -[00e31fa...e181011](https://github.com/rust-lang/rust-clippy/compare/00e31fa...e181011) +[**View 73 PRs merged since 1.57**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-12-02..2022-01-13+base%3Amaster+sort%3Amerged-desc+) + ### Rust 1.58.1 @@ -1876,7 +1885,8 @@ Released 2022-01-13 Released 2021-12-02 -[7bfc26e...00e31fa](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...00e31fa) +[**View 92 PRs merged since 1.56**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-10-21..2021-12-02+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2027,7 +2037,7 @@ Released 2021-12-02 Released 2021-10-21 -[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e) +[**View 92 PRs merged since 1.55**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-09-09..2021-10-21+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -2093,7 +2103,7 @@ Released 2021-10-21 Released 2021-09-09 -[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561) +[**View 61 PRs merged since 1.54**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-07-29..2021-09-09+base%3Amaster+sort%3Amerged-desc+) ### Important Changes @@ -2211,7 +2221,8 @@ Released 2021-09-09 Released 2021-07-29 -[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf) +[**View 68 PRs merged since 1.53**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-06-17..2021-07-29+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2339,7 +2350,7 @@ Released 2021-07-29 Released 2021-06-17 -[6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c) +[**View 80 PRs merged since 1.52**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-05-06..2021-06-17+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -2523,7 +2534,8 @@ Released 2021-06-17 Released 2021-05-06 -[3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e) +[**View 113 PRs merged since 1.51**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-03-25..2021-05-06+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2658,7 +2670,8 @@ Released 2021-05-06 Released 2021-03-25 -[4911ab1...3e41797](https://github.com/rust-lang/rust-clippy/compare/4911ab1...3e41797) +[**View 117 PRs merged since 1.50**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-02-11..2021-03-25+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2773,7 +2786,8 @@ Released 2021-03-25 Released 2021-02-11 -[b20d4c1...4bd77a1](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...4bd77a1) +[**View 90 PRs merged since 1.49**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-12-31..2021-02-11+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2902,7 +2916,8 @@ Released 2021-02-11 Released 2020-12-31 -[e636b88...b20d4c1](https://github.com/rust-lang/rust-clippy/compare/e636b88...b20d4c1) +[**View 85 PRs merged since 1.48**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-11-19..2020-12-31+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -3008,7 +3023,7 @@ Released 2020-12-31 Released 2020-11-19 -[09bd400...e636b88](https://github.com/rust-lang/rust-clippy/compare/09bd400...e636b88) +[**View 112 PRs merged since 1.47**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-10-08..2020-11-19+base%3Amaster+sort%3Amerged-desc+) ### New lints @@ -3126,7 +3141,8 @@ Released 2020-11-19 Released 2020-10-08 -[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400) +[**View 80 PRs merged since 1.46**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-08-27..2020-10-08+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3228,7 +3244,8 @@ Released 2020-10-08 Released 2020-08-27 -[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa) +[**View 93 PRs merged since 1.45**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-07-16..2020-08-27+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3290,7 +3307,8 @@ Released 2020-08-27 Released 2020-07-16 -[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1) +[**View 65 PRs merged since 1.44**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-06-04..2020-07-16+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3367,7 +3385,8 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565 Released 2020-06-04 -[204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8) +[**View 88 PRs merged since 1.43**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-04-23..2020-06-04+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3450,7 +3469,8 @@ Released 2020-06-04 Released 2020-04-23 -[4ee1206...204bb9b](https://github.com/rust-lang/rust-clippy/compare/4ee1206...204bb9b) +[**View 121 PRs merged since 1.42**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-03-12..2020-04-23+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3508,7 +3528,7 @@ Released 2020-04-23 Released 2020-03-12 -[69f99e7...4ee1206](https://github.com/rust-lang/rust-clippy/compare/69f99e7...4ee1206) +[**View 106 PRs merged since 1.41**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-01-30..2020-03-12+base%3Amaster+sort%3Amerged-desc+) ### New lints @@ -3575,7 +3595,7 @@ Released 2020-03-12 Released 2020-01-30 -[c8e3cfb...69f99e7](https://github.com/rust-lang/rust-clippy/compare/c8e3cfb...69f99e7) +[**View 107 PRs merged since 1.40**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-12-19..2020-01-30+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`exit`] [#4697](https://github.com/rust-lang/rust-clippy/pull/4697) @@ -3620,7 +3640,8 @@ Released 2020-01-30 Released 2019-12-19 -[4e7e71b...c8e3cfb](https://github.com/rust-lang/rust-clippy/compare/4e7e71b...c8e3cfb) +[**View 69 😺 PRs merged since 1.39**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-11-07..2019-12-19+base%3Amaster+sort%3Amerged-desc+) + * New Lints: * [`unneeded_wildcard_pattern`] [#4537](https://github.com/rust-lang/rust-clippy/pull/4537) @@ -3662,7 +3683,7 @@ Released 2019-12-19 Released 2019-11-07 -[3aea860...4e7e71b](https://github.com/rust-lang/rust-clippy/compare/3aea860...4e7e71b) +[**View 84 PRs merged since 1.38**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-09-26..2019-11-07+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`uninit_assumed_init`] [#4479](https://github.com/rust-lang/rust-clippy/pull/4479) @@ -3706,7 +3727,7 @@ Released 2019-11-07 Released 2019-09-26 -[e3cb40e...3aea860](https://github.com/rust-lang/rust-clippy/compare/e3cb40e...3aea860) +[**View 102 PRs merged since 1.37**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-08-15..2019-09-26+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`main_recursion`] [#4203](https://github.com/rust-lang/rust-clippy/pull/4203) @@ -3736,7 +3757,7 @@ Released 2019-09-26 Released 2019-08-15 -[082cfa7...e3cb40e](https://github.com/rust-lang/rust-clippy/compare/082cfa7...e3cb40e) +[**View 83 PRs merged since 1.36**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-07-04..2019-08-15+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`checked_conversions`] [#4088](https://github.com/rust-lang/rust-clippy/pull/4088) @@ -3760,7 +3781,8 @@ Released 2019-08-15 Released 2019-07-04 -[eb9f9b1...082cfa7](https://github.com/rust-lang/rust-clippy/compare/eb9f9b1...082cfa7) +[**View 75 PRs merged since 1.35**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-05-20..2019-07-04+base%3Amaster+sort%3Amerged-desc+) + * New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039) * New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954) @@ -3791,7 +3813,8 @@ Released 2019-07-04 Released 2019-05-20 -[1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e) +[**View 90 PRs merged since 1.34**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-04-10..2019-05-20+base%3Amaster+sort%3Amerged-desc+) + * New lint: `drop_bounds` to detect `T: Drop` bounds * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) @@ -3819,7 +3842,8 @@ Released 2019-05-20 Released 2019-04-10 -[1b89724...1fac380](https://github.com/rust-lang/rust-clippy/compare/1b89724...1fac380) +[**View 66 PRs merged since 1.33**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-02-26..2019-04-10+base%3Amaster+sort%3Amerged-desc+) + * New lint: [`assertions_on_constants`] to detect for example `assert!(true)` * New lint: [`dbg_macro`] to detect uses of the `dbg!` macro @@ -3849,7 +3873,7 @@ Released 2019-04-10 Released 2019-02-26 -[b2601be...1b89724](https://github.com/rust-lang/rust-clippy/compare/b2601be...1b89724) +[**View 83 PRs merged since 1.32**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-01-17..2019-02-26+base%3Amaster+sort%3Amerged-desc+) * New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`] * The `rust-clippy` repository is now part of the `rust-lang` org. @@ -3882,7 +3906,7 @@ Released 2019-02-26 Released 2019-01-17 -[2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be) +[**View 106 PRs merged since 1.31**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-12-06..2019-01-17+base%3Amaster+sort%3Amerged-desc+) * New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`, [`redundant_clone`], [`wildcard_dependencies`], @@ -3912,7 +3936,8 @@ Released 2019-01-17 Released 2018-12-06 -[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2) +[**View 85 PRs merged since 1.30**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-10-25..2018-12-06+base%3Amaster+sort%3Amerged-desc+) + * Clippy has been relicensed under a dual MIT / Apache license. See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more @@ -3952,7 +3977,8 @@ Released 2018-12-06 Released 2018-10-25 -[14207503...125907ad](https://github.com/rust-lang/rust-clippy/compare/14207503...125907ad) +[**View 106 PRs merged since 1.29**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-09-13..2018-10-25+base%3Amaster+sort%3Amerged-desc+) + * Deprecate `assign_ops` lint * New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`], @@ -4628,6 +4654,7 @@ Released 2018-09-13 [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions [`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut @@ -4641,6 +4668,7 @@ Released 2018-09-13 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask +[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#big_endian_bytes [`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name [`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints @@ -4735,6 +4763,7 @@ Released 2018-09-13 [`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens +[`drain_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect [`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy [`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop @@ -4757,6 +4786,7 @@ Released 2018-09-13 [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op [`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence +[`excessive_nesting`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision [`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums [`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs @@ -4811,6 +4841,7 @@ Released 2018-09-13 [`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap +[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes [`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex @@ -4829,6 +4860,7 @@ Released 2018-09-13 [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor +[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type [`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask @@ -4879,6 +4911,7 @@ Released 2018-09-13 [`large_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures [`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file [`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 [`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 @@ -4892,6 +4925,7 @@ Released 2018-09-13 [`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore [`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist +[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports @@ -4915,6 +4949,7 @@ Released 2018-09-13 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains +[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid [`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic @@ -4924,6 +4959,7 @@ Released 2018-09-13 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`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_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 @@ -4947,11 +4983,13 @@ Released 2018-09-13 [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm [`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter +[`maybe_misused_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_misused_cfg [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none [`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default [`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit +[`min_ident_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars [`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max [`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute [`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os @@ -5002,6 +5040,7 @@ Released 2018-09-13 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main [`needless_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each +[`needless_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_if [`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match @@ -5009,8 +5048,11 @@ Released 2018-09-13 [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value +[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop +[`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes +[`needless_raw_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_strings [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return [`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update @@ -5081,6 +5123,8 @@ Released 2018-09-13 [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use +[`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand +[`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark [`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one @@ -5094,6 +5138,7 @@ Released 2018-09-13 [`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation [`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block +[`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_at_rest_pattern [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call @@ -5106,6 +5151,7 @@ Released 2018-09-13 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes +[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref @@ -5146,6 +5192,7 @@ Released 2018-09-13 [`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names +[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern @@ -5154,6 +5201,7 @@ Released 2018-09-13 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count [`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next @@ -5216,6 +5264,7 @@ Released 2018-09-13 [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err +[`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction @@ -5238,6 +5287,7 @@ Released 2018-09-13 [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations +[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings @@ -5311,3 +5361,65 @@ Released 2018-09-13 [`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 + +[`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed +[`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary +[`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary +[`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api +[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv +[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold +[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names +[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline +[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents +[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold +[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold +[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold +[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold +[`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold +[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold +[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit +[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold +[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold +[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold +[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold +[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds +[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools +[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools +[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports +[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros +[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods +[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types +[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions +[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive +[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else +[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish +[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces +[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames +[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts +[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send +[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length +[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types +[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size +[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests +[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests +[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests +[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold +[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability +[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const +[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items +[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size +[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception +[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars +[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold +[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement +[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes +[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings + diff --git a/Cargo.toml b/Cargo.toml index ca8bf9fac91a0..76c804f935e29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,27 +27,14 @@ tempfile = { version = "3.2", optional = true } termize = "0.1" [dev-dependencies] -compiletest_rs = { version = "0.10", features = ["tmp"] } +ui_test = "0.11.5" tester = "0.9" regex = "1.5" toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. filetime = "0.2" - -# UI test dependencies -clap = { version = "4.1.4", features = ["derive"] } -clippy_utils = { path = "clippy_utils" } -derive-new = "0.5" -if_chain = "1.0" itertools = "0.10.1" -quote = "1.0" -serde = { version = "1.0.125", features = ["derive"] } -syn = { version = "2.0", features = ["full"] } -futures = "0.3" -parking_lot = "0.12" -tokio = { version = "1", features = ["io-util"] } -rustc-semver = "1.1" [build-dependencies] rustc_tools_util = "0.3.0" @@ -60,3 +47,7 @@ internal = ["clippy_lints/internal", "tempfile"] [package.metadata.rust-analyzer] # This package uses #[feature(rustc_private)] rustc_private = true + +[[test]] +name = "compile-test" +harness = false diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index c26aa883ebae2..a0db808925021 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -122,20 +122,17 @@ fn main() { } ``` -Now we can run the test with `TESTNAME=foo_functions cargo uitest`, currently +Now we can run the test with `TESTNAME=foo_functions cargo uibless`, currently this test is meaningless though. While we are working on implementing our lint, we can keep running the UI test. -That allows us to check if the output is turning into what we want. +That allows us to check if the output is turning into what we want by checking the +`.stderr` file that gets updated on every test run. -Once we are satisfied with the output, we need to run `cargo dev bless` to -update the `.stderr` file for our lint. Please note that, we should run -`TESTNAME=foo_functions cargo uitest` every time before running `cargo dev -bless`. Running `TESTNAME=foo_functions cargo uitest` should pass then. When we +Running `TESTNAME=foo_functions cargo uitest` should pass on its own. When we commit our lint, we need to commit the generated `.stderr` files, too. In -general, you should only commit files changed by `cargo dev bless` for the -specific lint you are creating/editing. Note that if the generated files are -empty, they should be removed. +general, you should only commit files changed by `cargo bless` for the +specific lint you are creating/editing. > _Note:_ you can run multiple test files by specifying a comma separated list: > `TESTNAME=foo_functions,test2,test3`. @@ -169,7 +166,7 @@ additionally run [rustfix] for that test. Rustfix will apply the suggestions from the lint to the code of the test file and compare that to the contents of a `.fixed` file. -Use `cargo dev bless` to automatically generate the `.fixed` file after running +Use `cargo bless` to automatically generate the `.fixed` file while running the tests. [rustfix]: https://github.com/rust-lang/rustfix @@ -417,7 +414,7 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { Now we should also run the full test suite with `cargo test`. At this point running `cargo test` should produce the expected output. Remember to run `cargo -dev bless` to update the `.stderr` file. +bless` to update the `.stderr` file. `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint implementation is not violating any Clippy lints itself. diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 7615dc12f9ebe..f4c109ff11917 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -66,7 +66,7 @@ If the output of a [UI test] differs from the expected output, you can update the reference file with: ```bash -cargo dev bless +cargo bless ``` For example, this is necessary if you fix a typo in an error message of a lint, diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index df9b1bbe18f32..52445494436c6 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -56,6 +56,28 @@ and open that file in your editor of choice. When updating the changelog it's also a good idea to make sure that `commit1` is already correct in the current changelog. +#### PR ranges + +We developed the concept of PR ranges to help the user understand the size of a new update. To create a PR range, +get the current release date and the date that the last version was released (YYYY-MM-DD) and use the following link: + +``` +[**View PRs merged since 1.**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A..+base%3Amaster+sort%3Amerged-desc+) +``` + +> Note: Be sure to check click the link and check how many PRs got merged between + +Example: + +``` +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) +``` + +Which renders to: +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) + +Note that **commit ranges should not be included**, only PR ranges. + ### 3. Authoring the final changelog The above script should have dumped all the relevant PRs to the file you diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 5646c9b15208f..60d7ce6e61559 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -3,63 +3,14 @@ This file is generated by `cargo collect-metadata`. Please use that command to update the file and do not edit it by hand. --> -## Lint Configuration Options -|
Option
| Default Value | -|--|--| -| [arithmetic-side-effects-allowed](#arithmetic-side-effects-allowed) | `{}` | -| [arithmetic-side-effects-allowed-binary](#arithmetic-side-effects-allowed-binary) | `[]` | -| [arithmetic-side-effects-allowed-unary](#arithmetic-side-effects-allowed-unary) | `{}` | -| [avoid-breaking-exported-api](#avoid-breaking-exported-api) | `true` | -| [msrv](#msrv) | `None` | -| [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` | -| [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` | -| [semicolon-inside-block-ignore-singleline](#semicolon-inside-block-ignore-singleline) | `false` | -| [semicolon-outside-block-ignore-multiline](#semicolon-outside-block-ignore-multiline) | `false` | -| [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` | -| [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` | -| [type-complexity-threshold](#type-complexity-threshold) | `250` | -| [single-char-binding-names-threshold](#single-char-binding-names-threshold) | `4` | -| [too-large-for-stack](#too-large-for-stack) | `200` | -| [enum-variant-name-threshold](#enum-variant-name-threshold) | `3` | -| [enum-variant-size-threshold](#enum-variant-size-threshold) | `200` | -| [verbose-bit-mask-threshold](#verbose-bit-mask-threshold) | `1` | -| [literal-representation-threshold](#literal-representation-threshold) | `16384` | -| [trivial-copy-size-limit](#trivial-copy-size-limit) | `None` | -| [pass-by-value-size-limit](#pass-by-value-size-limit) | `256` | -| [too-many-lines-threshold](#too-many-lines-threshold) | `100` | -| [array-size-threshold](#array-size-threshold) | `512000` | -| [vec-box-size-threshold](#vec-box-size-threshold) | `4096` | -| [max-trait-bounds](#max-trait-bounds) | `3` | -| [max-struct-bools](#max-struct-bools) | `3` | -| [max-fn-params-bools](#max-fn-params-bools) | `3` | -| [warn-on-all-wildcard-imports](#warn-on-all-wildcard-imports) | `false` | -| [disallowed-macros](#disallowed-macros) | `[]` | -| [disallowed-methods](#disallowed-methods) | `[]` | -| [disallowed-types](#disallowed-types) | `[]` | -| [unreadable-literal-lint-fractions](#unreadable-literal-lint-fractions) | `true` | -| [upper-case-acronyms-aggressive](#upper-case-acronyms-aggressive) | `false` | -| [matches-for-let-else](#matches-for-let-else) | `WellKnownTypes` | -| [cargo-ignore-publish](#cargo-ignore-publish) | `false` | -| [standard-macro-braces](#standard-macro-braces) | `[]` | -| [enforced-import-renames](#enforced-import-renames) | `[]` | -| [allowed-scripts](#allowed-scripts) | `["Latin"]` | -| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` | -| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` | -| [await-holding-invalid-types](#await-holding-invalid-types) | `[]` | -| [max-include-file-size](#max-include-file-size) | `1000000` | -| [allow-expect-in-tests](#allow-expect-in-tests) | `false` | -| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` | -| [allow-dbg-in-tests](#allow-dbg-in-tests) | `false` | -| [allow-print-in-tests](#allow-print-in-tests) | `false` | -| [large-error-threshold](#large-error-threshold) | `128` | -| [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` | -| [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` | -| [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` | -| [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` | -| [future-size-threshold](#future-size-threshold) | `16384` | -| [unnecessary-box-size](#unnecessary-box-size) | `128` | - -### arithmetic-side-effects-allowed +# Lint Configuration Options + +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +## `arithmetic-side-effects-allowed` Suppress checking of the passed type names in all types of operations. If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. @@ -77,10 +28,12 @@ A type, say `SomeType`, listed in this configuration has the same behavior of **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### arithmetic-side-effects-allowed-binary +## `arithmetic-side-effects-allowed-binary` Suppress checking of the passed type pair names in binary operations like addition or multiplication. @@ -98,10 +51,12 @@ arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", **Default Value:** `[]` (`Vec<[String; 2]>`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### arithmetic-side-effects-allowed-unary +## `arithmetic-side-effects-allowed-unary` Suppress checking of the passed type names in unary operations like "negation" (`-`). #### Example @@ -112,116 +67,145 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### avoid-breaking-exported-api +## `avoid-breaking-exported-api` Suppress lints whenever the suggested change would cause breakage for other crates. **Default Value:** `true` (`bool`) -* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -* [unnecessary_wraps](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) -* [unused_self](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) -* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -* [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -* [box_collection](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) -* [redundant_allocation](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) -* [rc_buffer](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) -* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -* [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) -* [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) -* [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) -* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) - - -### msrv +--- +**Affected lints:** +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) +* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) +* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) +* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) +* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) +* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) +* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) + + +## `msrv` The minimum rust version that the project supports **Default Value:** `None` (`Option`) -* [manual_split_once](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) -* [manual_str_repeat](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) -* [cloned_instead_of_copied](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) -* [redundant_field_names](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) -* [redundant_static_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) -* [filter_map_next](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) -* [checked_conversions](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) -* [manual_range_contains](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) -* [use_self](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -* [mem_replace_with_default](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) -* [manual_non_exhaustive](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) -* [option_as_ref_deref](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) -* [map_unwrap_or](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) -* [match_like_matches_macro](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) -* [manual_strip](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) -* [missing_const_for_fn](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) -* [unnested_or_patterns](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) -* [from_over_into](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) -* [ptr_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) -* [if_then_some_else_none](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) -* [approx_constant](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) -* [deprecated_cfg_attr](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) -* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -* [map_clone](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) -* [borrow_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) -* [manual_bits](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) -* [err_expect](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) -* [cast_abs_to_unsigned](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) -* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) -* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) -* [collapsible_str_replace](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) -* [seek_from_current](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) -* [seek_rewind](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) -* [unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) -* [transmute_ptr_to_ref](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) -* [almost_complete_range](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) -* [needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) -* [derivable_impls](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) -* [manual_is_ascii_check](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) -* [manual_rem_euclid](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) -* [manual_retain](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) - - -### cognitive-complexity-threshold +--- +**Affected lints:** +* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) +* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) +* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) +* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) +* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) +* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) +* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) +* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) +* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) +* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) +* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) +* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) +* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) +* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) +* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) +* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) +* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) +* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) +* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) +* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) +* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) +* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) +* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) +* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) +* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) +* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) +* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) +* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) +* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) +* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) +* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) +* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) +* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) +* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) +* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) +* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) +* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) +* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) + + +## `cognitive-complexity-threshold` The maximum cognitive complexity a function can have **Default Value:** `25` (`u64`) -* [cognitive_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +--- +**Affected lints:** +* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) + + +## `excessive-nesting-threshold` +The maximum amount of nesting a block can reside in +**Default Value:** `0` (`u64`) -### disallowed-names +--- +**Affected lints:** +* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) + + +## `disallowed-names` The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value `".."` can be used as part of the list to indicate, that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. **Default Value:** `["foo", "baz", "quux"]` (`Vec`) -* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +--- +**Affected lints:** +* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) -### semicolon-inside-block-ignore-singleline +## `semicolon-inside-block-ignore-singleline` Whether to lint only if it's multiline. **Default Value:** `false` (`bool`) -* [semicolon_inside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) +--- +**Affected lints:** +* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) -### semicolon-outside-block-ignore-multiline +## `semicolon-outside-block-ignore-multiline` Whether to lint only if it's singleline. **Default Value:** `false` (`bool`) -* [semicolon_outside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) +--- +**Affected lints:** +* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) -### doc-valid-idents +## `doc-valid-idents` The list of words this lint should not consider as identifiers needing ticks. The value `".."` can be used as part of the list to indicate, that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. For example: @@ -230,207 +214,267 @@ default configuration of Clippy. By default, any configuration will replace the Default list: -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec`) +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec`) -* [doc_markdown](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) +--- +**Affected lints:** +* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) -### too-many-arguments-threshold +## `too-many-arguments-threshold` The maximum number of argument a function or method can have **Default Value:** `7` (`u64`) -* [too_many_arguments](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) +--- +**Affected lints:** +* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) -### type-complexity-threshold +## `type-complexity-threshold` The maximum complexity a type can have **Default Value:** `250` (`u64`) -* [type_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) +--- +**Affected lints:** +* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) -### single-char-binding-names-threshold +## `single-char-binding-names-threshold` The maximum number of single char bindings a scope may have **Default Value:** `4` (`u64`) -* [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +--- +**Affected lints:** +* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) -### too-large-for-stack +## `too-large-for-stack` The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap **Default Value:** `200` (`u64`) -* [boxed_local](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) -* [useless_vec](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +--- +**Affected lints:** +* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) -### enum-variant-name-threshold +## `enum-variant-name-threshold` The minimum number of enum variants for the lints about variant names to trigger **Default Value:** `3` (`u64`) -* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +--- +**Affected lints:** +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -### enum-variant-size-threshold +## `enum-variant-size-threshold` The maximum size of an enum's variant to avoid box suggestion **Default Value:** `200` (`u64`) -* [large_enum_variant](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) +--- +**Affected lints:** +* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) -### verbose-bit-mask-threshold +## `verbose-bit-mask-threshold` The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' **Default Value:** `1` (`u64`) -* [verbose_bit_mask](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) +--- +**Affected lints:** +* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) -### literal-representation-threshold +## `literal-representation-threshold` The lower bound for linting decimal literals **Default Value:** `16384` (`u64`) -* [decimal_literal_representation](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) +--- +**Affected lints:** +* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) -### trivial-copy-size-limit +## `trivial-copy-size-limit` The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. **Default Value:** `None` (`Option`) -* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +--- +**Affected lints:** +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -### pass-by-value-size-limit +## `pass-by-value-size-limit` The minimum size (in bytes) to consider a type for passing by reference instead of by value. **Default Value:** `256` (`u64`) -* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +--- +**Affected lints:** +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -### too-many-lines-threshold +## `too-many-lines-threshold` The maximum number of lines a function or method can have **Default Value:** `100` (`u64`) -* [too_many_lines](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +--- +**Affected lints:** +* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) -### array-size-threshold +## `array-size-threshold` The maximum allowed size for arrays on the stack **Default Value:** `512000` (`u64`) -* [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) -* [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) +--- +**Affected lints:** +* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) +* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) + + +## `stack-size-threshold` +The maximum allowed stack size for functions in bytes + +**Default Value:** `512000` (`u64`) + +--- +**Affected lints:** +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) -### vec-box-size-threshold +## `vec-box-size-threshold` The size of the boxed type in bytes, where boxing in a `Vec` is allowed **Default Value:** `4096` (`u64`) -* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +--- +**Affected lints:** +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -### max-trait-bounds +## `max-trait-bounds` The maximum number of bounds a trait can have to be linted **Default Value:** `3` (`u64`) -* [type_repetition_in_bounds](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +--- +**Affected lints:** +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -### max-struct-bools +## `max-struct-bools` The maximum number of bool fields a struct can have **Default Value:** `3` (`u64`) -* [struct_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) +--- +**Affected lints:** +* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) -### max-fn-params-bools +## `max-fn-params-bools` The maximum number of bool parameters a function can have **Default Value:** `3` (`u64`) -* [fn_params_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) +--- +**Affected lints:** +* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) -### warn-on-all-wildcard-imports +## `warn-on-all-wildcard-imports` Whether to allow certain wildcard imports (prelude, super in tests). **Default Value:** `false` (`bool`) -* [wildcard_imports](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +--- +**Affected lints:** +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) -### disallowed-macros +## `disallowed-macros` The list of disallowed macros, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_macros](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) +--- +**Affected lints:** +* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) -### disallowed-methods +## `disallowed-methods` The list of disallowed methods, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) +--- +**Affected lints:** +* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) -### disallowed-types +## `disallowed-types` The list of disallowed types, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_types](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) +--- +**Affected lints:** +* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) -### unreadable-literal-lint-fractions +## `unreadable-literal-lint-fractions` Should the fraction of a decimal be linted to include separators. **Default Value:** `true` (`bool`) -* [unreadable_literal](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) +--- +**Affected lints:** +* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) -### upper-case-acronyms-aggressive +## `upper-case-acronyms-aggressive` Enables verbose mode. Triggers if there is more than one uppercase char next to each other **Default Value:** `false` (`bool`) -* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +--- +**Affected lints:** +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -### matches-for-let-else +## `matches-for-let-else` Whether the matches should be considered by the lint, and whether there should be filtering for common types. **Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`) -* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +--- +**Affected lints:** +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -### cargo-ignore-publish +## `cargo-ignore-publish` For internal testing only, ignores the current `publish` settings in the Cargo manifest. **Default Value:** `false` (`bool`) -* [_cargo_common_metadata](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata) +--- +**Affected lints:** +* [`_cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata) -### standard-macro-braces +## `standard-macro-braces` Enforce the named macros always use the braces specified. A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro @@ -439,119 +483,147 @@ could be used with a full path two `MacroMatcher`s have to be added one with the **Default Value:** `[]` (`Vec`) -* [nonstandard_macro_braces](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) +--- +**Affected lints:** +* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) -### enforced-import-renames +## `enforced-import-renames` The list of imports to always rename, a fully qualified path followed by the rename. **Default Value:** `[]` (`Vec`) -* [missing_enforced_import_renames](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) +--- +**Affected lints:** +* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) -### allowed-scripts +## `allowed-scripts` The list of unicode scripts allowed to be used in the scope. **Default Value:** `["Latin"]` (`Vec`) -* [disallowed_script_idents](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) +--- +**Affected lints:** +* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) -### enable-raw-pointer-heuristic-for-send +## `enable-raw-pointer-heuristic-for-send` Whether to apply the raw pointer heuristic to determine if a type is `Send`. **Default Value:** `true` (`bool`) -* [non_send_fields_in_send_ty](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) +--- +**Affected lints:** +* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) -### max-suggested-slice-pattern-length +## `max-suggested-slice-pattern-length` When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. **Default Value:** `3` (`u64`) -* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +--- +**Affected lints:** +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -### await-holding-invalid-types +## `await-holding-invalid-types` **Default Value:** `[]` (`Vec`) -* [await_holding_invalid_type](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) +--- +**Affected lints:** +* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) -### max-include-file-size +## `max-include-file-size` The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes **Default Value:** `1000000` (`u64`) -* [large_include_file](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) +--- +**Affected lints:** +* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) -### allow-expect-in-tests +## `allow-expect-in-tests` Whether `expect` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [expect_used](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +--- +**Affected lints:** +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) -### allow-unwrap-in-tests +## `allow-unwrap-in-tests` Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [unwrap_used](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +--- +**Affected lints:** +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) -### allow-dbg-in-tests +## `allow-dbg-in-tests` Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [dbg_macro](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +--- +**Affected lints:** +* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) -### allow-print-in-tests +## `allow-print-in-tests` Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [print_stdout](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -* [print_stderr](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +--- +**Affected lints:** +* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) +* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) -### large-error-threshold +## `large-error-threshold` The maximum size of the `Err`-variant in a `Result` returned from a function **Default Value:** `128` (`u64`) -* [result_large_err](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +--- +**Affected lints:** +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) -### ignore-interior-mutability +## `ignore-interior-mutability` A list of paths to types that should be treated like `Arc`, i.e. ignored but for the generic parameters for determining interior mutability **Default Value:** `["bytes::Bytes"]` (`Vec`) -* [mutable_key_type](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -* [ifs_same_cond](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +--- +**Affected lints:** +* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) +* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) -### allow-mixed-uninlined-format-args +## `allow-mixed-uninlined-format-args` Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` **Default Value:** `true` (`bool`) -* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +--- +**Affected lints:** +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -### suppress-restriction-lint-in-const +## `suppress-restriction-lint-in-const` Whether to suppress a restriction lint in constant code. In same cases the restructured operation might not be unavoidable, as the suggested counterparts are unavailable in constant code. This @@ -560,32 +632,101 @@ if no suggestion can be made. **Default Value:** `false` (`bool`) -* [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) +--- +**Affected lints:** +* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) -### missing-docs-in-crate-items +## `missing-docs-in-crate-items` Whether to **only** check for missing documentation in items visible within the current crate. For example, `pub(crate)` items. **Default Value:** `false` (`bool`) -* [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +--- +**Affected lints:** +* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) -### future-size-threshold +## `future-size-threshold` The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint **Default Value:** `16384` (`u64`) -* [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) +--- +**Affected lints:** +* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) -### unnecessary-box-size +## `unnecessary-box-size` The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint **Default Value:** `128` (`u64`) -* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +--- +**Affected lints:** +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) + + +## `allow-private-module-inception` +Whether to allow module inception if it's not public. + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) + + +## `allowed-idents-below-min-chars` +Allowed names below the minimum allowed characters. The value `".."` can be used as part of +the list to indicate, that the configured values should be appended to the default +configuration of Clippy. By default, any configuration will replace the default value. + +**Default Value:** `{"j", "z", "i", "y", "n", "x", "w"}` (`rustc_data_structures::fx::FxHashSet`) + +--- +**Affected lints:** +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) + + +## `min-ident-chars-threshold` +Minimum chars an ident can have, anything below or equal to this will be linted. + +**Default Value:** `1` (`u64`) + +--- +**Affected lints:** +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) + + +## `accept-comment-above-statement` +Whether to accept a safety comment to be placed above the statement containing the `unsafe` block + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) + + +## `accept-comment-above-attributes` +Whether to accept a safety comment to be placed above the attributes for the `unsafe` block + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) + + +## `allow-one-hash-in-raw-strings` +Whether to allow `r#""#` when `r""` can be used + +**Default Value:** `false` (`bool`) +--- +**Affected lints:** +* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) diff --git a/clippy_dev/src/bless.rs b/clippy_dev/src/bless.rs deleted file mode 100644 index 92b2771f3fe73..0000000000000 --- a/clippy_dev/src/bless.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! `bless` updates the reference files in the repo with changed output files -//! from the last test run. - -use crate::cargo_clippy_path; -use std::ffi::OsStr; -use std::fs; -use std::path::{Path, PathBuf}; -use std::sync::LazyLock; -use walkdir::{DirEntry, WalkDir}; - -static CLIPPY_BUILD_TIME: LazyLock> = - LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok()); - -/// # Panics -/// -/// Panics if the path to a test file is broken -pub fn bless(ignore_timestamp: bool) { - let extensions = ["stdout", "stderr", "fixed"].map(OsStr::new); - - WalkDir::new(build_dir()) - .into_iter() - .map(Result::unwrap) - .filter(|entry| entry.path().extension().map_or(false, |ext| extensions.contains(&ext))) - .for_each(|entry| update_reference_file(&entry, ignore_timestamp)); -} - -fn update_reference_file(test_output_entry: &DirEntry, ignore_timestamp: bool) { - let test_output_path = test_output_entry.path(); - - let reference_file_name = test_output_entry.file_name().to_str().unwrap().replace(".stage-id", ""); - let reference_file_path = Path::new("tests") - .join(test_output_path.strip_prefix(build_dir()).unwrap()) - .with_file_name(reference_file_name); - - // If the test output was not updated since the last clippy build, it may be outdated - if !ignore_timestamp && !updated_since_clippy_build(test_output_entry).unwrap_or(true) { - return; - } - - let test_output_file = fs::read(test_output_path).expect("Unable to read test output file"); - let reference_file = fs::read(&reference_file_path).unwrap_or_default(); - - if test_output_file != reference_file { - // If a test run caused an output file to change, update the reference file - println!("updating {}", reference_file_path.display()); - fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file"); - } -} - -fn updated_since_clippy_build(entry: &DirEntry) -> Option { - let clippy_build_time = (*CLIPPY_BUILD_TIME)?; - let modified = entry.metadata().ok()?.modified().ok()?; - Some(modified >= clippy_build_time) -} - -fn build_dir() -> PathBuf { - let mut path = std::env::current_exe().unwrap(); - path.set_file_name("test"); - path -} diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 2562314418172..ee559d45dd16d 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -35,6 +35,7 @@ struct FmtContext { } // the "main" function of cargo dev fmt +#[allow(clippy::missing_panics_doc)] pub fn run(check: bool, verbose: bool) { fn try_run(context: &FmtContext) -> Result { let mut success = true; diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 56a269288c053..4624451cff4fc 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -14,7 +14,6 @@ use std::io; use std::path::PathBuf; use std::process::{self, ExitStatus}; -pub mod bless; pub mod dogfood; pub mod fmt; pub mod lint; @@ -29,6 +28,10 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; /// Returns the path to the `cargo-clippy` binary +/// +/// # Panics +/// +/// Panics if the path of current executable could not be retrieved. #[must_use] pub fn cargo_clippy_path() -> PathBuf { let mut path = std::env::current_exe().expect("failed to get current executable name"); @@ -61,6 +64,8 @@ pub fn clippy_project_root() -> PathBuf { panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); } +/// # Panics +/// Panics if given command result was failed. pub fn exit_if_err(status: io::Result) { match status.expect("failed to run command").code() { Some(0) => {}, diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index c03fbe9d275f3..43eaccdf5a31a 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Arg, ArgAction, ArgMatches, Command}; -use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints}; +use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; use indoc::indoc; use std::convert::Infallible; @@ -11,8 +11,8 @@ fn main() { let matches = get_clap_config(); match matches.subcommand() { - Some(("bless", matches)) => { - bless::bless(matches.get_flag("ignore-timestamp")); + Some(("bless", _)) => { + eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run"); }, Some(("dogfood", matches)) => { dogfood::dogfood( @@ -35,7 +35,7 @@ fn main() { }, Some(("new_lint", matches)) => { match new_lint::create( - matches.get_one::("pass"), + matches.get_one::("pass").unwrap(), matches.get_one::("name"), matches.get_one::("category").map(String::as_str), matches.get_one::("type").map(String::as_str), @@ -176,7 +176,7 @@ fn get_clap_config() -> ArgMatches { .help("Specify whether the lint runs during the early or late pass") .value_parser(["early", "late"]) .conflicts_with("type") - .required_unless_present("type"), + .default_value("late"), Arg::new("name") .short('n') .long("name") diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 13a2770342781..f11aa547bd734 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -36,8 +36,9 @@ impl Context for io::Result { /// # Errors /// /// This function errors out if the files couldn't be created or written to. +#[allow(clippy::missing_panics_doc)] pub fn create( - pass: Option<&String>, + pass: &String, lint_name: Option<&String>, category: Option<&str>, mut ty: Option<&str>, @@ -49,7 +50,7 @@ pub fn create( } let lint = LintData { - pass: pass.map_or("", String::as_str), + pass, name: lint_name.expect("`name` argument is validated by clap"), category: category.expect("`category` argument is validated by clap"), ty, @@ -63,6 +64,14 @@ pub fn create( add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?; } + if pass == "early" { + println!( + "\n\ + NOTE: Use a late pass unless you need something specific from\ + an early pass, as they lack many features and utilities" + ); + } + Ok(()) } @@ -87,7 +96,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> { path.push("src"); fs::create_dir(&path)?; - let header = format!("// compile-flags: --crate-name={lint_name}"); + let header = format!("//@compile-flags: --crate-name={lint_name}"); write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?; Ok(()) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index be9261a47041c..c23054443bb96 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } tempfile = { version = "3.3.0", optional = true } toml = "0.7.3" +regex = { version = "1.5", optional = true } unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } semver = "1.0" @@ -31,7 +32,7 @@ url = "2.2" [features] deny-warnings = ["clippy_utils/deny-warnings"] # build clippy with internal lints enabled, off by default -internal = ["clippy_utils/internal", "serde_json", "tempfile"] +internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"] [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index 554efdc58e1cb..eb21184713e89 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -1,5 +1,5 @@ -use ast::AttrStyle; -use clippy_utils::diagnostics::span_lint_and_sugg; +use ast::{AttrStyle, Attribute}; +use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -50,13 +50,14 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]); impl LateLintPass<'_> for AllowAttribute { // Separate each crate's features. - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { + fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) { if_chain! { if !in_external_macro(cx.sess(), attr.span); if cx.tcx.features().lint_reasons; if let AttrStyle::Outer = attr.style; if let Some(ident) = attr.ident(); if ident.name == rustc_span::symbol::sym::allow; + if !is_from_proc_macro(cx, &attr); then { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs new file mode 100644 index 0000000000000..a1e44668e1adc --- /dev/null +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -0,0 +1,72 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::last_path_segment; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use if_chain::if_chain; + +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_lint::LateLintPass; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does. + /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. + /// + /// ### Why is this bad? + /// Wrapping a type in Arc doesn't add thread safety to the underlying data, so data races + /// could occur when touching the underlying data. + /// + /// ### Example + /// ```rust + /// # use std::cell::RefCell; + /// # use std::sync::Arc; + /// + /// fn main() { + /// // This is safe, as `i32` implements `Send` and `Sync`. + /// let a = Arc::new(42); + /// + /// // This is not safe, as `RefCell` does not implement `Sync`. + /// let b = Arc::new(RefCell::new(42)); + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub ARC_WITH_NON_SEND_SYNC, + correctness, + "using `Arc` with a type that does not implement `Send` or `Sync`" +} +declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); + +impl LateLintPass<'_> for ArcWithNonSendSync { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + let ty = cx.typeck_results().expr_ty(expr); + if_chain! { + if is_type_diagnostic_item(cx, ty, sym::Arc); + if let ExprKind::Call(func, [arg]) = expr.kind; + if let ExprKind::Path(func_path) = func.kind; + if last_path_segment(&func_path).ident.name == sym::new; + if let arg_ty = cx.typeck_results().expr_ty(arg); + if !matches!(arg_ty.kind(), ty::Param(_)); + if !cx.tcx + .lang_items() + .sync_trait() + .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])) || + !cx.tcx + .get_diagnostic_item(sym::Send) + .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])); + + then { + span_lint_and_help( + cx, + ARC_WITH_NON_SEND_SYNC, + expr.span, + "usage of `Arc` where `T` is not `Send` or `Sync`", + None, + "consider using `Rc` instead or wrapping `T` in a std::sync type like \ + `Mutex`", + ); + } + } + } +} diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index c7a76e5f9077c..b9dda49ca4124 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; -use rustc_ast::ast::{Expr, ExprKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use clippy_utils::is_from_proc_macro; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -45,9 +46,9 @@ declare_clippy_lint! { declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); -impl EarlyLintPass for AsConversions { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx.sess(), expr.span) { +impl<'tcx> LateLintPass<'tcx> for AsConversions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) { return; } diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 897495ba10874..2ba78f99569ab 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,9 +1,12 @@ //! checks for attributes -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; +use clippy_utils::{ + diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}, + is_from_proc_macro, +}; use if_chain::if_chain; use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_errors::Applicability; @@ -362,6 +365,32 @@ declare_clippy_lint! { "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg(features = "...")]` and suggests to replace it with + /// `#[cfg(feature = "...")]`. + /// + /// ### Why is this bad? + /// Misspelling `feature` as `features` can be sometimes hard to spot. It + /// may cause conditional compilation not work quitely. + /// + /// ### Example + /// ```rust + /// #[cfg(features = "some-feature")] + /// fn conditional() { } + /// ``` + /// + /// Use instead: + /// ```rust + /// #[cfg(feature = "some-feature")] + /// fn conditional() { } + /// ``` + #[clippy::version = "1.69.0"] + pub MAYBE_MISUSED_CFG, + suspicious, + "prevent from misusing the wrong attr name" +} + declare_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, @@ -540,7 +569,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe } } -fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) { +fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { // Check for the feature if !cx.tcx.features().lint_reasons { return; @@ -555,7 +584,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem } // Check if the attribute is in an external macro and therefore out of the developer's control - if in_external_macro(cx.sess(), attr.span) { + if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) { return; } @@ -676,6 +705,7 @@ impl_lint_pass!(EarlyAttributes => [ EMPTY_LINE_AFTER_OUTER_ATTR, EMPTY_LINE_AFTER_DOC_COMMENTS, NON_MINIMAL_CFG, + MAYBE_MISUSED_CFG, ]); impl EarlyLintPass for EarlyAttributes { @@ -687,6 +717,7 @@ impl EarlyLintPass for EarlyAttributes { check_deprecated_cfg_attr(cx, attr, &self.msrv); check_mismatched_target_os(cx, attr); check_minimal_cfg_condition(cx, attr); + check_misused_cfg(cx, attr); } extract_msrv_attr!(EarlyContext); @@ -777,7 +808,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr } fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { - for item in items.iter() { + for item in items { if let NestedMetaItem::MetaItem(meta) = item { if !meta.has_name(sym::any) && !meta.has_name(sym::all) { continue; @@ -810,6 +841,27 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { } } +fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { + for item in items { + if let NestedMetaItem::MetaItem(meta) = item { + if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() { + span_lint_and_sugg( + cx, + MAYBE_MISUSED_CFG, + meta.span, + "feature may misspelled as features", + "use", + format!("feature = \"{val}\""), + Applicability::MaybeIncorrect, + ); + } + if let MetaItemKind::List(list) = &meta.kind { + check_nested_misused_cfg(cx, list); + } + } + } +} + fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() @@ -818,6 +870,14 @@ fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { } } +fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) && + let Some(items) = attr.meta_item_list() + { + check_nested_misused_cfg(cx, &items); + } +} + fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { fn find_os(name: &str) -> Option<&'static str> { UNIX_SYSTEMS diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ff0102255a0a9..04cca9e3177c4 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { diag.span_suggestions( e.span, "try", - suggestions.into_iter(), + suggestions, // nonminimal_bool can produce minimal but // not human readable expressions (#3141) Applicability::Unspecified, diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index 294d22d34de95..b7256dd2eae9d 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -4,6 +4,7 @@ use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::Adjust; use super::BORROW_AS_PTR; @@ -23,6 +24,15 @@ pub(super) fn check<'tcx>( }; let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; + // Fix #9884 + if !e.is_place_expr(|base| { + cx.typeck_results() + .adjustments() + .get(base.hir_id) + .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) + }) { + return; + } span_lint_and_sugg( cx, diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs index 28ecdea7ea06c..ffa571abb3910 100644 --- a/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/clippy_lints/src/casts/cast_possible_wrap.rs @@ -1,41 +1,90 @@ -use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::is_isize_or_usize; use rustc_hir::Expr; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Ty; use super::{utils, CAST_POSSIBLE_WRAP}; +// this should be kept in sync with the allowed bit widths of `usize` and `isize` +const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64]; + +// whether the lint should be emitted, and the required pointer size, if it matters +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum EmitState { + NoLint, + LintAlways, + LintOnPtrSize(u64), +} + pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { if !(cast_from.is_integral() && cast_to.is_integral()) { return; } - let arch_64_suffix = " on targets with 64-bit wide pointers"; - let arch_32_suffix = " on targets with 32-bit wide pointers"; - let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); + // emit a lint if a cast is: + // 1. unsigned to signed + // and + // 2. either: + // + // 2a. between two types of constant size that are always the same size + // 2b. between one target-dependent size and one constant size integer, + // and the constant integer is in the allowed set of target dependent sizes + // (the ptr size could be chosen to be the same as the constant size) + + if cast_from.is_signed() || !cast_to.is_signed() { + return; + } + let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); - let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => (to_nbits == from_nbits && cast_unsigned_to_signed, ""), - (true, false) => (to_nbits <= 32 && cast_unsigned_to_signed, arch_32_suffix), - (false, true) => ( - cast_unsigned_to_signed, - if from_nbits == 64 { - arch_64_suffix + let should_lint = match (cast_from.is_ptr_sized_integral(), cast_to.is_ptr_sized_integral()) { + (true, true) => { + // casts between two ptr sized integers are trivially always the same size + // so do not depend on any specific pointer size to be the same + EmitState::LintAlways + }, + (true, false) => { + // the first type is `usize` and the second is a constant sized signed integer + if ALLOWED_POINTER_SIZES.contains(&to_nbits) { + EmitState::LintOnPtrSize(to_nbits) + } else { + EmitState::NoLint + } + }, + (false, true) => { + // the first type is a constant sized unsigned integer, and the second is `isize` + if ALLOWED_POINTER_SIZES.contains(&from_nbits) { + EmitState::LintOnPtrSize(from_nbits) + } else { + EmitState::NoLint + } + }, + (false, false) => { + // the types are both a constant known size + // and do not depend on any specific pointer size to be the same + if from_nbits == to_nbits { + EmitState::LintAlways } else { - arch_32_suffix - }, + EmitState::NoLint + } + }, + }; + + let message = match should_lint { + EmitState::NoLint => return, + EmitState::LintAlways => format!("casting `{cast_from}` to `{cast_to}` may wrap around the value"), + EmitState::LintOnPtrSize(ptr_size) => format!( + "casting `{cast_from}` to `{cast_to}` may wrap around the value on targets with {ptr_size}-bit wide pointers", ), }; - if should_lint { - span_lint( - cx, - CAST_POSSIBLE_WRAP, - expr.span, - &format!("casting `{cast_from}` to `{cast_to}` may wrap around the value{suffix}",), - ); - } + cx.struct_span_lint(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") + .note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types") + } else { + diag + } + }); } diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index b90dab07a274a..0ac6ef6496a8a 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -118,9 +118,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for casts from an unsigned type to a signed type of - /// the same size. Performing such a cast is a 'no-op' for the compiler, - /// i.e., nothing is changed at the bit level, and the binary representation of - /// the value is reinterpreted. This can cause wrapping if the value is too big + /// the same size, or possibly smaller due to target dependent integers. + /// Performing such a cast is a 'no-op' for the compiler, i.e., nothing is + /// changed at the bit level, and the binary representation of the value is + /// reinterpreted. This can cause wrapping if the value is too big /// for the target signed type. However, the cast works as defined, so this lint /// is `Allow` by default. /// @@ -174,8 +175,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for casts to the same type, casts of int literals to integer types - /// and casts of float literals to float types. + /// Checks for casts to the same type, casts of int literals to integer types, casts of float + /// literals to float types and casts between raw pointers without changing type or constness. /// /// ### Why is this bad? /// It's just unnecessary. @@ -522,7 +523,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for the usage of `as _` conversion using inferred type. + /// Checks for the usage of `as _` conversion using inferred type. /// /// ### Why is this bad? /// The conversion might include lossy conversion and dangerous cast that might go diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index ab015f8822e1b..f0c1df0143072 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -9,20 +9,21 @@ use rustc_middle::ty::{self, Ty, TypeAndMut}; use super::PTR_CAST_CONSTNESS; -pub(super) fn check( +pub(super) fn check<'tcx>( cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, - cast_from: Ty<'_>, - cast_to: Ty<'_>, + cast_from: Ty<'tcx>, + cast_to: Ty<'tcx>, msrv: &Msrv, ) { if_chain! { if msrv.meets(POINTER_CAST_CONSTNESS); - if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind(); - if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind(); if matches!((from_mutbl, to_mutbl), (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)); + if from_ty == to_ty; then { let sugg = Sugg::hir(cx, cast_expr, "_"); let constness = match *to_mutbl { @@ -34,7 +35,7 @@ pub(super) fn check( cx, PTR_CAST_CONSTNESS, expr.span, - "`as` casting between raw pointers while changing its constness", + "`as` casting between raw pointers while changing only its constness", &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 804ae841100a5..71cf2aea0f8da 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,18 +1,21 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; -use clippy_utils::{get_parent_expr, path_to_local}; +use clippy_utils::visitors::{for_each_expr, Visitable}; +use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::{Expr, ExprKind, Lit, QPath, TyKind, UnOp}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; +use std::ops::ControlFlow; use super::UNNECESSARY_CAST; +#[expect(clippy::too_many_lines)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &Expr<'tcx>, @@ -20,19 +23,84 @@ pub(super) fn check<'tcx>( cast_from: Ty<'tcx>, cast_to: Ty<'tcx>, ) -> bool { - // skip non-primitive type cast + let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); + + if_chain! { + if let ty::RawPtr(..) = cast_from.kind(); + // check both mutability and type are the same + if cast_from.kind() == cast_to.kind(); + if let ExprKind::Cast(_, cast_to_hir) = expr.kind; + // Ignore casts to e.g. type aliases and infer types + // - p as pointer_alias + // - p as _ + if let TyKind::Ptr(to_pointee) = cast_to_hir.kind; + then { + match to_pointee.ty.kind { + // Ignore casts to pointers that are aliases or cfg dependant, e.g. + // - p as *const std::ffi::c_char (alias) + // - p as *const std::os::raw::c_char (cfg dependant) + TyKind::Path(qpath) => { + if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) { + return false; + } + }, + // Ignore `p as *const _` + TyKind::Infer => return false, + _ => {}, + } + + span_lint_and_sugg( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"), + "try", + cast_str.clone(), + Applicability::MachineApplicable, + ); + } + } + + // skip cast of local that is a type alias + if let ExprKind::Cast(inner, ..) = expr.kind + && let ExprKind::Path(qpath) = inner.kind + && let QPath::Resolved(None, Path { res, .. }) = qpath + && let Res::Local(hir_id) = res + && let parent = cx.tcx.hir().get_parent(*hir_id) + && let Node::Local(local) = parent + { + if let Some(ty) = local.ty + && let TyKind::Path(qpath) = ty.kind + && is_ty_alias(&qpath) + { + return false; + } + + if let Some(expr) = local.init + && let ExprKind::Cast(.., cast_to) = expr.kind + && let TyKind::Path(qpath) = cast_to.kind + && is_ty_alias(&qpath) + { + return false; + } + } + + // skip cast of fn call that returns type alias + if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) { + return false; + } + + // skip cast to non-primitive type if_chain! { if let ExprKind::Cast(_, cast_to) = expr.kind; if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind; if let Res::PrimTy(_) = path.res; then {} else { - return false + return false; } } - let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); - if let Some(lit) = get_numeric_literal(cast_expr) { let literal_str = &cast_str; @@ -162,3 +230,61 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 { _ => 0, } } + +/// Finds whether an `Expr` returns a type alias. +/// +/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark, +/// dark path reimplementing this (or something similar). +fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool { + for_each_expr(expr, |expr| { + // Calls are a `Path`, and usage of locals are a `Path`. So, this checks + // - call() as i32 + // - local as i32 + if let ExprKind::Path(qpath) = expr.kind { + let res = cx.qpath_res(&qpath, expr.hir_id); + // Function call + if let Res::Def(DefKind::Fn, def_id) = res { + let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else { + return ControlFlow::Continue(()); + }; + // This is the worst part of this entire function. This is the only way I know of to + // check whether a function returns a type alias. Sure, you can get the return type + // from a function in the current crate as an hir ty, but how do you get it for + // external functions?? Simple: It's impossible. So, we check whether a part of the + // function's declaration snippet is exactly equal to the `Ty`. That way, we can + // see whether it's a type alias. + // + // Will this work for more complex types? Probably not! + if !snippet + .split("->") + .skip(0) + .map(|s| { + s.trim() == cast_from.to_string() + || s.split("where").any(|ty| ty.trim() == cast_from.to_string()) + }) + .any(|a| a) + { + return ControlFlow::Break(()); + } + // Local usage + } else if let Res::Local(hir_id) = res + && let Some(parent) = get_parent_node(cx.tcx, hir_id) + && let Node::Local(l) = parent + { + if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) { + return ControlFlow::Break::<()>(()); + } + + if let Some(ty) = l.ty + && let TyKind::Path(qpath) = ty.kind + && is_ty_alias(&qpath) + { + return ControlFlow::Break::<()>(()); + } + } + } + + ControlFlow::Continue(()) + }) + .is_some() +} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index f1d1355123ab6..9d9ee6ba30792 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -3,6 +3,8 @@ // Manual edits will be overwritten. pub(crate) static LINTS: &[&crate::LintInfo] = &[ + #[cfg(feature = "internal")] + crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO, #[cfg(feature = "internal")] @@ -38,6 +40,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, crate::approx_const::APPROX_CONSTANT_INFO, + crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, crate::as_conversions::AS_CONVERSIONS_INFO, crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO, crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO, @@ -51,6 +54,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO, crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO, crate::attrs::INLINE_ALWAYS_INFO, + crate::attrs::MAYBE_MISUSED_CFG_INFO, crate::attrs::MISMATCHED_TARGET_OS_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, crate::attrs::USELESS_ATTRIBUTE_INFO, @@ -136,11 +140,15 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, crate::drop_forget_ref::FORGET_NON_DROP_INFO, + crate::drop_forget_ref::MEM_FORGET_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, crate::empty_enum::EMPTY_ENUM_INFO, crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO, + crate::endian_bytes::BIG_ENDIAN_BYTES_INFO, + crate::endian_bytes::HOST_ENDIAN_BYTES_INFO, + crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO, crate::entry::MAP_ENTRY_INFO, crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO, crate::enum_variants::ENUM_VARIANT_NAMES_INFO, @@ -152,6 +160,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO, crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO, crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO, + crate::excessive_nesting::EXCESSIVE_NESTING_INFO, crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, crate::exit::EXIT_INFO, @@ -197,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO, crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO, crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO, + crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO, crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO, crate::indexing_slicing::INDEXING_SLICING_INFO, crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO, @@ -219,6 +229,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::large_futures::LARGE_FUTURES_INFO, 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::len_zero::COMPARISON_TO_EMPTY_INFO, crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO, crate::len_zero::LEN_ZERO_INFO, @@ -266,6 +277,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, + crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO, crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO, crate::manual_retain::MANUAL_RETAIN_INFO, crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, @@ -299,7 +311,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::matches::TRY_ERR_INFO, crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO, crate::matches::WILDCARD_IN_OR_PATTERNS_INFO, - crate::mem_forget::MEM_FORGET_INFO, crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO, crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO, crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO, @@ -314,6 +325,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::DRAIN_COLLECT_INFO, crate::methods::ERR_EXPECT_INFO, crate::methods::EXPECT_FUN_CALL_INFO, crate::methods::EXPECT_USED_INFO, @@ -352,6 +364,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO, crate::methods::MANUAL_SPLIT_ONCE_INFO, crate::methods::MANUAL_STR_REPEAT_INFO, + crate::methods::MANUAL_TRY_FOLD_INFO, crate::methods::MAP_CLONE_INFO, crate::methods::MAP_COLLECT_RESULT_UNIT_INFO, crate::methods::MAP_ERR_IGNORE_INFO, @@ -398,6 +411,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_FOLD_INFO, crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, + crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, crate::methods::UNNECESSARY_TO_OWNED_INFO, crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO, @@ -407,6 +421,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::VERBOSE_FILE_READS_INFO, crate::methods::WRONG_SELF_CONVENTION_INFO, crate::methods::ZST_OFFSET_INFO, + crate::min_ident_chars::MIN_IDENT_CHARS_INFO, crate::minmax::MIN_MAX_INFO, crate::misc::SHORT_CIRCUIT_STATEMENT_INFO, crate::misc::TOPLEVEL_REF_ARG_INFO, @@ -416,6 +431,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::misc_early::DOUBLE_NEG_INFO, crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO, crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO, + crate::misc_early::REDUNDANT_AT_REST_PATTERN_INFO, crate::misc_early::REDUNDANT_PATTERN_INFO, crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO, crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO, @@ -450,6 +466,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_continue::NEEDLESS_CONTINUE_INFO, crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, + crate::needless_if::NEEDLESS_IF_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, @@ -524,6 +541,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::ranges::RANGE_MINUS_ONE_INFO, crate::ranges::RANGE_PLUS_ONE_INFO, crate::ranges::REVERSED_EMPTY_RANGES_INFO, + crate::raw_strings::NEEDLESS_RAW_STRINGS_INFO, + crate::raw_strings::NEEDLESS_RAW_STRING_HASHES_INFO, crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO, crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO, crate::redundant_async_block::REDUNDANT_ASYNC_BLOCK_INFO, @@ -535,6 +554,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::redundant_slicing::DEREF_BY_SLICING_INFO, crate::redundant_slicing::REDUNDANT_SLICING_INFO, crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO, + crate::redundant_type_annotations::REDUNDANT_TYPE_ANNOTATIONS_INFO, crate::ref_option_ref::REF_OPTION_REF_INFO, crate::ref_patterns::REF_PATTERNS_INFO, crate::reference::DEREF_ADDROF_INFO, @@ -553,8 +573,10 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::shadow::SHADOW_SAME_INFO, crate::shadow::SHADOW_UNRELATED_INFO, crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, + crate::single_call_fn::SINGLE_CALL_FN_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, + crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, @@ -602,6 +624,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO, crate::transmute::USELESS_TRANSMUTE_INFO, crate::transmute::WRONG_TRANSMUTE_INFO, + crate::tuple_array_conversions::TUPLE_ARRAY_CONVERSIONS_INFO, crate::types::BORROWED_BOX_INFO, crate::types::BOX_COLLECTION_INFO, crate::types::LINKEDLIST_INFO, @@ -644,6 +667,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::useless_conversion::USELESS_CONVERSION_INFO, crate::vec::USELESS_VEC_INFO, crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO, + crate::visibility::NEEDLESS_PUB_SELF_INFO, + crate::visibility::PUB_WITHOUT_SHORTHAND_INFO, + crate::visibility::PUB_WITH_SHORTHAND_INFO, crate::wildcard_imports::ENUM_GLOB_USE_INFO, crate::wildcard_imports::WILDCARD_IMPORTS_INFO, crate::write::PRINTLN_EMPTY_STRING_INFO, diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index fb037bbcbf3eb..ca9514ccc7d00 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does - /// Check for construction on unit struct using `default`. + /// Checks for construction on unit struct using `default`. /// /// ### Why is this bad? /// This adds code complexity and an unnecessary function call. diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 4e1a6cd4d7355..e53a9877b20ca 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { let fields_def = &variant.fields; // Push field type then visit each field expr. - for field in fields.iter() { + for field in *fields { let bound = fields_def .iter() diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 1ecaa1a123ce4..73556c1053ecd 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -56,9 +56,11 @@ declare_clippy_lint! { /// let b = &*a; /// ``` /// - /// This lint excludes: + /// This lint excludes all of: /// ```rust,ignore /// let _ = d.unwrap().deref(); + /// let _ = Foo::deref(&foo); + /// let _ = ::deref(&foo); /// ``` #[clippy::version = "1.44.0"] pub EXPLICIT_DEREF_METHODS, @@ -355,15 +357,17 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { // start auto-deref. // 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow // adjustments will not be inserted automatically, then leave one further reference to avoid - // moving a mutable borrow. - // e.g. - // fn foo(x: &mut Option<&mut T>, y: &mut T) { - // let x = match x { - // // Removing the borrow will cause `x` to be moved - // Some(x) => &mut *x, - // None => y - // }; - // } + // moving a mutable borrow. e.g. + // + // ```rust + // fn foo(x: &mut Option<&mut T>, y: &mut T) { + // let x = match x { + // // Removing the borrow will cause `x` to be moved + // Some(x) => &mut *x, + // None => y + // }; + // } + // ``` let deref_msg = "this expression creates a reference which is immediately dereferenced by the compiler"; let borrow_msg = "this expression borrows a value the compiler would automatically borrow"; @@ -1481,7 +1485,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data target_mut, } => { let mut app = Applicability::MachineApplicable; - let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); + let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); let ty = cx.typeck_results().expr_ty(expr); let (_, ref_count) = peel_mid_ty_refs(ty); let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { @@ -1504,11 +1508,20 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data "&" }; - let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { - format!("({expr_str})") + // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's + // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. + /* + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { + Cow::Owned(format!("({expr_str})")) } else { - expr_str.into_owned() + expr_str }; + */ + + // Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`. + if is_final_ufcs { + return; + } span_lint_and_sugg( cx, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 8f68f90a2a130..ec0ca50cfec70 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -4,11 +4,13 @@ use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{ + self as hir, def::{CtorKind, CtorOf, DefKind, Res}, - Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind, + Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{Adt, AdtDef, SubstsRef}; +use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -75,13 +77,23 @@ 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, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object), + ty::Dynamic(..) => true, + _ => false, + } +} + fn check_struct<'tcx>( cx: &LateContext<'tcx>, item: &'tcx Item<'_>, - self_ty: &Ty<'_>, + self_ty: &hir::Ty<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>, substs: SubstsRef<'_>, + typeck_results: &'tcx TypeckResults<'tcx>, ) { if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind { if let Some(PathSegment { args, .. }) = p.segments.last() { @@ -96,10 +108,23 @@ fn check_struct<'tcx>( } } } + + // the default() call might unsize coerce to a trait object (e.g. Box to Box), + // which would not be the same if derived (see #10158). + // this closure checks both if the expr is equivalent to a `default()` call and does not + // have such coercions. + let is_default_without_adjusts = |expr| { + is_default_equivalent(cx, expr) + && typeck_results.expr_adjustments(expr).iter().all(|adj| { + !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) + if contains_trait_object(adj.target)) + }) + }; + let should_emit = match peel_blocks(func_expr).kind { - ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)), - ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)), - ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)), + ExprKind::Tup(fields) => fields.iter().all(is_default_without_adjusts), + ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(is_default_without_adjusts), + ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_without_adjusts(ef.expr)), _ => false, }; @@ -197,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { then { if adt_def.is_struct() { - check_struct(cx, item, self_ty, func_expr, adt_def, substs); + check_struct(cx, item, self_ty, func_expr, adt_def, substs, cx.tcx.typeck_body(*b)); } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) { check_enum(cx, item, func_expr, adt_def); } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 10a2f0cb1e7ee..a005a360e9cef 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, - ToPredicate, TraitPredicate, Ty, TyCtxt, + self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, + TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; @@ -520,7 +520,8 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, - }).to_predicate(tcx) + }) + .to_predicate(tcx) }), )), Reveal::UserFacing, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 384aca7feadd6..87d88f707529c 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -571,6 +571,7 @@ fn check_doc<'a, Events: Iterator, Range, Span)> = Vec::new(); @@ -584,6 +585,8 @@ fn check_doc<'a, Events: Iterator, Range, Range Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { if is_panic(self.cx, macro_call.def_id) || matches!( self.cx.tcx.item_name(macro_call.def_id).as_str(), - "assert" | "assert_eq" | "assert_ne" | "todo" + "assert" | "assert_eq" | "assert_ne" ) { self.panic_span = Some(macro_call.span); } } - // check for `unwrap` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + // check for `unwrap` and `expect` for both `Option` and `Result` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 7a4b9a87aeb47..976ce47e8694a 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -6,6 +6,7 @@ use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -47,6 +48,27 @@ declare_clippy_lint! { "call to `std::mem::forget` with a value which does not implement `Drop`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `std::mem::forget(t)` where `t` is + /// `Drop` or has a field that implements `Drop`. + /// + /// ### Why is this bad? + /// `std::mem::forget(t)` prevents `t` from running its + /// destructor, possibly causing leaks. + /// + /// ### Example + /// ```rust + /// # use std::mem; + /// # use std::rc::Rc; + /// mem::forget(Rc::new(55)) + /// ``` + #[clippy::version = "pre 1.29.0"] + pub MEM_FORGET, + restriction, + "`mem::forget` usage on `Drop` types, likely to cause memory leaks" +} + const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \ Dropping such a type only extends its contained lifetimes"; const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \ @@ -55,6 +77,7 @@ const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value t declare_lint_pass!(DropForgetRef => [ DROP_NON_DROP, FORGET_NON_DROP, + MEM_FORGET, ]); impl<'tcx> LateLintPass<'tcx> for DropForgetRef { @@ -67,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { let arg_ty = cx.typeck_results().expr_ty(arg); let is_copy = is_copy(cx, arg_ty); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); - let (lint, msg) = match fn_name { + let (lint, msg, note_span) = match fn_name { // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return, sym::mem_forget if arg_ty.is_ref() => return, @@ -81,19 +104,34 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { || drop_is_single_call_in_arm ) => { - (DROP_NON_DROP, DROP_NON_DROP_SUMMARY) - }, - sym::mem_forget if !arg_ty.needs_drop(cx.tcx, cx.param_env) => { - (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY) + (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) }, + sym::mem_forget => { + if arg_ty.needs_drop(cx.tcx, cx.param_env) { + ( + MEM_FORGET, + Cow::Owned(format!( + "usage of `mem::forget` on {}", + if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { + "`Drop` type" + } else { + "type with `Drop` fields" + } + )), + None, + ) + } else { + (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span)) + } + } _ => return, }; span_lint_and_note( cx, lint, expr.span, - msg, - Some(arg.span), + &msg, + note_span, &format!("argument has type `{arg_ty}`"), ); } diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs new file mode 100644 index 0000000000000..f470987833e42 --- /dev/null +++ b/clippy_lints/src/endian_bytes.rs @@ -0,0 +1,216 @@ +use crate::Lint; +use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::{lint::in_external_macro, ty::Ty}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Symbol; +use std::borrow::Cow; + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`. + /// + /// ### Why is this bad? + /// It's not, but some may prefer to specify the target endianness explicitly. + /// + /// ### Example + /// ```rust,ignore + /// let _x = 2i32.to_ne_bytes(); + /// let _y = 2i64.to_ne_bytes(); + /// ``` + #[clippy::version = "1.71.0"] + pub HOST_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_ne_bytes` method" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`. + /// + /// ### Why is this bad? + /// It's not, but some may wish to lint usage of this method, either to suggest using the host + /// endianness or big endian. + /// + /// ### Example + /// ```rust,ignore + /// let _x = 2i32.to_le_bytes(); + /// let _y = 2i64.to_le_bytes(); + /// ``` + #[clippy::version = "1.71.0"] + pub LITTLE_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_le_bytes` method" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`. + /// + /// ### Why is this bad? + /// It's not, but some may wish to lint usage of this method, either to suggest using the host + /// endianness or little endian. + /// + /// ### Example + /// ```rust,ignore + /// let _x = 2i32.to_be_bytes(); + /// let _y = 2i64.to_be_bytes(); + /// ``` + #[clippy::version = "1.71.0"] + pub BIG_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_be_bytes` method" +} + +declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]); + +const HOST_NAMES: [&str; 2] = ["from_ne_bytes", "to_ne_bytes"]; +const LITTLE_NAMES: [&str; 2] = ["from_le_bytes", "to_le_bytes"]; +const BIG_NAMES: [&str; 2] = ["from_be_bytes", "to_be_bytes"]; + +#[derive(Clone, Debug)] +enum LintKind { + Host, + Little, + Big, +} + +#[derive(Clone, Copy, PartialEq)] +enum Prefix { + From, + To, +} + +impl LintKind { + fn allowed(&self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + is_lint_allowed(cx, self.as_lint(), expr.hir_id) + } + + fn as_lint(&self) -> &'static Lint { + match self { + LintKind::Host => HOST_ENDIAN_BYTES, + LintKind::Little => LITTLE_ENDIAN_BYTES, + LintKind::Big => BIG_ENDIAN_BYTES, + } + } + + fn as_name(&self, prefix: Prefix) -> &str { + let index = usize::from(prefix == Prefix::To); + + match self { + LintKind::Host => HOST_NAMES[index], + LintKind::Little => LITTLE_NAMES[index], + LintKind::Big => BIG_NAMES[index], + } + } +} + +impl LateLintPass<'_> for EndianBytes { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + + if_chain! { + if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind; + if args.is_empty(); + let ty = cx.typeck_results().expr_ty(receiver); + if ty.is_primitive_ty(); + if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty); + then { + return; + } + } + + if_chain! { + if let ExprKind::Call(function, ..) = expr.kind; + if let ExprKind::Path(qpath) = function.kind; + if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id(); + if let Some(function_name) = cx.get_def_path(def_id).last(); + let ty = cx.typeck_results().expr_ty(expr); + if ty.is_primitive_ty(); + then { + maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty); + } + } + } +} + +fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) -> bool { + let ne = LintKind::Host.as_name(prefix); + let le = LintKind::Little.as_name(prefix); + let be = LintKind::Big.as_name(prefix); + + let (lint, other_lints) = match name.as_str() { + name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]), + name if name == le => ((&LintKind::Little), [(&LintKind::Host), (&LintKind::Big)]), + name if name == be => ((&LintKind::Big), [(&LintKind::Host), (&LintKind::Little)]), + _ => return false, + }; + + let mut help = None; + + 'build_help: { + // all lints disallowed, don't give help here + if [&[lint], other_lints.as_slice()] + .concat() + .iter() + .all(|lint| !lint.allowed(cx, expr)) + { + break 'build_help; + } + + // ne_bytes and all other lints allowed + if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) { + help = Some(Cow::Borrowed("specify the desired endianness explicitly")); + break 'build_help; + } + + // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but + // le_bytes is not + if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) { + help = Some(Cow::Borrowed("use the native endianness instead")); + break 'build_help; + } + + let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr)); + let len = allowed_lints.clone().count(); + + let mut help_str = "use ".to_owned(); + + for (i, lint) in allowed_lints.enumerate() { + let only_one = len == 1; + if !only_one { + help_str.push_str("either of "); + } + + help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix))); + + if i != len && !only_one { + help_str.push_str("or "); + } + } + + help = Some(Cow::Owned(help_str + "instead")); + } + + span_lint_and_then( + cx, + lint.as_lint(), + expr.span, + &format!( + "usage of the {}`{ty}::{}`{}", + if prefix == Prefix::From { "function " } else { "" }, + lint.as_name(prefix), + if prefix == Prefix::To { " method" } else { "" }, + ), + move |diag| { + if let Some(help) = help { + diag.help(help); + } + }, + ); + + true +} diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e275efaba25fb..d85650712db82 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .const_eval_poly(def_id.to_def_id()) .ok() .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty)); - if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { + if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) { if let ty::Adt(adt, _) = ty.kind() { if adt.is_enum() { ty = adt.repr().discr_type().to_ty(cx.tcx); diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index faac63404199c..d4df6f7aa2d09 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::source::is_present_in_source; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start}; -use rustc_hir::{EnumDef, Item, ItemKind, Variant}; +use rustc_hir::{EnumDef, Item, ItemKind, OwnerId, Variant}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; @@ -105,18 +105,20 @@ declare_clippy_lint! { } pub struct EnumVariantNames { - modules: Vec<(Symbol, String)>, + modules: Vec<(Symbol, String, OwnerId)>, threshold: u64, avoid_breaking_exported_api: bool, + allow_private_module_inception: bool, } impl EnumVariantNames { #[must_use] - pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self { + pub fn new(threshold: u64, avoid_breaking_exported_api: bool, allow_private_module_inception: bool) -> Self { Self { modules: Vec::new(), threshold, avoid_breaking_exported_api, + allow_private_module_inception, } } } @@ -252,18 +254,19 @@ impl LateLintPass<'_> for EnumVariantNames { let item_name = item.ident.name.as_str(); let item_camel = to_camel_case(item_name); if !item.span.from_expansion() && is_present_in_source(cx, item.span) { - if let Some((mod_name, mod_camel)) = self.modules.last() { + if let [.., (mod_name, mod_camel, owner_id)] = &*self.modules { // constants don't have surrounding modules if !mod_camel.is_empty() { - if mod_name == &item.ident.name { - if let ItemKind::Mod(..) = item.kind { - span_lint( - cx, - MODULE_INCEPTION, - item.span, - "module has the same name as its containing module", - ); - } + if mod_name == &item.ident.name + && let ItemKind::Mod(..) = item.kind + && (!self.allow_private_module_inception || cx.tcx.visibility(owner_id.def_id).is_public()) + { + span_lint( + cx, + MODULE_INCEPTION, + item.span, + "module has the same name as its containing module", + ); } // The `module_name_repetitions` lint should only trigger if the item has the module in its // name. Having the same name is accepted. @@ -302,6 +305,6 @@ impl LateLintPass<'_> for EnumVariantNames { check_variant(cx, self.threshold, def, item_name, item.span); } } - self.modules.push((item.ident.name, item_camel)); + self.modules.push((item.ident.name, item_camel, item.owner_id)); } } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index c919b4de65dea..58e62d1f3d377 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -120,6 +120,13 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc); if let ty::Closure(_, substs) = *closure_ty.kind(); + // Don't lint if this is an inclusive range expression. + // They desugar to a call to `RangeInclusiveNew` which would have odd suggestions. (#10684) + if !matches!(higher::Range::hir(body.value), Some(higher::Range { + start: Some(_), + end: Some(_), + limits: rustc_ast::RangeLimits::Closed + })); then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { @@ -136,6 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { // Mutable closure is used after current expr; we cannot consume it. snippet = format!("&mut {snippet}"); } + diag.span_suggestion( expr.span, "replace the closure with the function itself", diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs new file mode 100644 index 0000000000000..d04d833e6304e --- /dev/null +++ b/clippy_lints/src/excessive_nesting.rs @@ -0,0 +1,181 @@ +use clippy_utils::{diagnostics::span_lint_and_help, source::snippet}; +use rustc_ast::{ + node_id::NodeSet, + visit::{walk_block, walk_item, Visitor}, + Block, Crate, Inline, Item, ItemKind, ModKind, NodeId, +}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for blocks which are nested beyond a certain threshold. + /// + /// Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file. + /// + /// ### Why is this bad? + /// It can severely hinder readability. + /// + /// ### Example + /// An example clippy.toml configuration: + /// ```toml + /// # clippy.toml + /// excessive-nesting-threshold = 3 + /// ``` + /// ```rust,ignore + /// // lib.rs + /// pub mod a { + /// pub struct X; + /// impl X { + /// pub fn run(&self) { + /// if true { + /// // etc... + /// } + /// } + /// } + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// // a.rs + /// fn private_run(x: &X) { + /// if true { + /// // etc... + /// } + /// } + /// + /// pub struct X; + /// impl X { + /// pub fn run(&self) { + /// private_run(self); + /// } + /// } + /// ``` + /// ```rust,ignore + /// // lib.rs + /// pub mod a; + /// ``` + #[clippy::version = "1.70.0"] + pub EXCESSIVE_NESTING, + complexity, + "checks for blocks nested beyond a certain threshold" +} +impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]); + +#[derive(Clone)] +pub struct ExcessiveNesting { + pub excessive_nesting_threshold: u64, + pub nodes: NodeSet, +} + +impl ExcessiveNesting { + pub fn check_node_id(&self, cx: &EarlyContext<'_>, span: Span, node_id: NodeId) { + if self.nodes.contains(&node_id) { + span_lint_and_help( + cx, + EXCESSIVE_NESTING, + span, + "this block is too nested", + None, + "try refactoring your code to minimize nesting", + ); + } + } +} + +impl EarlyLintPass for ExcessiveNesting { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + if self.excessive_nesting_threshold == 0 { + return; + } + + let mut visitor = NestingVisitor { + conf: self, + cx, + nest_level: 0, + }; + + for item in &krate.items { + visitor.visit_item(item); + } + } + + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { + self.check_node_id(cx, block.span, block.id); + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + self.check_node_id(cx, item.span, item.id); + } +} + +struct NestingVisitor<'conf, 'cx> { + conf: &'conf mut ExcessiveNesting, + cx: &'cx EarlyContext<'cx>, + nest_level: u64, +} + +impl NestingVisitor<'_, '_> { + fn check_indent(&mut self, span: Span, id: NodeId) -> bool { + if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { + self.conf.nodes.insert(id); + + return true; + } + + false + } +} + +impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { + fn visit_block(&mut self, block: &Block) { + if block.span.from_expansion() { + return; + } + + // TODO: This should be rewritten using `LateLintPass` so we can use `is_from_proc_macro` instead, + // but for now, this is fine. + let snippet = snippet(self.cx, block.span, "{}").trim().to_owned(); + if !snippet.starts_with('{') || !snippet.ends_with('}') { + return; + } + + self.nest_level += 1; + + if !self.check_indent(block.span, block.id) { + walk_block(self, block); + } + + self.nest_level -= 1; + } + + fn visit_item(&mut self, item: &Item) { + if item.span.from_expansion() { + return; + } + + match &item.kind { + ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { + self.nest_level += 1; + + if !self.check_indent(item.span, item.id) { + walk_item(self, item); + } + + self.nest_level -= 1; + }, + // Reset nesting level for non-inline modules (since these are in another file) + ItemKind::Mod(..) => walk_item( + &mut NestingVisitor { + conf: self.conf, + cx: self.cx, + nest_level: 0, + }, + item, + ), + _ => walk_item(self, item), + } + } +} diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index eeb4de8b58f48..126bed6789c4a 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; +use clippy_utils::is_from_proc_macro; use clippy_utils::trait_ref_of_method; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -265,6 +266,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let ItemKind::Fn(_, generics, body_id) = item.kind && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id) + && !is_from_proc_macro(cx, item) { let mut walker = TypeWalker::new(cx, generics); walk_item(&mut walker, item); diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 93bf50fd5e795..d182bb621950f 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -82,19 +82,24 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"), LitFloatType::Unsuffixed => None }; - let (is_whole, mut float_str) = match fty { + let (is_whole, is_inf, mut float_str) = match fty { FloatTy::F32 => { let value = sym_str.parse::().unwrap(); - (value.fract() == 0.0, formatter.format(value)) + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, FloatTy::F64 => { let value = sym_str.parse::().unwrap(); - (value.fract() == 0.0, formatter.format(value)) + + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, }; + if is_inf { + return; + } + if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') { // Normalize the literal by stripping the fractional portion if sym_str.split('.').next().unwrap() != float_str { diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 3c55a563af455..5e0fcd743392d 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -215,7 +215,7 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { // ranges [-16777215, 16777216) for type f32 as whole number floats outside // this range are lossy and ambiguous. #[expect(clippy::cast_possible_truncation)] -fn get_integer_from_float_constant(value: &Constant) -> Option { +fn get_integer_from_float_constant(value: &Constant<'_>) -> Option { match value { F32(num) if num.fract() == 0.0 => { if (-16_777_215.0..16_777_216.0).contains(num) { diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index 68c5c3673fe15..45f67020c2db5 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_type_lang_item; -use clippy_utils::{match_def_path, paths, peel_hir_expr_refs}; -use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem}; +use clippy_utils::{higher, match_def_path, paths}; +use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -44,10 +44,24 @@ fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String) } fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - if let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id { + let e = e.peel_blocks().peel_borrows(); + + if e.span.from_expansion() + && let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id + { cx.tcx.get_diagnostic_name(macro_def_id) == Some(sym::format_macro) + } else if let Some(higher::If { then, r#else, .. }) = higher::If::hir(e) { + is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e)) } else { - false + match higher::IfLetOrMatch::parse(cx, e) { + Some(higher::IfLetOrMatch::Match(_, arms, MatchSource::Normal)) => { + arms.iter().any(|arm| is_format(cx, arm.body)) + }, + Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => { + is_format(cx, then) ||r#else.is_some_and(|e| is_format(cx, e)) + }, + _ => false, + } } } @@ -68,7 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString { }, _ => return, }; - let (arg, _) = peel_hir_expr_refs(arg); if is_format(cx, arg) { span_lint_and_help( cx, diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 4762b354392b8..d03480c21084c 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -236,6 +236,12 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { } } + // Don't warn if the only thing inside post_else_post_eol is a comment block. + let trimmed_post_else_post_eol = post_else_post_eol.trim(); + if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") { + return + } + let else_desc = if is_if(else_) { "if" } else { "{..}" }; span_lint_and_note( cx, diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 10ce2a0f0c7ec..92d67ef359dca 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -134,9 +134,10 @@ impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> { kw::SelfUpper => self.upper.push(segment.ident.span), _ => continue, } + + self.invalid |= segment.ident.span.from_expansion(); } - self.invalid |= path.span.from_expansion(); if !self.invalid { walk_path(self, path); } @@ -156,6 +157,11 @@ fn convert_to_from( self_ty: &Ty<'_>, impl_item_ref: &ImplItemRef, ) -> Option> { + if !target_ty.find_self_aliases().is_empty() { + // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a + // bad suggestion/fix. + return None; + } let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else { return None }; let body = cx.tcx.hir().body(body_id); diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs new file mode 100644 index 0000000000000..13cc0b23ba33d --- /dev/null +++ b/clippy_lints/src/incorrect_impls.rs @@ -0,0 +1,124 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait}; +use rustc_errors::Applicability; +use rustc_hir::{ExprKind, ImplItem, ImplItemKind, ItemKind, Node, UnOp}; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::EarlyBinder; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of `Clone` when `Copy` is already implemented. + /// + /// ### Why is this bad? + /// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing + /// `self` in `Clone`'s implementation. Anything else is incorrect. + /// + /// ### Example + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Clone for A { + /// fn clone(&self) -> Self { + /// Self(self.0) + /// } + /// } + /// + /// impl Copy for A {} + /// ``` + /// Use instead: + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Clone for A { + /// fn clone(&self) -> Self { + /// *self + /// } + /// } + /// + /// impl Copy for A {} + /// ``` + #[clippy::version = "1.72.0"] + pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE, + correctness, + "manual implementation of `Clone` on a `Copy` type" +} +declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]); + +impl LateLintPass<'_> for IncorrectImpls { + #[expect(clippy::needless_return)] + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { + let node = get_parent_node(cx.tcx, impl_item.hir_id()); + let Some(Node::Item(item)) = node else { + return; + }; + let ItemKind::Impl(imp) = item.kind else { + return; + }; + let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { + return; + }; + let trait_impl_def_id = trait_impl.def_id; + if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { + return; + } + let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { + return; + }; + let body = cx.tcx.hir().body(impl_item_id); + let ExprKind::Block(block, ..) = body.value.kind else { + return; + }; + // Above is duplicated from the `duplicate_manual_partial_ord_impl` branch. + // Remove it while solving conflicts once that PR is merged. + + // Actual implementation; remove this comment once aforementioned PR is merged + if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id) + && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) + && implements_trait( + cx, + hir_ty_to_ty(cx.tcx, imp.self_ty), + copy_def_id, + trait_impl.substs, + ) + { + if impl_item.ident.name == sym::clone { + if block.stmts.is_empty() + && let Some(expr) = block.expr + && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind + && let ExprKind::Path(qpath) = inner.kind + && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower + {} else { + span_lint_and_sugg( + cx, + INCORRECT_CLONE_IMPL_ON_COPY_TYPE, + block.span, + "incorrect implementation of `clone` on a `Copy` type", + "change this to", + "{ *self }".to_owned(), + Applicability::MaybeIncorrect, + ); + + return; + } + } + + if impl_item.ident.name == sym::clone_from { + span_lint_and_sugg( + cx, + INCORRECT_CLONE_IMPL_ON_COPY_TYPE, + impl_item.span, + "incorrect implementation of `clone_from` on a `Copy` type", + "remove this", + String::new(), + Applicability::MaybeIncorrect, + ); + + return; + } + } + } +} diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index b992d689aa979..40378ee8205cf 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -1,4 +1,4 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_in_cfg_test}; +use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test}; use rustc_hir::{HirId, ItemId, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -59,6 +59,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule { if !matches!(item.kind, ItemKind::Mod(_)); if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself if !in_external_macro(cx.sess(), item.span); + if !is_from_proc_macro(cx, item); then { span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined"); diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs new file mode 100644 index 0000000000000..9c0cc978a391f --- /dev/null +++ b/clippy_lints/src/large_stack_frames.rs @@ -0,0 +1,162 @@ +use std::ops::AddAssign; + +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::fn_has_unsatisfiable_preds; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::FnKind; +use rustc_hir::Body; +use rustc_hir::FnDecl; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_tool_lint; +use rustc_session::impl_lint_pass; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for functions that use a lot of stack space. + /// + /// This often happens when constructing a large type, such as an array with a lot of elements, + /// or constructing *many* smaller-but-still-large structs, or copying around a lot of large types. + /// + /// This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays) + /// that is intended to look at functions as a whole instead of only individual array expressions inside of a function. + /// + /// ### Why is this bad? + /// The stack region of memory is very limited in size (usually *much* smaller than the heap) and attempting to + /// use too much will result in a stack overflow and crash the program. + /// To avoid this, you should consider allocating large types on the heap instead (e.g. by boxing them). + /// + /// Keep in mind that the code path to construction of large types does not even need to be reachable; + /// it purely needs to *exist* inside of the function to contribute to the stack size. + /// For example, this causes a stack overflow even though the branch is unreachable: + /// ```rust,ignore + /// fn main() { + /// if false { + /// let x = [0u8; 10000000]; // 10 MB stack array + /// black_box(&x); + /// } + /// } + /// ``` + /// + /// ### Known issues + /// False positives. The stack size that clippy sees is an estimated value and can be vastly different + /// from the actual stack usage after optimizations passes have run (especially true in release mode). + /// Modern compilers are very smart and are able to optimize away a lot of unnecessary stack allocations. + /// In debug mode however, it is usually more accurate. + /// + /// This lint works by summing up the size of all variables that the user typed, variables that were + /// implicitly introduced by the compiler for temporaries, function arguments and the return value, + /// and comparing them against a (configurable, but high-by-default). + /// + /// ### Example + /// This function creates four 500 KB arrays on the stack. Quite big but just small enough to not trigger `large_stack_arrays`. + /// However, looking at the function as a whole, it's clear that this uses a lot of stack space. + /// ```rust + /// struct QuiteLargeType([u8; 500_000]); + /// fn foo() { + /// // ... some function that uses a lot of stack space ... + /// let _x1 = QuiteLargeType([0; 500_000]); + /// let _x2 = QuiteLargeType([0; 500_000]); + /// let _x3 = QuiteLargeType([0; 500_000]); + /// let _x4 = QuiteLargeType([0; 500_000]); + /// } + /// ``` + /// + /// Instead of doing this, allocate the arrays on the heap. + /// This currently requires going through a `Vec` first and then converting it to a `Box`: + /// ```rust + /// struct NotSoLargeType(Box<[u8]>); + /// + /// fn foo() { + /// let _x1 = NotSoLargeType(vec![0; 500_000].into_boxed_slice()); + /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Now heap allocated. + /// // The size of `NotSoLargeType` is 16 bytes. + /// // ... + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub LARGE_STACK_FRAMES, + nursery, + "checks for functions that allocate a lot of stack space" +} + +pub struct LargeStackFrames { + maximum_allowed_size: u64, +} + +impl LargeStackFrames { + #[must_use] + pub fn new(size: u64) -> Self { + Self { + maximum_allowed_size: size, + } + } +} + +impl_lint_pass!(LargeStackFrames => [LARGE_STACK_FRAMES]); + +#[derive(Copy, Clone)] +enum Space { + Used(u64), + Overflow, +} + +impl Space { + pub fn exceeds_limit(self, limit: u64) -> bool { + match self { + Self::Used(used) => used > limit, + Self::Overflow => true, + } + } +} + +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<'tcx> LateLintPass<'tcx> for LargeStackFrames { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + _: &'tcx Body<'tcx>, + span: Span, + local_def_id: LocalDefId, + ) { + let def_id = local_def_id.to_def_id(); + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if fn_has_unsatisfiable_preds(cx, def_id) { + return; + } + + let mir = cx.tcx.optimized_mir(def_id); + let param_env = cx.tcx.param_env(def_id); + + let mut frame_size = Space::Used(0); + + for local in &mir.local_decls { + if let Ok(layout) = cx.tcx.layout_of(param_env.and(local.ty)) { + frame_size += layout.size.bytes(); + } + } + + if frame_size.exceeds_limit(self.maximum_allowed_size) { + span_lint_and_note( + 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", + ); + } + } +} diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 2f10e3d258133..4e9d77ea156af 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; use rustc_hir::{Local, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -25,14 +26,21 @@ declare_clippy_lint! { declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); impl LateLintPass<'_> for UnderscoreTyped { - fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { if_chain! { if !in_external_macro(cx.tcx.sess, local.span); if let Some(ty) = local.ty; // Ensure that it has a type defined if let TyKind::Infer = &ty.kind; // that type is '_' if local.span.ctxt() == ty.span.ctxt(); then { - span_lint_and_help(cx, + // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, + // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` + if snippet(cx, ty.span, "_").trim() != "_" { + return; + } + + span_lint_and_help( + cx, LET_WITH_TYPE_UNDERSCORE, local.span, "variable declared with type underscore", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4a23edb58aaa4..87329ee5e14ac 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -68,6 +68,7 @@ mod renamed_lints; mod allow_attributes; mod almost_complete_range; mod approx_const; +mod arc_with_non_send_sync; mod as_conversions; mod asm_syntax; mod assertions_on_constants; @@ -114,6 +115,7 @@ mod else_if_without_else; mod empty_drop; mod empty_enum; mod empty_structs_with_brackets; +mod endian_bytes; mod entry; mod enum_clike; mod enum_variants; @@ -121,6 +123,7 @@ mod equatable_if_let; mod escape; mod eta_reduction; mod excessive_bools; +mod excessive_nesting; mod exhaustive_items; mod exit; mod explicit_write; @@ -147,6 +150,7 @@ mod implicit_return; mod implicit_saturating_add; mod implicit_saturating_sub; mod inconsistent_struct_constructor; +mod incorrect_impls; mod index_refutable_slice; mod indexing_slicing; mod infinite_iter; @@ -165,6 +169,7 @@ mod large_enum_variant; mod large_futures; mod large_include_file; mod large_stack_arrays; +mod large_stack_frames; mod len_zero; mod let_if_seq; mod let_underscore; @@ -183,6 +188,7 @@ mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; +mod manual_range_patterns; mod manual_rem_euclid; mod manual_retain; mod manual_slice_size_calculation; @@ -191,9 +197,9 @@ mod manual_strip; mod map_unit_fn; mod match_result_ok; mod matches; -mod mem_forget; mod mem_replace; mod methods; +mod min_ident_chars; mod minmax; mod misc; mod misc_early; @@ -220,6 +226,7 @@ mod needless_borrowed_ref; mod needless_continue; mod needless_else; mod needless_for_each; +mod needless_if; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; @@ -256,6 +263,7 @@ mod pub_use; mod question_mark; mod question_mark_used; mod ranges; +mod raw_strings; mod rc_clone_in_vec_init; mod read_zero_byte_vec; mod redundant_async_block; @@ -266,6 +274,7 @@ mod redundant_field_names; mod redundant_pub_crate; mod redundant_slicing; mod redundant_static_lifetimes; +mod redundant_type_annotations; mod ref_option_ref; mod ref_patterns; mod reference; @@ -279,8 +288,10 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod significant_drop_tightening; +mod single_call_fn; mod single_char_lifetime_names; mod single_component_path_imports; +mod single_range_in_vec_init; mod size_of_in_element_count; mod size_of_ref; mod slow_vector_initialization; @@ -300,6 +311,7 @@ mod to_digit_is_some; mod trailing_empty_array; mod trait_bounds; mod transmute; +mod tuple_array_conversions; mod types; mod undocumented_unsafe_blocks; mod unicode; @@ -327,6 +339,7 @@ mod use_self; mod useless_conversion; mod vec; mod vec_init_then_push; +mod visibility; mod wildcard_imports; mod write; mod zero_div_zero; @@ -486,26 +499,27 @@ pub(crate) struct LintInfo { explanation: &'static str, } -pub fn explain(name: &str) { +pub fn explain(name: &str) -> i32 { let target = format!("clippy::{}", name.to_ascii_uppercase()); - match declared_lints::LINTS.iter().find(|info| info.lint.name == target) { - Some(info) => { - println!("{}", info.explanation); - // Check if the lint has configuration - let mdconf = get_configuration_metadata(); - if let Some(config_vec_positions) = mdconf - .iter() - .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned())) - { - // If it has, print it - println!("### Configuration for {}:\n", info.lint.name_lower()); - for position in config_vec_positions { - let conf = &mdconf[position]; - println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default); - } + if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) { + println!("{}", info.explanation); + // Check if the lint has configuration + let mdconf = get_configuration_metadata(); + if let Some(config_vec_positions) = mdconf + .iter() + .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned())) + { + // If it has, print it + println!("### Configuration for {}:\n", info.lint.name_lower()); + for position in config_vec_positions { + let conf = &mdconf[position]; + println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default); } - }, - None => println!("unknown lint: {name}"), + } + 0 + } else { + println!("unknown lint: {name}"); + 1 } } @@ -564,6 +578,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass)); store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl)); + store.register_late_pass(|_| { + Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new()) + }); } let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone(); @@ -672,7 +689,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unit_types::UnitTypes)); - store.register_late_pass(|_| Box::new(loops::Loops)); + store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv()))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(lifetimes::Lifetimes)); store.register_late_pass(|_| Box::new(entry::HashMapPass)); @@ -693,7 +710,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let too_large_for_stack = conf.too_large_for_stack; store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack })); - store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack })); + store.register_late_pass(move |_| { + Box::new(vec::UselessVec { + too_large_for_stack, + msrv: msrv(), + }) + }); store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); store.register_late_pass(|_| Box::new(strings::StringLitAsBytes)); store.register_late_pass(|_| Box::new(derive::Derive)); @@ -725,7 +747,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let missing_docs_in_crate_items = conf.missing_docs_in_crate_items; store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); - store.register_late_pass(|_| Box::new(mem_forget::MemForget)); store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items))); @@ -751,7 +772,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher)); store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|_| Box::new(question_mark::QuestionMark)); + store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl)); @@ -773,7 +794,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates)); store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString)); let max_trait_bounds = conf.max_trait_bounds; - store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); + store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv()))); store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone()))); @@ -785,7 +806,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); store.register_early_pass(|| Box::new(formatting::Formatting)); store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints)); - store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); @@ -810,10 +830,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let enum_variant_name_threshold = conf.enum_variant_name_threshold; + let allow_private_module_inception = conf.allow_private_module_inception; store.register_late_pass(move |_| { Box::new(enum_variants::EnumVariantNames::new( enum_variant_name_threshold, avoid_breaking_exported_api, + allow_private_module_inception, )) }); store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments)); @@ -833,7 +855,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); - store.register_early_pass(|| Box::new(as_conversions::AsConversions)); + store.register_late_pass(|_| Box::new(as_conversions::AsConversions)); store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); store.register_early_pass(|| Box::::default()); let max_fn_params_bools = conf.max_fn_params_bools; @@ -909,7 +931,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: enable_raw_pointer_heuristic_for_send, )) }); - store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); + let accept_comment_above_statement = conf.accept_comment_above_statement; + let accept_comment_above_attributes = conf.accept_comment_above_attributes; + store.register_late_pass(move |_| { + Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new( + accept_comment_above_statement, + accept_comment_above_attributes, + )) + }); let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args; store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined))); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); @@ -1002,11 +1031,49 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule)); store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); + let excessive_nesting_threshold = conf.excessive_nesting_threshold; + store.register_early_pass(move || { + Box::new(excessive_nesting::ExcessiveNesting { + excessive_nesting_threshold, + nodes: rustc_ast::node_id::NodeSet::new(), + }) + }); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); store.register_early_pass(|| Box::new(ref_patterns::RefPatterns)); store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug)); + store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes)); + store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); + store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); + store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); + let allowed_idents_below_min_chars = conf.allowed_idents_below_min_chars.clone(); + let min_ident_chars_threshold = conf.min_ident_chars_threshold; + store.register_late_pass(move |_| { + Box::new(min_ident_chars::MinIdentChars { + allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(), + min_ident_chars_threshold, + }) + }); + let stack_size_threshold = conf.stack_size_threshold; + store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); + store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); + store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls)); + store.register_late_pass(move |_| { + Box::new(single_call_fn::SingleCallFn { + avoid_breaking_exported_api, + def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(), + }) + }); + let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_strings; + store.register_early_pass(move || { + Box::new(raw_strings::RawStrings { + needless_raw_string_hashes_allow_one, + }) + }); + 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() })); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 986ffcad883db..852f6736585bc 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; +use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; @@ -201,7 +202,19 @@ fn check_fn_inner<'tcx>( span_lint_and_then( cx, NEEDLESS_LIFETIMES, - span.with_hi(sig.decl.output.span().hi()), + elidable_lts + .iter() + .map(|<| cx.tcx.def_span(lt)) + .chain(usages.iter().filter_map(|usage| { + if let LifetimeName::Param(def_id) = usage.res + && elidable_lts.contains(&def_id) + { + return Some(usage.ident.span); + } + + None + })) + .collect_vec(), &format!("the following explicit lifetimes could be elided: {lts}"), |diag| { if sig.header.is_async() { @@ -562,7 +575,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ // if the bounds define new lifetimes, they are fine to occur let allowed_lts = allowed_lts_from(pred.bound_generic_params); // now walk the bounds - for bound in pred.bounds.iter() { + for bound in pred.bounds { walk_param_bound(&mut visitor, bound); } // and check that all lifetimes are allowed diff --git a/clippy_lints/src/loops/explicit_into_iter_loop.rs b/clippy_lints/src/loops/explicit_into_iter_loop.rs index 175e2b382e3f6..93d6b80864699 100644 --- a/clippy_lints/src/loops/explicit_into_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_into_iter_loop.rs @@ -5,15 +5,76 @@ use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_span::symbol::sym; +#[derive(Clone, Copy)] +enum AdjustKind { + None, + Borrow, + BorrowMut, + Reborrow, + ReborrowMut, +} +impl AdjustKind { + fn borrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Borrow, + AutoBorrowMutability::Mut { .. } => Self::BorrowMut, + } + } + + fn reborrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Reborrow, + AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, + } + } + + fn display(self) -> &'static str { + match self { + Self::None => "", + Self::Borrow => "&", + Self::BorrowMut => "&mut ", + Self::Reborrow => "&*", + Self::ReborrowMut => "&mut *", + } + } +} + pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) { - let self_ty = cx.typeck_results().expr_ty(self_arg); - let self_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); - if !(self_ty == self_ty_adjusted && is_trait_method(cx, call_expr, sym::IntoIterator)) { + if !is_trait_method(cx, call_expr, sym::IntoIterator) { return; } + let typeck = cx.typeck_results(); + let self_ty = typeck.expr_ty(self_arg); + let adjust = match typeck.expr_adjustments(self_arg) { + [] => AdjustKind::None, + &[ + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + .. + }, + ] => AdjustKind::borrow(mutbl), + &[ + Adjustment { + kind: Adjust::Deref(_), .. + }, + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + ] => { + if self_ty == target && matches!(mutbl, AutoBorrowMutability::Not) { + AdjustKind::None + } else { + AdjustKind::reborrow(mutbl) + } + }, + _ => return, + }; + let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); span_lint_and_sugg( @@ -23,7 +84,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr< "it is more concise to loop over containers instead of using explicit \ iteration methods", "to write this more concisely, try", - object.to_string(), + format!("{}{object}", adjust.display()), applicability, ); } diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 151c7f1d5d254..f3347e33077b7 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,75 +1,235 @@ use super::EXPLICIT_ITER_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{ + implements_trait, implements_trait_with_env, is_copy, make_normalized_projection, + make_normalized_projection_with_regions, normalize_with_regions, +}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut}; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, method_name: &str) { - let should_lint = match method_name { - "iter" | "iter_mut" => is_ref_iterable_type(cx, self_arg), - "into_iter" if is_trait_method(cx, arg, sym::IntoIterator) => { - let receiver_ty = cx.typeck_results().expr_ty(self_arg); - let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); - let ref_receiver_ty = cx.tcx.mk_ref( - cx.tcx.lifetimes.re_erased, - ty::TypeAndMut { - ty: receiver_ty, - mutbl: Mutability::Not, - }, - ); - receiver_ty_adjusted == ref_receiver_ty - }, - _ => false, - }; - - if !should_lint { +pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) { + let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else { return; + }; + if let ty::Array(_, count) = *ty.peel_refs().kind() { + if !ty.is_ref() { + if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { + return; + } + } else if count + .try_eval_target_usize(cx.tcx, cx.param_env) + .map_or(true, |x| x > 32) + && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) + { + return; + } } let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); - let muta = if method_name == "iter_mut" { "mut " } else { "" }; span_lint_and_sugg( cx, EXPLICIT_ITER_LOOP, - arg.span, + call_expr.span, "it is more concise to loop over references to containers instead of using explicit \ iteration methods", "to write this more concisely, try", - format!("&{muta}{object}"), + format!("{}{object}", adjust.display()), applicability, ); } -/// Returns `true` if the type of expr is one that provides `IntoIterator` impls -/// for `&T` and `&mut T`, such as `Vec`. -#[rustfmt::skip] -fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - // no walk_ptrs_ty: calling iter() on a reference can make sense because it - // will allow further borrows afterwards - let ty = cx.typeck_results().expr_ty(e); - is_iterable_array(ty, cx) || - is_type_diagnostic_item(cx, ty, sym::Vec) || - is_type_diagnostic_item(cx, ty, sym::LinkedList) || - is_type_diagnostic_item(cx, ty, sym::HashMap) || - is_type_diagnostic_item(cx, ty, sym::HashSet) || - is_type_diagnostic_item(cx, ty, sym::VecDeque) || - is_type_diagnostic_item(cx, ty, sym::BinaryHeap) || - is_type_diagnostic_item(cx, ty, sym::BTreeMap) || - is_type_diagnostic_item(cx, ty, sym::BTreeSet) +#[derive(Clone, Copy)] +enum AdjustKind { + None, + Borrow, + BorrowMut, + Deref, + Reborrow, + ReborrowMut, } +impl AdjustKind { + fn borrow(mutbl: Mutability) -> Self { + match mutbl { + Mutability::Not => Self::Borrow, + Mutability::Mut => Self::BorrowMut, + } + } -fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { - // IntoIterator is currently only implemented for array sizes <= 32 in rustc - match ty.kind() { - ty::Array(_, n) => n - .try_eval_target_usize(cx.tcx, cx.param_env) - .map_or(false, |val| (0..=32).contains(&val)), - _ => false, + fn auto_borrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Borrow, + AutoBorrowMutability::Mut { .. } => Self::BorrowMut, + } + } + + fn reborrow(mutbl: Mutability) -> Self { + match mutbl { + Mutability::Not => Self::Reborrow, + Mutability::Mut => Self::ReborrowMut, + } + } + + fn auto_reborrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Reborrow, + AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, + } + } + + fn display(self) -> &'static str { + match self { + Self::None => "", + Self::Borrow => "&", + Self::BorrowMut => "&mut ", + Self::Deref => "*", + Self::Reborrow => "&*", + Self::ReborrowMut => "&mut *", + } + } +} + +/// Checks if an `iter` or `iter_mut` call returns `IntoIterator::IntoIter`. Returns how the +/// argument needs to be adjusted. +#[expect(clippy::too_many_lines)] +fn is_ref_iterable<'tcx>( + cx: &LateContext<'tcx>, + self_arg: &Expr<'_>, + call_expr: &Expr<'_>, +) -> Option<(AdjustKind, Ty<'tcx>)> { + let typeck = cx.typeck_results(); + if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let Some(fn_id) = typeck.type_dependent_def_id(call_expr.hir_id) + && let sig = cx.tcx.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) + && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output + && let param_env = cx.tcx.param_env(fn_id) + && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, []) + && let Some(into_iter_ty) = + make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) + && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) + && into_iter_ty == req_res_ty + { + let adjustments = typeck.expr_adjustments(self_arg); + let self_ty = typeck.expr_ty(self_arg); + let self_is_copy = is_copy(cx, self_ty); + + if adjustments.is_empty() && self_is_copy { + // Exact type match, already checked earlier + return Some((AdjustKind::None, self_ty)); + } + + let res_ty = cx.tcx.erase_regions(EarlyBinder::bind(req_res_ty) + .subst(cx.tcx, typeck.node_substs(call_expr.hir_id))); + let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() { + Some(mutbl) + } else { + None + }; + + if !adjustments.is_empty() { + if self_is_copy { + // Using by value won't consume anything + 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 + { + return Some((AdjustKind::None, self_ty)); + } + } else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind() + && let Some(mutbl) = mutbl + { + // Attempt to reborrow the mutable reference + let self_ty = if mutbl.is_mut() { + self_ty + } else { + cx.tcx.mk_ref(region, TypeAndMut { 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 + { + return Some((AdjustKind::reborrow(mutbl), self_ty)); + } + } + } + if let Some(mutbl) = mutbl + && !self_ty.is_ref() + { + // Attempt to borrow + let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut { + ty: 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 + { + return Some((AdjustKind::borrow(mutbl), self_ty)); + } + } + + match adjustments { + [] => Some((AdjustKind::None, self_ty)), + &[ + Adjustment { kind: Adjust::Deref(_), ..}, + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + .. + ] => { + if target != self_ty + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::auto_reborrow(mutbl), target)) + } else { + None + } + } + &[Adjustment { kind: Adjust::Deref(_), target }, ..] => { + if is_copy(cx, target) + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::Deref, target)) + } else { + None + } + } + &[ + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + .. + ] => { + if self_ty.is_ref() + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::auto_borrow(mutbl), target)) + } else { + None + } + } + _ => None, + } + } else { + None } } diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index d4c3f76b86417..7d1f8ef29c817 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -51,7 +51,7 @@ pub(super) fn check<'tcx>( iter_b = Some(get_assignment(body)); } - let assignments = iter_a.into_iter().flatten().chain(iter_b.into_iter()); + let assignments = iter_a.into_iter().flatten().chain(iter_b); let big_sugg = assignments // The only statements in the for loops can be indexed assignments from @@ -402,7 +402,7 @@ fn get_assignments<'a, 'tcx>( StmtKind::Local(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) - .chain((*expr).into_iter()) + .chain(*expr) .filter(move |e| { if let ExprKind::AssignOp(_, place, _) = e.kind { path_to_local(place).map_or(false, |id| { diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index f83ad388a742f..529189b52acda 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -20,9 +20,10 @@ mod while_let_loop; mod while_let_on_iterator; use clippy_utils::higher; +use clippy_utils::msrvs::Msrv; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; @@ -479,7 +480,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for unnecessary `if let` usage in a for loop + /// Checks for unnecessary `if let` usage in a for loop /// where only the `Some` or `Ok` variant of the iterator element is used. /// /// ### Why is this bad? @@ -511,7 +512,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for empty spin loops + /// Checks for empty spin loops /// /// ### Why is this bad? /// The loop body should have something like `thread::park()` or at least @@ -547,7 +548,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for manual implementations of Iterator::find + /// Checks for manual implementations of Iterator::find /// /// ### Why is this bad? /// It doesn't affect performance, but using `find` is shorter and easier to read. @@ -606,7 +607,15 @@ declare_clippy_lint! { "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" } -declare_lint_pass!(Loops => [ +pub struct Loops { + msrv: Msrv, +} +impl Loops { + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} +impl_lint_pass!(Loops => [ MANUAL_MEMCPY, MANUAL_FLATTEN, NEEDLESS_RANGE_LOOP, @@ -645,7 +654,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { if body.span.from_expansion() { return; } - check_for_loop(cx, pat, arg, body, expr, span); + self.check_for_loop(cx, pat, arg, body, expr, span); if let ExprKind::Block(block, _) = body.kind { never_loop::check(cx, block, loop_id, span, for_loop.as_ref()); } @@ -678,46 +687,48 @@ impl<'tcx> LateLintPass<'tcx> for Loops { manual_while_let_some::check(cx, condition, body, span); } } + + extract_msrv_attr!(LateContext); } -fn check_for_loop<'tcx>( - cx: &LateContext<'tcx>, - pat: &'tcx Pat<'_>, - arg: &'tcx Expr<'_>, - body: &'tcx Expr<'_>, - expr: &'tcx Expr<'_>, - span: Span, -) { - let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); - if !is_manual_memcpy_triggered { - needless_range_loop::check(cx, pat, arg, body, expr); - explicit_counter_loop::check(cx, pat, arg, body, expr); +impl Loops { + fn check_for_loop<'tcx>( + &self, + cx: &LateContext<'tcx>, + pat: &'tcx Pat<'_>, + arg: &'tcx Expr<'_>, + body: &'tcx Expr<'_>, + expr: &'tcx Expr<'_>, + span: Span, + ) { + let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); + if !is_manual_memcpy_triggered { + needless_range_loop::check(cx, pat, arg, body, expr); + explicit_counter_loop::check(cx, pat, arg, body, expr); + } + self.check_for_loop_arg(cx, pat, arg); + for_kv_map::check(cx, pat, arg, body); + mut_range_bound::check(cx, arg, body); + single_element_loop::check(cx, pat, arg, body, expr); + same_item_push::check(cx, pat, arg, body, expr); + manual_flatten::check(cx, pat, arg, body, span); + manual_find::check(cx, pat, arg, body, span, expr); } - check_for_loop_arg(cx, pat, arg); - for_kv_map::check(cx, pat, arg, body); - mut_range_bound::check(cx, arg, body); - single_element_loop::check(cx, pat, arg, body, expr); - same_item_push::check(cx, pat, arg, body, expr); - manual_flatten::check(cx, pat, arg, body, span); - manual_find::check(cx, pat, arg, body, span, expr); -} -fn check_for_loop_arg(cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { - if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { - let method_name = method.ident.as_str(); - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - match method_name { - "iter" | "iter_mut" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name); - }, - "into_iter" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name); - explicit_into_iter_loop::check(cx, self_arg, arg); - }, - "next" => { - iter_next_loop::check(cx, arg); - }, - _ => {}, + fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { + if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { + match method.ident.as_str() { + "iter" | "iter_mut" => { + explicit_iter_loop::check(cx, self_arg, arg, &self.msrv); + }, + "into_iter" => { + explicit_into_iter_loop::check(cx, self_arg, arg); + }, + "next" => { + iter_next_loop::check(cx, arg); + }, + _ => {}, + } } } } diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 10b5e1edf9250..ee338c6beb06d 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -1,22 +1,23 @@ use super::utils::make_iterator_snippet; use super::NEVER_LOOP; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::consts::constant; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet; +use clippy_utils::{consts::Constant, diagnostics::span_lint_and_then}; use rustc_errors::Applicability; use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_span::Span; use std::iter::{once, Iterator}; -pub(super) fn check( - cx: &LateContext<'_>, - block: &Block<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + block: &Block<'tcx>, loop_id: HirId, span: Span, for_loop: Option<&ForLoop<'_>>, ) { - match never_loop_block(block, &mut Vec::new(), loop_id) { + match never_loop_block(cx, block, &mut Vec::new(), loop_id) { NeverLoopResult::AlwaysBreak => { span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| { if let Some(ForLoop { @@ -95,7 +96,12 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirI } } -fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec, main_loop_id: HirId) -> NeverLoopResult { +fn never_loop_block<'tcx>( + cx: &LateContext<'tcx>, + block: &Block<'tcx>, + ignore_ids: &mut Vec, + main_loop_id: HirId, +) -> NeverLoopResult { let iter = block .stmts .iter() @@ -103,10 +109,10 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec, main_loop_id .chain(block.expr.map(|expr| (expr, None))); iter.map(|(e, els)| { - let e = never_loop_expr(e, ignore_ids, main_loop_id); + let e = never_loop_expr(cx, e, ignore_ids, main_loop_id); // els is an else block in a let...else binding els.map_or(e, |els| { - combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id), ignore_ids) + combine_branches(e, never_loop_block(cx, els, ignore_ids, main_loop_id), ignore_ids) }) }) .fold(NeverLoopResult::Otherwise, combine_seq) @@ -122,7 +128,12 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t } #[allow(clippy::too_many_lines)] -fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: HirId) -> NeverLoopResult { +fn never_loop_expr<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + ignore_ids: &mut Vec, + main_loop_id: HirId, +) -> NeverLoopResult { match expr.kind { ExprKind::Unary(_, e) | ExprKind::Cast(e, _) @@ -130,45 +141,51 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Repeat(e, _) - | ExprKind::DropTemps(e) => never_loop_expr(e, ignore_ids, main_loop_id), - ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, ignore_ids, main_loop_id), - ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), ignore_ids, main_loop_id), + | ExprKind::DropTemps(e) => never_loop_expr(cx, e, ignore_ids, main_loop_id), + ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, ignore_ids, main_loop_id), + ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, &mut es.iter(), ignore_ids, main_loop_id), ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all( + cx, &mut std::iter::once(receiver).chain(es.iter()), ignore_ids, main_loop_id, ), ExprKind::Struct(_, fields, base) => { - let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id); + let fields = never_loop_expr_all(cx, &mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id); if let Some(base) = base { - combine_seq(fields, never_loop_expr(base, ignore_ids, main_loop_id)) + combine_seq(fields, never_loop_expr(cx, base, ignore_ids, main_loop_id)) } else { fields } }, - ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), ignore_ids, main_loop_id), + ExprKind::Call(e, es) => never_loop_expr_all(cx, &mut once(e).chain(es.iter()), ignore_ids, main_loop_id), ExprKind::Binary(_, e1, e2) | ExprKind::Assign(e1, e2, _) | ExprKind::AssignOp(_, e1, e2) - | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), ignore_ids, main_loop_id), + | ExprKind::Index(e1, e2) => never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id), ExprKind::Loop(b, _, _, _) => { // Break can come from the inner loop so remove them. - absorb_break(never_loop_block(b, ignore_ids, main_loop_id)) + absorb_break(never_loop_block(cx, b, ignore_ids, main_loop_id)) }, ExprKind::If(e, e2, e3) => { - let e1 = never_loop_expr(e, ignore_ids, main_loop_id); - let e2 = never_loop_expr(e2, ignore_ids, main_loop_id); + let e1 = never_loop_expr(cx, e, ignore_ids, main_loop_id); + let e2 = never_loop_expr(cx, e2, ignore_ids, main_loop_id); + // If we know the `if` condition evaluates to `true`, don't check everything past it; it + // should just return whatever's evaluated for `e1` and `e2` since `e3` is unreachable + if let Some(Constant::Bool(true)) = constant(cx, cx.typeck_results(), e) { + return combine_seq(e1, e2); + } let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| { - never_loop_expr(e, ignore_ids, main_loop_id) + never_loop_expr(cx, e, ignore_ids, main_loop_id) }); combine_seq(e1, combine_branches(e2, e3, ignore_ids)) }, ExprKind::Match(e, arms, _) => { - let e = never_loop_expr(e, ignore_ids, main_loop_id); + let e = never_loop_expr(cx, e, ignore_ids, main_loop_id); if arms.is_empty() { e } else { - let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id); + let arms = never_loop_expr_branch(cx, &mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id); combine_seq(e, arms) } }, @@ -176,7 +193,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H if l.is_some() { ignore_ids.push(b.hir_id); } - let ret = never_loop_block(b, ignore_ids, main_loop_id); + let ret = never_loop_block(cx, b, ignore_ids, main_loop_id); if l.is_some() { ignore_ids.pop(); } @@ -198,31 +215,30 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H // checks if break targets a block instead of a loop ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| { - never_loop_expr(e, ignore_ids, main_loop_id) + never_loop_expr(cx, e, ignore_ids, main_loop_id) }), ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| { combine_seq( - never_loop_expr(e, ignore_ids, main_loop_id), + never_loop_expr(cx, e, ignore_ids, main_loop_id), NeverLoopResult::AlwaysBreak, ) }), - ExprKind::Become(e) => { - combine_seq( - never_loop_expr(e, ignore_ids, main_loop_id), - NeverLoopResult::AlwaysBreak, - ) - } + ExprKind::Become(e) => combine_seq( + never_loop_expr(cx, e, ignore_ids, main_loop_id), + NeverLoopResult::AlwaysBreak, + ), ExprKind::InlineAsm(asm) => asm .operands .iter() .map(|(o, _)| match o { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { - never_loop_expr(expr, ignore_ids, main_loop_id) + never_loop_expr(cx, expr, ignore_ids, main_loop_id) }, InlineAsmOperand::Out { expr, .. } => { - never_loop_expr_all(&mut expr.iter().copied(), ignore_ids, main_loop_id) + never_loop_expr_all(cx, &mut expr.iter().copied(), ignore_ids, main_loop_id) }, InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all( + cx, &mut once(*in_expr).chain(out_expr.iter().copied()), ignore_ids, main_loop_id, @@ -242,22 +258,24 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H } } -fn never_loop_expr_all<'a, T: Iterator>>( +fn never_loop_expr_all<'tcx, T: Iterator>>( + cx: &LateContext<'tcx>, es: &mut T, ignore_ids: &mut Vec, main_loop_id: HirId, ) -> NeverLoopResult { - es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id)) + es.map(|e| never_loop_expr(cx, e, ignore_ids, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_seq) } -fn never_loop_expr_branch<'a, T: Iterator>>( +fn never_loop_expr_branch<'tcx, T: Iterator>>( + cx: &LateContext<'tcx>, e: &mut T, ignore_ids: &mut Vec, main_loop_id: HirId, ) -> NeverLoopResult { e.fold(NeverLoopResult::AlwaysBreak, |a, b| { - combine_branches(a, never_loop_expr(b, ignore_ids, main_loop_id), ignore_ids) + combine_branches(a, never_loop_expr(cx, b, ignore_ids, main_loop_id), ignore_ids) }) } diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 9d9341559ac72..f7b3b2358a0bd 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { } fn visit_block(&mut self, b: &'tcx Block<'_>) { - for stmt in b.stmts.iter() { + for stmt in b.stmts { self.visit_stmt(stmt); } } diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index e2e6a87a30151..8e322a9790726 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { }); if !id.is_local(); then { - for kid in cx.tcx.module_children(id).iter() { + for kid in cx.tcx.module_children(id) { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { let span = mac_attr.span; let def_path = cx.tcx.def_path_str(mac_id); diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 389b0a4a62dc5..59e421c162202 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -6,17 +6,18 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; use if_chain::if_chain; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use serde::Deserialize; use std::ops::ControlFlow; +use std::slice; declare_clippy_lint! { /// ### What it does @@ -81,11 +82,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { { match if_let_or_match { IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! { - if expr_is_simple_identity(let_pat, if_then); + if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then); if let Some(if_else) = if_else; if expr_diverges(cx, if_else); then { - emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else); + emit_manual_let_else(cx, stmt.span, if_let_expr, &ident_map, let_pat, if_else); } }, IfLetOrMatch::Match(match_expr, arms, source) => { @@ -118,11 +119,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { return; } let pat_arm = &arms[1 - idx]; - if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) { - return; - } + let Some(ident_map) = expr_simple_identity_map(local.pat, pat_arm.pat, pat_arm.body) else { + return + }; - emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body); + emit_manual_let_else(cx, stmt.span, match_expr, &ident_map, pat_arm.pat, diverging_arm.body); }, } }; @@ -135,7 +136,7 @@ fn emit_manual_let_else( cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, - local: &Pat<'_>, + ident_map: &FxHashMap>, pat: &Pat<'_>, else_body: &Expr<'_>, ) { @@ -146,8 +147,8 @@ fn emit_manual_let_else( "this could be rewritten as `let...else`", |diag| { // This is far from perfect, for example there needs to be: - // * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ... - // * renamings of the bindings for many `PatKind`s like structs, slices, etc. + // * renamings of the bindings for many `PatKind`s like slices, etc. + // * limitations in the existing replacement algorithms // * unused binding collision detection with existing ones // for this to be machine applicable. let mut app = Applicability::HasPlaceholders; @@ -159,57 +160,126 @@ fn emit_manual_let_else( } else { format!("{{ {sn_else} }}") }; - let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app); + let sn_bl = replace_in_pattern(cx, span, ident_map, pat, &mut app, true); let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};"); diag.span_suggestion(span, "consider writing", sugg, app); }, ); } -// replaces the locals in the pattern +/// Replaces the locals in the pattern +/// +/// For this example: +/// +/// ```ignore +/// let (a, FooBar { b, c }) = if let Bar { Some(a_i), b_i } = ex { (a_i, b_i) } else { return }; +/// ``` +/// +/// We have: +/// +/// ```ignore +/// pat: Bar { Some(a_i), b_i } +/// ident_map: (a_i) -> (a), (b_i) -> (FooBar { b, c }) +/// ``` +/// +/// We return: +/// +/// ```ignore +/// Bar { Some(a), b_i: FooBar { b, c } } +/// ``` fn replace_in_pattern( cx: &LateContext<'_>, span: Span, - local: &Pat<'_>, + ident_map: &FxHashMap>, pat: &Pat<'_>, app: &mut Applicability, + top_level: bool, ) -> String { - let mut bindings_count = 0; - pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1); - // If the pattern creates multiple bindings, exit early, - // as otherwise we might paste the pattern to the positions of multiple bindings. - if bindings_count > 1 { - let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); - return sn_pat.into_owned(); - } + // We put a labeled block here so that we can implement the fallback in this function. + // As the function has multiple call sites, implementing the fallback via an Option + // return type and unwrap_or_else would cause repetition. Similarly, the function also + // invokes the fall back multiple times. + 'a: { + // If the ident map is empty, there is no replacement to do. + // The code following this if assumes a non-empty ident_map. + if ident_map.is_empty() { + break 'a; + } - match pat.kind { - PatKind::Binding(..) => { - let (sn_bdg, _) = snippet_with_context(cx, local.span, span.ctxt(), "", app); - return sn_bdg.to_string(); - }, - PatKind::Or(pats) => { - let patterns = pats - .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app)) - .collect::>(); - let or_pat = patterns.join(" | "); - return format!("({or_pat})"); - }, - // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. - PatKind::TupleStruct(ref w, args, dot_dot_pos) => { - let mut args = args - .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app)) - .collect::>(); - if let Some(pos) = dot_dot_pos.as_opt_usize() { - args.insert(pos, "..".to_owned()); - } - let args = args.join(", "); - let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); - return format!("{sn_wrapper}({args})"); - }, - _ => {}, + match pat.kind { + PatKind::Binding(_ann, _id, binding_name, opt_subpt) => { + let Some(pat_to_put) = ident_map.get(&binding_name.name) else { break 'a }; + let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); + if let Some(subpt) = opt_subpt { + let subpt = replace_in_pattern(cx, span, ident_map, subpt, app, false); + return format!("{sn_ptp} @ {subpt}"); + } + return sn_ptp.to_string(); + }, + PatKind::Or(pats) => { + let patterns = pats + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + let or_pat = patterns.join(" | "); + if top_level { + return format!("({or_pat})"); + } + return or_pat; + }, + PatKind::Struct(path, fields, has_dot_dot) => { + let fields = fields + .iter() + .map(|fld| { + if let PatKind::Binding(_, _, name, None) = fld.pat.kind && + let Some(pat_to_put) = ident_map.get(&name.name) + { + let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app); + let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); + // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is + // a PatKind::Binding but that is also hard to get right. + if sn_fld_name == sn_ptp { + // Field init shorthand + return format!("{sn_fld_name}"); + } + return format!("{sn_fld_name}: {sn_ptp}"); + } + let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app); + sn_fld.into_owned() + }) + .collect::>(); + let fields_string = fields.join(", "); + + let dot_dot_str = if has_dot_dot { " .." } else { "" }; + let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); + return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); + }, + // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. + PatKind::TupleStruct(ref w, args, dot_dot_pos) => { + let mut args = args + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + if let Some(pos) = dot_dot_pos.as_opt_usize() { + args.insert(pos, "..".to_owned()); + } + let args = args.join(", "); + let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); + return format!("{sn_wrapper}({args})"); + }, + PatKind::Tuple(args, dot_dot_pos) => { + let mut args = args + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + if let Some(pos) = dot_dot_pos.as_opt_usize() { + args.insert(pos, "..".to_owned()); + } + let args = args.join(", "); + return format!("({args})"); + }, + _ => {}, + } } let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); sn_pat.into_owned() @@ -353,37 +423,74 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: boo !has_disallowed } -/// Checks if the passed block is a simple identity referring to bindings created by the pattern -fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool { - // We support patterns with multiple bindings and tuples, like: - // let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... } +/// Checks if the passed block is a simple identity referring to bindings created by the pattern, +/// and if yes, returns a mapping between the relevant sub-pattern and the identifier it corresponds +/// to. +/// +/// We support patterns with multiple bindings and tuples, e.g.: +/// +/// ```ignore +/// let (foo_o, bar_o) = if let (Some(foo), bar) = g() { (foo, bar) } else { ... } +/// ``` +/// +/// The expected params would be: +/// +/// ```ignore +/// local_pat: (foo_o, bar_o) +/// let_pat: (Some(foo), bar) +/// expr: (foo, bar) +/// ``` +/// +/// We build internal `sub_pats` so that it looks like `[foo_o, bar_o]` and `paths` so that it looks +/// like `[foo, bar]`. Then we turn that into `FxHashMap [(foo) -> (foo_o), (bar) -> (bar_o)]` which +/// we return. +fn expr_simple_identity_map<'a, 'hir>( + local_pat: &'a Pat<'hir>, + let_pat: &'_ Pat<'hir>, + expr: &'_ Expr<'hir>, +) -> Option>> { let peeled = peel_blocks(expr); - let paths = match peeled.kind { - ExprKind::Tup(exprs) | ExprKind::Array(exprs) => exprs, - ExprKind::Path(_) => std::slice::from_ref(peeled), - _ => return false, + let (sub_pats, paths) = match (local_pat.kind, peeled.kind) { + (PatKind::Tuple(pats, _), ExprKind::Tup(exprs)) | (PatKind::Slice(pats, ..), ExprKind::Array(exprs)) => { + (pats, exprs) + }, + (_, ExprKind::Path(_)) => (slice::from_ref(local_pat), slice::from_ref(peeled)), + _ => return None, }; + + // There is some length mismatch, which indicates usage of .. in the patterns above e.g.: + // let (a, ..) = if let [a, b, _c] = ex { (a, b) } else { ... }; + // We bail in these cases as they should be rare. + if paths.len() != sub_pats.len() { + return None; + } + let mut pat_bindings = FxHashSet::default(); - pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { + let_pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { pat_bindings.insert(ident); }); if pat_bindings.len() < paths.len() { - return false; + // This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple + // times. We don't support these cases so we bail here. E.g.: + // let foo = 0; + // let (new_foo, bar, bar_copied) = if let Some(bar) = Some(0) { (foo, bar, bar) } else { .. }; + return None; } - for path in paths { - if_chain! { - if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind; - if let [path_seg] = path.segments; - then { - if !pat_bindings.remove(&path_seg.ident) { - return false; - } - } else { - return false; + let mut ident_map = FxHashMap::default(); + for (sub_pat, path) in sub_pats.iter().zip(paths.iter()) { + if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind && + let [path_seg] = path.segments + { + let ident = path_seg.ident; + if !pat_bindings.remove(&ident) { + return None; } + ident_map.insert(ident.name, sub_pat); + } else { + return None; } } - true + Some(ident_map) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)] diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs new file mode 100644 index 0000000000000..65ff555209a69 --- /dev/null +++ b/clippy_lints/src/manual_range_patterns.rs @@ -0,0 +1,123 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::LitKind; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_hir::ExprKind; +use rustc_hir::PatKind; +use rustc_hir::RangeEnd; +use rustc_lint::LintContext; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for combined OR patterns that are all contained in a specific range, + /// e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`. + /// + /// ### Why is this bad? + /// Using an explicit range is more concise and easier to read. + /// + /// ### Example + /// ```rust + /// let x = 6; + /// let foo = matches!(x, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + /// ``` + /// Use instead: + /// ```rust + /// let x = 6; + /// let foo = matches!(x, 1..=10); + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_RANGE_PATTERNS, + complexity, + "manually writing range patterns using a combined OR pattern (`|`)" +} +declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); + +fn expr_as_u128(expr: &Expr<'_>) -> Option { + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Int(num, _) = lit.node + { + Some(num) + } else { + None + } +} + +impl LateLintPass<'_> for ManualRangePatterns { + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) { + if in_external_macro(cx.sess(), pat.span) { + return; + } + + // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives + if let PatKind::Or(pats) = pat.kind + && pats.len() >= 3 + { + let mut min = u128::MAX; + let mut max = 0; + let mut numbers_found = FxHashSet::default(); + let mut ranges_found = Vec::new(); + + for pat in pats { + if let PatKind::Lit(lit) = pat.kind + && let Some(num) = expr_as_u128(lit) + { + numbers_found.insert(num); + + min = min.min(num); + max = max.max(num); + } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind + && let Some(left) = expr_as_u128(left) + && let Some(right) = expr_as_u128(right) + && right >= left + { + min = min.min(left); + max = max.max(right); + ranges_found.push(left..=match end { + RangeEnd::Included => right, + RangeEnd::Excluded => right - 1, + }); + } else { + return; + } + } + + let contains_whole_range = 'contains: { + let mut num = min; + while num <= max { + if numbers_found.contains(&num) { + num += 1; + } + // Given a list of (potentially overlapping) ranges like: + // 1..=5, 3..=7, 6..=10 + // We want to find the range with the highest end that still contains the current number + else if let Some(range) = ranges_found + .iter() + .filter(|range| range.contains(&num)) + .max_by_key(|range| range.end()) + { + num = range.end() + 1; + } else { + break 'contains false; + } + } + break 'contains true; + }; + + if contains_whole_range { + span_lint_and_sugg( + cx, + MANUAL_RANGE_PATTERNS, + pat.span, + "this OR pattern can be rewritten using a range", + "try", + format!("{min}..={max}"), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index ae8262ace9687..3d2fbea63f5e8 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; -use clippy_utils::{path_to_local, search_same, SpanlessEq, SpanlessHash}; +use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; use core::iter; use core::slice; @@ -9,6 +9,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd}; +use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Symbol; @@ -103,17 +104,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect(); for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) { if matches!(arm2.pat.kind, PatKind::Wild) { - span_lint_and_then( - cx, - MATCH_SAME_ARMS, - arm1.span, - "this match arm has an identical body to the `_` wildcard arm", - |diag| { - diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect) - .help("or try changing either arm body") - .span_note(arm2.span, "`_` wildcard arm here"); - }, - ); + if !cx.tcx.features().non_exhaustive_omitted_patterns_lint + || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id) + { + span_lint_and_then( + cx, + MATCH_SAME_ARMS, + arm1.span, + "this match arm has an identical body to the `_` wildcard arm", + |diag| { + diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect) + .help("or try changing either arm body") + .span_note(arm2.span, "`_` wildcard arm here"); + }, + ); + } } else { let back_block = backwards_blocking_idxs[j]; let (keep_arm, move_arm) = if back_block < i || (back_block == 0 && forwards_blocking_idxs[i] <= j) { diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs index 6424ac31d9f68..de911f7a02803 100644 --- a/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/clippy_lints/src/matches/match_wild_err_arm.rs @@ -25,7 +25,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' let mut ident_bind_name = kw::Underscore; if !matching_wild { // Looking for unused bindings (i.e.: `_e`) - for pat in inner.iter() { + for pat in inner { if let PatKind::Binding(_, id, ident, None) = pat.kind { if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) { ident_bind_name = ident.name; diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 0d91051632a18..00fa3eb9bfe53 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -38,6 +38,11 @@ declare_clippy_lint! { /// Checks for matches with a single arm where an `if let` /// will usually suffice. /// + /// This intentionally does not lint if there are comments + /// inside of the other arm, so as to allow the user to document + /// why having another explicit pattern with an empty body is necessary, + /// or because the comments need to be preserved for other reasons. + /// /// ### Why is this bad? /// Just readability – `if let` nests less than a `match`. /// @@ -559,6 +564,9 @@ declare_clippy_lint! { /// ### What it does /// Checks for `match` with identical arm bodies. /// + /// Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is + /// enabled and disallowed. + /// /// ### Why is this bad? /// This is probably a copy & paste error. If arm bodies /// are the same on purpose, you can factor them @@ -777,7 +785,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for temporaries returned from function calls in a match scrutinee that have the + /// Checks for temporaries returned from function calls in a match scrutinee that have the /// `clippy::has_significant_drop` attribute. /// /// ### Why is this bad? diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs index abf2525a61c68..8be3c178a2912 100644 --- a/clippy_lints/src/matches/overlapping_arms.rs +++ b/clippy_lints/src/matches/overlapping_arms.rs @@ -41,7 +41,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())), ty, ); - miri_to_const(cx.tcx, min_constant)? + miri_to_const(cx, min_constant)? }, }; let rhs_const = match rhs { @@ -52,7 +52,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())), ty, ); - miri_to_const(cx.tcx, max_constant)? + miri_to_const(cx, max_constant)? }, }; let lhs_val = lhs_const.int_value(cx, ty)?; diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 93ef07d36aea7..37528d9f7f200 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { } } - for generic_arg in b.iter() { + for generic_arg in *b { if let GenericArgKind::Type(ty) = generic_arg.unpack() { if self.has_sig_drop_attr(cx, ty) { return true; diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index ad47c13896c58..35627d6c6491a 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{expr_block, snippet}; +use clippy_utils::source::{expr_block, get_source_text, snippet}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs}; use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs}; use core::cmp::max; @@ -7,10 +7,26 @@ use rustc_errors::Applicability; use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::sym; +use rustc_span::{sym, Span}; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; +/// Checks if there are comments contained within a span. +/// This is a very "naive" check, as it just looks for the literal characters // and /* in the +/// source text. This won't be accurate if there are potentially expressions contained within the +/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty +/// match arms. +fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { + if let Some(ff) = get_source_text(cx, span) + && let Some(text) = ff.as_str() + { + text.as_bytes().windows(2) + .any(|w| w == b"//" || w == b"/*") + } else { + false + } +} + #[rustfmt::skip] pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { @@ -25,7 +41,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: return; } let els = arms[1].body; - let els = if is_unit_expr(peel_blocks(els)) { + let els = if is_unit_expr(peel_blocks(els)) && !empty_arm_has_comment(cx, els.span) { None } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind { if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() { @@ -35,7 +51,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: // block with 2+ statements or 1 expr and 1+ statement Some(els) } else { - // not a block, don't lint + // not a block or an emtpy block w/ comments, don't lint return; }; diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index 704c34c32bf74..3a7f1e034f310 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine /// Finds function return type by examining return expressions in match arms. fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option> { if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr { - for arm in arms.iter() { + for arm in *arms { if let ExprKind::Ret(Some(ret)) = arm.body.kind { return Some(cx.typeck_results().expr_ty(ret)); } diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs deleted file mode 100644 index d6c235b5a693a..0000000000000 --- a/clippy_lints/src/mem_forget.rs +++ /dev/null @@ -1,46 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `std::mem::forget(t)` where `t` is - /// `Drop`. - /// - /// ### Why is this bad? - /// `std::mem::forget(t)` prevents `t` from running its - /// destructor, possibly causing leaks. - /// - /// ### Example - /// ```rust - /// # use std::mem; - /// # use std::rc::Rc; - /// mem::forget(Rc::new(55)) - /// ``` - #[clippy::version = "pre 1.29.0"] - pub MEM_FORGET, - restriction, - "`mem::forget` usage on `Drop` types, likely to cause memory leaks" -} - -declare_lint_pass!(MemForget => [MEM_FORGET]); - -impl<'tcx> LateLintPass<'tcx> for MemForget { - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind { - if let ExprKind::Path(ref qpath) = path_expr.kind { - if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if cx.tcx.is_diagnostic_item(sym::mem_forget, def_id) { - let forgot_ty = cx.typeck_results().expr_ty(first_arg); - - if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { - span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type"); - } - } - } - } - } - } -} diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs new file mode 100644 index 0000000000000..d0c79dc11b071 --- /dev/null +++ b/clippy_lints/src/methods/drain_collect.rs @@ -0,0 +1,85 @@ +use crate::methods::DRAIN_COLLECT; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_range_full; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_lang_item; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_hir::ExprKind; +use rustc_hir::LangItem; +use rustc_hir::Path; +use rustc_hir::QPath; +use rustc_lint::LateContext; +use rustc_middle::query::Key; +use rustc_middle::ty; +use rustc_middle::ty::Ty; +use rustc_span::sym; +use rustc_span::Symbol; + +/// Checks if both types match the given diagnostic item, e.g.: +/// +/// `vec![1,2].drain(..).collect::>()` +/// ^^^^^^^^^ ^^^^^^ true +/// `vec![1,2].drain(..).collect::>()` +/// ^^^^^^^^^ ^^^^^^^^^^ false +fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool { + if let Some(expr_adt_did) = expr.ty_adt_id() + && let Some(recv_adt_did) = recv.ty_adt_id() + { + cx.tcx.is_diagnostic_item(sym, expr_adt_did) && cx.tcx.is_diagnostic_item(sym, recv_adt_did) + } else { + false + } +} + +/// Checks `std::{vec::Vec, collections::VecDeque}`. +fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { + (types_match_diagnostic_item(cx, expr, recv, sym::Vec) + || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque)) + && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) +} + +/// Checks `std::string::String` +fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { + is_type_lang_item(cx, expr, LangItem::String) + && is_type_lang_item(cx, recv, LangItem::String) + && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) +} + +/// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`. +fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> { + types_match_diagnostic_item(cx, expr, recv, sym::HashSet) + .then_some("HashSet") + .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap")) + .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::BinaryHeap).then_some("BinaryHeap")) +} + +pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, recv: &Expr<'_>) { + let expr_ty = cx.typeck_results().expr_ty(expr); + let recv_ty = cx.typeck_results().expr_ty(recv); + let recv_ty_no_refs = recv_ty.peel_refs(); + + if let ExprKind::Path(QPath::Resolved(_, recv_path)) = recv.kind + && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty_no_refs, recv_path) + .then_some("Vec") + .or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String")) + .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs)) + { + let recv = snippet(cx, recv.span, ""); + let sugg = if let ty::Ref(..) = recv_ty.kind() { + format!("std::mem::take({recv})") + } else { + format!("std::mem::take(&mut {recv})") + }; + + span_lint_and_sugg( + cx, + DRAIN_COLLECT, + expr.span, + &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/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index ffc3a4d780e5d..e35fb12ed7910 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -23,21 +22,15 @@ pub(super) fn check<'tcx>( let mut applicability = Applicability::MachineApplicable; let expr_ty = cx.typeck_results().expr_ty(recv); let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability); - let mut needs_ref; let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { - needs_ref = get_args_str.parse::().is_ok(); "slice" } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) { - needs_ref = get_args_str.parse::().is_ok(); "Vec" } else if is_type_diagnostic_item(cx, expr_ty, sym::VecDeque) { - needs_ref = get_args_str.parse::().is_ok(); "VecDeque" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::HashMap) { - needs_ref = true; "HashMap" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::BTreeMap) { - needs_ref = true; "BTreeMap" } else { return; // caller is not a type that we want to lint @@ -45,18 +38,24 @@ pub(super) fn check<'tcx>( let mut span = expr.span; - // Handle the case where the result is immediately dereferenced - // by not requiring ref and pulling the dereference into the - // suggestion. - if_chain! { - if needs_ref; - if let Some(parent) = get_parent_expr(cx, expr); - if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind; - then { - needs_ref = false; + // Handle the case where the result is immediately dereferenced, + // either directly be the user, or as a result of a method call or the like + // by not requiring an explicit reference + let needs_ref = if let Some(parent) = get_parent_expr(cx, expr) + && let hir::ExprKind::Unary(hir::UnOp::Deref, _) + | hir::ExprKind::MethodCall(..) + | hir::ExprKind::Field(..) + | hir::ExprKind::Index(..) = parent.kind + { + if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind { + // if the user explicitly dereferences the result, we can adjust + // the span to also include the deref part span = parent.span; } - } + false + } else { + true + }; let mut_str = if is_mut { "_mut" } else { "" }; let borrow_str = if !needs_ref { diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index ceee12784cbb7..121043104058f 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -20,9 +20,9 @@ pub(super) fn check<'tcx>( 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" + "`Vec`" } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) { - "VecDeque" + "`VecDeque`" } else { iter_nth_zero::check(cx, expr, nth_recv, nth_arg); return; // caller is not a type that we want to lint diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs index d1609eebfdca9..e1f950d5a4a5f 100644 --- a/clippy_lints/src/methods/iter_nth_zero.rs +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -1,8 +1,8 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_trait_method; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; +use clippy_utils::{is_lang_item_or_ctor, is_trait_method}; +use hir::{LangItem, OwnerNode}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -11,20 +11,21 @@ use rustc_span::sym; use super::ITER_NTH_ZERO; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - if_chain! { - if is_trait_method(cx, expr, sym::Iterator); - if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - ITER_NTH_ZERO, - expr.span, - "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", - "try calling `.next()` instead of `.nth(0)`", - format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)), - applicability, - ); - } + if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + && let def_id = item.owner_id.to_def_id() + && is_trait_method(cx, expr, sym::Iterator) + && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) + && !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext) + { + let mut app = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + ITER_NTH_ZERO, + expr.span, + "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", + "try calling `.next()` instead of `.nth(0)`", + format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut app)), + app, + ); } } diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs new file mode 100644 index 0000000000000..576a58499b154 --- /dev/null +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -0,0 +1,55 @@ +use clippy_utils::{ + diagnostics::span_lint_and_sugg, + is_from_proc_macro, + msrvs::{Msrv, ITERATOR_TRY_FOLD}, + source::snippet_opt, + ty::implements_trait, +}; +use rustc_errors::Applicability; +use rustc_hir::{ + def::{DefKind, Res}, + Expr, ExprKind, +}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::Span; + +use super::MANUAL_TRY_FOLD; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + init: &Expr<'_>, + acc: &Expr<'_>, + fold_span: Span, + msrv: &Msrv, +) { + if !in_external_macro(cx.sess(), fold_span) + && msrv.meets(ITERATOR_TRY_FOLD) + && let init_ty = cx.typeck_results().expr_ty(init) + && let Some(try_trait) = cx.tcx.lang_items().try_trait() + && implements_trait(cx, init_ty, try_trait, &[]) + && let ExprKind::Call(path, [first, rest @ ..]) = init.kind + && let ExprKind::Path(qpath) = path.kind + && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) + && let ExprKind::Closure(closure) = acc.kind + && !is_from_proc_macro(cx, expr) + && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) + { + let init_snip = rest + .is_empty() + .then_some(first.span) + .and_then(|span| snippet_opt(cx, span)) + .unwrap_or("...".to_owned()); + + span_lint_and_sugg( + cx, + MANUAL_TRY_FOLD, + fold_span, + "usage of `Iterator::fold` on a type that implements `Try`", + "use `try_fold` instead", + format!("try_fold({init_snip}, {args_snip} ...)", ), + Applicability::HasPlaceholders, + ); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 88cbefbb5d3d5..24dbe8c1d7518 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -14,6 +14,7 @@ mod clone_on_copy; mod clone_on_ref_ptr; mod cloned_instead_of_copied; mod collapsible_str_replace; +mod drain_collect; mod err_expect; mod expect_fun_call; mod expect_used; @@ -49,6 +50,7 @@ mod manual_next_back; mod manual_ok_or; mod manual_saturating_arithmetic; mod manual_str_repeat; +mod manual_try_fold; mod map_clone; mod map_collect_result_unit; mod map_err_ignore; @@ -93,6 +95,7 @@ mod unnecessary_fold; mod unnecessary_iter_cloned; mod unnecessary_join; mod unnecessary_lazy_eval; +mod unnecessary_literal_unwrap; mod unnecessary_sort_by; mod unnecessary_to_owned; mod unwrap_or_else_default; @@ -273,6 +276,32 @@ declare_clippy_lint! { "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed. + /// + /// ### Why is this bad? + /// It is better to write the value directly without the indirection. + /// + /// ### Examples + /// ```rust + /// let val1 = Some(1).unwrap(); + /// let val2 = Ok::<_, ()>(1).unwrap(); + /// let val3 = Err::<(), _>(1).unwrap_err(); + /// ``` + /// + /// Use instead: + /// ```rust + /// let val1 = 1; + /// let val2 = 1; + /// let val3 = 1; + /// ``` + #[clippy::version = "1.69.0"] + pub UNNECESSARY_LITERAL_UNWRAP, + complexity, + "using `unwrap()` related calls on `Result` and `Option` constructors" +} + declare_clippy_lint! { /// ### What it does /// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s. @@ -485,6 +514,7 @@ declare_clippy_lint! { /// # let result: Result = Ok(1); /// # fn some_function(foo: ()) -> usize { 1 } /// option.map(|a| a + 1).unwrap_or(0); + /// option.map(|a| a > 10).unwrap_or(false); /// result.map(|a| a + 1).unwrap_or_else(some_function); /// ``` /// @@ -494,6 +524,7 @@ declare_clippy_lint! { /// # let result: Result = Ok(1); /// # fn some_function(foo: ()) -> usize { 1 } /// option.map_or(0, |a| a + 1); + /// option.is_some_and(|a| a > 10); /// result.map_or_else(some_function, |a| a + 1); /// ``` #[clippy::version = "1.45.0"] @@ -3220,6 +3251,71 @@ declare_clippy_lint! { "manual reverse iteration of `DoubleEndedIterator`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`. + /// + /// > "Collection" in this context refers to any type with a `drain` method: + /// > `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String` + /// + /// ### Why is this bad? + /// Using `mem::take` is faster as it avoids the allocation. + /// When using `mem::take`, the old collection is replaced with an empty one and ownership of + /// the old collection is returned. + /// + /// ### Known issues + /// `mem::take(&mut vec)` is almost equivalent to `vec.drain(..).collect()`, except that + /// it also moves the **capacity**. The user might have explicitly written it this way + /// to keep the capacity on the original `Vec`. + /// + /// ### Example + /// ```rust + /// fn remove_all(v: &mut Vec) -> Vec { + /// v.drain(..).collect() + /// } + /// ``` + /// Use instead: + /// ```rust + /// use std::mem; + /// fn remove_all(v: &mut Vec) -> Vec { + /// mem::take(v) + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub DRAIN_COLLECT, + perf, + "calling `.drain(..).collect()` to move all elements into a new collection" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `Iterator::fold` with a type that implements `Try`. + /// + /// ### Why is this bad? + /// The code should use `try_fold` instead, which short-circuits on failure, thus opening the + /// door for additional optimizations not possible with `fold` as rustc can guarantee the + /// function is never called on `None`, `Err`, etc., alleviating otherwise necessary checks. It's + /// also slightly more idiomatic. + /// + /// ### Known issues + /// This lint doesn't take into account whether a function does something on the failure case, + /// i.e., whether short-circuiting will affect behavior. Refactoring to `try_fold` is not + /// desirable in those cases. + /// + /// ### Example + /// ```rust + /// vec![1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)); + /// ``` + /// Use instead: + /// ```rust + /// vec![1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)); + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_TRY_FOLD, + perf, + "checks for usage of `Iterator::fold` with a type that implements `Try`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3349,6 +3445,9 @@ impl_lint_pass!(Methods => [ SUSPICIOUS_COMMAND_ARG_SPACE, CLEAR_WITH_DRAIN, MANUAL_NEXT_BACK, + UNNECESSARY_LITERAL_UNWRAP, + DRAIN_COLLECT, + MANUAL_TRY_FOLD, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3578,6 +3677,9 @@ impl Methods { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } }, + Some(("drain", recv, args, ..)) => { + drain_collect::check(cx, args, expr, recv); + } _ => {}, } }, @@ -3606,12 +3708,18 @@ impl Methods { case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); } }, - ("expect", [_]) => match method_call(recv) { - Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), - Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), - _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), + ("expect", [_]) => { + match method_call(recv) { + Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), + Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), + _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), + } + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + }, + ("expect_err", [_]) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests); }, - ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), ("extend", [arg]) => { string_extend_chars::check(cx, expr, recv, arg); extend_with_drain::check(cx, expr, recv, arg); @@ -3632,7 +3740,10 @@ impl Methods { Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true), _ => {}, }, - ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span), + ("fold", [init, acc]) => { + manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv); + unnecessary_fold::check(cx, expr, init, acc, span); + }, ("for_each", [_]) => { if let Some(("inspect", _, [_], span2, _)) = method_call(recv) { inspect_for_each::check(cx, expr, span2); @@ -3816,28 +3927,41 @@ impl Methods { }, _ => {}, } + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, - ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests), - ("unwrap_or", [u_arg]) => match method_call(recv) { - Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => { - manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); - }, - Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); - }, - Some(("then_some", t_recv, [t_arg], _, _)) => { - obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); - }, - _ => {}, + ("unwrap_err", []) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests); }, - ("unwrap_or_else", [u_arg]) => match method_call(recv) { - Some(("map", recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, - _ => { - unwrap_or_else_default::check(cx, expr, recv, u_arg); - unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); - }, + ("unwrap_or", [u_arg]) => { + match method_call(recv) { + Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => { + manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); + }, + Some(("map", m_recv, [m_arg], span, _)) => { + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); + }, + Some(("then_some", t_recv, [t_arg], _, _)) => { + obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); + }, + _ => {}, + } + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + }, + ("unwrap_or_default", []) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + } + ("unwrap_or_else", [u_arg]) => { + match method_call(recv) { + Some(("map", recv, [map_arg], _, _)) + if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, + _ => { + unwrap_or_else_default::check(cx, expr, recv, u_arg); + unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); + }, + } + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, ("zip", [arg]) => { if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 0699997d0d2bd..ac209d014062e 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -322,7 +322,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection - if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind { + if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind { if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) { self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv)); self.visit_expr(recv); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4c6328481e438..f4f158c0439ed 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,19 +1,26 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; use clippy_utils::ty::is_type_diagnostic_item; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_path, Visitor}; +use rustc_hir::ExprKind; +use rustc_hir::Node; +use rustc_hir::PatKind; +use rustc_hir::QPath; use rustc_hir::{self, HirId, Path}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_span::source_map::Span; -use rustc_span::{sym, Symbol}; +use rustc_span::sym; use super::MAP_UNWRAP_OR; /// lint use of `map().unwrap_or()` for `Option`s +#[expect(clippy::too_many_arguments)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &rustc_hir::Expr<'_>, @@ -22,12 +29,27 @@ pub(super) fn check<'tcx>( unwrap_recv: &rustc_hir::Expr<'_>, unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, + msrv: &Msrv, ) { // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { - // Do not lint if the `map` argument uses identifiers in the `map` - // argument that are also used in the `unwrap_or` argument + // Replacing `.map().unwrap_or(
)` with `.map_or(, )` can sometimes lead to + // borrowck errors, see #10579 for one such instance. + // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); + // ``` + // This compiles, but changing it to `map_or` will produce a compile error: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map_or(x, |s| s.to_vec()) + // ^ moving `x` here + // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) + // ``` + // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) + // before the call to `unwrap_or`. let mut unwrap_visitor = UnwrapVisitor { cx, @@ -35,14 +57,18 @@ pub(super) fn check<'tcx>( }; unwrap_visitor.visit_expr(unwrap_arg); - let mut map_expr_visitor = MapExprVisitor { + let mut reference_visitor = ReferenceVisitor { cx, identifiers: unwrap_visitor.identifiers, - found_identifier: false, + found_reference: false, + unwrap_or_span: unwrap_arg.span, }; - map_expr_visitor.visit_expr(map_arg); - if map_expr_visitor.found_identifier { + let map = cx.tcx.hir(); + let body = map.body(map.body_owned_by(map.enclosing_body_owner(expr.hir_id))); + reference_visitor.visit_body(body); + + if reference_visitor.found_reference { return; } } @@ -51,16 +77,29 @@ pub(super) fn check<'tcx>( return; } + // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead + let suggest_is_some_and = msrv.meets(msrvs::OPTION_IS_SOME_AND) + && matches!(&unwrap_arg.kind, ExprKind::Lit(lit) + if matches!(lit.node, rustc_ast::LitKind::Bool(false))); + let mut applicability = Applicability::MachineApplicable; // get snippet for unwrap_or() let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { "None" } else { "" }; + let arg = if unwrap_snippet == "None" { + "None" + } else if suggest_is_some_and { + "false" + } else { + "" + }; let unwrap_snippet_none = unwrap_snippet == "None"; let suggest = if unwrap_snippet_none { "and_then()" + } else if suggest_is_some_and { + "is_some_and()" } else { "map_or(, )" }; @@ -75,12 +114,18 @@ pub(super) fn check<'tcx>( let mut suggestion = vec![ ( map_span, - String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }), + String::from(if unwrap_snippet_none { + "and_then" + } else if suggest_is_some_and { + "is_some_and" + } else { + "map_or" + }), ), (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), ]; - if !unwrap_snippet_none { + if !unwrap_snippet_none && !suggest_is_some_and { suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); } @@ -91,14 +136,19 @@ pub(super) fn check<'tcx>( struct UnwrapVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, + identifiers: FxHashSet, } impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { type NestedFilter = nested_filter::All; - fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { - self.identifiers.insert(ident(path)); + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); + } walk_path(self, path); } @@ -107,32 +157,35 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { } } -struct MapExprVisitor<'a, 'tcx> { +struct ReferenceVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, - found_identifier: bool, + identifiers: FxHashSet, + found_reference: bool, + unwrap_or_span: Span, } -impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> { type NestedFilter = nested_filter::All; - - fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { - if self.identifiers.contains(&ident(path)) { - self.found_identifier = true; - return; + fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) { + // If we haven't found a reference yet, check if this references + // one of the locals that was moved in the `unwrap_or` argument. + // We are only interested in exprs that appear before the `unwrap_or` call. + if !self.found_reference { + if expr.span < self.unwrap_or_span + && let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + self.found_reference = true; + } + rustc_hir::intravisit::walk_expr(self, expr); } - walk_path(self, path); } fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } } - -fn ident(path: &Path<'_>) -> Symbol { - path.segments - .last() - .expect("segments should be composed of at least 1 element") - .ident - .name -} diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 5ea12c441840d..88a3c2620a406 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -289,7 +289,7 @@ fn parse_iter_usage<'tcx>( ) -> Option { let (kind, span) = match iter.next() { Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => { - let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind else { + let ExprKind::MethodCall(name, _, args, _) = e.kind else { return None; }; let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?; diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index 5a3d12fd790ea..8ec15a1c1b765 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -7,71 +7,120 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; use rustc_lint::LateContext; +use rustc_middle::ty; use rustc_span::{source_map::Span, sym}; use super::UNNECESSARY_FOLD; -pub(super) fn check( +/// Do we need to suggest turbofish when suggesting a replacement method? +/// Changing `fold` to `sum` needs it sometimes when the return type can't be +/// inferred. This checks for some common cases where it can be safely omitted +fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let parent = cx.tcx.hir().get_parent(expr.hir_id); + + // some common cases where turbofish isn't needed: + // - assigned to a local variable with a type annotation + if let hir::Node::Local(local) = parent + && local.ty.is_some() + { + return false; + } + + // - part of a function call argument, can be inferred from the function signature (provided that + // the parameter is not a generic type parameter) + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(recv, args) = parent_expr.kind + && let hir::ExprKind::Path(ref qpath) = recv.kind + && let Some(fn_def_id) = cx.qpath_res(qpath, recv.hir_id).opt_def_id() + && let fn_sig = cx.tcx.fn_sig(fn_def_id).skip_binder().skip_binder() + && let Some(arg_pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(ty) = fn_sig.inputs().get(arg_pos) + && !matches!(ty.kind(), ty::Param(_)) + { + return false; + } + + // if it's neither of those, stay on the safe side and suggest turbofish, + // even if it could work! + true +} + +#[derive(Copy, Clone)] +struct Replacement { + method_name: &'static str, + has_args: bool, + has_generic_return: bool, +} + +fn check_fold_with_op( cx: &LateContext<'_>, expr: &hir::Expr<'_>, - init: &hir::Expr<'_>, acc: &hir::Expr<'_>, fold_span: Span, + op: hir::BinOpKind, + replacement: Replacement, ) { - fn check_fold_with_op( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - acc: &hir::Expr<'_>, - fold_span: Span, - op: hir::BinOpKind, - replacement_method_name: &str, - replacement_has_args: bool, - ) { - if_chain! { - // Extract the body of the closure passed to fold - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; - let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(closure_body.value); - - // Check if the closure body is of the form `acc some_expr(x)` - if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; - if bin_op.node == op; - - // Extract the names of the two arguments to the closure - if let [param_a, param_b] = closure_body.params; - if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; - if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; - - if path_to_local_id(left_expr, first_arg_id); - if replacement_has_args || path_to_local_id(right_expr, second_arg_id); - - then { - let mut applicability = Applicability::MachineApplicable; - let sugg = if replacement_has_args { - format!( - "{replacement_method_name}(|{second_arg_ident}| {r})", - r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), - ) - } else { - format!( - "{replacement_method_name}()", - ) - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_FOLD, - fold_span.with_hi(expr.span.hi()), - // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) - "this `.fold` can be written more succinctly using another method", - "try", - sugg, - applicability, - ); - } + if_chain! { + // Extract the body of the closure passed to fold + if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; + let closure_body = cx.tcx.hir().body(body); + let closure_expr = peel_blocks(closure_body.value); + + // Check if the closure body is of the form `acc some_expr(x)` + if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; + if bin_op.node == op; + + // Extract the names of the two arguments to the closure + if let [param_a, param_b] = closure_body.params; + if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; + if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; + + if path_to_local_id(left_expr, first_arg_id); + if replacement.has_args || path_to_local_id(right_expr, second_arg_id); + + then { + let mut applicability = Applicability::MachineApplicable; + + let turbofish = if replacement.has_generic_return { + format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) + } else { + String::new() + }; + + let sugg = if replacement.has_args { + format!( + "{method}{turbofish}(|{second_arg_ident}| {r})", + method = replacement.method_name, + r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), + ) + } else { + format!( + "{method}{turbofish}()", + method = replacement.method_name, + ) + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_FOLD, + fold_span.with_hi(expr.span.hi()), + // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) + "this `.fold` can be written more succinctly using another method", + "try", + sugg, + applicability, + ); } } +} +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + init: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, +) { // Check that this is a call to Iterator::fold rather than just some function called fold if !is_trait_method(cx, expr, sym::Iterator) { return; @@ -80,11 +129,59 @@ pub(super) fn check( // Check if the first argument to .fold is a suitable literal if let hir::ExprKind::Lit(lit) = init.kind { match lit.node { - ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true), - ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true), - ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false), + ast::LitKind::Bool(false) => { + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Or, + Replacement { + has_args: true, + has_generic_return: false, + method_name: "any", + }, + ); + }, + ast::LitKind::Bool(true) => { + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::And, + Replacement { + has_args: true, + has_generic_return: false, + method_name: "all", + }, + ); + }, + ast::LitKind::Int(0, _) => check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Add, + Replacement { + has_args: false, + has_generic_return: needs_turbofish(cx, expr), + method_name: "sum", + }, + ), ast::LitKind::Int(1, _) => { - check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false); + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Mul, + Replacement { + has_args: false, + has_generic_return: needs_turbofish(cx, expr), + method_name: "product", + }, + ); }, _ => (), } diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs new file mode 100644 index 0000000000000..7877f6a386cb3 --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -0,0 +1,95 @@ +use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, last_path_segment, path_res, MaybePath}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::UNNECESSARY_LITERAL_UNWRAP; + +fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a>> { + let args = args?; + + if args.len() <= index { + return None; + } + + match args[index] { + hir::GenericArg::Type(ty) => match ty.kind { + hir::TyKind::Infer => None, + _ => Some(ty), + }, + _ => None, + } +} + +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + recv: &hir::Expr<'_>, + method: &str, + args: &[hir::Expr<'_>], +) { + let init = clippy_utils::expr_or_init(cx, recv); + + let (constructor, call_args, ty) = if let hir::ExprKind::Call(call, call_args) = init.kind { + let Some(qpath) = call.qpath_opt() else { return }; + + let args = last_path_segment(qpath).args.map(|args| args.args); + let res = cx.qpath_res(qpath, call.hir_id()); + + if is_res_lang_ctor(cx, res, hir::LangItem::OptionSome) { + ("Some", call_args, get_ty_from_args(args, 0)) + } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultOk) { + ("Ok", call_args, get_ty_from_args(args, 0)) + } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultErr) { + ("Err", call_args, get_ty_from_args(args, 1)) + } else { + return; + } + } else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) { + let call_args: &[hir::Expr<'_>] = &[]; + ("None", call_args, None) + } else { + return; + }; + + 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| { + let suggestions = match (constructor, method, ty) { + ("None", "unwrap", _) => Some(vec![(expr.span, "panic!()".to_string())]), + ("None", "expect", _) => Some(vec![ + (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), + (expr.span.with_lo(args[0].span.hi()), ")".to_string()), + ]), + (_, _, Some(_)) => None, + ("Ok", "unwrap_err", None) | ("Err", "unwrap", None) => Some(vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{:?}\", ".to_string(), + ), + (expr.span.with_lo(call_args[0].span.hi()), ")".to_string()), + ]), + ("Ok", "expect_err", None) | ("Err", "expect", None) => Some(vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{1}: {:?}\", ".to_string(), + ), + (call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()), + ]), + (_, _, None) => Some(vec![ + (recv.span.with_hi(call_args[0].span.lo()), String::new()), + (expr.span.with_lo(call_args[0].span.hi()), String::new()), + ]), + }; + + match (init.span == recv.span, suggestions) { + (true, Some(suggestions)) => { + diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable); + }, + _ => { + diag.span_help(init.span, suggestion_message); + }, + } + }); +} diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 80eb00a1b42d9..16ef24bd4e345 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -144,6 +144,11 @@ fn check_addr_of_expr( if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); if implements_trait(cx, receiver_ty, deref_trait_id, &[]); if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty); + // Make sure that it's actually calling the right `.to_string()`, (#10033) + // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow) + // but that's ok for Cow::into_owned specifically) + if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty + || is_cow_into_owned(cx, method_name, method_def_id); then { if n_receiver_refs > 0 { span_lint_and_sugg( diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs new file mode 100644 index 0000000000000..d49bb0ca6e291 --- /dev/null +++ b/clippy_lints/src/min_ident_chars.rs @@ -0,0 +1,153 @@ +use clippy_utils::{diagnostics::span_lint, is_from_proc_macro}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::{ + def::{DefKind, Res}, + intravisit::{walk_item, Visitor}, + GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, +}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; +use std::borrow::Cow; + +declare_clippy_lint! { + /// ### What it does + /// Checks for idents which comprise of a single letter. + /// + /// Note: This lint can be very noisy when enabled; it may be desirable to only enable it + /// temporarily. + /// + /// ### Why is this bad? + /// In many cases it's not, but at times it can severely hinder readability. Some codebases may + /// wish to disallow this to improve readability. + /// + /// ### Example + /// ```rust,ignore + /// for m in movies { + /// let title = m.t; + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// for movie in movies { + /// let title = movie.title; + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub MIN_IDENT_CHARS, + restriction, + "disallows idents that are too short" +} +impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]); + +#[derive(Clone)] +pub struct MinIdentChars { + pub allowed_idents_below_min_chars: FxHashSet, + pub min_ident_chars_threshold: u64, +} + +impl MinIdentChars { + #[expect(clippy::cast_possible_truncation)] + fn is_ident_too_short(&self, cx: &LateContext<'_>, str: &str, span: Span) -> bool { + !in_external_macro(cx.sess(), span) + && str.len() <= self.min_ident_chars_threshold as usize + && !str.starts_with('_') + && !str.is_empty() + && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() + } +} + +impl LateLintPass<'_> for MinIdentChars { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if self.min_ident_chars_threshold == 0 { + return; + } + + walk_item(&mut IdentVisitor { conf: self, cx }, item); + } + + // This is necessary as `Node::Pat`s are not visited in `visit_id`. :/ + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { + if let PatKind::Binding(_, _, ident, ..) = pat.kind + && let str = ident.as_str() + && self.is_ident_too_short(cx, str, ident.span) + { + emit_min_ident_chars(self, cx, str, ident.span); + } + } +} + +struct IdentVisitor<'cx, 'tcx> { + conf: &'cx MinIdentChars, + cx: &'cx LateContext<'tcx>, +} + +impl Visitor<'_> for IdentVisitor<'_, '_> { + fn visit_id(&mut self, hir_id: HirId) { + let Self { conf, cx } = *self; + // FIXME(#112534) Reimplementation of `find`, as it uses indexing, which can (and will in + // async functions, or really anything async) panic. This should probably be fixed on the + // rustc side, this is just a temporary workaround. + let node = if hir_id.local_id == ItemLocalId::from_u32(0) { + // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't + // reimplement it even if we wanted to + cx.tcx.hir().find(hir_id) + } else { + let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else { + return; + }; + owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) + }; + let Some(node) = node else { + return; + }; + let Some(ident) = node.ident() else { + return; + }; + + let str = ident.as_str(); + if conf.is_ident_too_short(cx, str, ident.span) { + if let Node::Item(item) = node && let ItemKind::Use(..) = item.kind { + return; + } + // `struct Awa(T)` + // ^ + if let Node::PathSegment(path) = node { + if let Res::Def(def_kind, ..) = path.res && let DefKind::TyParam = def_kind { + return; + } + if matches!(path.res, Res::PrimTy(..)) || path.res.opt_def_id().is_some_and(|def_id| !def_id.is_local()) + { + return; + } + } + // `struct Awa(T)` + // ^ + if let Node::GenericParam(generic_param) = node + && let GenericParamKind::Type { .. } = generic_param.kind + { + return; + } + + if is_from_proc_macro(cx, &ident) { + return; + } + + emit_min_ident_chars(conf, cx, str, ident.span); + } + } +} + +fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str, span: Span) { + let help = if conf.min_ident_chars_threshold == 1 { + Cow::Borrowed("this ident consists of a single char") + } else { + Cow::Owned(format!( + "this ident is too short ({} <= {})", + ident.len(), + conf.min_ident_chars_threshold, + )) + }; + span_lint(cx, MIN_IDENT_CHARS, span, &help); +} diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 4f967755bfa19..e0904f17b8de0 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -66,7 +66,7 @@ enum MinMax { Max, } -fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> { match expr.kind { ExprKind::Call(path, args) => { if let ExprKind::Path(ref qpath) = path.kind { @@ -99,12 +99,12 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons } } -fn fetch_const<'a>( - cx: &LateContext<'_>, +fn fetch_const<'a, 'tcx>( + cx: &LateContext<'tcx>, receiver: Option<&'a Expr<'a>>, args: &'a [Expr<'a>], m: MinMax, -) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> { let mut args = receiver.into_iter().chain(args); let first_arg = args.next()?; let second_arg = args.next()?; diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index ddb8b9173a537..9151cc6332004 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -13,7 +13,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_sni return; } let mut seen = (false, false); - for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() { + for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] { match ch { b'a'..=b'f' => seen.0 = true, b'A'..=b'F' => seen.1 = true, diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 78be6b9e23fa2..b226b87812377 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -2,6 +2,7 @@ mod builtin_type_shadow; mod double_neg; mod literal_suffix; mod mixed_case_hex_literals; +mod redundant_at_rest_pattern; mod redundant_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; @@ -318,6 +319,36 @@ declare_clippy_lint! { "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `[all @ ..]` patterns. + /// + /// ### Why is this bad? + /// In all cases, `all` works fine and can often make code simpler, as you possibly won't need + /// to convert from say a `Vec` to a slice by dereferencing. + /// + /// ### Example + /// ```rust,ignore + /// if let [all @ ..] = &*v { + /// // NOTE: Type is a slice here + /// println!("all elements: {all:#?}"); + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// if let all = v { + /// // NOTE: Type is a `Vec` here + /// println!("all elements: {all:#?}"); + /// } + /// // or + /// println!("all elements: {v:#?}"); + /// ``` + #[clippy::version = "1.72.0"] + pub REDUNDANT_AT_REST_PATTERN, + complexity, + "checks for `[all @ ..]` where `all` would suffice" +} + declare_lint_pass!(MiscEarlyLints => [ UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, @@ -329,6 +360,7 @@ declare_lint_pass!(MiscEarlyLints => [ BUILTIN_TYPE_SHADOW, REDUNDANT_PATTERN, UNNEEDED_WILDCARD_PATTERN, + REDUNDANT_AT_REST_PATTERN, ]); impl EarlyLintPass for MiscEarlyLints { @@ -339,8 +371,13 @@ impl EarlyLintPass for MiscEarlyLints { } fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { + if in_external_macro(cx.sess(), pat.span) { + return; + } + unneeded_field_pattern::check(cx, pat); redundant_pattern::check(cx, pat); + redundant_at_rest_pattern::check(cx, pat); unneeded_wildcard_pattern::check(cx, pat); } diff --git a/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs b/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs new file mode 100644 index 0000000000000..0c81ee5eced85 --- /dev/null +++ b/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs @@ -0,0 +1,26 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::{Pat, PatKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, LintContext}; +use rustc_middle::lint::in_external_macro; + +use super::REDUNDANT_AT_REST_PATTERN; + +pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { + if !in_external_macro(cx.sess(), pat.span) + && let PatKind::Slice(slice) = &pat.kind + && let [one] = &**slice + && let PatKind::Ident(annotation, ident, Some(rest)) = &one.kind + && let PatKind::Rest = rest.kind + { + span_lint_and_sugg( + cx, + REDUNDANT_AT_REST_PATTERN, + pat.span, + "using a rest pattern to bind an entire slice to a local", + "this is better represented with just the binding", + format!("{}{ident}", annotation.prefix_str()), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs index 9de4b56b77b56..28e041dee0dbb 100644 --- a/clippy_lints/src/mismatching_type_param_order.rs +++ b/clippy_lints/src/mismatching_type_param_order.rs @@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch { then { // get the name and span of the generic parameters in the Impl let mut impl_params = Vec::new(); - for p in generic_args.args.iter() { + for p in generic_args.args { match p { GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) => impl_params.push((path.segments[0].ident.to_string(), path.span)), diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index b6f0de7e504f0..1138d1163a4a9 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -207,6 +207,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { 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 && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind + // don't trigger if self is a generic parameter, e.g. `impl Debug for T` + // this can only happen in core itself, where the trait is defined, + // but it caused ICEs in the past: + // https://github.com/rust-lang/rust-clippy/issues/10887 + && !matches!(self_path.res, Res::Def(DefKind::TyParam, _)) && cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug]) // don't trigger if this impl was derived && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index f0be7771bb1a6..57ec3a1f1e63c 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { - ExprKind::Closure { .. } => {}, + ExprKind::Closure(..) | ExprKind::If(..) | ExprKind::Loop(..) => {}, ExprKind::Match(e, arms, _) => { self.visit_expr(e); for arm in arms { @@ -128,6 +128,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { _ => walk_expr(self, e), } } + fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) { span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges"); } @@ -136,6 +137,15 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { + // fix #10776 + ExprKind::Block(block, ..) => match (block.stmts, block.expr) { + ([], Some(e)) => self.visit_expr(e), + ([stmt], None) => match stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), + _ => {}, + }, + _ => {}, + }, ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e), ExprKind::Call(func, _) => { let typ = self.cx.typeck_results().expr_ty(func); diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 349fcd2274d3e..439cae812b7ff 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -2,6 +2,7 @@ use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{FileName, SourceFile, Span, SyntaxContext}; use std::ffi::OsStr; use std::path::{Component, Path}; @@ -90,7 +91,14 @@ impl EarlyLintPass for ModStyle { // `{ foo => path/to/foo.rs, .. } let mut file_map = FxHashMap::default(); for file in files.iter() { - if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() { + if let FileName::Real(name) = &file.name + && let Some(lp) = name.local_path() + && file.cnum == LOCAL_CRATE + { + // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) + // Only check files in the current crate. + // Fix false positive that crate dependency in workspace sub directory + // is checked unintentionally. let path = if lp.is_relative() { lp } else if let Ok(relative) = lp.strip_prefix(trim_to_src) { diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs new file mode 100644 index 0000000000000..ad5c3e1dc8229 --- /dev/null +++ b/clippy_lints/src/needless_if.rs @@ -0,0 +1,75 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, higher::If, is_from_proc_macro, source::snippet_opt}; +use rustc_errors::Applicability; +use rustc_hir::{ExprKind, Stmt, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for empty `if` branches with no else branch. + /// + /// ### Why is this bad? + /// It can be entirely omitted, and often the condition too. + /// + /// ### Known issues + /// This will usually only suggest to remove the `if` statement, not the condition. Other lints + /// such as `no_effect` will take care of removing the condition if it's unnecessary. + /// + /// ### Example + /// ```rust,ignore + /// if really_expensive_condition(&i) {} + /// if really_expensive_condition_with_side_effects(&mut i) {} + /// ``` + /// Use instead: + /// ```rust,ignore + /// // + /// really_expensive_condition_with_side_effects(&mut i); + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_IF, + complexity, + "checks for empty if branches" +} +declare_lint_pass!(NeedlessIf => [NEEDLESS_IF]); + +impl LateLintPass<'_> for NeedlessIf { + fn check_stmt<'tcx>(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'tcx>) { + if let StmtKind::Expr(expr) = stmt.kind + && let Some(If {cond, then, r#else: None }) = If::hir(expr) + && let ExprKind::Block(block, ..) = then.kind + && block.stmts.is_empty() + && block.expr.is_none() + && !in_external_macro(cx.sess(), expr.span) + && !is_from_proc_macro(cx, expr) + && let Some(then_snippet) = snippet_opt(cx, then.span) + // Ignore + // - empty macro expansions + // - empty reptitions in macro expansions + // - comments + // - #[cfg]'d out code + && then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace()) + && let Some(cond_snippet) = snippet_opt(cx, cond.span) + { + span_lint_and_sugg( + cx, + NEEDLESS_IF, + stmt.span, + "this `if` branch is empty", + "you can remove it", + if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() { + // `{ foo }` or `{ foo } && bar` placed into a statement position would be + // interpreted as a block statement, force it to be an expression + if cond_snippet.starts_with('{') { + format!("({cond_snippet});") + } else { + format!("{cond_snippet};") + } + } else { + String::new() + }, + Applicability::MachineApplicable, + ); + } + } +} diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c0970048cdfe2..ece10474715f2 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -7,13 +7,12 @@ use clippy_utils::ty::{ use clippy_utils::{get_trait_def_id, is_self, paths}; use if_chain::if_chain; use rustc_ast::ast::Attribute; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind, }; -use rustc_hir::{HirIdMap, HirIdSet, LangItem}; +use rustc_hir::{HirIdSet, LangItem}; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; @@ -126,9 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. match pred.kind().no_bound_vars() { - Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => { - Some(pred) - }, + Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => Some(pred), _ => None, } }) @@ -136,11 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { // Collect moved variables and spans which will need dereferencings from the // function body. - let MovedVariablesCtxt { - moved_vars, - spans_need_deref, - .. - } = { + let MovedVariablesCtxt { moved_vars } = { let mut ctx = MovedVariablesCtxt::default(); let infcx = cx.tcx.infer_ctxt().build(); euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body); @@ -211,7 +204,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - let deref_span = spans_need_deref.get(&canonical_id); if_chain! { if is_type_diagnostic_item(cx, ty, sym::Vec); if let Some(clone_spans) = @@ -247,7 +239,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } // cannot be destructured, no need for `*` suggestion - assert!(deref_span.is_none()); return; } } @@ -275,23 +266,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ); } - assert!(deref_span.is_none()); return; } } - let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; - - // Suggests adding `*` to dereference the added reference. - if let Some(deref_span) = deref_span { - spans.extend( - deref_span - .iter() - .copied() - .map(|span| (span, format!("*{}", snippet(cx, span, "")))), - ); - spans.sort_by_key(|&(span, _)| span); - } + let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; + multispan_sugg(diag, "consider taking a reference instead", spans); }; @@ -320,9 +300,6 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool { #[derive(Default)] struct MovedVariablesCtxt { moved_vars: HirIdSet, - /// Spans which need to be prefixed with `*` for dereferencing the - /// suggested additional reference. - spans_need_deref: HirIdMap>, } impl MovedVariablesCtxt { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index e3712190e6722..a4c7da7e48db3 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,11 +1,16 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::is_lint_allowed; use clippy_utils::peel_blocks; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; +use clippy_utils::{get_parent_node, is_lint_allowed}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource}; +use rustc_hir::{ + is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, FnRetTy, ItemKind, Node, PatKind, Stmt, StmtKind, + UnsafeSource, +}; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -86,7 +91,43 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { if let StmtKind::Semi(expr) = stmt.kind { if has_no_effect(cx, expr) { - span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect"); + span_lint_hir_and_then( + cx, + NO_EFFECT, + expr.hir_id, + stmt.span, + "statement with no effect", + |diag| { + for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { + if let Node::Item(item) = parent.1 + && let ItemKind::Fn(sig, ..) = item.kind + && let FnRetTy::Return(ret_ty) = sig.decl.output + && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) + && let [.., final_stmt] = block.stmts + && final_stmt.hir_id == stmt.hir_id + { + let expr_ty = cx.typeck_results().expr_ty(expr); + let mut ret_ty = hir_ty_to_ty(cx.tcx, ret_ty); + + // Remove `impl Future` to get `T` + if cx.tcx.ty_is_opaque_future(ret_ty) && + let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty) + { + ret_ty = true_ret_ty; + } + + if ret_ty == expr_ty { + diag.span_suggestion( + stmt.span.shrink_to_lo(), + "did you mean to return it?", + "return ", + Applicability::MaybeIncorrect, + ); + } + } + } + }, + ); return true; } } else if let StmtKind::Local(local) = stmt.kind { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index ac49ccdb5011b..75f1e95276a69 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -182,15 +182,15 @@ fn is_value_unfrozen_raw<'tcx>( // have a value that is a frozen variant with a generic param (an example is // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::GENERIC_VARIANT`). // However, it prevents a number of false negatives that is, I think, important: - // 1. assoc consts in trait defs referring to consts of themselves - // (an example is `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`). - // 2. a path expr referring to assoc consts whose type is doesn't have - // any frozen variants in trait defs (i.e. without substitute for `Self`). - // (e.g. borrowing `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`) - // 3. similar to the false positive above; - // but the value is an unfrozen variant, or the type has no enums. (An example is - // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT` - // and `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`). + // 1. assoc consts in trait defs referring to consts of themselves (an example is + // `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`). + // 2. a path expr referring to assoc consts whose type is doesn't have any frozen variants in trait + // defs (i.e. without substitute for `Self`). (e.g. borrowing + // `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`) + // 3. similar to the false positive above; but the value is an unfrozen variant, or the type has no + // enums. (An example is + // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT` and + // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`). // One might be able to prevent these FNs correctly, and replace this with `false`; // e.g. implementing `has_frozen_variant` described above, and not running this function // when the type doesn't have any frozen variants would be the 'correct' way for the 2nd diff --git a/clippy_lints/src/operators/eq_op.rs b/clippy_lints/src/operators/eq_op.rs index 67913f7392c04..78965b7d6f74b 100644 --- a/clippy_lints/src/operators/eq_op.rs +++ b/clippy_lints/src/operators/eq_op.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace}; use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function}; use rustc_hir::{BinOpKind, Expr}; @@ -35,11 +35,16 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if is_useless_with_eq_exprs(op.into()) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) { - span_lint( + span_lint_and_then( cx, EQ_OP, e.span, &format!("equal expressions as operands to `{}`", op.as_str()), + |diag| { + if let BinOpKind::Ne = op && cx.typeck_results().expr_ty(left).is_floating_point() { + diag.note("if you intended to check if the operand is NaN, use `.is_nan()` instead"); + } + }, ); } } diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs index 15dff126be76e..f3e0c58a78711 100644 --- a/clippy_lints/src/operators/float_cmp.rs +++ b/clippy_lints/src/operators/float_cmp.rs @@ -85,7 +85,7 @@ fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static } } -fn is_allowed(val: &Constant) -> bool { +fn is_allowed(val: &Constant<'_>) -> bool { match val { &Constant::F32(f) => f == 0.0 || f.is_infinite(), &Constant::F64(f) => f == 0.0 || f.is_infinite(), diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index aa6d40042688d..abdccc47f5475 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -140,6 +140,9 @@ fn try_get_option_occurrence<'tcx>( let (as_ref, as_mut) = match &expr.kind { ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), + _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => { + (mutb == Mutability::Not, mutb == Mutability::Mut) + } _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT), }; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index b8911f109076a..866a04466c909 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -5,6 +5,7 @@ use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths}; +use hir::LifetimeName; use if_chain::if_chain; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::def_id::DefId; @@ -15,6 +16,7 @@ use rustc_hir::{ ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, }; +use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_lint::{LateContext, LateLintPass}; @@ -166,6 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { cx, cx.tcx.fn_sig(item.owner_id).subst_identity().skip_binder().inputs(), sig.decl.inputs, + &sig.decl.output, &[], ) .filter(|arg| arg.mutability() == Mutability::Not) @@ -218,7 +221,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { check_mut_from_ref(cx, sig, Some(body)); let decl = sig.decl; let sig = cx.tcx.fn_sig(item_id).subst_identity().skip_binder(); - let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, body.params) + let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, &decl.output, body.params) .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not) .collect(); let results = check_ptr_arg_usage(cx, body, &lint_args); @@ -407,29 +410,27 @@ impl<'tcx> DerefTy<'tcx> { } } +#[expect(clippy::too_many_lines)] fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, tys: &'tcx [Ty<'tcx>], hir_tys: &'tcx [hir::Ty<'tcx>], + ret_ty: &'tcx FnRetTy<'tcx>, params: &'tcx [Param<'tcx>], ) -> impl Iterator> + 'cx { tys.iter() .zip(hir_tys.iter()) .enumerate() - .filter_map(|(i, (ty, hir_ty))| { - if_chain! { - if let ty::Ref(_, ty, mutability) = *ty.kind(); - if let ty::Adt(adt, substs) = *ty.kind(); - - if let TyKind::Ref(lt, ref ty) = hir_ty.kind; - if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind; - + .filter_map(move |(i, (ty, hir_ty))| { + if let ty::Ref(_, ty, mutability) = *ty.kind() + && let ty::Adt(adt, substs) = *ty.kind() + && let TyKind::Ref(lt, ref ty) = hir_ty.kind + && let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind // Check that the name as typed matches the actual name of the type. // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec` - if let [.., name] = path.segments; - if cx.tcx.item_name(adt.did()) == name.ident.name; - - then { + && let [.., name] = path.segments + && cx.tcx.item_name(adt.did()) == name.ident.name + { let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id); let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { Some(sym::Vec) => ( @@ -454,30 +455,65 @@ fn check_fn_args<'cx, 'tcx: 'cx>( DerefTy::Path, ), Some(sym::Cow) if mutability == Mutability::Not => { - let ty_name = name.args + if let Some((lifetime, ty)) = name.args .and_then(|args| { - args.args.iter().find_map(|a| match a { - GenericArg::Type(x) => Some(x), - _ => None, - }) + if let [GenericArg::Lifetime(lifetime), ty] = args.args { + return Some((lifetime, ty)); + } + None }) - .and_then(|arg| snippet_opt(cx, arg.span)) - .unwrap_or_else(|| substs.type_at(1).to_string()); - span_lint_hir_and_then( - cx, - PTR_ARG, - emission_id, - hir_ty.span, - "using a reference to `Cow` is not recommended", - |diag| { - diag.span_suggestion( - hir_ty.span, - "change this to", - format!("&{}{ty_name}", mutability.prefix_str()), - Applicability::Unspecified, - ); + { + if !lifetime.is_anonymous() + && let FnRetTy::Return(ret_ty) = ret_ty + && let ret_ty = hir_ty_to_ty(cx.tcx, ret_ty) + && ret_ty + .walk() + .filter_map(|arg| { + arg.as_region().and_then(|lifetime| { + match lifetime.kind() { + ty::ReEarlyBound(r) => Some(r.def_id), + ty::ReLateBound(_, r) => r.kind.get_id(), + ty::ReFree(r) => r.bound_region.get_id(), + ty::ReStatic + | ty::ReVar(_) + | ty::RePlaceholder(_) + | ty::ReErased + | ty::ReError(_) => None, + } + }) + }) + .any(|def_id| { + matches!( + lifetime.res, + LifetimeName::Param(param_def_id) if def_id + .as_local() + .is_some_and(|def_id| def_id == param_def_id), + ) + }) + { + // `&Cow<'a, T>` when the return type uses 'a is okay + return None; } - ); + + let ty_name = + snippet_opt(cx, ty.span()).unwrap_or_else(|| substs.type_at(1).to_string()); + + span_lint_hir_and_then( + cx, + PTR_ARG, + emission_id, + hir_ty.span, + "using a reference to `Cow` is not recommended", + |diag| { + diag.span_suggestion( + hir_ty.span, + "change this to", + format!("&{}{ty_name}", mutability.prefix_str()), + Applicability::Unspecified, + ); + } + ); + } return None; }, _ => return None, @@ -495,7 +531,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }, deref_ty, }); - } } None }) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 5269bbd1f1acc..e3d940ad2a44c 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,19 +1,20 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, }; +use clippy_utils::{higher, is_path_lang_item}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_tool_lint; +use rustc_session::impl_lint_pass; use rustc_span::{sym, symbol::Symbol}; declare_clippy_lint! { @@ -41,7 +42,16 @@ declare_clippy_lint! { "checks for expressions that could be replaced by the question mark operator" } -declare_lint_pass!(QuestionMark => [QUESTION_MARK]); +#[derive(Default)] +pub struct QuestionMark { + /// Keeps track of how many try blocks we are in at any point during linting. + /// This allows us to answer the question "are we inside of a try block" + /// very quickly, without having to walk up the parent chain, by simply checking + /// if it is greater than zero. + /// As for why we need this in the first place: + try_block_depth_stack: Vec, +} +impl_lint_pass!(QuestionMark => [QUESTION_MARK]); enum IfBlockType<'hir> { /// An `if x.is_xxx() { a } else { b } ` expression. @@ -68,98 +78,6 @@ enum IfBlockType<'hir> { ), } -/// Checks if the given expression on the given context matches the following structure: -/// -/// ```ignore -/// if option.is_none() { -/// return None; -/// } -/// ``` -/// -/// ```ignore -/// if result.is_err() { -/// return result; -/// } -/// ``` -/// -/// If it matches, it will suggest to use the question mark operator instead -fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); - if !is_else_clause(cx.tcx, expr); - if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; - let caller_ty = cx.typeck_results().expr_ty(caller); - let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); - if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && - !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); - let sugg = if let Some(else_inner) = r#else { - if eq_expr_value(cx, caller, peel_blocks(else_inner)) { - format!("Some({receiver_str}?)") - } else { - return; - } - } else { - format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) - }; - - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } - } -} - -fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); - if !is_else_clause(cx.tcx, expr); - if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind; - if ddpos.as_opt_usize().is_none(); - if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; - let caller_ty = cx.typeck_results().expr_ty(let_expr); - let if_block = IfBlockType::IfLet( - cx.qpath_res(path1, let_pat.hir_id), - caller_ty, - ident.name, - let_expr, - if_then, - if_else - ); - if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) - || is_early_return(sym::Result, cx, &if_block); - if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none(); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); - let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, - if requires_semi { ";" } else { "" } - ); - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } - } -} - fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_>) -> bool { match *if_block { IfBlockType::IfIs(caller, caller_ty, call_sym, if_then, _) => { @@ -230,11 +148,147 @@ fn expr_return_none_or_err( } } +impl QuestionMark { + fn inside_try_block(&self) -> bool { + self.try_block_depth_stack.last() > Some(&0) + } + + /// Checks if the given expression on the given context matches the following structure: + /// + /// ```ignore + /// if option.is_none() { + /// return None; + /// } + /// ``` + /// + /// ```ignore + /// if result.is_err() { + /// return result; + /// } + /// ``` + /// + /// If it matches, it will suggest to use the question mark operator instead + fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if_chain! { + if !self.inside_try_block(); + if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); + if !is_else_clause(cx.tcx, expr); + if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; + let caller_ty = cx.typeck_results().expr_ty(caller); + let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); + if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); + then { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && + !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); + let sugg = if let Some(else_inner) = r#else { + if eq_expr_value(cx, caller, peel_blocks(else_inner)) { + format!("Some({receiver_str}?)") + } else { + return; + } + } else { + format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) + }; + + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } + } + } + + fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if_chain! { + if !self.inside_try_block(); + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); + if !is_else_clause(cx.tcx, expr); + if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind; + if ddpos.as_opt_usize().is_none(); + if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; + let caller_ty = cx.typeck_results().expr_ty(let_expr); + let if_block = IfBlockType::IfLet( + cx.qpath_res(path1, let_pat.hir_id), + caller_ty, + ident.name, + let_expr, + if_then, + if_else + ); + if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) + || is_early_return(sym::Result, cx, &if_block); + if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none(); + then { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); + let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); + let sugg = format!( + "{receiver_str}{}?{}", + if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + if requires_semi { ";" } else { "" } + ); + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } + } + } +} + +fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool { + if let Some(expr) = bl.expr + && let rustc_hir::ExprKind::Call(callee, _) = expr.kind + { + is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput) + } else { + false + } +} + impl<'tcx> LateLintPass<'tcx> for QuestionMark { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !in_constant(cx, expr.hir_id) { - check_is_none_or_err_and_early_return(cx, expr); - check_if_let_some_or_err_and_early_return(cx, expr); + self.check_is_none_or_err_and_early_return(cx, expr); + self.check_if_let_some_or_err_and_early_return(cx, expr); + } + } + + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + if is_try_block(cx, block) { + *self + .try_block_depth_stack + .last_mut() + .expect("blocks are always part of bodies and must have a depth") += 1; + } + } + + fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) { + self.try_block_depth_stack.push(0); + } + + fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) { + self.try_block_depth_stack.pop(); + } + + fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + if is_try_block(cx, block) { + *self + .try_block_depth_stack + .last_mut() + .expect("blocks are always part of bodies and must have a depth") -= 1; } } } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index dd7ded491e792..d2018aba9e3dd 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -296,8 +296,8 @@ fn check_possible_range_contains( } } -struct RangeBounds<'a> { - val: Constant, +struct RangeBounds<'a, 'tcx> { + val: Constant<'tcx>, expr: &'a Expr<'a>, id: HirId, name_span: Span, @@ -309,7 +309,7 @@ struct RangeBounds<'a> { // Takes a binary expression such as x <= 2 as input // Breaks apart into various pieces, such as the value of the number, // hir id of the variable, and direction/inclusiveness of the operator -fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option> { +fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> Option> { if let ExprKind::Binary(ref op, l, r) = ex.kind { let (inclusive, ordering) = match op.node { BinOpKind::Gt => (false, Ordering::Greater), diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs new file mode 100644 index 0000000000000..f45bb1ef3e1f8 --- /dev/null +++ b/clippy_lints/src/raw_strings.rs @@ -0,0 +1,143 @@ +use std::{iter::once, ops::ControlFlow}; + +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet}; +use rustc_ast::{ + ast::{Expr, ExprKind}, + token::LitKind, +}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for raw string literals where a string literal can be used instead. + /// + /// ### Why is this bad? + /// It's just unnecessary, but there are many cases where using a raw string literal is more + /// idiomatic than a string literal, so it's opt-in. + /// + /// ### Example + /// ```rust + /// let r = r"Hello, world!"; + /// ``` + /// Use instead: + /// ```rust + /// let r = "Hello, world!"; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_RAW_STRINGS, + restriction, + "suggests using a string literal when a raw string literal is unnecessary" +} +declare_clippy_lint! { + /// ### What it does + /// Checks for raw string literals with an unnecessary amount of hashes around them. + /// + /// ### Why is this bad? + /// It's just unnecessary, and makes it look like there's more escaping needed than is actually + /// necessary. + /// + /// ### Example + /// ```rust + /// let r = r###"Hello, "world"!"###; + /// ``` + /// Use instead: + /// ```rust + /// let r = r#"Hello, "world"!"#; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_RAW_STRING_HASHES, + style, + "suggests reducing the number of hashes around a raw string literal" +} +impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]); + +pub struct RawStrings { + pub needless_raw_string_hashes_allow_one: bool, +} + +impl EarlyLintPass for RawStrings { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if !in_external_macro(cx.sess(), expr.span) + && let ExprKind::Lit(lit) = expr.kind + && let LitKind::StrRaw(max) | LitKind::ByteStrRaw(max) | LitKind::CStrRaw(max) = lit.kind + { + let str = lit.symbol.as_str(); + let prefix = match lit.kind { + LitKind::StrRaw(..) => "r", + LitKind::ByteStrRaw(..) => "br", + LitKind::CStrRaw(..) => "cr", + _ => unreachable!(), + }; + if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) { + return; + } + + if !str.contains(['\\', '"']) { + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRINGS, + expr.span, + "unnecessary raw string literal", + "try", + format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol), + Applicability::MachineApplicable, + ); + + return; + } + + let req = { + let mut following_quote = false; + let mut req = 0; + // `once` so a raw string ending in hashes is still checked + let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| { + match b { + b'"' => (following_quote, req) = (true, 1), + // I'm a bit surprised the compiler didn't optimize this out, there's no + // branch but it still ends up doing an unnecessary comparison, it's: + // - cmp r9b,1h + // - sbb cl,-1h + // which will add 1 if it's true. With this change, it becomes: + // - add cl,r9b + // isn't that so much nicer? + b'#' => req += u8::from(following_quote), + _ => { + if following_quote { + following_quote = false; + + if req == max { + return ControlFlow::Break(req); + } + + return ControlFlow::Continue(acc.max(req)); + } + }, + } + + ControlFlow::Continue(acc) + }); + + match num { + ControlFlow::Continue(num) | ControlFlow::Break(num) => num, + } + }; + + if req < max { + let hashes = "#".repeat(req as usize); + + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRING_HASHES, + expr.span, + "unnecessary hashes around raw string literal", + "try", + format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 944a33cc3e53f..e36adef555e65 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -57,7 +57,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.32.0"] pub REDUNDANT_CLONE, - perf, + nursery, "`clone()` of an owned value that is going to be dropped immediately" } @@ -320,8 +320,6 @@ fn base_local_and_movability<'tcx>( mir: &mir::Body<'tcx>, place: mir::Place<'tcx>, ) -> (mir::Local, CannotMoveOut) { - use rustc_middle::mir::PlaceRef; - // Dereference. You cannot move things out from a borrowed value. let mut deref = false; // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. @@ -330,17 +328,14 @@ fn base_local_and_movability<'tcx>( // underlying type implements Copy let mut slice = false; - let PlaceRef { local, mut projection } = place.as_ref(); - while let [base @ .., elem] = projection { - projection = base; + for (base, elem) in place.as_ref().iter_projections() { + let base_ty = base.ty(&mir.local_decls, cx.tcx).ty; deref |= matches!(elem, mir::ProjectionElem::Deref); - field |= matches!(elem, mir::ProjectionElem::Field(..)) - && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); - slice |= matches!(elem, mir::ProjectionElem::Index(..)) - && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); + field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, base_ty); + slice |= matches!(elem, mir::ProjectionElem::Index(..)) && !is_copy(cx, base_ty); } - (local, deref || field || slice) + (place.local, deref || field || slice) } #[derive(Default)] diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 2a42e73488f19..b6ce4ebc28f2e 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -1,14 +1,14 @@ +use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; use if_chain::if_chain; -use rustc_ast::ast; -use rustc_ast::visit as ast_visit; -use rustc_ast::visit::Visitor as AstVisitor; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::Visitor as HirVisitor; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_hir::intravisit::Visitor; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -51,59 +51,136 @@ impl ReturnVisitor { } } -impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor { - fn visit_expr(&mut self, ex: &'ast ast::Expr) { - if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind { +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 { self.found_return = true; + } else { + hir_visit::walk_expr(self, ex); } + } +} - ast_visit::walk_expr(self, ex); +/// Checks if the body is owned by an async closure +fn is_async_closure(body: &hir::Body<'_>) -> bool { + if let hir::ExprKind::Closure(closure) = body.value.kind + && let [resume_ty] = closure.fn_decl.inputs + && let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind + { + true + } else { + false } } -impl EarlyLintPass for RedundantClosureCall { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { +/// Tries to find the innermost closure: +/// ```rust,ignore +/// (|| || || || 42)()()()() +/// ^^^^^^^^^^^^^^ given this nested closure expression +/// ^^^^^ we want to return this closure +/// ``` +/// It also has a parameter for how many steps to go in at most, so as to +/// not take more closures than there are calls. +fn find_innermost_closure<'tcx>( + cx: &LateContext<'tcx>, + mut expr: &'tcx hir::Expr<'tcx>, + mut steps: usize, +) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> { + let mut data = None; + + while let hir::ExprKind::Closure(closure) = expr.kind + && let body = cx.tcx.hir().body(closure.body) + && { + let mut visitor = ReturnVisitor::new(); + visitor.visit_expr(body.value); + !visitor.found_return + } + && steps > 0 + { + expr = body.value; + data = Some((body.value, closure.fn_decl, if is_async_closure(body) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + })); + steps -= 1; + } + + data +} + +/// "Walks up" the chain of calls to find the outermost call expression, and returns the depth: +/// ```rust,ignore +/// (|| || || 3)()()() +/// ^^ this is the call expression we were given +/// ^^ this is what we want to return (and the depth is 3) +/// ``` +fn get_parent_call_exprs<'tcx>( + cx: &LateContext<'tcx>, + mut expr: &'tcx hir::Expr<'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 + && expr.span == recv.span + { + expr = parent; + depth += 1; + } + (expr, depth) +} + +impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if in_external_macro(cx.sess(), expr.span) { return; } - if_chain! { - if let ast::ExprKind::Call(ref paren, _) = expr.kind; - if let ast::ExprKind::Paren(ref closure) = paren.kind; - if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind; - then { - let mut visitor = ReturnVisitor::new(); - visitor.visit_expr(body); - if !visitor.found_return { - span_lint_and_then( - cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "try not to call a closure in the expression where it is declared", - |diag| { - if fn_decl.inputs.is_empty() { - let mut app = Applicability::MachineApplicable; - let mut hint = Sugg::ast(cx, body, "..", closure.span.ctxt(), &mut app); - - if asyncness.is_async() { - // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(body.kind, ast::ExprKind::Block(_, _)) { - hint = hint.blockify(); - } - - hint = hint.asyncify(); - } - - diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app); + + if let hir::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(..)) + && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) + && let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth) + { + span_lint_and_then( + cx, + REDUNDANT_CLOSURE_CALL, + full_expr.span, + "try not to call a closure in the expression where it is declared", + |diag| { + if fn_decl.inputs.is_empty() { + let mut applicability = Applicability::MachineApplicable; + let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability); + + if generator_kind.is_async() + && let hir::ExprKind::Closure(closure) = body.kind + { + let async_closure_body = cx.tcx.hir().body(closure.body); + + // `async x` is a syntax error, so it becomes `async { x }` + if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) { + hint = hint.blockify(); } - }, - ); + + hint = hint.asyncify(); + } + + diag.span_suggestion( + full_expr.span, + "try doing something like", + hint.maybe_par(), + applicability + ); + } } - } + ); } } -} -impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { fn count_closure_usage<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs new file mode 100644 index 0000000000000..8e9234bba3c86 --- /dev/null +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -0,0 +1,210 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::LitKind; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Warns about needless / redundant type annotations. + /// + /// ### Why is this bad? + /// Code without type annotations is shorter and in most cases + /// more idiomatic and easier to modify. + /// + /// ### Limitations + /// This lint doesn't support: + /// + /// - Generics + /// - Refs returned from anything else than a `MethodCall` + /// - Complex types (tuples, arrays, etc...) + /// - `Path` to anything else than a primitive type. + /// + /// ### Example + /// ```rust + /// let foo: String = String::new(); + /// ``` + /// Use instead: + /// ```rust + /// let foo = String::new(); + /// ``` + #[clippy::version = "1.70.0"] + pub REDUNDANT_TYPE_ANNOTATIONS, + restriction, + "warns about needless / redundant type annotations." +} +declare_lint_pass!(RedundantTypeAnnotations => [REDUNDANT_TYPE_ANNOTATIONS]); + +fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, func_return_type: Ty<'tcx>) -> bool { + // type annotation is primitive + if let hir::def::Res::PrimTy(primty) = ty_resolved_path + && func_return_type.is_primitive() + && let Some(func_return_type_sym) = func_return_type.primitive_symbol() + { + return primty.name() == func_return_type_sym; + } + + // type annotation is any other non generic type + if let hir::def::Res::Def(_, defid) = ty_resolved_path + && let Some(annotation_ty) = cx.tcx.type_of(defid).no_bound_vars() + { + return annotation_ty == func_return_type; + } + + false +} + +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 + && let Some(init_ty) = cx.tcx.type_of(func_defid).no_bound_vars() + { + Some(init_ty) + } else { + None + } +} + +fn func_ty_to_return_type<'tcx>(cx: &LateContext<'tcx>, func_ty: Ty<'tcx>) -> Option> { + if func_ty.is_fn() { + Some(func_ty.fn_sig(cx.tcx).output().skip_binder()) + } else { + None + } +} + +/// Extracts the fn Ty, e.g. `fn() -> std::string::String {f}` +fn extract_fn_ty<'tcx>( + cx: &LateContext<'tcx>, + call: &hir::Expr<'tcx>, + func_return_path: &hir::QPath<'tcx>, +) -> Option> { + match func_return_path { + // let a: String = f(); where f: fn f() -> String + hir::QPath::Resolved(_, resolved_path) => { + if let hir::def::Res::Def(_, defid) = resolved_path.res + && let Some(middle_ty_init) = cx.tcx.type_of(defid).no_bound_vars() + { + Some(middle_ty_init) + } else { + None + } + }, + // Associated functions like + // let a: String = String::new(); + // let a: String = String::get_string(); + hir::QPath::TypeRelative(..) => func_hir_id_to_func_ty(cx, call.hir_id), + hir::QPath::LangItem(..) => None, + } +} + +fn is_redundant_in_func_call<'tcx>( + cx: &LateContext<'tcx>, + ty_resolved_path: hir::def::Res, + call: &hir::Expr<'tcx>, +) -> bool { + if let hir::ExprKind::Path(init_path) = &call.kind { + let func_type = extract_fn_ty(cx, call, init_path); + + if let Some(func_type) = func_type + && let Some(init_return_type) = func_ty_to_return_type(cx, func_type) + { + return is_same_type(cx, ty_resolved_path, init_return_type); + } + } + + false +} + +fn extract_primty(ty_kind: &hir::TyKind<'_>) -> Option { + if let hir::TyKind::Path(ty_path) = ty_kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res + { + Some(primty) + } else { + None + } +} + +impl LateLintPass<'_> for RedundantTypeAnnotations { + fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) { + // type annotation part + if !local.span.from_expansion() + && let Some(ty) = &local.ty + + // initialization part + && let Some(init) = local.init + { + match &init.kind { + // When the initialization is a call to a function + hir::ExprKind::Call(init_call, _) => { + if let hir::TyKind::Path(ty_path) = &ty.kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + + && is_redundant_in_func_call(cx, resolved_path_ty.res, init_call) { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + hir::ExprKind::MethodCall(_, _, _, _) => { + let mut is_ref = false; + let mut ty_kind = &ty.kind; + + // If the annotation is a ref we "peel" it + if let hir::TyKind::Ref(_, mut_ty) = &ty.kind { + is_ref = true; + ty_kind = &mut_ty.ty.kind; + } + + if let hir::TyKind::Path(ty_path) = ty_kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + && let Some(func_ty) = func_hir_id_to_func_ty(cx, init.hir_id) + && let Some(return_type) = func_ty_to_return_type(cx, func_ty) + && is_same_type(cx, resolved_path_ty.res, if is_ref { + return_type.peel_refs() + } else { + return_type + }) + { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + // When the initialization is a path for example u32::MAX + hir::ExprKind::Path(init_path) => { + // TODO: check for non primty + if let Some(primty) = extract_primty(&ty.kind) + + && let hir::QPath::TypeRelative(init_ty, _) = init_path + && let Some(primty_init) = extract_primty(&init_ty.kind) + + && primty == primty_init + { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + hir::ExprKind::Lit(init_lit) => { + match init_lit.node { + // In these cases the annotation is redundant + LitKind::Str(..) + | LitKind::ByteStr(..) + | LitKind::Byte(..) + | LitKind::Char(..) + | LitKind::Bool(..) + | LitKind::CStr(..) => { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + }, + LitKind::Int(..) | LitKind::Float(..) => { + // If the initialization value is a suffixed literal we lint + if init_lit.node.is_suffixed() { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + LitKind::Err => (), + } + } + _ => () + } + }; + } +} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 631ecf1428d6a..958351ad81bb7 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -25,6 +25,12 @@ declare_clippy_lint! { /// It is just extraneous code. Remove it to make your code /// more rusty. /// + /// ### Known problems + /// In the case of some temporaries, e.g. locks, eliding the variable binding could lead + /// to deadlocks. See [this issue](https://github.com/rust-lang/rust/issues/37612). + /// This could become relevant if the code is later changed to use the code that would have been + /// bound without first assigning it to a let-binding. + /// /// ### Example /// ```rust /// fn foo() -> String { @@ -286,7 +292,7 @@ fn check_final_expr<'tcx>( // (except for unit type functions) so we don't match it ExprKind::Match(_, arms, MatchSource::Normal) => { let match_ty = cx.typeck_results().expr_ty(peeled_drop_expr); - for arm in arms.iter() { + for arm in *arms { check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit, Some(match_ty)); } }, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index b930b2c8dd7b8..fffa8a380c2f8 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -1,10 +1,10 @@ use clippy_utils::{ diagnostics::span_lint_and_then, - get_attr, + expr_or_init, get_attr, path_to_local, source::{indent_of, snippet}, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_errors::Applicability; use rustc_hir::{ self as hir, intravisit::{walk_expr, Visitor}, @@ -13,6 +13,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::Ident, Span, DUMMY_SP}; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -56,255 +57,102 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]); #[derive(Default)] pub struct SignificantDropTightening<'tcx> { + apas: FxIndexMap, /// Auxiliary structure used to avoid having to verify the same type multiple times. seen_types: FxHashSet>, type_cache: FxHashMap, bool>, } -impl<'tcx> SignificantDropTightening<'tcx> { - /// Unifies the statements of a block with its return expression. - fn all_block_stmts<'ret, 'rslt, 'stmts>( - block_stmts: &'stmts [hir::Stmt<'tcx>], - dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>, - ) -> impl Iterator> - where - 'ret: 'rslt, - 'stmts: 'rslt, - { - block_stmts.iter().chain(dummy_ret_stmt) - } - - /// Searches for at least one statement that could slow down the release of a significant drop. - fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator>) -> bool - where - 'tcx: 'stmt, - { - for stmt in stmts { - match stmt.kind { - hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {} - hir::StmtKind::Local(local) if let Some(expr) = local.init - && let hir::ExprKind::Path(_) = expr.kind => {}, - _ => return true - }; - } - false - } - - /// Verifies if the expression is of type `drop(some_lock_path)` to assert that the temporary - /// is already being dropped before the end of its scope. - fn has_drop(expr: &'tcx hir::Expr<'_>, init_bind_ident: Ident) -> bool { - if let hir::ExprKind::Call(fun, args) = expr.kind - && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind - && let [fun_ident, ..] = fun_path.segments - && fun_ident.ident.name == rustc_span::sym::drop - && let [first_arg, ..] = args - && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind - && let [first_arg_ps, .. ] = arg_path.segments - { - first_arg_ps.ident == init_bind_ident - } - else { - false - } - } - - /// Tries to find types marked with `#[has_significant_drop]` of an expression `expr` that is - /// originated from `stmt` and then performs common logic on `sdap`. - fn modify_sdap_if_sig_drop_exists( +impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { + fn check_fn( &mut self, cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - idx: usize, - sdap: &mut SigDropAuxParams, - stmt: &hir::Stmt<'_>, - cb: impl Fn(&mut SigDropAuxParams), + _: hir::intravisit::FnKind<'_>, + _: &hir::FnDecl<'_>, + body: &'tcx hir::Body<'_>, + _: Span, + _: hir::def_id::LocalDefId, ) { - let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache); - sig_drop_finder.visit_expr(expr); - if sig_drop_finder.has_sig_drop { - cb(sdap); - if sdap.number_of_stmts > 0 { - sdap.last_use_stmt_idx = idx; - sdap.last_use_stmt_span = stmt.span; - if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind { - sdap.last_use_method_span = span; - } + self.apas.clear(); + let initial_dummy_stmt = dummy_stmt_expr(body.value); + let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt); + StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body); + for apa in ap.apas.values() { + if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr { + continue; } - sdap.number_of_stmts = sdap.number_of_stmts.wrapping_add(1); - } - } - - /// Shows generic overall messages as well as specialized messages depending on the usage. - fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) { - match sdap.number_of_stmts { - 0 | 1 => {}, - 2 => { - let indent = " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)); - let init_method = snippet(cx, sdap.init_method_span, ".."); - let usage_method = snippet(cx, sdap.last_use_method_span, ".."); - let stmt = if let Some(last_use_bind_span) = sdap.last_use_bind_span { - format!( - "\n{indent}let {} = {init_method}.{usage_method};", - snippet(cx, last_use_bind_span, ".."), - ) - } else { - format!("\n{indent}{init_method}.{usage_method};") - }; - diag.span_suggestion_verbose( - sdap.init_stmt_span, - "merge the temporary construction with its single usage", - stmt, - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - sdap.last_use_stmt_span, - "remove separated single usage", - "", - Applicability::MaybeIncorrect, - ); - }, - _ => { - diag.span_suggestion( - sdap.last_use_stmt_span.shrink_to_hi(), - "drop the temporary after the end of its last usage", - format!( - "\n{}drop({});", - " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)), - sdap.init_bind_ident - ), - Applicability::MaybeIncorrect, - ); - }, - } - diag.note("this might lead to unnecessary resource contention"); - diag.span_label( - block_span, - format!( - "temporary `{}` is currently being dropped at the end of its contained scope", - sdap.init_bind_ident - ), - ); - } -} - -impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { - fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { - let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt { - hir_id: hir::HirId::INVALID, - kind: hir::StmtKind::Expr(expr), - span: DUMMY_SP, - }); - let mut sdap = SigDropAuxParams::default(); - for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() { - match stmt.kind { - hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists( - cx, - expr, - idx, - &mut sdap, - stmt, - |_| {} - ), - hir::StmtKind::Local(local) if let Some(expr) = local.init => self.modify_sdap_if_sig_drop_exists( - cx, - expr, - idx, - &mut sdap, - stmt, - |local_sdap| { - if local_sdap.number_of_stmts == 0 { - if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - local_sdap.init_bind_ident = ident; - } - if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr.kind { - local_sdap.init_method_span = local_expr.span.to(span); - } - local_sdap.init_stmt_span = stmt.span; - } - else if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - local_sdap.last_use_bind_span = Some(ident.span); - } - } - ), - hir::StmtKind::Semi(expr) => { - if Self::has_drop(expr, sdap.init_bind_ident) { - return; - } - self.modify_sdap_if_sig_drop_exists(cx, expr, idx, &mut sdap, stmt, |_| {}); - }, - _ => {} - }; - } - - let idx = sdap.last_use_stmt_idx.wrapping_add(1); - let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx); - if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) { span_lint_and_then( cx, SIGNIFICANT_DROP_TIGHTENING, - sdap.init_bind_ident.span, + apa.first_bind_ident.span, "temporary with significant `Drop` can be early dropped", |diag| { - Self::set_suggestions(cx, block.span, diag, &sdap); + match apa.counter { + 0 | 1 => {}, + 2 => { + let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); + let init_method = snippet(cx, apa.first_method_span, ".."); + let usage_method = snippet(cx, apa.last_method_span, ".."); + let stmt = if apa.last_bind_ident == Ident::empty() { + format!("\n{indent}{init_method}.{usage_method};") + } else { + format!( + "\n{indent}let {} = {init_method}.{usage_method};", + snippet(cx, apa.last_bind_ident.span, ".."), + ) + }; + diag.span_suggestion_verbose( + apa.first_stmt_span, + "merge the temporary construction with its single usage", + stmt, + Applicability::MaybeIncorrect, + ); + diag.span_suggestion( + apa.last_stmt_span, + "remove separated single usage", + "", + Applicability::MaybeIncorrect, + ); + }, + _ => { + diag.span_suggestion( + apa.last_stmt_span.shrink_to_hi(), + "drop the temporary after the end of its last usage", + format!( + "\n{}drop({});", + " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)), + apa.first_bind_ident + ), + Applicability::MaybeIncorrect, + ); + }, + } + diag.note("this might lead to unnecessary resource contention"); + diag.span_label( + apa.first_block_span, + format!( + "temporary `{}` is currently being dropped at the end of its contained scope", + apa.first_bind_ident + ), + ); }, ); } } } -/// Auxiliary parameters used on each block check. -struct SigDropAuxParams { - /// The binding or variable that references the initial construction of the type marked with - /// `#[has_significant_drop]`. - init_bind_ident: Ident, - /// Similar to `init_bind_ident` but encompasses the right-hand method call. - init_method_span: Span, - /// Similar to `init_bind_ident` but encompasses the whole contained statement. - init_stmt_span: Span, - - /// The last visited binding or variable span within a block that had any referenced inner type - /// marked with `#[has_significant_drop]`. - last_use_bind_span: Option, - /// Index of the last visited statement within a block that had any referenced inner type - /// marked with `#[has_significant_drop]`. - last_use_stmt_idx: usize, - /// Similar to `last_use_bind_span` but encompasses the whole contained statement. - last_use_stmt_span: Span, - /// Similar to `last_use_bind_span` but encompasses the right-hand method call. - last_use_method_span: Span, - - /// Total number of statements within a block that have any referenced inner type marked with - /// `#[has_significant_drop]`. - number_of_stmts: usize, -} - -impl Default for SigDropAuxParams { - fn default() -> Self { - Self { - init_bind_ident: Ident::empty(), - init_method_span: DUMMY_SP, - init_stmt_span: DUMMY_SP, - last_use_bind_span: None, - last_use_method_span: DUMMY_SP, - last_use_stmt_idx: 0, - last_use_stmt_span: DUMMY_SP, - number_of_stmts: 0, - } - } -} - -/// Checks the existence of the `#[has_significant_drop]` attribute -struct SigDropChecker<'cx, 'sdt, 'tcx> { +/// Checks the existence of the `#[has_significant_drop]` attribute. +struct AttrChecker<'cx, 'others, 'tcx> { cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, } -impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { +impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { pub(crate) fn new( cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, ) -> Self { seen_types.clear(); Self { @@ -314,7 +162,17 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { } } - pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool { + fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool { + // The borrow checker prevents us from using something fancier like or_insert_with. + if let Some(ty) = self.type_cache.get(&ty) { + return *ty; + } + let value = self.has_sig_drop_attr_uncached(ty); + self.type_cache.insert(ty, value); + value + } + + fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() { let mut iter = get_attr( self.cx.sess(), @@ -333,7 +191,7 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { return true; } } - for generic_arg in b.iter() { + for generic_arg in *b { if let GenericArgKind::Type(ty) = generic_arg.unpack() { if self.has_sig_drop_attr(ty) { return true; @@ -350,73 +208,244 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { } } - pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool { - // The borrow checker prevents us from using something fancier like or_insert_with. - if let Some(ty) = self.type_cache.get(&ty) { - return *ty; - } - let value = self.has_sig_drop_attr_uncached(ty); - self.type_cache.insert(ty, value); - value - } - fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool { !self.seen_types.insert(ty) } } -/// Performs recursive calls to find any inner type marked with `#[has_significant_drop]`. -struct SigDropFinder<'cx, 'sdt, 'tcx> { - cx: &'cx LateContext<'tcx>, - has_sig_drop: bool, - sig_drop_checker: SigDropChecker<'cx, 'sdt, 'tcx>, +struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { + ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>, + cx: &'lc LateContext<'tcx>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, } -impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> { +impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { fn new( - cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>, + cx: &'lc LateContext<'tcx>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, ) -> Self { Self { + ap, cx, - has_sig_drop: false, - sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache), + seen_types, + type_cache, + } + } + + fn manage_has_expensive_expr_after_last_attr(&mut self) { + let has_expensive_stmt = match self.ap.curr_stmt.kind { + hir::StmtKind::Expr(expr) if !is_expensive_expr(expr) => false, + hir::StmtKind::Local(local) if let Some(expr) = local.init + && let hir::ExprKind::Path(_) = expr.kind => false, + _ => true + }; + if has_expensive_stmt { + for apa in self.ap.apas.values_mut() { + let last_stmt_is_not_dummy = apa.last_stmt_span != DUMMY_SP; + let last_stmt_is_not_curr = self.ap.curr_stmt.span != apa.last_stmt_span; + let block_equals_curr = self.ap.curr_block_hir_id == apa.first_block_hir_id; + let block_is_ancestor = self + .cx + .tcx + .hir() + .parent_iter(self.ap.curr_block_hir_id) + .any(|(id, _)| id == apa.first_block_hir_id); + if last_stmt_is_not_dummy && last_stmt_is_not_curr && (block_equals_curr || block_is_ancestor) { + apa.has_expensive_expr_after_last_attr = true; + } + } } } } -impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx hir::Expr<'_>) { - if self - .sig_drop_checker - .has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex)) - { - self.has_sig_drop = true; - return; +impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { + fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + for stmt in block.stmts { + self.ap.curr_stmt = Cow::Borrowed(stmt); + self.visit_stmt(stmt); + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + self.manage_has_expensive_expr_after_last_attr(); + } + if let Some(expr) = block.expr { + self.ap.curr_stmt = Cow::Owned(dummy_stmt_expr(expr)); + self.visit_expr(expr); + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + self.manage_has_expensive_expr_after_last_attr(); } + } - match ex.kind { - hir::ExprKind::MethodCall(_, expr, ..) => { - self.visit_expr(expr); - }, - hir::ExprKind::Array(..) - | hir::ExprKind::Assign(..) - | hir::ExprKind::AssignOp(..) - | hir::ExprKind::Binary(..) - | hir::ExprKind::Call(..) - | hir::ExprKind::Field(..) - | hir::ExprKind::If(..) - | hir::ExprKind::Index(..) - | hir::ExprKind::Match(..) - | hir::ExprKind::Repeat(..) - | hir::ExprKind::Ret(..) - | hir::ExprKind::Tup(..) - | hir::ExprKind::Unary(..) - | hir::ExprKind::Yield(..) => { - walk_expr(self, ex); - }, - _ => {}, + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + let modify_apa_params = |apa: &mut AuxParamsAttr| { + apa.counter = apa.counter.wrapping_add(1); + apa.has_expensive_expr_after_last_attr = false; + }; + let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache); + if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) { + if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind + && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind + && !self.ap.apas.contains_key(&hir_id) + && { + if let Some(local_hir_id) = path_to_local(expr) { + local_hir_id == hir_id + } + else { + true + } + } + { + let mut apa = AuxParamsAttr { + first_bind_ident: ident, + first_block_hir_id: self.ap.curr_block_hir_id, + first_block_span: self.ap.curr_block_span, + first_method_span: { + let expr_or_init = expr_or_init(self.cx, expr); + if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { + local_expr.span.to(span) + } + else { + expr_or_init.span + } + }, + first_stmt_span: self.ap.curr_stmt.span, + ..Default::default() + }; + modify_apa_params(&mut apa); + let _ = self.ap.apas.insert(hir_id, apa); + } else { + let Some(hir_id) = path_to_local(expr) else { return; }; + let Some(apa) = self.ap.apas.get_mut(&hir_id) else { return; }; + match self.ap.curr_stmt.kind { + hir::StmtKind::Local(local) => { + if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { + apa.last_bind_ident = ident; + } + if let Some(local_init) = local.init + && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind + { + apa.last_method_span = span; + } + }, + hir::StmtKind::Semi(expr) => { + if has_drop(expr, &apa.first_bind_ident) { + apa.has_expensive_expr_after_last_attr = false; + apa.last_stmt_span = DUMMY_SP; + return; + } + if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind { + apa.last_method_span = span; + } + }, + _ => {}, + } + apa.last_stmt_span = self.ap.curr_stmt.span; + modify_apa_params(apa); + } + } + walk_expr(self, expr); + } +} + +/// Auxiliary parameters used on each block check of an item +struct AuxParams<'others, 'stmt, 'tcx> { + //// See [AuxParamsAttr]. + apas: &'others mut FxIndexMap, + /// The current block identifier that is being visited. + curr_block_hir_id: hir::HirId, + /// The current block span that is being visited. + curr_block_span: Span, + /// The current statement that is being visited. + curr_stmt: Cow<'stmt, hir::Stmt<'tcx>>, +} + +impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> { + fn new(apas: &'others mut FxIndexMap, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self { + Self { + apas, + curr_block_hir_id: hir::HirId::INVALID, + curr_block_span: DUMMY_SP, + curr_stmt: Cow::Borrowed(curr_stmt), + } + } +} + +/// Auxiliary parameters used on expression created with `#[has_significant_drop]`. +#[derive(Debug)] +struct AuxParamsAttr { + /// The number of times `#[has_significant_drop]` was referenced. + counter: usize, + /// If an expensive expression follows the last use of anything marked with + /// `#[has_significant_drop]`. + has_expensive_expr_after_last_attr: bool, + + /// The identifier of the block that involves the first `#[has_significant_drop]`. + first_block_hir_id: hir::HirId, + /// The span of the block that involves the first `#[has_significant_drop]`. + first_block_span: Span, + /// The binding or variable that references the initial construction of the type marked with + /// `#[has_significant_drop]`. + first_bind_ident: Ident, + /// Similar to `init_bind_ident` but encompasses the right-hand method call. + first_method_span: Span, + /// Similar to `init_bind_ident` but encompasses the whole contained statement. + first_stmt_span: Span, + + /// The last visited binding or variable span within a block that had any referenced inner type + /// marked with `#[has_significant_drop]`. + last_bind_ident: Ident, + /// Similar to `last_bind_span` but encompasses the right-hand method call. + last_method_span: Span, + /// Similar to `last_bind_span` but encompasses the whole contained statement. + last_stmt_span: Span, +} + +impl Default for AuxParamsAttr { + fn default() -> Self { + Self { + counter: 0, + has_expensive_expr_after_last_attr: false, + first_block_hir_id: hir::HirId::INVALID, + first_bind_ident: Ident::empty(), + first_block_span: DUMMY_SP, + first_method_span: DUMMY_SP, + first_stmt_span: DUMMY_SP, + last_bind_ident: Ident::empty(), + last_method_span: DUMMY_SP, + last_stmt_span: DUMMY_SP, } } } + +fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> { + hir::Stmt { + hir_id: hir::HirId::INVALID, + kind: hir::StmtKind::Expr(expr), + span: DUMMY_SP, + } +} + +fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident) -> bool { + if let hir::ExprKind::Call(fun, args) = expr.kind + && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind + && let [fun_ident, ..] = fun_path.segments + && fun_ident.ident.name == rustc_span::sym::drop + && let [first_arg, ..] = args + && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind + && let [first_arg_ps, .. ] = arg_path.segments + { + &first_arg_ps.ident == first_bind_ident + } + else { + false + } +} + +fn is_expensive_expr(expr: &hir::Expr<'_>) -> bool { + !matches!(expr.kind, hir::ExprKind::Path(_)) +} diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs new file mode 100644 index 0000000000000..42753d2e95114 --- /dev/null +++ b/clippy_lints/src/single_call_fn.rs @@ -0,0 +1,133 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{is_from_proc_macro, is_in_test_function}; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::nested_filter::OnlyBodies; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for functions that are only used once. Does not lint tests. + /// + /// ### Why is this bad? + /// It's usually not, splitting a function into multiple parts often improves readability and in + /// the case of generics, can prevent the compiler from duplicating the function dozens of + /// time; instead, only duplicating a thunk. But this can prevent segmentation across a + /// codebase, where many small functions are used only once. + /// + /// Note: If this lint is used, prepare to allow this a lot. + /// + /// ### Example + /// ```rust + /// pub fn a(t: &T) + /// where + /// T: AsRef, + /// { + /// a_inner(t.as_ref()) + /// } + /// + /// fn a_inner(t: &str) { + /// /* snip */ + /// } + /// + /// ``` + /// Use instead: + /// ```rust + /// pub fn a(t: &T) + /// where + /// T: AsRef, + /// { + /// let t = t.as_ref(); + /// /* snip */ + /// } + /// + /// ``` + #[clippy::version = "1.72.0"] + pub SINGLE_CALL_FN, + restriction, + "checks for functions that are only used once" +} +impl_lint_pass!(SingleCallFn => [SINGLE_CALL_FN]); + +#[derive(Clone)] +pub struct SingleCallFn { + pub avoid_breaking_exported_api: bool, + pub def_id_to_usage: FxHashMap)>, +} + +impl<'tcx> LateLintPass<'tcx> for SingleCallFn { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + span: Span, + def_id: LocalDefId, + ) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) + || in_external_macro(cx.sess(), span) + || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span)) + || is_in_test_function(cx.tcx, body.value.hir_id) + { + return; + } + + self.def_id_to_usage.insert(def_id, (span, vec![])); + } + + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { + let mut v = FnUsageVisitor { + cx, + def_id_to_usage: &mut self.def_id_to_usage, + }; + cx.tcx.hir().visit_all_item_likes_in_crate(&mut v); + + for usage in self.def_id_to_usage.values() { + let single_call_fn_span = usage.0; + if let [caller_span] = *usage.1 { + span_lint_and_help( + cx, + SINGLE_CALL_FN, + single_call_fn_span, + "this function is only used once", + Some(caller_span), + "used here", + ); + } + } + } +} + +struct FnUsageVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + def_id_to_usage: &'a mut FxHashMap)>, +} + +impl<'a, 'tcx> Visitor<'tcx> for FnUsageVisitor<'a, 'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.cx.tcx.hir() + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + let Self { cx, .. } = *self; + + if let ExprKind::Path(qpath) = expr.kind + && let res = cx.qpath_res(&qpath, expr.hir_id) + && let Some(call_def_id) = res.opt_def_id() + && let Some(def_id) = call_def_id.as_local() + && let Some(usage) = self.def_id_to_usage.get_mut(&def_id) + { + usage.1.push(expr.span); + } + + walk_expr(self, expr); + } +} diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs new file mode 100644 index 0000000000000..dfe8be7a6a619 --- /dev/null +++ b/clippy_lints/src/single_range_in_vec_init.rs @@ -0,0 +1,147 @@ +use clippy_utils::{ + diagnostics::span_lint_and_then, get_trait_def_id, higher::VecArgs, macros::root_macro_call_first_node, + source::snippet_opt, ty::implements_trait, +}; +use rustc_ast::{LitIntType, LitKind, UintTy}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, LangItem, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use std::fmt::{self, Display, Formatter}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `Vec` or array initializations that contain only one range. + /// + /// ### Why is this bad? + /// This is almost always incorrect, as it will result in a `Vec` that has only one element. + /// Almost always, the programmer intended for it to include all elements in the range or for + /// the end of the range to be the length instead. + /// + /// ### Example + /// ```rust + /// let x = [0..200]; + /// ``` + /// Use instead: + /// ```rust + /// // If it was intended to include every element in the range... + /// let x = (0..200).collect::>(); + /// // ...Or if 200 was meant to be the len + /// let x = [0; 200]; + /// ``` + #[clippy::version = "1.72.0"] + pub SINGLE_RANGE_IN_VEC_INIT, + suspicious, + "checks for initialization of `Vec` or arrays which consist of a single range" +} +declare_lint_pass!(SingleRangeInVecInit => [SINGLE_RANGE_IN_VEC_INIT]); + +enum SuggestedType { + Vec, + Array, +} + +impl SuggestedType { + fn starts_with(&self) -> &'static str { + if matches!(self, SuggestedType::Vec) { + "vec!" + } else { + "[" + } + } + + fn ends_with(&self) -> &'static str { + if matches!(self, SuggestedType::Vec) { "" } else { "]" } + } +} + +impl Display for SuggestedType { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if matches!(&self, SuggestedType::Vec) { + write!(f, "a `Vec`") + } else { + write!(f, "an array") + } + } +} + +impl LateLintPass<'_> for SingleRangeInVecInit { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + // inner_expr: `vec![0..200]` or `[0..200]` + // ^^^^^^ ^^^^^^^ + // span: `vec![0..200]` or `[0..200]` + // ^^^^^^^^^^^^ ^^^^^^^^ + // suggested_type: What to print, "an array" or "a `Vec`" + let (inner_expr, span, suggested_type) = if let ExprKind::Array([inner_expr]) = expr.kind + && !expr.span.from_expansion() + { + (inner_expr, expr.span, SuggestedType::Array) + } else if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && let Some(VecArgs::Vec([expr])) = VecArgs::hir(cx, expr) + { + (expr, macro_call.span, SuggestedType::Vec) + } else { + return; + }; + + let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else { + return; + }; + + if matches!(lang_item, LangItem::Range) + && let ty = cx.typeck_results().expr_ty(start.expr) + && let Some(snippet) = snippet_opt(cx, span) + // `is_from_proc_macro` will skip any `vec![]`. Let's not! + && snippet.starts_with(suggested_type.starts_with()) + && snippet.ends_with(suggested_type.ends_with()) + && let Some(start_snippet) = snippet_opt(cx, start.span) + && let Some(end_snippet) = snippet_opt(cx, end.span) + { + let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"]) + && implements_trait(cx, ty, step_def_id, &[]) + { + true + } else { + false + }; + let should_emit_of_len = if let Some(copy_def_id) = cx.tcx.lang_items().copy_trait() + && implements_trait(cx, ty, copy_def_id, &[]) + && let ExprKind::Lit(lit_kind) = end.expr.kind + && let LitKind::Int(.., suffix_type) = lit_kind.node + && let LitIntType::Unsigned(UintTy::Usize) | LitIntType::Unsuffixed = suffix_type + { + true + } else { + false + }; + + if should_emit_every_value || should_emit_of_len { + span_lint_and_then( + cx, + SINGLE_RANGE_IN_VEC_INIT, + span, + &format!("{suggested_type} of `Range` that is only one element"), + |diag| { + if should_emit_every_value { + diag.span_suggestion( + span, + "if you wanted a `Vec` that contains the entire range, try", + format!("({start_snippet}..{end_snippet}).collect::>()"), + Applicability::MaybeIncorrect, + ); + } + + if should_emit_of_len { + diag.span_suggestion( + inner_expr.span, + format!("if you wanted {suggested_type} of len {end_snippet}, try"), + format!("{start_snippet}; {end_snippet}"), + Applicability::MaybeIncorrect, + ); + } + }, + ); + } + } + } +} diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 4ccda15068bbb..6db330dfa617b 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; -use clippy_utils::{SpanlessEq, SpanlessHash}; +use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; use if_chain::if_chain; use itertools::Itertools; @@ -9,7 +10,7 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, + GenericArg, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; @@ -86,15 +87,16 @@ declare_clippy_lint! { "check if the same trait bounds are specified more than once during a generic declaration" } -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct TraitBounds { max_trait_bounds: u64, + msrv: Msrv, } impl TraitBounds { #[must_use] - pub fn new(max_trait_bounds: u64) -> Self { - Self { max_trait_bounds } + pub fn new(max_trait_bounds: u64, msrv: Msrv) -> Self { + Self { max_trait_bounds, msrv } } } @@ -139,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { ) = cx.tcx.hir().get_if_local(*def_id); then { if self_bounds_map.is_empty() { - for bound in self_bounds.iter() { + for bound in *self_bounds { let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue }; self_bounds_map.insert(self_res, self_segments); } @@ -184,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // Iterate the bounds and add them to our seen hash // If we haven't yet seen it, add it to the fixed traits - for bound in bounds.iter() { + for bound in bounds { let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; let new_trait = seen_def_ids.insert(def_id); @@ -222,10 +224,24 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } } + + extract_msrv_attr!(LateContext); } impl TraitBounds { - fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { + /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on + /// this MSRV? See for details. + fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { + if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) + && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound + { + cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() + } else { + false + } + } + + fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { struct SpanlessTy<'cx, 'tcx> { ty: &'tcx Ty<'tcx>, cx: &'cx LateContext<'tcx>, @@ -256,11 +272,10 @@ impl TraitBounds { if p.origin != PredicateOrigin::ImplTrait; if p.bounds.len() as u64 <= self.max_trait_bounds; if !p.span.from_expansion(); - if let Some(ref v) = map.insert( - SpanlessTy { ty: p.bounded_ty, cx }, - p.bounds.iter().collect::>() - ); - + let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::>(); + if !bounds.is_empty(); + if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds); + if !is_from_proc_macro(cx, p.bounded_ty); then { let trait_bounds = v .iter() @@ -342,7 +357,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { "this trait bound is already specified in the where clause", None, "consider removing this trait bound", - ); + ); } } } diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs new file mode 100644 index 0000000000000..bd983306508ba --- /dev/null +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -0,0 +1,235 @@ +use clippy_utils::{ + diagnostics::span_lint_and_help, + is_from_proc_macro, + msrvs::{self, Msrv}, + path_to_local, +}; +use rustc_ast::LitKind; +use rustc_hir::{Expr, ExprKind, HirId, Node, Pat}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::{lint::in_external_macro, ty}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use std::iter::once; + +declare_clippy_lint! { + /// ### What it does + /// Checks for tuple<=>array conversions that are not done with `.into()`. + /// + /// ### Why is this bad? + /// It's unnecessary complexity. `.into()` works for tuples<=>arrays at or below 12 elements and + /// conveys the intent a lot better, while also leaving less room for hard to spot bugs! + /// + /// ### Example + /// ```rust,ignore + /// let t1 = &[(1, 2), (3, 4)]; + /// let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + /// ``` + /// Use instead: + /// ```rust,ignore + /// let t1 = &[(1, 2), (3, 4)]; + /// let v1: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); + /// ``` + #[clippy::version = "1.72.0"] + pub TUPLE_ARRAY_CONVERSIONS, + complexity, + "checks for tuple<=>array conversions that are not done with `.into()`" +} +impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); + +#[derive(Clone)] +pub struct TupleArrayConversions { + pub msrv: Msrv, +} + +impl LateLintPass<'_> for TupleArrayConversions { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if !in_external_macro(cx.sess(), expr.span) && self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { + match expr.kind { + ExprKind::Array(elements) if (1..=12).contains(&elements.len()) => check_array(cx, expr, elements), + ExprKind::Tup(elements) if (1..=12).contains(&elements.len()) => check_tuple(cx, expr, elements), + _ => {}, + } + } + } + + extract_msrv_attr!(LateContext); +} + +#[expect( + clippy::blocks_in_if_conditions, + reason = "not a FP, but this is much easier to understand" +)] +fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { + if should_lint( + cx, + elements, + // This is cursed. + Some, + |(first_id, local)| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Tuple(len) if len.len() == elements.len() + ); + } + + false + }, + ) || should_lint( + cx, + elements, + |(i, expr)| { + if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() { + return Some((i, path)); + }; + + None + }, + |(first_id, local)| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Tuple(len) if len.len() == elements.len() + ); + } + + false + }, + ) { + emit_lint(cx, expr, ToType::Array); + } +} + +#[expect( + clippy::blocks_in_if_conditions, + reason = "not a FP, but this is much easier to understand" +)] +#[expect(clippy::cast_possible_truncation)] +fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { + if should_lint(cx, elements, Some, |(first_id, local)| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() + ); + } + + false + }) || should_lint( + cx, + elements, + |(i, expr)| { + if let ExprKind::Index(path, index) = expr.kind + && let ExprKind::Lit(lit) = index.kind + && let LitKind::Int(val, _) = lit.node + && val as usize == i + { + return Some((i, path)); + }; + + None + }, + |(first_id, local)| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() + ); + } + + false + }, + ) { + emit_lint(cx, expr, ToType::Tuple); + } +} + +/// Walks up the `Pat` until it's reached the final containing `Pat`. +fn parent_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat<'tcx> { + let mut end = start; + for (_, node) in cx.tcx.hir().parent_iter(start.hir_id) { + if let Node::Pat(pat) = node { + end = pat; + } else { + break; + } + } + end +} + +#[derive(Clone, Copy)] +enum ToType { + Array, + Tuple, +} + +impl ToType { + fn msg(self) -> &'static str { + match self { + ToType::Array => "it looks like you're trying to convert a tuple to an array", + ToType::Tuple => "it looks like you're trying to convert an array to a tuple", + } + } + + fn help(self) -> &'static str { + match self { + ToType::Array => "use `.into()` instead, or `<[T; N]>::from` if type annotations are needed", + ToType::Tuple => "use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed", + } + } +} + +fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToType) -> bool { + if !is_from_proc_macro(cx, expr) { + span_lint_and_help( + cx, + TUPLE_ARRAY_CONVERSIONS, + expr.span, + to_type.msg(), + None, + to_type.help(), + ); + + return true; + } + + false +} + +fn should_lint<'tcx>( + cx: &LateContext<'tcx>, + elements: &'tcx [Expr<'tcx>], + map: impl FnMut((usize, &'tcx Expr<'tcx>)) -> Option<(usize, &Expr<'_>)>, + predicate: impl FnMut((HirId, &Node<'tcx>)) -> bool, +) -> bool { + if let Some(elements) = elements + .iter() + .enumerate() + .map(map) + .collect::>>() + && let Some(locals) = elements + .iter() + .map(|(_, element)| path_to_local(element).and_then(|local| cx.tcx.hir().find(local))) + .collect::>>() + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let parent = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).map(|i| (parent, i)).all(predicate) + { + return true; + } + + false +} diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 2920684ade33c..a9deee9678495 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource}; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{BytePos, Pos, Span, SyntaxContext}; declare_clippy_lint! { @@ -92,7 +92,22 @@ declare_clippy_lint! { "annotating safe code with a safety comment" } -declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]); +#[derive(Copy, Clone)] +pub struct UndocumentedUnsafeBlocks { + accept_comment_above_statement: bool, + accept_comment_above_attributes: bool, +} + +impl UndocumentedUnsafeBlocks { + pub fn new(accept_comment_above_statement: bool, accept_comment_above_attributes: bool) -> Self { + Self { + accept_comment_above_statement, + accept_comment_above_attributes, + } + } +} + +impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]); impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { @@ -101,7 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span) - && !block_parents_have_safety_comment(cx, block.hir_id) + && !block_parents_have_safety_comment( + self.accept_comment_above_statement, + self.accept_comment_above_attributes, + cx, + block.hir_id, + ) { let source_map = cx.tcx.sess.source_map(); let span = if source_map.is_multiline(block.span) { @@ -313,29 +333,95 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { // Checks if any parent {expression, statement, block, local, const, static} // has a safety comment -fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool { +fn block_parents_have_safety_comment( + accept_comment_above_statement: bool, + accept_comment_above_attributes: bool, + cx: &LateContext<'_>, + id: hir::HirId, +) -> bool { if let Some(node) = get_parent_node(cx.tcx, id) { return match node { - Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span), + Node::Expr(expr) => { + if let Some( + Node::Local(hir::Local { span, .. }) + | Node::Item(hir::Item { + kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + span, + .. + }), + ) = get_parent_node(cx.tcx, expr.hir_id) + { + let hir_id = match get_parent_node(cx.tcx, expr.hir_id) { + Some(Node::Local(hir::Local { hir_id, .. })) => *hir_id, + Some(Node::Item(hir::Item { owner_id, .. })) => { + cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id) + }, + _ => unreachable!(), + }; + + // if unsafe block is part of a let/const/static statement, + // and accept_comment_above_statement is set to true + // we accept the safety comment in the line the precedes this statement. + accept_comment_above_statement + && span_with_attrs_in_body_has_safety_comment( + cx, + *span, + hir_id, + accept_comment_above_attributes, + ) + } else { + !is_branchy(expr) + && span_with_attrs_in_body_has_safety_comment( + cx, + expr.span, + expr.hir_id, + accept_comment_above_attributes, + ) + } + }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { span, .. }) - | hir::StmtKind::Expr(hir::Expr { span, .. }) - | hir::StmtKind::Semi(hir::Expr { span, .. }), + hir::StmtKind::Local(hir::Local { span, hir_id, .. }) + | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) + | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. }) - | Node::Local(hir::Local { span, .. }) - | Node::Item(hir::Item { + | Node::Local(hir::Local { span, hir_id, .. }) => { + span_with_attrs_in_body_has_safety_comment(cx, *span, *hir_id, accept_comment_above_attributes) + }, + Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, + owner_id, .. - }) => span_in_body_has_safety_comment(cx, *span), + }) => span_with_attrs_in_body_has_safety_comment( + cx, + *span, + cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id), + accept_comment_above_attributes, + ), _ => false, }; } false } +/// Extends `span` to also include its attributes, then checks if that span has a safety comment. +fn span_with_attrs_in_body_has_safety_comment( + cx: &LateContext<'_>, + span: Span, + hir_id: HirId, + accept_comment_above_attributes: bool, +) -> bool { + let span = if accept_comment_above_attributes { + include_attrs_in_span(cx, hir_id, span) + } else { + span + }; + + span_in_body_has_safety_comment(cx, span) +} + /// Checks if an expression is "branchy", e.g. loop, match/if/etc. fn is_branchy(expr: &hir::Expr<'_>) -> bool { matches!( @@ -360,6 +446,15 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { ) || span_in_body_has_safety_comment(cx, span) } +fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { + span.to(cx + .tcx + .hir() + .attrs(hir_id) + .iter() + .fold(span, |acc, attr| acc.to(attr.span))) +} + enum HasSafetyComment { Yes(BytePos), No, @@ -546,7 +641,14 @@ 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::Local(_) + | Node::Item(hir::Item { + kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + .. + }) => (), _ => break, } } diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index 117dda092223e..5e42cf7e4f3f6 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_def_id_trait_method; use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; @@ -91,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { span: Span, def_id: LocalDefId, ) { - if !span.from_expansion() && fn_kind.asyncness().is_async() { + if !span.from_expansion() && fn_kind.asyncness().is_async() && !is_def_id_trait_method(cx, def_id) { let mut visitor = AsyncFnVisitor { cx, found_await: false, diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs index 1d2d3eb12e114..4df1e3299ed9c 100644 --- a/clippy_lints/src/upper_case_acronyms.rs +++ b/clippy_lints/src/upper_case_acronyms.rs @@ -65,7 +65,7 @@ fn correct_ident(ident: &str) -> String { let mut ident = fragments.clone().next().unwrap(); for (ref prev, ref curr) in fragments.tuple_windows() { - if [prev, curr] + if <[&String; 2]>::from((prev, curr)) .iter() .all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase()) { diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 28c3fc859e332..b6c11cfb35568 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,16 +1,17 @@ -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_ty_alias; -use clippy_utils::source::{snippet, snippet_with_context}; +use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::sym; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -43,6 +44,64 @@ pub struct UselessConversion { impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]); +enum MethodOrFunction { + Method, + Function, +} + +impl MethodOrFunction { + /// Maps the argument position in `pos` to the parameter position. + /// For methods, `self` is skipped. + fn param_pos(self, pos: usize) -> usize { + match self { + MethodOrFunction::Method => pos + 1, + MethodOrFunction::Function => pos, + } + } +} + +/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` +fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option { + cx.tcx + .predicates_of(fn_did) + .predicates + .iter() + .find_map(|&(ref pred, span)| { + if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() + && tr.def_id() == into_iter_did + && tr.self_ty().is_param(param_index) + { + Some(span) + } else { + None + } + }) +} + +/// Extracts the receiver of a `.into_iter()` method call. +fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { + if let ExprKind::MethodCall(name, recv, _, _) = expr.kind + && is_trait_method(cx, expr, sym::IntoIterator) + && name.ident.name == sym::into_iter + { + Some(recv) + } else { + None + } +} + +/// Same as [`into_iter_call`], but tries to look for the innermost `.into_iter()` call, e.g.: +/// `foo.into_iter().into_iter()` +/// ^^^ we want this expression +fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> (&'hir Expr<'hir>, usize) { + let mut depth = 0; + while let Some(recv) = into_iter_call(cx, expr) { + expr = recv; + depth += 1; + } + (expr, depth) +} + #[expect(clippy::too_many_lines)] impl<'tcx> LateLintPass<'tcx> for UselessConversion { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { @@ -82,9 +141,59 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ); } } - if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter { - if get_parent_expr(cx, e).is_some() && - let Some(id) = path_to_local(recv) && + if let Some(into_iter_recv) = into_iter_call(cx, e) + // Make sure that there is no parent expression, or if there is, make sure it's not a `.into_iter()` call. + // The reason for that is that we only want to lint once (the outermost call) + // in cases like `foo.into_iter().into_iter()` + && get_parent_expr(cx, e) + .and_then(|parent| into_iter_call(cx, parent)) + .is_none() + { + if let Some(parent) = get_parent_expr(cx, e) { + let parent_fn = match parent.kind { + ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => { + cx.qpath_res(qpath, recv.hir_id).opt_def_id() + .map(|did| (did, args, MethodOrFunction::Function)) + } + ExprKind::MethodCall(.., args, _) => { + cx.typeck_results().type_dependent_def_id(parent.hir_id) + .map(|did| (did, args, MethodOrFunction::Method)) + } + _ => None, + }; + + if let Some((parent_fn_did, args, kind)) = parent_fn + && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() + && let Some(arg_pos) = args.iter().position(|x| x.hir_id == e.hir_id) + && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) + && let ty::Param(param) = into_iter_param.kind() + && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) + { + // Get the "innermost" `.into_iter()` call, e.g. given this expression: + // `foo.into_iter().into_iter()` + // ^^^ + let (into_iter_recv, depth) = into_iter_deep_call(cx, into_iter_recv); + + let plural = if depth == 0 { "" } else { "s" }; + let mut applicability = Applicability::MachineApplicable; + let sugg = snippet_with_applicability(cx, into_iter_recv.span.source_callsite(), "", &mut applicability).into_owned(); + span_lint_and_then(cx, USELESS_CONVERSION, e.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { + diag.span_suggestion( + e.span, + format!("consider removing the `.into_iter()`{plural}"), + sugg, + applicability, + ); + diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`"); + }); + + // Early return to avoid linting again with contradicting suggestions + return; + } + } + + if let Some(id) = path_to_local(recv) && let Node::Pat(pat) = cx.tcx.hir().get(id) && let PatKind::Binding(ann, ..) = pat.kind && ann != BindingAnnotation::MUT diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 35f40830681d6..f1d05c7529bef 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -21,6 +21,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", + "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", @@ -34,6 +35,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "CamelCase", ]; const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; +const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"]; /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. #[derive(Clone, Debug, Deserialize)] @@ -288,11 +290,11 @@ define_Conf! { /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] /// ``` (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet = <_>::default()), - /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS. + /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN. /// /// 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, 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. + /// 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. /// /// The minimum rust version that the project supports (msrv: Option = None), @@ -305,6 +307,10 @@ define_Conf! { /// /// The maximum cognitive complexity a function can have (cognitive_complexity_threshold: u64 = 25), + /// Lint: EXCESSIVE_NESTING. + /// + /// The maximum amount of nesting a block can reside in + (excessive_nesting_threshold: u64 = 0), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. /// /// Use the Cognitive Complexity lint instead. @@ -382,6 +388,10 @@ define_Conf! { /// /// The maximum allowed size for arrays on the stack (array_size_threshold: u64 = 512_000), + /// Lint: LARGE_STACK_FRAMES. + /// + /// The maximum allowed stack size for functions in bytes + (stack_size_threshold: u64 = 512_000), /// Lint: VEC_BOX. /// /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed @@ -514,6 +524,33 @@ define_Conf! { /// /// The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint (unnecessary_box_size: u64 = 128), + /// Lint: MODULE_INCEPTION. + /// + /// Whether to allow module inception if it's not public. + (allow_private_module_inception: bool = false), + /// Lint: MIN_IDENT_CHARS. + /// + /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of + /// the list to indicate, that the configured values should be appended to the default + /// configuration of Clippy. By default, any configuration will replace the default value. + (allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet = + super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()), + /// Lint: MIN_IDENT_CHARS. + /// + /// Minimum chars an ident can have, anything below or equal to this will be linted. + (min_ident_chars_threshold: u64 = 1), + /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. + /// + /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block + (accept_comment_above_statement: bool = false), + /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. + /// + /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block + (accept_comment_above_attributes: bool = false), + /// Lint: UNNECESSARY_RAW_STRING_HASHES. + /// + /// Whether to allow `r#""#` when `r""` can be used + (allow_one_hash_in_raw_strings: bool = false), } /// Search for the configuration file. @@ -581,6 +618,12 @@ pub fn read(sess: &Session, path: &Path) -> TryConf { Ok(mut conf) => { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); + // TODO: THIS SHOULD BE TESTED, this comment will be gone soon + if conf.conf.allowed_idents_below_min_chars.contains(&"..".to_owned()) { + conf.conf + .allowed_idents_below_min_chars + .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); + } conf }, diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 71f6c9909ddda..e222a5448c9cd 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,3 +1,4 @@ +pub mod almost_standard_lint_formulation; pub mod clippy_lints_internal; pub mod collapsible_calls; pub mod compiler_lint_functions; 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 new file mode 100644 index 0000000000000..570a88a0ed2b4 --- /dev/null +++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -0,0 +1,87 @@ +use crate::utils::internal_lints::lint_without_lint_pass::is_lint_ref_type; +use clippy_utils::diagnostics::span_lint_and_help; +use regex::Regex; +use rustc_ast as ast; +use rustc_hir::{Item, ItemKind, Mutability}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// ### What it does + /// Checks if lint formulations have a standardized format. + /// + /// ### Why is this bad? + /// It's not neccessarily bad, but we try to enforce a standard in Clippy. + /// + /// ### Example + /// `Checks for use...` can be written as `Checks for usage...` . + pub ALMOST_STANDARD_LINT_FORMULATION, + internal, + "lint formulations must have a standardized format." +} + +impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]); + +pub struct AlmostStandardFormulation { + standard_formulations: Vec>, +} + +#[derive(Debug)] +struct StandardFormulations<'a> { + wrong_pattern: Regex, + correction: &'a str, +} + +impl AlmostStandardFormulation { + pub fn new() -> Self { + let standard_formulations = vec![StandardFormulations { + wrong_pattern: Regex::new("^(Check for|Detects? uses?)").unwrap(), + correction: "Checks for", + }]; + Self { standard_formulations } + } +} + +impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let mut check_next = false; + if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { + let lines = cx + .tcx + .hir() + .attrs(item.hir_id()) + .iter() + .filter_map(|attr| ast::Attribute::doc_str(attr).map(|sym| (sym, attr))); + if is_lint_ref_type(cx, ty) { + for (line, attr) in lines { + let cur_line = line.as_str().trim(); + if check_next && !cur_line.is_empty() { + for formulation in &self.standard_formulations { + let starts_with_correct_formulation = cur_line.starts_with(formulation.correction); + if !starts_with_correct_formulation && formulation.wrong_pattern.is_match(cur_line) { + if let Some(ident) = attr.ident() { + span_lint_and_help( + cx, + ALMOST_STANDARD_LINT_FORMULATION, + ident.span, + "non-standard lint formulation", + None, + &format!("try using `{}` instead", formulation.correction), + ); + } + return; + } + } + return; + } else if cur_line.contains("What it does") { + check_next = true; + } else if cur_line.contains("Why is this bad") { + // Formulation documentation is done. Can add check to ensure that missing formulation is added + // and add a check if it matches no accepted formulation + return; + } + } + } + } + } +} diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index f8978e30a8e2b..dced9fcf9abd3 100644 --- a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] { for def_id in def_path_def_ids(cx, module) { - for item in cx.tcx.module_children(def_id).iter() { + for item in cx.tcx.module_children(def_id) { if_chain! { if let Res::Def(DefKind::Const, item_def_id) = item.res; let ty = cx.tcx.type_of(item_def_id).subst_identity(); diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 7a1cd3effaef2..107a62806a82b 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -104,6 +104,8 @@ const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved"; /// The version that will be displayed if none has been defined const VERSION_DEFAULT_STR: &str = "Unknown"; +const CHANGELOG_PATH: &str = "../CHANGELOG.md"; + declare_clippy_lint! { /// ### What it does /// Collects metadata about clippy lints for the website. @@ -195,8 +197,14 @@ This lint has the following configuration variables: fn get_markdown_docs(&self) -> String { format!( - "## Lint Configuration Options\n|
Option
| Default Value |\n|--|--|\n{}\n\n{}\n", - self.configs_to_markdown(ClippyConfiguration::to_markdown_table_entry), + r#"# Lint Configuration Options + +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +{}"#, self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph), ) } @@ -254,6 +262,22 @@ Please use that command to update the file and do not edit it by hand. self.get_markdown_docs(), ) .unwrap(); + + // Write configuration links to CHANGELOG.md + let mut changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap(); + let mut changelog_file = OpenOptions::new().read(true).write(true).open(CHANGELOG_PATH).unwrap(); + + if let Some(position) = changelog.find("") { + // I know this is kinda wasteful, we just don't have regex on `clippy_lints` so... this is the best + // we can do AFAIK. + changelog = changelog[..position].to_string(); + } + writeln!( + changelog_file, + "{changelog}\n{}\n", + self.configs_to_markdown(ClippyConfiguration::to_markdown_link) + ) + .unwrap(); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d3ea7cafa80c2..fb08256931f66 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -12,6 +12,9 @@ fn to_kebab(config_name: &str) -> String { config_name.replace('_', "-") } +#[cfg(feature = "internal")] +const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html"; + // ================================================================== // Configuration // ================================================================== @@ -51,7 +54,7 @@ impl ClippyConfiguration { #[cfg(feature = "internal")] fn to_markdown_paragraph(&self) -> String { format!( - "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n", + "## `{}`\n{}\n\n**Default Value:** `{}` (`{}`)\n\n---\n**Affected lints:**\n{}\n\n", self.name, self.doc .lines() @@ -62,14 +65,13 @@ impl ClippyConfiguration { self.lints .iter() .map(|name| name.to_string().split_whitespace().next().unwrap().to_string()) - .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})")) + .map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})")) .join("\n"), ) } - #[cfg(feature = "internal")] - fn to_markdown_table_entry(&self) -> String { - format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default) + fn to_markdown_link(&self) -> String { + format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name) } } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 7329e508106d9..2a594e750b9b2 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,26 +1,32 @@ +use std::ops::ControlFlow; + use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; 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 if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; +use rustc_span::sym; #[expect(clippy::module_name_repetitions)] -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct UselessVec { pub too_large_for_stack: u64, + pub msrv: Msrv, } declare_clippy_lint! { /// ### What it does - /// Checks for usage of `&vec![..]` when using `&[..]` would + /// Checks for usage of `vec![..]` when using `[..]` would /// be possible. /// /// ### Why is this bad? @@ -46,16 +52,73 @@ declare_clippy_lint! { impl_lint_pass!(UselessVec => [USELESS_VEC]); +fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + matches!(cx.typeck_results().expr_ty_adjusted(e).kind(), ty::Ref(_, ty, _) if ty.is_slice()) +} + +/// Checks if the given expression is a method call to a `Vec` method +/// that also exists on slices. If this returns true, it means that +/// this expression does not actually require a `Vec` and could just work with an array. +fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"]; + + if let ExprKind::MethodCall(path, ..) = e.kind { + ALLOWED_METHOD_NAMES.contains(&path.ident.name.as_str()) + } else { + is_trait_method(cx, e, sym::IntoIterator) + } +} + impl<'tcx> LateLintPass<'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // search for `&vec![_]` expressions where the adjusted type is `&[_]` + // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]` if_chain! { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind(); - if let ty::Slice(..) = ty.kind(); - if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; - if let Some(vec_args) = higher::VecArgs::hir(cx, addressee); + if adjusts_to_slice(cx, expr); + if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()); then { - self.check_vec_macro(cx, &vec_args, mutability, expr.span); + let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind { + // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.) + (SuggestedType::SliceRef(mutability), expr.span) + } else { + // `expr` is the `vec![_]` expansion, so suggest `[_]` + // and also use the span of the actual `vec![_]` expression + (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site) + }; + + self.check_vec_macro(cx, &vec_args, span, suggest_slice); + } + } + + // 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) + if let Some(vec_args) = higher::VecArgs::hir(cx, expr) + && let Node::Local(local) = cx.tcx.hir().get_parent(expr.hir_id) + // for now ignore locals with type annotations. + // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..]; + && local.ty.is_none() + && let PatKind::Binding(_, id, ..) = local.pat.kind + && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr))) + { + let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| { + // allow indexing into a vec and some set of allowed method calls that exist on slices, too + if let Some(parent) = get_parent_expr(cx, expr) + && (adjusts_to_slice(cx, expr) + || matches!(parent.kind, ExprKind::Index(..)) + || is_allowed_vec_method(cx, parent)) + { + ControlFlow::Continue(()) + } else { + ControlFlow::Break(()) + } + }).is_continue(); + + if only_slice_uses { + self.check_vec_macro( + cx, + &vec_args, + expr.span.ctxt().outer_expn_data().call_site, + SuggestedType::Array + ); } } @@ -63,25 +126,36 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if_chain! { if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr); if let Some(vec_args) = higher::VecArgs::hir(cx, arg); - if is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(arg))); + if self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR); then { // report the error around the `vec!` not inside `:` let span = arg.span.ctxt().outer_expn_data().call_site; - self.check_vec_macro(cx, &vec_args, Mutability::Not, span); + self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array); } } } + + extract_msrv_attr!(LateContext); +} + +#[derive(Copy, Clone)] +enum SuggestedType { + /// Suggest using a slice `&[..]` / `&mut [..]` + SliceRef(Mutability), + /// Suggest using an array: `[..]` + Array, } impl UselessVec { fn check_vec_macro<'tcx>( - self, + &mut self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, - mutability: Mutability, span: Span, + suggest_slice: SuggestedType, ) { let mut applicability = Applicability::MachineApplicable; + let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) { @@ -90,21 +164,13 @@ impl UselessVec { return; } - match mutability { - Mutability::Mut => { - format!( - "&mut [{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) - }, - Mutability::Not => { - format!( - "&[{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) - }, + let elem = snippet_with_applicability(cx, elem.span, "elem", &mut applicability); + let len = snippet_with_applicability(cx, len.span, "len", &mut applicability); + + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => format!("&mut [{elem}; {len}]"), + SuggestedType::SliceRef(Mutability::Not) => format!("&[{elem}; {len}]"), + SuggestedType::Array => format!("[{elem}; {len}]"), } } else { return; @@ -116,22 +182,24 @@ impl UselessVec { return; } let span = args[0].span.to(last.span); + let args = snippet_with_applicability(cx, span, "..", &mut applicability); - match mutability { - Mutability::Mut => { - format!( - "&mut [{}]", - snippet_with_applicability(cx, span, "..", &mut applicability) - ) + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => { + format!("&mut [{args}]") + }, + SuggestedType::SliceRef(Mutability::Not) => { + format!("&[{args}]") }, - Mutability::Not => { - format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + SuggestedType::Array => { + format!("[{args}]") }, } } else { - match mutability { - Mutability::Mut => "&mut []".into(), - Mutability::Not => "&[]".into(), + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => "&mut []".to_owned(), + SuggestedType::SliceRef(Mutability::Not) => "&[]".to_owned(), + SuggestedType::Array => "[]".to_owned(), } } }, @@ -142,7 +210,13 @@ impl UselessVec { USELESS_VEC, span, "useless use of `vec!`", - "you can use a slice directly", + &format!( + "you can use {} directly", + match suggest_slice { + SuggestedType::SliceRef(_) => "a slice", + SuggestedType::Array => "an array", + } + ), snippet, applicability, ); diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs new file mode 100644 index 0000000000000..43248bccc13d5 --- /dev/null +++ b/clippy_lints/src/visibility.rs @@ -0,0 +1,131 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; +use rustc_ast::ast::{Item, VisibilityKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::kw, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `pub(self)` and `pub(in self)`. + /// + /// ### Why is this bad? + /// It's unnecessary, omitting the `pub` entirely will give the same results. + /// + /// ### Example + /// ```rust,ignore + /// pub(self) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_PUB_SELF, + style, + "checks for usage of `pub(self)` and `pub(in self)`." +} +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `pub()` with `in`. + /// + /// ### Why is this bad? + /// Consistency. Use it or don't, just be consistent about it. + /// + /// Also see the `pub_without_shorthand` lint for an alternative. + /// + /// ### Example + /// ```rust,ignore + /// pub(super) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// pub(in super) type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub PUB_WITH_SHORTHAND, + restriction, + "disallows usage of `pub()`, without `in`" +} +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `pub()` without `in`. + /// + /// Note: As you cannot write a module's path in `pub()`, this will only trigger on + /// `pub(super)` and the like. + /// + /// ### Why is this bad? + /// Consistency. Use it or don't, just be consistent about it. + /// + /// Also see the `pub_with_shorthand` lint for an alternative. + /// + /// ### Example + /// ```rust,ignore + /// pub(in super) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// pub(super) type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub PUB_WITHOUT_SHORTHAND, + restriction, + "disallows usage of `pub(in )` with `in`" +} +declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WITHOUT_SHORTHAND]); + +impl EarlyLintPass for Visibility { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if !in_external_macro(cx.sess(), item.span) + && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind + { + if **path == kw::SelfLower && let Some(false) = is_from_proc_macro(cx, item.vis.span) { + span_lint_and_sugg( + cx, + NEEDLESS_PUB_SELF, + item.vis.span, + &format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }), + "remove it", + String::new(), + Applicability::MachineApplicable, + ); + } + + if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate) + && !*shorthand + && let [.., last] = &*path.segments + && let Some(false) = is_from_proc_macro(cx, item.vis.span) + { + span_lint_and_sugg( + cx, + PUB_WITHOUT_SHORTHAND, + item.vis.span, + "usage of `pub` with `in`", + "remove it", + format!("pub({})", last.ident), + Applicability::MachineApplicable, + ); + } + + if *shorthand + && let [.., last] = &*path.segments + && let Some(false) = is_from_proc_macro(cx, item.vis.span) + { + span_lint_and_sugg( + cx, + PUB_WITH_SHORTHAND, + item.vis.span, + "usage of `pub` without `in`", + "add it", + format!("pub(in {})", last.ident), + Applicability::MachineApplicable, + ); + } + } + } +} + +fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option { + snippet_opt(cx, span).map(|s| !s.starts_with("pub")) +} diff --git a/clippy_test_deps/Cargo.toml b/clippy_test_deps/Cargo.toml new file mode 100644 index 0000000000000..362c08e0d7790 --- /dev/null +++ b/clippy_test_deps/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "clippy_test_deps" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clippy_utils = { path = "../clippy_utils" } +derive-new = "0.5" +if_chain = "1.0" +itertools = "0.10.1" +quote = "1.0" +serde = { version = "1.0.125", features = ["derive"] } +syn = { version = "2.0", features = ["full"] } +futures = "0.3" +parking_lot = "0.12" +tokio = { version = "1", features = ["io-util"] } +regex = "1.5" +clippy_lints = { path = "../clippy_lints" } + +[features] +internal = ["clippy_lints/internal"] diff --git a/clippy_test_deps/src/lib.rs b/clippy_test_deps/src/lib.rs new file mode 100644 index 0000000000000..7d12d9af8195b --- /dev/null +++ b/clippy_test_deps/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 9edaae853734c..c6d0b654f57b6 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -12,25 +12,33 @@ //! code was written, and check if the span contains that text. Note this will only work correctly //! if the span is not from a `macro_rules` based macro. -use rustc_ast::ast::{IntTy, LitIntType, LitKind, StrStyle, UintTy}; +use rustc_ast::{ + ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy}, + token::CommentKind, + AttrStyle, +}; use rustc_hir::{ intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, - Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, Node, QPath, TraitItem, - TraitItemKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, + TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; /// The search pattern to look for. Used by `span_matches_pat` -#[derive(Clone, Copy)] +#[derive(Clone)] pub enum Pat { /// A single string. Str(&'static str), + /// A single string. + OwnedStr(String), /// Any of the given strings. MultiStr(&'static [&'static str]), + /// Any of the given strings. + OwnedMultiStr(Vec), /// The string representation of the symbol. Sym(Symbol), /// Any decimal or hexadecimal digit depending on the location. @@ -51,12 +59,16 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ','); (match start_pat { Pat::Str(text) => start_str.starts_with(text), + Pat::OwnedStr(text) => start_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), + Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), } && match end_pat { Pat::Str(text) => end_str.ends_with(text), + Pat::OwnedStr(text) => end_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)), + Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit), }) @@ -271,14 +283,79 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI (start_pat, end_pat) } -pub trait WithSearchPat { +fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { + match attr.kind { + AttrKind::Normal(..) => { + let mut pat = if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("#["), Pat::Str("]")) + } else { + (Pat::Str("#!["), Pat::Str("]")) + }; + + if let Some(ident) = attr.ident() && let Pat::Str(old_pat) = pat.0 { + // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of + // refactoring + // NOTE: This will likely have false positives, like `allow = 1` + pat.0 = Pat::OwnedMultiStr(vec![ident.to_string(), old_pat.to_owned()]); + pat.1 = Pat::Str(""); + } + + pat + }, + AttrKind::DocComment(_kind @ CommentKind::Line, ..) => { + if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("///"), Pat::Str("")) + } else { + (Pat::Str("//!"), Pat::Str("")) + } + }, + AttrKind::DocComment(_kind @ CommentKind::Block, ..) => { + if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("/**"), Pat::Str("*/")) + } else { + (Pat::Str("/*!"), Pat::Str("*/")) + } + }, + } +} + +fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { + match ty.kind { + TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), + TyKind::Ptr(MutTy { mutbl, ty }) => ( + if mutbl.is_mut() { + Pat::Str("*const") + } else { + Pat::Str("*mut") + }, + ty_search_pat(ty).1, + ), + TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::BareFn(bare_fn) => ( + Pat::OwnedStr(format!("{}{} fn", bare_fn.unsafety.prefix_str(), bare_fn.abi.name())), + ty_search_pat(ty).1, + ), + TyKind::Never => (Pat::Str("!"), Pat::Str("")), + TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")), + TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), + TyKind::Path(qpath) => qpath_search_pat(&qpath), + // NOTE: This is missing `TraitObject`. It always return true then. + _ => (Pat::Str(""), Pat::Str("")), + } +} + +fn ident_search_pat(ident: Ident) -> (Pat, Pat) { + (Pat::OwnedStr(ident.name.as_str().to_owned()), Pat::Str("")) +} + +pub trait WithSearchPat<'cx> { type Context: LintContext; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); fn span(&self) -> Span; } macro_rules! impl_with_search_pat { ($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))?) => { - impl<'cx> WithSearchPat for $ty<'cx> { + impl<'cx> WithSearchPat<'cx> for $ty<'cx> { type Context = $cx<'cx>; #[allow(unused_variables)] fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { @@ -297,8 +374,9 @@ impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat); impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat); impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat); impl_with_search_pat!(LateContext: Variant with variant_search_pat); +impl_with_search_pat!(LateContext: Ty with ty_search_pat); -impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { +impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { type Context = LateContext<'cx>; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { @@ -310,11 +388,37 @@ impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { } } +// `Attribute` does not have the `hir` associated lifetime, so we cannot use the macro +impl<'cx> WithSearchPat<'cx> for &'cx Attribute { + type Context = LateContext<'cx>; + + fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { + attr_search_pat(self) + } + + fn span(&self) -> Span { + self.span + } +} + +// `Ident` does not have the `hir` associated lifetime, so we cannot use the macro +impl<'cx> WithSearchPat<'cx> for Ident { + type Context = LateContext<'cx>; + + fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { + ident_search_pat(*self) + } + + fn span(&self) -> Span { + self.span + } +} + /// Checks if the item likely came from a proc-macro. /// /// This should be called after `in_external_macro` and the initial pattern matching of the ast as /// it is significantly slower than both of those. -pub fn is_from_proc_macro(cx: &T::Context, item: &T) -> bool { +pub fn is_from_proc_macro<'cx, T: WithSearchPat<'cx>>(cx: &T::Context, item: &T) -> bool { let (start_pat, end_pat) = item.search_pat(cx); !span_matches_pat(cx.sess(), item.span(), start_pat, end_pat) } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index cc3183759ae7a..068820801dfe0 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; +use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir; @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt}; use rustc_middle::ty::{List, SubstsRef}; use rustc_middle::{bug, span_bug}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; use std::cmp::Ordering::{self, Equal}; use std::hash::{Hash, Hasher}; @@ -22,7 +22,8 @@ use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] -pub enum Constant { +pub enum Constant<'tcx> { + Adt(rustc_middle::mir::ConstantKind<'tcx>), /// A `String` (e.g., "abc"). Str(String), /// A binary string (e.g., `b"abc"`). @@ -38,20 +39,20 @@ pub enum Constant { /// `true` or `false`. Bool(bool), /// An array of constants. - Vec(Vec), + Vec(Vec>), /// Also an array, but with only one constant, repeated N times. - Repeat(Box, u64), + Repeat(Box>, u64), /// A tuple of constants. - Tuple(Vec), + Tuple(Vec>), /// A raw pointer. RawPtr(u128), /// A reference - Ref(Box), + Ref(Box>), /// A literal with syntax error. Err, } -impl PartialEq for Constant { +impl<'tcx> PartialEq for Constant<'tcx> { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Str(ls), Self::Str(rs)) => ls == rs, @@ -80,13 +81,16 @@ impl PartialEq for Constant { } } -impl Hash for Constant { +impl<'tcx> Hash for Constant<'tcx> { fn hash(&self, state: &mut H) where H: Hasher, { std::mem::discriminant(self).hash(state); match *self { + Self::Adt(ref elem) => { + elem.hash(state); + }, Self::Str(ref s) => { s.hash(state); }, @@ -126,7 +130,7 @@ impl Hash for Constant { } } -impl Constant { +impl<'tcx> Constant<'tcx> { pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option { match (left, right) { (Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)), @@ -209,7 +213,7 @@ impl Constant { } /// Parses a `LitKind` to a `Constant`. -pub fn lit_to_mir_constant(lit: &LitKind, ty: Option>) -> Constant { +pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constant<'tcx> { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), @@ -248,7 +252,7 @@ pub fn constant<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option { +) -> Option> { ConstEvalLateContext::new(lcx, typeck_results).expr(e) } @@ -257,7 +261,7 @@ pub fn constant_with_source<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option<(Constant, ConstantSource)> { +) -> Option<(Constant<'tcx>, ConstantSource)> { let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results); let res = ctxt.expr(e); res.map(|x| (x, ctxt.source)) @@ -268,7 +272,7 @@ pub fn constant_simple<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option { +) -> Option> { constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c)) } @@ -338,8 +342,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } /// Simple constant folding: Insert an expression, get a constant or none. - pub fn expr(&mut self, e: &Expr<'_>) -> Option { + pub fn expr(&mut self, e: &Expr<'_>) -> Option> { 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::Block(block, _) => self.block(block), ExprKind::Lit(lit) => { @@ -392,13 +398,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { }, ExprKind::Index(arr, index) => self.index(arr, index), ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))), - // TODO: add other expressions. + ExprKind::Field(local_expr, ref field) => { + let result = self.expr(local_expr); + if let Some(Constant::Adt(constant)) = &self.expr(local_expr) + && let ty::Adt(adt_def, _) = constant.ty().kind() + && adt_def.is_struct() + && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field) + { + miri_to_const(self.lcx, desired_field) + } + else { + result + } + }, _ => None, } } #[expect(clippy::cast_possible_wrap)] - fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option { + fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option> { use self::Constant::{Bool, Int}; match *o { Bool(b) => Some(Bool(!b)), @@ -414,7 +432,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option { + fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option> { use self::Constant::{Int, F32, F64}; match *o { Int(value) => { @@ -433,28 +451,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Create `Some(Vec![..])` of all constants, unless there is any /// non-constant part. - fn multi(&mut self, vec: &[Expr<'_>]) -> Option> { + fn multi(&mut self, vec: &[Expr<'_>]) -> Option>> { 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 { + fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option> { let res = self.typeck_results.qpath_res(qpath, id); match res { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { // Check if this constant is based on `cfg!(..)`, // which is NOT constant for our purposes. - if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) && - let Node::Item(&Item { - kind: ItemKind::Const(_, body_id), - .. - }) = node && - let Node::Expr(&Expr { - kind: ExprKind::Lit(_), - span, - .. - }) = self.lcx.tcx.hir().get(body_id.hir_id) && - is_direct_expn_of(span, "cfg").is_some() { + if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) + && let Node::Item(Item { kind: ItemKind::Const(_, body_id), .. }) = node + && let Node::Expr(Expr { kind: ExprKind::Lit(_), span, .. }) = self.lcx + .tcx + .hir() + .get(body_id.hir_id) + && is_direct_expn_of(*span, "cfg").is_some() + { return None; } @@ -464,23 +479,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } else { EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs) }; - let result = self .lcx .tcx .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None) .ok() .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?; - let result = miri_to_const(self.lcx.tcx, result)?; + let result = miri_to_const(self.lcx, result)?; self.source = ConstantSource::Constant; Some(result) }, - // FIXME: cover all usable cases. _ => None, } } - fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option { + fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option> { let lhs = self.expr(lhs); let index = self.expr(index); @@ -506,7 +519,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } /// A block can only yield a constant if it only has one constant expression. - fn block(&mut self, block: &Block<'_>) -> Option { + fn block(&mut self, block: &Block<'_>) -> Option> { if block.stmts.is_empty() && let Some(expr) = block.expr { @@ -539,7 +552,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option { + fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option> { if let Some(Constant::Bool(b)) = self.expr(cond) { if b { self.expr(then) @@ -551,7 +564,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option { + fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { @@ -644,23 +657,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option { +pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option> { use rustc_middle::mir::interpret::ConstValue; match result { - mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => { - match result.ty().kind() { - ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), - ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), - ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( - int.try_into().expect("invalid f32 bit representation"), - ))), - 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()))), - // FIXME: implement other conversions. - _ => None, - } + mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() { + ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), + ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), + ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), + ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( + int.try_into().expect("invalid f32 bit representation"), + ))), + 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()))), + _ => None, }, mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() { ty::Ref(_, tam, _) => match tam.kind() { @@ -676,35 +687,53 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - _ => None, }, mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { + ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) { + ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) .to_owned() .array_chunks::<4>() .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk)))) - .collect::>>() + .collect::>>>() .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) { + ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) .to_owned() .array_chunks::<8>() .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk)))) - .collect::>>() + .collect::>>>() .map(Constant::Vec), _ => None, }, - // FIXME: implement other array type conversions. _ => None, }, _ => None, }, - // FIXME: implement other conversions. _ => None, } } + +fn field_of_struct<'tcx>( + adt_def: ty::AdtDef<'tcx>, + lcx: &LateContext<'tcx>, + result: mir::ConstantKind<'tcx>, + field: &Ident, +) -> Option> { + let dc = lcx.tcx.destructure_mir_constant(lcx.param_env, result); + if let Some(dc_variant) = dc.variant + && let Some(variant) = adt_def.variants().get(dc_variant) + && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) + && let Some(dc_field) = dc.fields.get(field_idx) + { + Some(*dc_field) + } + else { + None + } +} diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 659c693f87aee..4a845ca63b49f 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; +use rustc_middle::ty::adjustment::Adjust; use rustc_span::{sym, Symbol}; use std::cmp; use std::ops; @@ -114,6 +115,20 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS if self.eagerness == ForceNoChange { return; } + + // Autoderef through a user-defined `Deref` impl can have side-effects, + // so don't suggest changing it. + if self + .cx + .typeck_results() + .expr_adjustments(e) + .iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) + { + self.eagerness |= NoChange; + return; + } + match e.kind { ExprKind::Call( &Expr { @@ -173,11 +188,15 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS self.eagerness = Lazy; } }, - + // Custom `Deref` impl might have side effects + ExprKind::Unary(UnOp::Deref, e) + if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => + { + self.eagerness |= NoChange; + }, // Dereferences should be cheap, but dereferencing a raw pointer earlier may not be safe. ExprKind::Unary(UnOp::Deref, e) if !self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => (), ExprKind::Unary(UnOp::Deref, _) => self.eagerness |= NoChange, - ExprKind::Unary(_, e) if matches!( self.cx.typeck_results().expr_ty(e).kind(), diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8c883445a7984..727b59f1f432a 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -20,6 +20,7 @@ extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_attr; +extern crate rustc_const_eval; extern crate rustc_data_structures; // The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate. #[allow(unused_extern_crates)] @@ -326,6 +327,18 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) .map_or(false, |did| is_diag_trait_item(cx, did, diag_item)) } +/// Checks if the `def_id` belongs to a function that is part of a trait impl. +pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { + if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id) + && let Node::Item(item) = cx.tcx.hir().get_parent(hir_id) + && let ItemKind::Impl(imp) = item.kind + { + imp.of_trait.is_some() + } else { + false + } +} + /// Checks if the given expression is a path referring an item on the trait /// that is marked with the given diagnostic item. /// @@ -1498,7 +1511,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree())) && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty) - && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind) + && let Some(min_const) = miri_to_const(cx, min_const_kind) && let Some(start_const) = constant(cx, cx.typeck_results(), start) { start_const == min_const @@ -1514,7 +1527,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree())) && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty) - && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind) + && let Some(max_const) = miri_to_const(cx, max_const_kind) && let Some(end_const) = constant(cx, cx.typeck_results(), end) { end_const == max_const @@ -2396,7 +2409,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol /// Checks if the function containing the given `HirId` is a `#[test]` function /// -/// Note: Add `// compile-flags: --test` to UI tests with 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 { with_test_item_names(tcx, tcx.parent_module(id), |names| { tcx.hir() @@ -2418,7 +2431,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { /// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied /// -/// Note: Add `// compile-flags: --test` to UI tests with a `#[cfg(test)]` function +/// Note: Add `//@compile-flags: --test` to UI tests with a `#[cfg(test)]` function pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { fn is_cfg_test(attr: &Attribute) -> bool { if attr.has_name(sym::cfg) @@ -2440,7 +2453,7 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { /// Checks whether item either has `test` attribute applied, or /// is a module with `test` in its name. /// -/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function +/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { is_in_test_function(tcx, item.hir_id()) || matches!(item.kind, ItemKind::Mod(..)) diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index e4a4936ff42fc..00f3abaec8a44 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -9,7 +9,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::LateContext; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; -use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol}; +use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol}; use std::cell::RefCell; use std::ops::ControlFlow; use std::sync::atomic::{AtomicBool, Ordering}; @@ -415,8 +415,18 @@ 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> { + let SpanData { + lo, + hi, + ctxt, + parent: _, + } = target.expr.span.data(); + for_each_expr(start, |expr| { - if expr.span == target.expr.span { + // When incremental compilation is enabled spans gain a parent during AST to HIR lowering, + // since we're comparing an AST span to a HIR one we need to ignore the parent field + let data = expr.span.data(); + if data.lo == lo && data.hi == hi && data.ctxt == ctxt { ControlFlow::Break(expr) } else { ControlFlow::Continue(()) diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 6f102308f0bf6..3637476c40872 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -19,6 +19,8 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,71,0 { TUPLE_ARRAY_CONVERSIONS } + 1,70,0 { OPTION_IS_SOME_AND } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } @@ -28,7 +30,7 @@ msrv_aliases! { 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS } 1,50,0 { BOOL_THEN, CLAMP } - 1,47,0 { TAU, IS_ASCII_DIGIT_CONST } + 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 } @@ -42,11 +44,13 @@ msrv_aliases! { 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,28,0 { FROM_BOOL } + 1,27,0 { ITERATOR_TRY_FOLD } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN } 1,24,0 { IS_ASCII_DIGIT } 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } + 1,15,0 { MAYBE_BOUND_IN_WHERE } } fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs index c225398ad2a8f..bbe4149fe2ab2 100644 --- a/clippy_utils/src/numeric_literal.rs +++ b/clippy_utils/src/numeric_literal.rs @@ -161,7 +161,7 @@ impl<'a> NumericLiteral<'a> { } if let Some((separator, exponent)) = self.exponent { - if exponent != "0" { + if !exponent.is_empty() && exponent != "0" { output.push_str(separator); Self::group_digits(&mut output, exponent, group_size, true, false); } diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index b7e83ce6caaca..c9938caefb067 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -4,17 +4,24 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::Msrv; +use hir::LangItem; +use rustc_const_eval::transform::check_consts::ConstCx; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::Obligation; use rustc_middle::mir::{ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; +use rustc_middle::traits::{ImplSource, ObligationCause}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_middle::ty::{BoundConstness, TraitRef}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -32,7 +39,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) body.local_decls.iter().next().unwrap().source_info.span, )?; - for bb in body.basic_blocks.iter() { + for bb in &*body.basic_blocks { check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { check_statement(tcx, body, def_id, stmt)?; @@ -60,7 +67,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { return Err((span, "function pointers in const fn are unstable".into())); }, ty::Dynamic(preds, _, _) => { - for pred in preds.iter() { + for pred in *preds { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { return Err(( @@ -227,7 +234,19 @@ fn check_statement<'tcx>( fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { match operand { - Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body), + Operand::Move(place) => { + if !place.projection.as_ref().is_empty() + && !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) + { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + + check_place(tcx, *place, span, body) + }, + Operand::Copy(place) => check_place(tcx, *place, span, body), Operand::Constant(c) => match c.check_static_ptr(tcx) { Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), @@ -236,12 +255,10 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b } fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { - let mut cursor = place.projection.as_ref(); - while let [ref proj_base @ .., elem] = *cursor { - cursor = proj_base; + for (base, elem) in place.as_ref().iter_projections() { match elem { ProjectionElem::Field(..) => { - let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; + let base_ty = base.ty(body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` if def.is_union() { @@ -276,15 +293,19 @@ fn check_terminator<'tcx>( | TerminatorKind::Resume | TerminatorKind::Terminate | TerminatorKind::Unreachable => Ok(()), - - TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), - + TerminatorKind::Drop { place, .. } => { + if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + Ok(()) + }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), - TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn generators are unstable".into())) }, - TerminatorKind::Call { func, args, @@ -328,7 +349,6 @@ fn check_terminator<'tcx>( Err((span, "can only call other const fns within const fn".into())) } }, - TerminatorKind::Assert { cond, expected: _, @@ -336,7 +356,6 @@ fn check_terminator<'tcx>( target: _, unwind: _, } => check_operand(tcx, cond, span, body), - TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } @@ -350,8 +369,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver` - // doesn't accept the `-dev` version number so we have to strip it - // off. + // doesn't accept the `-dev` version number so we have to strip it off. let short_version = since .as_str() .split('-') @@ -369,3 +387,35 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { } }) } + +#[expect(clippy::similar_names)] // bit too pedantic +fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { + // Avoid selecting for simple cases, such as builtin types. + if ty::util::is_trivially_const_drop(ty) { + return true; + } + + let obligation = Obligation::new( + tcx, + ObligationCause::dummy_with_span(body.span), + ConstCx::new(tcx, body).param_env.with_const(), + TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst), + ); + + let infcx = tcx.infer_ctxt().build(); + let mut selcx = SelectionContext::new(&infcx); + let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { + return false; + }; + + if !matches!( + impl_src, + ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ) { + return false; + } + + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(impl_src.nested_obligations()); + ocx.select_all_or_error().is_empty() +} diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index b38b9553558c8..cf781e18cd66e 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -944,7 +944,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { }, // item is used in a call // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)` - ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => { + ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => { let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id); let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind(); diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 8d3aecd4785b1..9c39d22c61b2a 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -17,8 +17,8 @@ use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, - Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, + Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + UintTy, VariantDef, VariantDiscr, }; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; @@ -277,7 +277,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { false }, ty::Dynamic(binder, _, _) => { - for predicate in binder.iter() { + for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) { return true; @@ -760,9 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - ty::ClauseKind::Projection(p) - if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => - { + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? return None; @@ -1180,3 +1178,51 @@ pub fn is_interior_mut_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { _ => false, } } + +pub fn make_normalized_projection_with_regions<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + container_id: DefId, + assoc_ty: Symbol, + substs: impl IntoIterator>>, +) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + #[cfg(debug_assertions)] + if let Some((i, subst)) = ty + .substs + .iter() + .enumerate() + .find(|(_, subst)| subst.has_late_bound_regions()) + { + debug_assert!( + false, + "substs contain late-bound region at index `{i}` which can't be normalized.\n\ + use `TyCtxt::erase_late_bound_regions`\n\ + note: subst is `{subst:#?}`", + ); + return None; + } + let cause = rustc_middle::traits::ObligationCause::dummy(); + match tcx + .infer_ctxt() + .build() + .at(&cause, param_env) + .query_normalize(tcx.mk_projection(ty.def_id, ty.substs)) + { + Ok(ty) => Some(ty.value), + Err(e) => { + debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); + None + }, + } + } + helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, substs)?) +} + +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(); + 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 ab3976a13bdbb..9855085216feb 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -82,7 +82,7 @@ pub struct ParamBindingIdCollector { impl<'tcx> ParamBindingIdCollector { fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec { let mut hir_ids: Vec = Vec::new(); - for param in body.params.iter() { + for param in body.params { let mut finder = ParamBindingIdCollector { binding_hir_ids: Vec::new(), }; diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs index 5232e4ab7d754..0057256f659b5 100644 --- a/declare_clippy_lint/src/lib.rs +++ b/declare_clippy_lint/src/lib.rs @@ -85,8 +85,8 @@ impl Parse for ClippyLint { /// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions. /// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or /// `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of. -/// 4. The `description` that contains a short explanation on what's wrong with code where the -/// lint is triggered. +/// 4. The `description` that contains a short explanation on what's wrong with code where the lint +/// is triggered. /// /// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are /// enabled by default. As said in the README.md of this repository, if the lint level mapping diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 03d1877d6c644..de56a6f82757d 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -474,7 +474,7 @@ fn read_crates(toml_path: &Path) -> (Vec, RecursiveOptions) { }); } else if let Some(ref versions) = tk.versions { // if we have multiple versions, save each one - for ver in versions.iter() { + for ver in versions { crate_sources.push(CrateSource::CratesIo { name: tk.name.clone(), version: ver.to_string(), diff --git a/rust-toolchain b/rust-toolchain index 0d2e1eee64384..4475d914cedb0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-06-02" +channel = "nightly-2023-06-29" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/rustfmt.toml b/rustfmt.toml index 10d39762043ea..18b2a33469da3 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -5,3 +5,4 @@ wrap_comments = true edition = "2021" error_on_line_overflow = true version = "Two" +ignore = ["tests/ui/crashes/ice-10912.rs"] diff --git a/src/driver.rs b/src/driver.rs index f3cc94aeff01c..1eb288b153a5a 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -16,9 +16,9 @@ extern crate rustc_session; extern crate rustc_span; use rustc_interface::interface; -use rustc_session::EarlyErrorHandler; use rustc_session::config::ErrorOutputType; use rustc_session::parse::ParseSess; +use rustc_session::EarlyErrorHandler; use rustc_span::symbol::Symbol; use std::env; diff --git a/src/main.rs b/src/main.rs index 188ff87abfc53..cdc85cb33ca2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use std::env; use std::path::PathBuf; use std::process::{self, Command}; -const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. +const CARGO_CLIPPY_HELP: &str = "Checks a package to catch common mistakes and improve your Rust code. Usage: cargo clippy [options] [--] [...] @@ -31,7 +31,7 @@ with: You can use tool lints to allow or deny lints from your code, e.g.: #[allow(clippy::needless_lifetimes)] -"#; +"; fn show_help() { println!("{CARGO_CLIPPY_HELP}"); @@ -57,7 +57,9 @@ pub fn main() { if let Some(pos) = env::args().position(|a| a == "--explain") { if let Some(mut lint) = env::args().nth(pos + 1) { lint.make_ascii_lowercase(); - clippy_lints::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_")); + process::exit(clippy_lints::explain( + &lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"), + )); } else { show_help(); } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 35d75cc51c210..dce6f2fc27269 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -4,16 +4,14 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] -use compiletest_rs as compiletest; -use compiletest_rs::common::Mode as TestMode; +use compiletest::{status_emitter, CommandBuilder}; +use ui_test as compiletest; +use ui_test::Mode as TestMode; -use std::collections::HashMap; use std::env::{self, remove_var, set_var, var_os}; use std::ffi::{OsStr, OsString}; use std::fs; -use std::io; use std::path::{Path, PathBuf}; -use std::sync::LazyLock; use test_utils::IS_RUSTC_TEST_SUITE; mod test_utils; @@ -21,143 +19,41 @@ mod test_utils; // whether to run internal tests or not const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); -/// All crates used in UI tests are listed here -static TEST_DEPENDENCIES: &[&str] = &[ - "clippy_lints", - "clippy_utils", - "derive_new", - "futures", - "if_chain", - "itertools", - "quote", - "regex", - "serde", - "serde_derive", - "syn", - "tokio", - "parking_lot", - "rustc_semver", -]; - -// Test dependencies may need an `extern crate` here to ensure that they show up -// in the depinfo file (otherwise cargo thinks they are unused) -#[allow(unused_extern_crates)] -extern crate clippy_lints; -#[allow(unused_extern_crates)] -extern crate clippy_utils; -#[allow(unused_extern_crates)] -extern crate derive_new; -#[allow(unused_extern_crates)] -extern crate futures; -#[allow(unused_extern_crates)] -extern crate if_chain; -#[allow(unused_extern_crates)] -extern crate itertools; -#[allow(unused_extern_crates)] -extern crate parking_lot; -#[allow(unused_extern_crates)] -extern crate quote; -#[allow(unused_extern_crates)] -extern crate rustc_semver; -#[allow(unused_extern_crates)] -extern crate syn; -#[allow(unused_extern_crates)] -extern crate tokio; - -/// Produces a string with an `--extern` flag for all UI test crate -/// dependencies. -/// -/// The dependency files are located by parsing the depinfo file for this test -/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test -/// dependencies must be added to Cargo.toml at the project root. Test -/// dependencies that are not *directly* used by this test module require an -/// `extern crate` declaration. -static EXTERN_FLAGS: LazyLock = LazyLock::new(|| { - let current_exe_depinfo = { - let mut path = env::current_exe().unwrap(); - path.set_extension("d"); - fs::read_to_string(path).unwrap() - }; - let mut crates: HashMap<&str, &str> = HashMap::with_capacity(TEST_DEPENDENCIES.len()); - for line in current_exe_depinfo.lines() { - // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:` - let parse_name_path = || { - if line.starts_with(char::is_whitespace) { - return None; - } - let path_str = line.strip_suffix(':')?; - let path = Path::new(path_str); - if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") { - return None; - } - let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?; - // the "lib" prefix is not present for dll files - let name = name.strip_prefix("lib").unwrap_or(name); - Some((name, path_str)) - }; - if let Some((name, path)) = parse_name_path() { - if TEST_DEPENDENCIES.contains(&name) { - // A dependency may be listed twice if it is available in sysroot, - // and the sysroot dependencies are listed first. As of the writing, - // this only seems to apply to if_chain. - crates.insert(name, path); - } - } - } - let not_found: Vec<&str> = TEST_DEPENDENCIES - .iter() - .copied() - .filter(|n| !crates.contains_key(n)) - .collect(); - assert!( - not_found.is_empty(), - "dependencies not found in depinfo: {not_found:?}\n\ - help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\ - help: Try adding to dev-dependencies in Cargo.toml\n\ - help: Be sure to also add `extern crate ...;` to tests/compile-test.rs", - ); - crates - .into_iter() - .map(|(name, path)| format!(" --extern {name}={path}")) - .collect() -}); - fn base_config(test_dir: &str) -> compiletest::Config { let mut config = compiletest::Config { - edition: Some("2021".into()), - mode: TestMode::Ui, - strict_headers: true, - ..Default::default() + mode: TestMode::Yolo, + stderr_filters: vec![], + stdout_filters: vec![], + output_conflict_handling: if var_os("BLESS").is_some() || env::args().any(|arg| arg == "--bless") { + compiletest::OutputConflictHandling::Bless + } else { + compiletest::OutputConflictHandling::Error("cargo test -- -- --bless".into()) + }, + dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()), + target: None, + out_dir: "target/ui_test".into(), + ..compiletest::Config::rustc(Path::new("tests").join(test_dir)) }; - if let Ok(filters) = env::var("TESTNAME") { - config.filters = filters.split(',').map(ToString::to_string).collect(); - } - - if let Some(path) = option_env!("RUSTC_LIB_PATH") { - let path = PathBuf::from(path); - config.run_lib_path = path.clone(); - config.compile_lib_path = path; + if let Some(_path) = option_env!("RUSTC_LIB_PATH") { + //let path = PathBuf::from(path); + //config.run_lib_path = path.clone(); + //config.compile_lib_path = path; } let current_exe_path = env::current_exe().unwrap(); let deps_path = current_exe_path.parent().unwrap(); let profile_path = deps_path.parent().unwrap(); - // Using `-L dependency={}` enforces that external dependencies are added with `--extern`. - // This is valuable because a) it allows us to monitor what external dependencies are used - // and b) it ensures that conflicting rlibs are resolved properly. - let host_libs = option_env!("HOST_LIBS") - .map(|p| format!(" -L dependency={}", Path::new(p).join("deps").display())) - .unwrap_or_default(); - config.target_rustcflags = Some(format!( - "--emit=metadata -Dwarnings -Zui-testing -L dependency={}{host_libs}{}", - deps_path.display(), - &*EXTERN_FLAGS, - )); - - config.src_base = Path::new("tests").join(test_dir); - config.build_base = profile_path.join("test").join(test_dir); - config.rustc_path = profile_path.join(if cfg!(windows) { + config.program.args.push("--emit=metadata".into()); + config.program.args.push("-Aunused".into()); + config.program.args.push("-Zui-testing".into()); + config.program.args.push("-Dwarnings".into()); + + // Normalize away slashes in windows paths. + config.stderr_filter(r"\\", "/"); + + //config.build_base = profile_path.join("test").join(test_dir); + config.program.program = profile_path.join(if cfg!(windows) { "clippy-driver.exe" } else { "clippy-driver" @@ -165,9 +61,18 @@ fn base_config(test_dir: &str) -> compiletest::Config { config } +fn test_filter() -> Box bool> { + if let Ok(filters) = env::var("TESTNAME") { + let filters: Vec<_> = filters.split(',').map(ToString::to_string).collect(); + Box::new(move |path| filters.iter().any(|f| path.to_string_lossy().contains(f))) + } else { + Box::new(|_| true) + } +} + fn run_ui() { - let mut config = base_config("ui"); - config.rustfix_coverage = true; + let config = base_config("ui"); + //config.rustfix_coverage = true; // use tests/clippy.toml let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap()); let _threads = VarGuard::set( @@ -179,7 +84,19 @@ fn run_ui() { .to_string() }), ); - compiletest::run_tests(&config); + eprintln!(" Compiler: {}", config.program.display()); + + let name = config.root_dir.display().to_string(); + + let test_filter = test_filter(); + + compiletest::run_tests_generic( + config, + move |path| compiletest::default_file_filter(path) && test_filter(path), + compiletest::default_per_file_config, + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); check_rustfix_coverage(); } @@ -188,177 +105,124 @@ fn run_internal_tests() { if !RUN_INTERNAL_TESTS { return; } - let config = base_config("ui-internal"); - compiletest::run_tests(&config); + let mut config = base_config("ui-internal"); + config.dependency_builder.args.push("--features".into()); + config.dependency_builder.args.push("internal".into()); + compiletest::run_tests(config).unwrap(); } fn run_ui_toml() { - fn run_tests(config: &compiletest::Config, mut tests: Vec) -> Result { - let mut result = true; - let opts = compiletest::test_opts(config); - for dir in fs::read_dir(&config.src_base)? { - let dir = dir?; - if !dir.file_type()?.is_dir() { - continue; - } - let dir_path = dir.path(); - let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path); - for file in fs::read_dir(&dir_path)? { - let file = file?; - let file_path = file.path(); - if file.file_type()?.is_dir() { - continue; - } - if file_path.extension() != Some(OsStr::new("rs")) { - continue; - } - let paths = compiletest::common::TestPaths { - file: file_path, - base: config.src_base.clone(), - relative_dir: dir_path.file_name().unwrap().into(), - }; - let test_name = compiletest::make_test_name(config, &paths); - let index = tests - .iter() - .position(|test| test.desc.name == test_name) - .expect("The test should be in there"); - result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; - } - } - Ok(result) - } - let mut config = base_config("ui-toml"); - config.src_base = config.src_base.canonicalize().unwrap(); - let tests = compiletest::make_tests(&config); + config.stderr_filter( + ®ex::escape( + &std::path::Path::new(file!()) + .parent() + .unwrap() + .canonicalize() + .unwrap() + .parent() + .unwrap() + .display() + .to_string() + .replace('\\', "/"), + ), + "$$DIR", + ); + + let name = config.root_dir.display().to_string(); - let res = run_tests(&config, tests); - match res { - Ok(true) => {}, - Ok(false) => panic!("Some tests failed"), - Err(e) => { - panic!("I/O failure during tests: {e:?}"); + let test_filter = test_filter(); + + ui_test::run_tests_generic( + config, + |path| test_filter(path) && path.extension() == Some("rs".as_ref()), + |config, path| { + let mut config = config.clone(); + config + .program + .envs + .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into()))); + Some(config) }, - } + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); } fn run_ui_cargo() { - fn run_tests( - config: &compiletest::Config, - filters: &[String], - mut tests: Vec, - ) -> Result { - let mut result = true; - let opts = compiletest::test_opts(config); - - for dir in fs::read_dir(&config.src_base)? { - let dir = dir?; - if !dir.file_type()?.is_dir() { - continue; - } - - // Use the filter if provided - let dir_path = dir.path(); - for filter in filters { - if !dir_path.ends_with(filter) { - continue; - } - } - - for case in fs::read_dir(&dir_path)? { - let case = case?; - if !case.file_type()?.is_dir() { - continue; - } - - let src_path = case.path().join("src"); - - // When switching between branches, if the previous branch had a test - // that the current branch does not have, the directory is not removed - // because an ignored Cargo.lock file exists. - if !src_path.exists() { - continue; - } - - env::set_current_dir(&src_path)?; - - let cargo_toml_path = case.path().join("Cargo.toml"); - let cargo_content = fs::read(cargo_toml_path)?; - let cargo_parsed: toml::Value = toml::from_str( - std::str::from_utf8(&cargo_content).expect("`Cargo.toml` is not a valid utf-8 file!"), - ) - .expect("Can't parse `Cargo.toml`"); - - let _g = VarGuard::set("CARGO_MANIFEST_DIR", case.path()); - let _h = VarGuard::set( - "CARGO_PKG_RUST_VERSION", - cargo_parsed - .get("package") - .and_then(|p| p.get("rust-version")) - .and_then(toml::Value::as_str) - .unwrap_or(""), - ); - - for file in fs::read_dir(&src_path)? { - let file = file?; - if file.file_type()?.is_dir() { - continue; - } - - // Search for the main file to avoid running a test for each file in the project - let file_path = file.path(); - match file_path.file_name().and_then(OsStr::to_str) { - Some("main.rs") => {}, - _ => continue, - } - let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path()); - let paths = compiletest::common::TestPaths { - file: file_path, - base: config.src_base.clone(), - relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(), - }; - let test_name = compiletest::make_test_name(config, &paths); - let index = tests - .iter() - .position(|test| test.desc.name == test_name) - .expect("The test should be in there"); - result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; - } - } - } - Ok(result) - } - if IS_RUSTC_TEST_SUITE { return; } let mut config = base_config("ui-cargo"); - config.src_base = config.src_base.canonicalize().unwrap(); + config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; + config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; + config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; + config + .program + .envs + .push(("RUSTFLAGS".into(), Some("-Dwarnings".into()))); + // We need to do this while we still have a rustc in the `program` field. + config.fill_host_and_target().unwrap(); + config.dependencies_crate_manifest_path = None; + config.program.program.set_file_name(if cfg!(windows) { + "cargo-clippy.exe" + } else { + "cargo-clippy" + }); + config.edition = None; - let tests = compiletest::make_tests(&config); + config.stderr_filter( + ®ex::escape( + &std::path::Path::new(file!()) + .parent() + .unwrap() + .canonicalize() + .unwrap() + .parent() + .unwrap() + .display() + .to_string() + .replace('\\', "/"), + ), + "$$DIR", + ); + + let name = config.root_dir.display().to_string(); - let current_dir = env::current_dir().unwrap(); - let res = run_tests(&config, &config.filters, tests); - env::set_current_dir(current_dir).unwrap(); + let test_filter = test_filter(); - match res { - Ok(true) => {}, - Ok(false) => panic!("Some tests failed"), - Err(e) => { - panic!("I/O failure during tests: {e:?}"); + ui_test::run_tests_generic( + config, + |path| test_filter(path) && path.ends_with("Cargo.toml"), + |config, path| { + let mut config = config.clone(); + config.out_dir = PathBuf::from("target/ui_test_cargo/").join(path.parent().unwrap()); + Some(config) }, - } + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); } -#[test] -fn compile_test() { +fn main() { + // Support being run by cargo nextest - https://nexte.st/book/custom-test-harnesses.html + if env::args().any(|arg| arg == "--list") { + if !env::args().any(|arg| arg == "--ignored") { + println!("compile_test: test"); + } + + return; + } + set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); run_ui(); run_ui_toml(); run_ui_cargo(); run_internal_tests(); + rustfix_coverage_known_exceptions_accuracy(); + ui_cargo_toml_metadata(); } const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ @@ -384,7 +248,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ "needless_for_each_unfixable.rs", "nonminimal_bool.rs", "print_literal.rs", - "print_with_newline.rs", "redundant_static_lifetimes_multiple.rs", "ref_binding_to_reference.rs", "repl_uninit.rs", @@ -399,7 +262,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ "unnecessary_lazy_eval_unfixable.rs", "write_literal.rs", "write_literal_2.rs", - "write_with_newline.rs", ]; fn check_rustfix_coverage() { @@ -432,25 +294,15 @@ fn check_rustfix_coverage() { } } -#[test] fn rustfix_coverage_known_exceptions_accuracy() { for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS { let rs_path = Path::new("tests/ui").join(filename); - assert!( - rs_path.exists(), - "`{}` does not exist", - rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display() - ); + assert!(rs_path.exists(), "`{}` does not exist", rs_path.display()); let fixed_path = rs_path.with_extension("fixed"); - assert!( - !fixed_path.exists(), - "`{}` exists", - fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display() - ); + assert!(!fixed_path.exists(), "`{}` exists", fixed_path.display()); } } -#[test] fn ui_cargo_toml_metadata() { let ui_cargo_path = Path::new("tests/ui-cargo"); let cargo_common_metadata_path = ui_cargo_path.join("cargo_common_metadata"); diff --git a/tests/headers.rs b/tests/headers.rs new file mode 100644 index 0000000000000..1d1e566cbf6fe --- /dev/null +++ b/tests/headers.rs @@ -0,0 +1,29 @@ +use regex::Regex; +use std::fs; +use walkdir::WalkDir; + +#[test] +fn old_test_headers() { + let old_headers = Regex::new( + r"^//( ?\[\w+\])? ?((check|build|run|ignore|aux|only|needs|rustc|unset|no|normalize|run|compile)-|edition|incremental|revisions).*", + ) + .unwrap(); + let mut failed = false; + + for entry in WalkDir::new("tests") { + let entry = entry.unwrap(); + if !entry.file_type().is_file() { + continue; + } + + let file = fs::read_to_string(entry.path()).unwrap(); + + if let Some(header) = old_headers.find(&file) { + println!("Found header `{}` in {}", header.as_str(), entry.path().display()); + + failed = true; + } + } + + assert!(!failed, "use `//@foo` style test headers instead"); +} diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs index 8feea800fdbe3..15e5cdd6992cc 100644 --- a/tests/lint_message_convention.rs +++ b/tests/lint_message_convention.rs @@ -20,16 +20,16 @@ impl Message { // also no punctuation (except for "?" ?) at the end of a line static REGEX_SET: LazyLock = LazyLock::new(|| { RegexSet::new([ - r"error: [A-Z]", - r"help: [A-Z]", - r"warning: [A-Z]", - r"note: [A-Z]", - r"try this: [A-Z]", - r"error: .*[.!]$", - r"help: .*[.!]$", - r"warning: .*[.!]$", - r"note: .*[.!]$", - r"try this: .*[.!]$", + "error: [A-Z]", + "help: [A-Z]", + "warning: [A-Z]", + "note: [A-Z]", + "try this: [A-Z]", + "error: .*[.!]$", + "help: .*[.!]$", + "warning: .*[.!]$", + "note: .*[.!]$", + "try this: .*[.!]$", ]) .unwrap() }); @@ -39,11 +39,11 @@ impl Message { static EXCEPTIONS_SET: LazyLock = LazyLock::new(|| { RegexSet::new([ r"\.\.\.$", - r".*C-like enum variant discriminant is not portable to 32-bit targets", - r".*Intel x86 assembly syntax used", - r".*AT&T x86 assembly syntax used", - r"note: Clippy version: .*", - r"the compiler unexpectedly panicked. this is a bug.", + ".*C-like enum variant discriminant is not portable to 32-bit targets", + ".*Intel x86 assembly syntax used", + ".*AT&T x86 assembly syntax used", + "note: Clippy version: .*", + "the compiler unexpectedly panicked. this is a bug.", ]) .unwrap() }); diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index caedd5d76cd6f..0d35a22cd9a4e 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -41,8 +41,8 @@ fn explore_directory(dir: &Path) -> Vec { x.path().extension().and_then(OsStr::to_str), y.path().extension().and_then(OsStr::to_str), ) { - (Some("rs"), _) => Ordering::Less, - (_, Some("rs")) => Ordering::Greater, + (Some("rs" | "toml"), _) => Ordering::Less, + (_, Some("rs" | "toml")) => Ordering::Greater, _ => Ordering::Equal, } }); @@ -54,7 +54,7 @@ fn explore_directory(dir: &Path) -> Vec { let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string(); if let Some(ext) = path.extension() { match ext.to_str().unwrap() { - "rs" => current_file = file_prefix.clone(), + "rs" | "toml" => current_file = file_prefix.clone(), "stderr" | "stdout" => { if file_prefix != current_file { missing_files.push(path.to_str().unwrap().to_string()); diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr index 86953142befad..e161507b53395 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail` is missing `package.keywords` metada error: package `cargo_common_metadata_fail` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail` (bin "cargo_common_metadata_fail") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr index ac1b5e8e90347..dbf494cc342d3 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail_publish` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail_publish` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish` is missing `package.keywords error: package `cargo_common_metadata_fail_publish` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail_publish` (bin "cargo_common_metadata_fail_publish") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr index be32c0dc418fa..ae5967406f62f 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail_publish_true` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail_publish_true` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish_true` is missing `package.key error: package `cargo_common_metadata_fail_publish_true` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail_publish_true` (bin "cargo_common_metadata_fail_publish_true") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr new file mode 100644 index 0000000000000..dfbf19d33a5e5 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr @@ -0,0 +1,21 @@ +warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml` + +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-both-diff` (bin "fail-both-diff") due to 2 previous errors; 1 warning emitted diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr deleted file mode 100644 index 163f8bb35e79b..0000000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr +++ /dev/null @@ -1,22 +0,0 @@ -warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml` - -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors; 1 warning emitted - diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr new file mode 100644 index 0000000000000..407a9055de80c --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-both-same` (bin "fail-both-same") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr new file mode 100644 index 0000000000000..566f5a68689b2 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-cargo` (bin "fail-cargo") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr deleted file mode 100644 index 259d39b12526c..0000000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr new file mode 100644 index 0000000000000..83d4be3bae464 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-clippy` (bin "fail-clippy") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr deleted file mode 100644 index 259d39b12526c..0000000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr similarity index 56% rename from tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr rename to tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr index 259d39b12526c..14a6b5047b183 100644 --- a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr +++ b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr @@ -1,20 +1,19 @@ error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 + --> src/main.rs:11:21 | -LL | pub fn bar() -> Foo { +11 | pub fn bar() -> Foo { | ^^^ help: use the applicable keyword: `Self` | note: the lint level is defined here - --> $DIR/main.rs:1:9 + --> src/main.rs:6:9 | -LL | #![deny(clippy::use_self)] +6 | #![deny(clippy::use_self)] | ^^^^^^^^^^^^^^^^ error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 + --> src/main.rs:12:9 | -LL | Foo +12 | Foo | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 2 previous errors - +error: could not compile `fail-file-attr` (bin "fail-file-attr") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr deleted file mode 100644 index 97e6c3d5a5592..0000000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:11:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:6:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:12:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr similarity index 77% rename from tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr rename to tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr index eeae5b7b275e9..e89388b501bf1 100644 --- a/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr +++ b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr @@ -1,4 +1,2 @@ warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.13.0` from `clippy.toml` -warning: 1 warning emitted - diff --git a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr new file mode 100644 index 0000000000000..fde3a1e659915 --- /dev/null +++ b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr @@ -0,0 +1,52 @@ +error: file is loaded as a module multiple times: `src/b.rs` + --> src/main.rs:5:1 + | +5 | mod b; + | ^^^^^^ first loaded here +6 | / #[path = "b.rs"] +7 | | mod b2; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + = note: `-D clippy::duplicate-mod` implied by `-D warnings` + +error: file is loaded as a module multiple times: `src/c.rs` + --> src/main.rs:9:1 + | +9 | mod c; + | ^^^^^^ first loaded here +10 | / #[path = "c.rs"] +11 | | mod c2; + | |_______^ loaded again here +12 | / #[path = "c.rs"] +13 | | mod c3; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: file is loaded as a module multiple times: `src/d.rs` + --> src/main.rs:18:1 + | +18 | mod d; + | ^^^^^^ first loaded here +19 | / #[path = "d.rs"] +20 | | mod d2; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: file is loaded as a module multiple times: `src/from_other_module.rs` + --> src/main.rs:15:1 + | +15 | mod from_other_module; + | ^^^^^^^^^^^^^^^^^^^^^^ first loaded here + | + ::: src/other_module/mod.rs:1:1 + | +1 | / #[path = "../from_other_module.rs"] +2 | | mod m; + | |______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: could not compile `duplicate_mod` (bin "duplicate_mod") due to 4 previous errors diff --git a/tests/ui-cargo/duplicate_mod/fail/src/main.stderr b/tests/ui-cargo/duplicate_mod/fail/src/main.stderr deleted file mode 100644 index 3b80d89a68655..0000000000000 --- a/tests/ui-cargo/duplicate_mod/fail/src/main.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error: file is loaded as a module multiple times: `$DIR/b.rs` - --> $DIR/main.rs:5:1 - | -LL | mod b; - | ^^^^^^ first loaded here -LL | / #[path = "b.rs"] -LL | | mod b2; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - = note: `-D clippy::duplicate-mod` implied by `-D warnings` - -error: file is loaded as a module multiple times: `$DIR/c.rs` - --> $DIR/main.rs:9:1 - | -LL | mod c; - | ^^^^^^ first loaded here -LL | / #[path = "c.rs"] -LL | | mod c2; - | |_______^ loaded again here -LL | / #[path = "c.rs"] -LL | | mod c3; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: file is loaded as a module multiple times: `$DIR/d.rs` - --> $DIR/main.rs:18:1 - | -LL | mod d; - | ^^^^^^ first loaded here -LL | / #[path = "d.rs"] -LL | | mod d2; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: file is loaded as a module multiple times: `$DIR/from_other_module.rs` - --> $DIR/main.rs:15:1 - | -LL | mod from_other_module; - | ^^^^^^^^^^^^^^^^^^^^^^ first loaded here - | - ::: $DIR/other_module/mod.rs:1:1 - | -LL | / #[path = "../from_other_module.rs"] -LL | | mod m; - | |______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: aborting due to 4 previous errors - diff --git a/tests/ui-cargo/feature_name/fail/Cargo.stderr b/tests/ui-cargo/feature_name/fail/Cargo.stderr new file mode 100644 index 0000000000000..da2db45d3b836 --- /dev/null +++ b/tests/ui-cargo/feature_name/fail/Cargo.stderr @@ -0,0 +1,43 @@ +error: the "no-" prefix in the feature name "no-qaq" is negative + | + = help: consider renaming the feature to "qaq", but make sure the feature adds functionality + = note: `-D clippy::negative-feature-names` implied by `-D warnings` + +error: the "no_" prefix in the feature name "no_qaq" is negative + | + = help: consider renaming the feature to "qaq", but make sure the feature adds functionality + +error: the "not-" prefix in the feature name "not-orz" is negative + | + = help: consider renaming the feature to "orz", but make sure the feature adds functionality + +error: the "not_" prefix in the feature name "not_orz" is negative + | + = help: consider renaming the feature to "orz", but make sure the feature adds functionality + +error: the "-support" suffix in the feature name "qvq-support" is redundant + | + = help: consider renaming the feature to "qvq" + = note: `-D clippy::redundant-feature-names` implied by `-D warnings` + +error: the "_support" suffix in the feature name "qvq_support" is redundant + | + = help: consider renaming the feature to "qvq" + +error: the "use-" prefix in the feature name "use-qwq" is redundant + | + = help: consider renaming the feature to "qwq" + +error: the "use_" prefix in the feature name "use_qwq" is redundant + | + = help: consider renaming the feature to "qwq" + +error: the "with-" prefix in the feature name "with-owo" is redundant + | + = help: consider renaming the feature to "owo" + +error: the "with_" prefix in the feature name "with_owo" is redundant + | + = help: consider renaming the feature to "owo" + +error: could not compile `feature_name` (bin "feature_name") due to 10 previous errors diff --git a/tests/ui-cargo/feature_name/fail/src/main.stderr b/tests/ui-cargo/feature_name/fail/src/main.stderr deleted file mode 100644 index c6a11fa93eb5b..0000000000000 --- a/tests/ui-cargo/feature_name/fail/src/main.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error: the "no-" prefix in the feature name "no-qaq" is negative - | - = help: consider renaming the feature to "qaq", but make sure the feature adds functionality - = note: `-D clippy::negative-feature-names` implied by `-D warnings` - -error: the "no_" prefix in the feature name "no_qaq" is negative - | - = help: consider renaming the feature to "qaq", but make sure the feature adds functionality - -error: the "not-" prefix in the feature name "not-orz" is negative - | - = help: consider renaming the feature to "orz", but make sure the feature adds functionality - -error: the "not_" prefix in the feature name "not_orz" is negative - | - = help: consider renaming the feature to "orz", but make sure the feature adds functionality - -error: the "-support" suffix in the feature name "qvq-support" is redundant - | - = help: consider renaming the feature to "qvq" - = note: `-D clippy::redundant-feature-names` implied by `-D warnings` - -error: the "_support" suffix in the feature name "qvq_support" is redundant - | - = help: consider renaming the feature to "qvq" - -error: the "use-" prefix in the feature name "use-qwq" is redundant - | - = help: consider renaming the feature to "qwq" - -error: the "use_" prefix in the feature name "use_qwq" is redundant - | - = help: consider renaming the feature to "qwq" - -error: the "with-" prefix in the feature name "with-owo" is redundant - | - = help: consider renaming the feature to "owo" - -error: the "with_" prefix in the feature name "with_owo" is redundant - | - = help: consider renaming the feature to "owo" - -error: aborting due to 10 previous errors - diff --git a/tests/ui-cargo/module_style/fail_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr new file mode 100644 index 0000000000000..c2907f319e643 --- /dev/null +++ b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr @@ -0,0 +1,18 @@ +error: `mod.rs` files are required, found `src/bad/inner.rs` + --> src/bad/inner.rs:1:1 + | +1 | pub mod stuff; + | ^ + | + = help: move `src/bad/inner.rs` to `src/bad/inner/mod.rs` + = note: `-D clippy::self-named-module-files` implied by `-D warnings` + +error: `mod.rs` files are required, found `src/bad/inner/stuff.rs` + --> src/bad/inner/stuff.rs:1:1 + | +1 | pub mod most; + | ^ + | + = help: move `src/bad/inner/stuff.rs` to `src/bad/inner/stuff/mod.rs` + +error: could not compile `fail-mod` (bin "fail-mod") due to 2 previous errors diff --git a/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/tests/ui-cargo/module_style/fail_mod/src/main.stderr deleted file mode 100644 index 697c8b57c4a29..0000000000000 --- a/tests/ui-cargo/module_style/fail_mod/src/main.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: `mod.rs` files are required, found `bad/inner.rs` - --> $DIR/bad/inner.rs:1:1 - | -LL | pub mod stuff; - | ^ - | - = help: move `bad/inner.rs` to `bad/inner/mod.rs` - = note: `-D clippy::self-named-module-files` implied by `-D warnings` - -error: `mod.rs` files are required, found `bad/inner/stuff.rs` - --> $DIR/bad/inner/stuff.rs:1:1 - | -LL | pub mod most; - | ^ - | - = help: move `bad/inner/stuff.rs` to `bad/inner/stuff/mod.rs` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr new file mode 100644 index 0000000000000..fcf1a3c5e66c6 --- /dev/null +++ b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr @@ -0,0 +1,10 @@ +error: `mod.rs` files are required, found `src/bad.rs` + --> src/bad.rs:1:1 + | +1 | pub mod inner; + | ^ + | + = help: move `src/bad.rs` to `src/bad/mod.rs` + = note: `-D clippy::self-named-module-files` implied by `-D warnings` + +error: could not compile `fail-mod-remap` (bin "fail-mod-remap") due to previous error diff --git a/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr b/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr deleted file mode 100644 index ea6ea98064a79..0000000000000 --- a/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `mod.rs` files are required, found `bad.rs` - --> /remapped/module_style/fail_mod_remap/src/bad.rs:1:1 - | -LL | pub mod inner; - | ^ - | - = help: move `bad.rs` to `bad/mod.rs` - = note: `-D clippy::self-named-module-files` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr new file mode 100644 index 0000000000000..f61642ca2efd7 --- /dev/null +++ b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr @@ -0,0 +1,10 @@ +error: `mod.rs` files are not allowed, found `src/bad/mod.rs` + --> src/bad/mod.rs:1:1 + | +1 | pub struct Thing; + | ^ + | + = help: move `src/bad/mod.rs` to `src/bad.rs` + = note: `-D clippy::mod-module-files` implied by `-D warnings` + +error: could not compile `fail-no-mod` (bin "fail-no-mod") due to previous error diff --git a/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr deleted file mode 100644 index f40ceea234b9d..0000000000000 --- a/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `mod.rs` files are not allowed, found `bad/mod.rs` - --> $DIR/bad/mod.rs:1:1 - | -LL | pub struct Thing; - | ^ - | - = help: move `bad/mod.rs` to `bad.rs` - = note: `-D clippy::mod-module-files` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr b/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr new file mode 100644 index 0000000000000..d82b9e73f786f --- /dev/null +++ b/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr @@ -0,0 +1,2 @@ +warning: using config file `$DIR/$DIR/.clippy.toml`, `$DIR/$DIR/clippy.toml` will be ignored + diff --git a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/tests/ui-cargo/multiple_config_files/warn/src/main.stderr deleted file mode 100644 index aa1b3c638a036..0000000000000 --- a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: using config file `$SRC_DIR/.clippy.toml`, `$SRC_DIR/clippy.toml` will be ignored - -warning: 1 warning emitted - diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr new file mode 100644 index 0000000000000..5bcce920455cf --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr @@ -0,0 +1,5 @@ +error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9 + | + = note: `-D clippy::multiple-crate-versions` implied by `-D warnings` + +error: could not compile `multiple_crate_versions` (bin "multiple_crate_versions") due to previous error diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr b/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr deleted file mode 100644 index f3113e0936502..0000000000000 --- a/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9 - | - = note: `-D clippy::multiple-crate-versions` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/update-all-references.sh b/tests/ui-cargo/update-all-references.sh index 4391499a1e1f8..d42043070261e 100755 --- a/tests/ui-cargo/update-all-references.sh +++ b/tests/ui-cargo/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr new file mode 100644 index 0000000000000..b1578c9f32490 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr @@ -0,0 +1,5 @@ +error: wildcard dependency for `regex` + | + = note: `-D clippy::wildcard-dependencies` implied by `-D warnings` + +error: could not compile `wildcard_dependencies` (bin "wildcard_dependencies") due to previous error diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr b/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr deleted file mode 100644 index 9e65d2f99420a..0000000000000 --- a/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: wildcard dependency for `regex` - | - = note: `-D clippy::wildcard-dependencies` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-internal/check_formulation.rs b/tests/ui-internal/check_formulation.rs new file mode 100644 index 0000000000000..43fc996033eac --- /dev/null +++ b/tests/ui-internal/check_formulation.rs @@ -0,0 +1,54 @@ +#![warn(clippy::almost_standard_lint_formulation)] +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +extern crate rustc_lint; + +declare_tool_lint! { + /// # What it does + /// + /// Checks for usage of correct lint formulations + #[clippy::version = "pre 1.29.0"] + pub clippy::VALID, + Warn, + "One", + report_in_external_macro: true +} + +declare_tool_lint! { + /// # What it does + /// Check for lint formulations that are correct + #[clippy::version = "pre 1.29.0"] + pub clippy::INVALID1, + Warn, + "One", + report_in_external_macro: true +} + +declare_tool_lint! { + /// # What it does + /// Detects uses of incorrect formulations + #[clippy::version = "pre 1.29.0"] + pub clippy::INVALID2, + Warn, + "One", + report_in_external_macro: true +} + +declare_tool_lint! { + /// # What it does + /// Detects uses of incorrect formulations (allowed with attribute) + #[allow(clippy::almost_standard_lint_formulation)] + #[clippy::version = "pre 1.29.0"] + pub clippy::ALLOWED_INVALID, + Warn, + "One", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [VALID, INVALID1, INVALID2]); + +fn main() {} diff --git a/tests/ui-internal/check_formulation.stderr b/tests/ui-internal/check_formulation.stderr new file mode 100644 index 0000000000000..10eabca4b9d74 --- /dev/null +++ b/tests/ui-internal/check_formulation.stderr @@ -0,0 +1,19 @@ +error: non-standard lint formulation + --> $DIR/check_formulation.rs:23:5 + | +LL | /// Check for lint formulations that are correct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try using `Checks for` instead + = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings` + +error: non-standard lint formulation + --> $DIR/check_formulation.rs:33:5 + | +LL | /// Detects uses of incorrect formulations + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try using `Checks for` instead + +error: aborting due to 2 previous errors + diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr index b9ea5a64de75e..b88aeae2a9b8e 100644 --- a/tests/ui-internal/custom_ice_message.stderr +++ b/tests/ui-internal/custom_ice_message.stderr @@ -7,7 +7,7 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy note: rustc running on -note: compiler flags: -C prefer-dynamic -Z ui-testing +note: compiler flags: -Z ui-testing + +note: Clippy version: foo -query stack during panic: -thread panicked while processing panic. aborting. diff --git a/tests/ui-internal/if_chain_style.rs b/tests/ui-internal/if_chain_style.rs index b0d89e038aa8b..b462b20e04c67 100644 --- a/tests/ui-internal/if_chain_style.rs +++ b/tests/ui-internal/if_chain_style.rs @@ -1,5 +1,10 @@ #![warn(clippy::if_chain_style)] -#![allow(clippy::no_effect, clippy::nonminimal_bool, clippy::missing_clippy_version_attribute)] +#![allow( + clippy::needless_if, + clippy::no_effect, + clippy::nonminimal_bool, + clippy::missing_clippy_version_attribute +)] extern crate if_chain; diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr index d8f1ffb21ba67..b12df2786520e 100644 --- a/tests/ui-internal/if_chain_style.stderr +++ b/tests/ui-internal/if_chain_style.stderr @@ -1,5 +1,5 @@ error: this `if` can be part of the inner `if_chain!` - --> $DIR/if_chain_style.rs:9:5 + --> $DIR/if_chain_style.rs:14:5 | LL | / if true { LL | | let x = ""; @@ -11,14 +11,14 @@ LL | | } | |_____^ | help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:10:9 + --> $DIR/if_chain_style.rs:15:9 | LL | let x = ""; | ^^^^^^^^^^^ = note: `-D clippy::if-chain-style` implied by `-D warnings` error: `if a && b;` should be `if a; if b;` - --> $DIR/if_chain_style.rs:19:12 + --> $DIR/if_chain_style.rs:24:12 | LL | if true | ____________^ @@ -27,25 +27,25 @@ LL | | && false; | |____________________^ error: `let` expression should be inside `then { .. }` - --> $DIR/if_chain_style.rs:24:9 + --> $DIR/if_chain_style.rs:29:9 | LL | let x = ""; | ^^^^^^^^^^^ error: this `if` can be part of the outer `if_chain!` - --> $DIR/if_chain_style.rs:35:13 + --> $DIR/if_chain_style.rs:40:13 | LL | if true {} | ^^^^^^^^^^ | help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:33:13 + --> $DIR/if_chain_style.rs:38:13 | LL | let x = ""; | ^^^^^^^^^^^ error: `if_chain!` only has one `if` - --> $DIR/if_chain_style.rs:29:5 + --> $DIR/if_chain_style.rs:34:5 | LL | / if_chain! { LL | | // single `if` condition @@ -59,13 +59,13 @@ LL | | } = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info) error: `let` expression should be above the `if_chain!` - --> $DIR/if_chain_style.rs:40:9 + --> $DIR/if_chain_style.rs:45:9 | LL | let x = ""; | ^^^^^^^^^^^ error: this `if_chain!` can be merged with the outer `if_chain!` - --> $DIR/if_chain_style.rs:46:13 + --> $DIR/if_chain_style.rs:51:13 | LL | / if_chain! { LL | | if true; @@ -75,7 +75,7 @@ LL | | } | |_____________^ | help: these `let` statements can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:43:13 + --> $DIR/if_chain_style.rs:48:13 | LL | / let x = ""; LL | | let x = ""; diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed index 23e7bc16d239a..c908568452809 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::uninlined_format_args)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let local_i32 = 1; diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs index d66b2b8ff6a03..661350c5c6d54 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::uninlined_format_args)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let local_i32 = 1; diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr index 1be0cda12fc11..6ec79a618de14 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:9:5 + --> $DIR/uninlined_format_args.rs:10:5 | LL | println!("val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:10:5 + --> $DIR/uninlined_format_args.rs:11:5 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); | error: literal with an empty format string - --> $DIR/uninlined_format_args.rs:10:35 + --> $DIR/uninlined_format_args.rs:11:35 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^ @@ -37,7 +37,7 @@ LL + println!("Hello x is {:.*}", local_i32, local_f64); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:11:5 + --> $DIR/uninlined_format_args.rs:12:5 | LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:12:5 + --> $DIR/uninlined_format_args.rs:13:5 | LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:13:5 + --> $DIR/uninlined_format_args.rs:14:5 | LL | println!("{}, {}", local_i32, local_opt.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs index fb5b1b193f841..33f7c8ba80424 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs @@ -1,4 +1,5 @@ #![warn(clippy::arithmetic_side_effects)] +#![allow(clippy::unnecessary_literal_unwrap)] use core::ops::{Add, Neg}; diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr index ad89534aa1b04..4f98ca1923114 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr @@ -1,5 +1,5 @@ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:68:13 + --> $DIR/arithmetic_side_effects_allowed.rs:69:13 | LL | let _ = Baz + Baz; | ^^^^^^^^^ @@ -7,49 +7,49 @@ LL | let _ = Baz + Baz; = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:79:13 + --> $DIR/arithmetic_side_effects_allowed.rs:80:13 | LL | let _ = 1i32 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:82:13 + --> $DIR/arithmetic_side_effects_allowed.rs:83:13 | LL | let _ = 1i64 + Foo; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:86:13 + --> $DIR/arithmetic_side_effects_allowed.rs:87:13 | LL | let _ = 1i64 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:97:13 + --> $DIR/arithmetic_side_effects_allowed.rs:98:13 | LL | let _ = Baz + 1i32; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:100:13 + --> $DIR/arithmetic_side_effects_allowed.rs:101:13 | LL | let _ = Foo + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:104:13 + --> $DIR/arithmetic_side_effects_allowed.rs:105:13 | LL | let _ = Baz + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:113:13 + --> $DIR/arithmetic_side_effects_allowed.rs:114:13 | LL | let _ = -Bar; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:115:13 + --> $DIR/arithmetic_side_effects_allowed.rs:116:13 | LL | let _ = -Baz; | ^^^^ diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs index f328e4d9d04c3..c69fcd300335f 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.rs +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -1 +1,3 @@ +//@error-in-other-file: error reading Clippy's configuration file: expected `.`, `=` + fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/tests/ui-toml/bad_toml/conf_bad_toml.stderr index 5b7e8c0db744d..f7d53763a4388 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.stderr +++ b/tests/ui-toml/bad_toml/conf_bad_toml.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: expected `.`, `=` - --> $DIR/clippy.toml:1:4 + --> $DIR/$DIR/clippy.toml:1:4 | LL | fn this_is_obviously(not: a, toml: file) { | ^ diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs index f328e4d9d04c3..688c92d8717d1 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.rs +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -1 +1,3 @@ +//@error-in-other-file: invalid type: integer `42`, expected a sequence + fn main() {} diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr index 386e1135df90d..fb0a14081524b 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: invalid type: integer `42`, expected a sequence - --> $DIR/clippy.toml:1:20 + --> $DIR/$DIR/clippy.toml:1:20 | LL | disallowed-names = 42 | ^^ diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr index 123ad94dd09da..89d84eb24556d 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr @@ -1,11 +1,11 @@ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cyclomatic-complexity-threshold = 2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `blacklisted-names`. Please use `disallowed-names` instead - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | blacklisted-names = [ "..", "wibble" ] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.rs b/tests/ui-toml/duplicated_keys/duplicated_keys.rs index f328e4d9d04c3..187775545ed77 100644 --- a/tests/ui-toml/duplicated_keys/duplicated_keys.rs +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.rs @@ -1 +1,3 @@ +//@error-in-other-file: duplicate key `cognitive-complexity-threshold` + fn main() {} diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr index 54997735274e4..7c56dfdb948e9 100644 --- a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: duplicate key `cognitive-complexity-threshold` in document root - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cognitive-complexity-threshold = 4 | ^ diff --git a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr index 2ae7848f183b5..0af8c0add6c6a 100644 --- a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr @@ -1,11 +1,11 @@ error: error reading Clippy's configuration file: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`) - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr index 53ad427124691..a4b1e9c335ca2 100644 --- a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr @@ -1,11 +1,11 @@ error: error reading Clippy's configuration file: duplicate field `cognitive-complexity-threshold` - --> $DIR/clippy.toml:4:1 + --> $DIR/$DIR/clippy.toml:4:1 | LL | cognitive-complexity-threshold = 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs new file mode 100644 index 0000000000000..ebadd4e440a95 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs @@ -0,0 +1,472 @@ +// NOTE: Copied from `ui/auxiliary/proc_macros.rs`, couldn't get `../` to work for some reason + +#![feature(let_chains)] +#![feature(proc_macro_span)] +#![allow(clippy::excessive_nesting, dead_code)] + +extern crate proc_macro; + +use core::mem; +use proc_macro::{ + token_stream::IntoIter, + Delimiter::{self, Brace, Parenthesis}, + Group, Ident, Literal, Punct, + Spacing::{self, Alone, Joint}, + Span, TokenStream, TokenTree as TT, +}; + +type Result = core::result::Result; + +/// Make a `compile_error!` pointing to the given span. +fn make_error(msg: &str, span: Span) -> TokenStream { + TokenStream::from_iter([ + TT::Ident(Ident::new("compile_error", span)), + TT::Punct(punct_with_span('!', Alone, span)), + TT::Group({ + let mut msg = Literal::string(msg); + msg.set_span(span); + group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span) + }), + ]) +} + +fn expect_tt(tt: Option, f: impl FnOnce(TT) -> Option, expected: &str, span: Span) -> Result { + match tt { + None => Err(make_error( + &format!("unexpected end of input, expected {expected}"), + span, + )), + Some(tt) => { + let span = tt.span(); + match f(tt) { + Some(x) => Ok(x), + None => Err(make_error(&format!("unexpected token, expected {expected}"), span)), + } + }, + } +} + +fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct { + let mut p = Punct::new(c, spacing); + p.set_span(span); + p +} + +fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group { + let mut g = Group::new(delimiter, stream); + g.set_span(span); + g +} + +/// Token used to escape the following token from the macro's span rules. +const ESCAPE_CHAR: char = '$'; + +/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their +/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`. +#[proc_macro] +pub fn with_span(input: TokenStream) -> TokenStream { + let mut iter = input.into_iter(); + let span = iter.next().unwrap().span(); + let mut res = TokenStream::new(); + if let Err(e) = write_with_span(span, iter, &mut res) { + e + } else { + res + } +} + +/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be +/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`. +#[proc_macro] +pub fn external(input: TokenStream) -> TokenStream { + let mut res = TokenStream::new(); + if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) { + e + } else { + res + } +} + +/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped +/// either by `#ident` or `#(tokens)`. +fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> { + while let Some(tt) = input.next() { + match tt { + TT::Punct(p) if p.as_char() == ESCAPE_CHAR => { + expect_tt( + input.next(), + |tt| match tt { + tt @ (TT::Ident(_) | TT::Literal(_)) => { + out.extend([tt]); + Some(()) + }, + TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => { + p.set_span(s); + out.extend([TT::Punct(p)]); + Some(()) + }, + TT::Group(g) if g.delimiter() == Parenthesis => { + out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]); + Some(()) + }, + _ => None, + }, + "an ident, a literal, or parenthesized tokens", + p.span(), + )?; + }, + TT::Group(g) => { + let mut stream = TokenStream::new(); + write_with_span(s, g.stream().into_iter(), &mut stream)?; + out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]); + }, + mut tt => { + tt.set_span(s); + out.extend([tt]); + }, + } + } + Ok(()) +} + +/// Within the item this attribute is attached to, an `inline!` macro is available which expands the +/// contained tokens as though they came from a macro expansion. +/// +/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument +/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or +/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will +/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another +/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will +/// expand the remaining tokens as a single argument. +/// +/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro +/// calls. However, any arguments will be passed as though they came from the outermost context. +#[proc_macro_attribute] +pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream { + let mut args = args.into_iter(); + let mac_name = match args.next() { + Some(TT::Ident(name)) => Some(name), + Some(tt) => { + return make_error( + "unexpected argument, expected either an ident or no arguments", + tt.span(), + ); + }, + None => None, + }; + if let Some(tt) = args.next() { + return make_error( + "unexpected argument, expected either an ident or no arguments", + tt.span(), + ); + }; + + let mac_name = if let Some(mac_name) = mac_name { + Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site()) + } else { + let mut input = match LookaheadIter::new(input.clone().into_iter()) { + Some(x) => x, + None => return input, + }; + loop { + match input.next() { + None => break Ident::new("__inline_mac", Span::call_site()), + Some(TT::Ident(kind)) => match &*kind.to_string() { + "impl" => break Ident::new("__inline_mac_impl", Span::call_site()), + kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => { + if let TT::Ident(name) = &input.tt { + break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site()); + } else { + break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site()); + } + }, + _ => {}, + }, + _ => {}, + } + } + }; + + let mut expander = Expander::default(); + let mut mac = MacWriter::new(mac_name); + if let Err(e) = expander.expand(input.into_iter(), &mut mac) { + return e; + } + let mut out = TokenStream::new(); + mac.finish(&mut out); + out.extend(expander.expn); + out +} + +/// Wraps a `TokenStream` iterator with a single token lookahead. +struct LookaheadIter { + tt: TT, + iter: IntoIter, +} +impl LookaheadIter { + fn new(mut iter: IntoIter) -> Option { + iter.next().map(|tt| Self { tt, iter }) + } + + /// Get's the lookahead token, replacing it with the next token in the stream. + /// Note: If there isn't a next token, this will not return the lookahead token. + fn next(&mut self) -> Option { + self.iter.next().map(|tt| mem::replace(&mut self.tt, tt)) + } +} + +/// Builds the macro used to implement all the `inline!` macro calls. +struct MacWriter { + name: Ident, + macros: TokenStream, + next_idx: usize, +} +impl MacWriter { + fn new(name: Ident) -> Self { + Self { + name, + macros: TokenStream::new(), + next_idx: 0, + } + } + + /// Inserts a new `inline!` call. + fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> { + let idx = self.next_idx; + self.next_idx += 1; + + let mut inner = Expander::for_arm(idx); + inner.expand(body.stream().into_iter(), self)?; + let new_arm = inner.arm.unwrap(); + + self.macros.extend([ + TT::Group(Group::new(Parenthesis, new_arm.args_def)), + TT::Punct(Punct::new('=', Joint)), + TT::Punct(Punct::new('>', Alone)), + TT::Group(Group::new(Parenthesis, inner.expn)), + TT::Punct(Punct::new(';', Alone)), + ]); + + expander.expn.extend([ + TT::Ident({ + let mut name = self.name.clone(); + name.set_span(name_span); + name + }), + TT::Punct(punct_with_span('!', Alone, bang_span)), + ]); + let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]); + if let Some(arm) = expander.arm.as_mut() { + if !new_arm.args.is_empty() { + arm.add_sub_args(new_arm.args, &mut call_body); + } + } else { + call_body.extend(new_arm.args); + } + let mut g = Group::new(body.delimiter(), call_body); + g.set_span(body.span()); + expander.expn.extend([TT::Group(g)]); + Ok(()) + } + + /// Creates the macro definition. + fn finish(self, out: &mut TokenStream) { + if self.next_idx != 0 { + out.extend([ + TT::Ident(Ident::new("macro_rules", Span::call_site())), + TT::Punct(Punct::new('!', Alone)), + TT::Ident(self.name), + TT::Group(Group::new(Brace, self.macros)), + ]) + } + } +} + +struct MacroArm { + args_def: TokenStream, + args: Vec, +} +impl MacroArm { + fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(Ident::new(kind, Span::call_site())), + ]); + name.set_span(arg_span); + out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]); + } + + fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(kind), + ]), + ))]); + name.set_span(arg_span); + out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]); + } + + fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(Ident::new("tt", Span::call_site())), + ]), + )), + TT::Punct(Punct::new('*', Alone)), + ]), + ))]); + name.set_span(arg_span); + out.extend([ + TT::Punct(punct_with_span('$', Alone, dollar_span)), + TT::Group(group_with_span( + Parenthesis, + TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]), + dollar_span, + )), + TT::Punct(punct_with_span('*', Alone, dollar_span)), + ]); + } + + fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> { + match tt { + TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]), + TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => { + let lt_name = expect_tt( + input.next(), + |tt| match tt { + TT::Ident(x) => Some(x), + _ => None, + }, + "lifetime name", + p.span(), + )?; + let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span()); + self.add_single_arg_def("lifetime", dollar_span, arg_span, out); + self.args.extend([TT::Punct(p), TT::Ident(lt_name)]); + }, + TT::Ident(x) => { + self.add_single_arg_def("ident", dollar_span, x.span(), out); + self.args.push(TT::Ident(x)); + }, + TT::Literal(x) => { + self.add_single_arg_def("literal", dollar_span, x.span(), out); + self.args.push(TT::Literal(x)); + }, + TT::Group(g) if g.delimiter() == Parenthesis => { + let mut inner = g.stream().into_iter(); + if let Some(TT::Punct(p)) = inner.next() + && p.as_char() == '@' + { + let kind = expect_tt( + inner.next(), + |tt| match tt { + TT::Ident(kind) => Some(kind), + _ => None, + }, + "a macro fragment specifier", + p.span(), + )?; + self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out); + self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span()))) + } else { + self.add_multi_arg_def(dollar_span, g.span(), out); + self.args.push(TT::Group(g)); + } + }, + tt => return Err(make_error("unsupported escape", tt.span())), + }; + Ok(()) + } + + fn add_sub_args(&mut self, args: Vec, out: &mut TokenStream) { + self.add_multi_arg_def(Span::call_site(), Span::call_site(), out); + self.args + .extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]); + } +} + +#[derive(Default)] +struct Expander { + arm: Option, + expn: TokenStream, +} +impl Expander { + fn for_arm(idx: usize) -> Self { + Self { + arm: Some(MacroArm { + args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]), + args: Vec::new(), + }), + expn: TokenStream::new(), + } + } + + fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> { + match tt { + TT::Group(g) => { + let outer = mem::take(&mut self.expn); + self.expand(g.stream().into_iter(), mac)?; + let inner = mem::replace(&mut self.expn, outer); + self.expn + .extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]); + }, + tt => self.expn.extend([tt]), + } + Ok(()) + } + + fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> { + let Some(mut input) = LookaheadIter::new(input) else { + return Ok(()); + }; + while let Some(tt) = input.next() { + if let TT::Punct(p) = &tt + && p.as_char() == ESCAPE_CHAR + && let Some(arm) = self.arm.as_mut() + { + arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?; + if input.next().is_none() { + return Ok(()); + } + } else if let TT::Punct(p) = &input.tt + && p.as_char() == '!' + && let TT::Ident(name) = &tt + && name.to_string() == "inline" + { + let g = expect_tt( + input.iter.next(), + |tt| match tt { + TT::Group(g) => Some(g), + _ => None, + }, + "macro arguments", + p.span(), + )?; + mac.insert(name.span(), p.span(), g, self)?; + if input.next().is_none() { + return Ok(()); + } + } else { + self.write_tt(tt, mac)?; + } + } + self.write_tt(input.tt, mac) + } +} diff --git a/tests/ui-toml/excessive_nesting/clippy.toml b/tests/ui-toml/excessive_nesting/clippy.toml new file mode 100644 index 0000000000000..e60ac978cac97 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/clippy.toml @@ -0,0 +1 @@ +excessive-nesting-threshold = 4 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs new file mode 100644 index 0000000000000..c28220b973ec3 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -0,0 +1,197 @@ +//@aux-build:proc_macros.rs:proc-macro +#![rustfmt::skip] +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![allow(clippy::let_and_return)] +#![allow(clippy::redundant_closure_call)] +#![allow(clippy::no_effect)] +#![allow(clippy::unnecessary_operation)] +#![allow(clippy::never_loop)] +#![allow(clippy::needless_if)] +#![warn(clippy::excessive_nesting)] +#![allow(clippy::collapsible_if)] + +#[macro_use] +extern crate proc_macros; + +static X: u32 = { + let x = { + let y = { + let z = { + let w = { 3 }; + w + }; + z + }; + y + }; + x +}; + +macro_rules! xx { + () => {{ + { + { + { + { + { + { + { + { + { + { + println!("ehe"); // should not lint + } + } + } + } + } + } + } + } + } + } + }}; +} + +struct A; + +impl A { + pub fn a(&self, v: u32) { + struct B; + + impl B { + pub fn b() { + struct C; + + impl C { + pub fn c() {} + } + } + } + } +} + +struct D { d: u32 } + +trait Lol { + fn lmao() { + fn bb() { + fn cc() { + let x = { 1 }; // not a warning, but cc is + } + + let x = { 1 }; // warning + } + } +} + +#[allow(clippy::excessive_nesting)] +fn l() {{{{{{{{{}}}}}}}}} + +use a::{b::{c::{d::{e::{f::{}}}}}}; // should not lint + +pub mod a { + pub mod b { + pub mod c { + pub mod d { + pub mod e { + pub mod f {} + } // not here + } // only warning should be here + } + } +} + +fn a_but_not(v: u32) {} + +fn main() { + let a = A; + + a_but_not({{{{{{{{0}}}}}}}}); + a.a({{{{{{{{{0}}}}}}}}}); + (0, {{{{{{{1}}}}}}}); + + if true { + if true { + if true { + if true { + if true { + + } + } + } + } + } + + let y = (|| { + let x = (|| { + let y = (|| { + let z = (|| { + let w = { 3 }; + w + })(); + z + })(); + y + })(); + x + })(); + + external! { {{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}} }; // ensure this isn't linted in external macros + with_span! { span {{{{{{{{{{{{}}}}}}}}}}}} }; // don't lint for proc macros + xx!(); // ensure this is never linted + let boo = true; + !{boo as u32 + !{boo as u32 + !{boo as u32}}}; + + // this is a mess, but that's intentional + let mut y = 1; + y += {{{{{5}}}}}; + let z = y + {{{{{{{{{5}}}}}}}}}; + [0, {{{{{{{{{{0}}}}}}}}}}]; + let mut xx = [0; {{{{{{{{100}}}}}}}}]; + xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + &mut {{{{{{{{{{y}}}}}}}}}}; + + for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + + while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + + while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + + let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + + {{{{1;}}}}..{{{{{{3}}}}}}; + {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + ..{{{{{{{5}}}}}}}; + ..={{{{{3}}}}}; + {{{{{1;}}}}}..; + + loop { break {{{{1}}}} }; + loop {{{{{{}}}}}} + + match {{{{{{true}}}}}} { + true => {{{{}}}}, + false => {{{{}}}}, + } + + { + { + { + { + println!("warning! :)"); + } + } + } + } +} + +async fn b() -> u32 { + async fn c() -> u32 {{{{{{{0}}}}}}} + + c().await +} + +async fn a() { + {{{{b().await}}}}; +} diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr new file mode 100644 index 0000000000000..1a7311b33e869 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -0,0 +1,314 @@ +error: this block is too nested + --> $DIR/excessive_nesting.rs:21:25 + | +LL | let w = { 3 }; + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + = note: `-D clippy::excessive-nesting` implied by `-D warnings` + +error: this block is too nested + --> $DIR/excessive_nesting.rs:67:17 + | +LL | / impl C { +LL | | pub fn c() {} +LL | | } + | |_________________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:81:25 + | +LL | let x = { 1 }; // not a warning, but cc is + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:98:17 + | +LL | / pub mod e { +LL | | pub mod f {} +LL | | } // not here + | |_________________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:111:18 + | +LL | a_but_not({{{{{{{{0}}}}}}}}); + | ^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:112:12 + | +LL | a.a({{{{{{{{{0}}}}}}}}}); + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:113:12 + | +LL | (0, {{{{{{{1}}}}}}}); + | ^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:118:25 + | +LL | if true { + | _________________________^ +LL | | if true { +LL | | +LL | | } +LL | | } + | |_________________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:130:29 + | +LL | let z = (|| { + | _____________________________^ +LL | | let w = { 3 }; +LL | | w +LL | | })(); + | |_________________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:149:13 + | +LL | y += {{{{{5}}}}}; + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:150:20 + | +LL | let z = y + {{{{{{{{{5}}}}}}}}}; + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:151:12 + | +LL | [0, {{{{{{{{{{0}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:152:25 + | +LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:153:11 + | +LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:154:13 + | +LL | &mut {{{{{{{{{{y}}}}}}}}}}; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:156:17 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:156:28 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:158:28 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:158:48 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:160:14 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:160:35 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:162:23 + | +LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:164:8 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:164:20 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:165:8 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:165:21 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:166:10 + | +LL | ..{{{{{{{5}}}}}}}; + | ^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:167:11 + | +LL | ..={{{{{3}}}}}; + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:168:8 + | +LL | {{{{{1;}}}}}..; + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:170:20 + | +LL | loop { break {{{{1}}}} }; + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:171:13 + | +LL | loop {{{{{{}}}}}} + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:173:14 + | +LL | match {{{{{{true}}}}}} { + | ^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:174:20 + | +LL | true => {{{{}}}}, + | ^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:175:21 + | +LL | false => {{{{}}}}, + | ^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:181:17 + | +LL | / { +LL | | println!("warning! :)"); +LL | | } + | |_________________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:190:28 + | +LL | async fn c() -> u32 {{{{{{{0}}}}}}} + | ^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:196:8 + | +LL | {{{{b().await}}}}; + | ^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: aborting due to 37 previous errors + diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs index 9e267c893005f..206788e19f025 100644 --- a/tests/ui-toml/expect_used/expect_used.rs +++ b/tests/ui-toml/expect_used/expect_used.rs @@ -1,5 +1,6 @@ //@compile-flags: --test #![warn(clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn expect_option() { let opt = Some(0); diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr index 1e9bb48c333ca..9eef0e1bfaa12 100644 --- a/tests/ui-toml/expect_used/expect_used.stderr +++ b/tests/ui-toml/expect_used/expect_used.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> $DIR/expect_used.rs:6:13 + --> $DIR/expect_used.rs:7:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.expect(""); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `expect()` on a `Result` value - --> $DIR/expect_used.rs:11:13 + --> $DIR/expect_used.rs:12:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs index 2ebf28645e51e..03fa719975b68 100644 --- a/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs +++ b/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs @@ -1,3 +1,5 @@ +//@error-in-other-file: `invalid.version` is not a valid Rust version + #![allow(clippy::redundant_clone)] fn main() {} diff --git a/tests/ui-toml/lint_decimal_readability/test.rs b/tests/ui-toml/lint_decimal_readability/test.rs index 2498672d77fb0..bd5110138c8c5 100644 --- a/tests/ui-toml/lint_decimal_readability/test.rs +++ b/tests/ui-toml/lint_decimal_readability/test.rs @@ -1,5 +1,5 @@ #![allow(clippy::excessive_precision)] -#[deny(clippy::unreadable_literal)] +#![warn(clippy::unreadable_literal)] fn allow_inconsistent_digit_grouping() { #![allow(clippy::inconsistent_digit_grouping)] diff --git a/tests/ui-toml/lint_decimal_readability/test.stderr b/tests/ui-toml/lint_decimal_readability/test.stderr index be505bda4792c..ac9d89d0cbeeb 100644 --- a/tests/ui-toml/lint_decimal_readability/test.stderr +++ b/tests/ui-toml/lint_decimal_readability/test.stderr @@ -6,5 +6,13 @@ LL | let _fail1 = 100_200_300.123456789; | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` -error: aborting due to previous error +error: long literal lacking separators + --> $DIR/test.rs:22:18 + | +LL | let _fail2 = 100200300.300200100; + | ^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.300_200_100` + | + = note: `-D clippy::unreadable-literal` implied by `-D warnings` + +error: aborting due to 2 previous errors diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs index 21849a14fa95e..da76bb20fd961 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs @@ -3,6 +3,7 @@ fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some(slice) = slice { + //~^ ERROR: binding can be a slice pattern // This would usually not be linted but is included now due to the // index limit in the config file println!("{}", slice[7]); diff --git a/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs new file mode 100644 index 0000000000000..06a144f2218ce --- /dev/null +++ b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs @@ -0,0 +1,3 @@ +#![allow(nonstandard_style, unused)] + +pub struct Aaa; diff --git a/tests/ui-toml/min_ident_chars/clippy.toml b/tests/ui-toml/min_ident_chars/clippy.toml new file mode 100644 index 0000000000000..0114ca7501432 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/clippy.toml @@ -0,0 +1,2 @@ +allowed-idents-below-min-chars = ["Owo", "Uwu", "wha", "t_e", "lse", "_do", "_i_", "put", "her", "_e"] +min-ident-chars-threshold = 3 diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/tests/ui-toml/min_ident_chars/min_ident_chars.rs new file mode 100644 index 0000000000000..4326c7159c832 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.rs @@ -0,0 +1,19 @@ +//@aux-build:extern_types.rs +#![allow(nonstandard_style, unused)] +#![warn(clippy::min_ident_chars)] + +extern crate extern_types; +use extern_types::Aaa; + +struct Owo { + Uwu: u128, + aaa: Aaa, +} + +fn main() { + let wha = 1; + let vvv = 1; + let uuu = 1; + let (mut a, mut b) = (1, 2); + for i in 0..1000 {} +} diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr new file mode 100644 index 0000000000000..d9a27628ddb22 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr @@ -0,0 +1,46 @@ +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:6:19 + | +LL | use extern_types::Aaa; + | ^^^ + | + = note: `-D clippy::min-ident-chars` implied by `-D warnings` + +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:10:5 + | +LL | aaa: Aaa, + | ^^^ + +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:15:9 + | +LL | let vvv = 1; + | ^^^ + +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:16:9 + | +LL | let uuu = 1; + | ^^^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:17:14 + | +LL | let (mut a, mut b) = (1, 2); + | ^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:17:21 + | +LL | let (mut a, mut b) = (1, 2); + | ^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:18:9 + | +LL | for i in 0..1000 {} + | ^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui-toml/min_rust_version/min_rust_version.rs b/tests/ui-toml/min_rust_version/min_rust_version.rs index 1e3ec123a3c8b..e1dc3f4389c0b 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -41,7 +41,7 @@ fn match_like_matches() { fn match_same_arms() { match (1, 2, 3) { (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body + (.., 3) => 42, _ => 0, }; } @@ -49,7 +49,7 @@ fn match_same_arms() { fn match_same_arms2() { let _ = match Some(42) { Some(_) => 24, - None => 24, //~ ERROR match arms have same body + None => 24, }; } diff --git a/tests/ui-toml/module_inception/clippy.toml b/tests/ui-toml/module_inception/clippy.toml new file mode 100644 index 0000000000000..787620d865cc5 --- /dev/null +++ b/tests/ui-toml/module_inception/clippy.toml @@ -0,0 +1 @@ +allow-private-module-inception = true diff --git a/tests/ui-toml/module_inception/module_inception.rs b/tests/ui-toml/module_inception/module_inception.rs new file mode 100644 index 0000000000000..cd495c884a43a --- /dev/null +++ b/tests/ui-toml/module_inception/module_inception.rs @@ -0,0 +1,34 @@ +#![warn(clippy::module_inception)] + +// Lint +pub mod foo2 { + pub mod bar2 { + pub mod bar2 { + pub mod foo2 {} + } + pub mod foo2 {} + } + pub mod foo2 { + pub mod bar2 {} + } +} + +// Don't lint +mod foo { + pub mod bar { + pub mod foo { + pub mod bar {} + } + } + pub mod foo { + pub mod bar {} + } +} + +// No warning. See . +pub mod bar { + #[allow(clippy::module_inception)] + pub mod bar {} +} + +fn main() {} diff --git a/tests/ui-toml/module_inception/module_inception.stderr b/tests/ui-toml/module_inception/module_inception.stderr new file mode 100644 index 0000000000000..a5a09c322e13d --- /dev/null +++ b/tests/ui-toml/module_inception/module_inception.stderr @@ -0,0 +1,20 @@ +error: module has the same name as its containing module + --> $DIR/module_inception.rs:6:9 + | +LL | / pub mod bar2 { +LL | | pub mod foo2 {} +LL | | } + | |_________^ + | + = note: `-D clippy::module-inception` implied by `-D warnings` + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:11:5 + | +LL | / pub mod foo2 { +LL | | pub mod bar2 {} +LL | | } + | |_____^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs b/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs index f5761c6afeb37..e7ac05dd3c63c 100644 --- a/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs +++ b/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed index e4747bedddb88..054db5d933059 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix #![warn(clippy::nonstandard_macro_braces)] diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs index 54edded99f41b..95d1a2297e531 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix #![warn(clippy::nonstandard_macro_braces)] diff --git a/tests/ui-toml/suppress_lint_in_const/test.rs b/tests/ui-toml/suppress_lint_in_const/test.rs index 5a2df9f6c5d91..17c1b03d88c61 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/tests/ui-toml/suppress_lint_in_const/test.rs @@ -3,11 +3,17 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + unconditional_panic, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::useless_vec +)] const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. +//~^ ERROR: failed const fn idx() -> usize { 1 @@ -29,6 +35,8 @@ fn main() { x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. + // + //~^^ ERROR: failed let y = &x; y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021 diff --git a/tests/ui-toml/suppress_lint_in_const/test.stderr b/tests/ui-toml/suppress_lint_in_const/test.stderr index bc178b7e1319d..14e13194427c0 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -1,17 +1,17 @@ error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/test.rs:31:14 + --> $DIR/test.rs:37:14 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant used - --> $DIR/test.rs:31:5 + --> $DIR/test.rs:37:5 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/test.rs:22:5 + --> $DIR/test.rs:28:5 | LL | x[index]; | ^^^^^^^^ @@ -20,7 +20,7 @@ LL | x[index]; = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic - --> $DIR/test.rs:38:5 + --> $DIR/test.rs:46:5 | LL | v[0]; | ^^^^ @@ -28,7 +28,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:39:5 + --> $DIR/test.rs:47:5 | LL | v[10]; | ^^^^^ @@ -36,7 +36,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:40:5 + --> $DIR/test.rs:48:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -44,7 +44,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:46:5 + --> $DIR/test.rs:54:5 | LL | v[N]; | ^^^^ @@ -52,7 +52,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:47:5 + --> $DIR/test.rs:55:5 | LL | v[M]; | ^^^^ @@ -60,7 +60,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed - --> $DIR/test.rs:10:24 + --> $DIR/test.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs index 8e1a1710a6ce2..63fdea710cb6e 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,6 +1,8 @@ //@compile-flags: --crate-name conf_disallowed_methods +#![allow(clippy::needless_raw_strings)] #![warn(clippy::disallowed_methods)] +#![allow(clippy::useless_vec)] extern crate futures; extern crate regex; diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr index 148d1cae51f10..fc137c225d83a 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr @@ -1,5 +1,5 @@ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:33:14 + --> $DIR/conf_disallowed_methods.rs:35:14 | LL | let re = Regex::new(r"ab.*c").unwrap(); | ^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let re = Regex::new(r"ab.*c").unwrap(); = note: `-D clippy::disallowed-methods` implied by `-D warnings` error: use of a disallowed method `regex::Regex::is_match` - --> $DIR/conf_disallowed_methods.rs:34:5 + --> $DIR/conf_disallowed_methods.rs:36:5 | LL | re.is_match("abc"); | ^^^^^^^^^^^^^^^^^^ @@ -15,73 +15,73 @@ LL | re.is_match("abc"); = note: no matching allowed (from clippy.toml) error: use of a disallowed method `std::iter::Iterator::sum` - --> $DIR/conf_disallowed_methods.rs:37:5 + --> $DIR/conf_disallowed_methods.rs:39:5 | LL | a.iter().sum::(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `slice::sort_unstable` - --> $DIR/conf_disallowed_methods.rs:39:5 + --> $DIR/conf_disallowed_methods.rs:41:5 | LL | a.sort_unstable(); | ^^^^^^^^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:41:13 + --> $DIR/conf_disallowed_methods.rs:43:13 | LL | let _ = 2.0f32.clamp(3.0f32, 4.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:44:61 + --> $DIR/conf_disallowed_methods.rs:46:61 | LL | let indirect: fn(&str) -> Result = Regex::new; | ^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:47:28 + --> $DIR/conf_disallowed_methods.rs:49:28 | LL | let in_call = Box::new(f32::clamp); | ^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:48:53 + --> $DIR/conf_disallowed_methods.rs:50:53 | LL | let in_method_call = ["^", "$"].into_iter().map(Regex::new); | ^^^^^^^^^^ error: use of a disallowed method `futures::stream::select_all` - --> $DIR/conf_disallowed_methods.rs:51:31 + --> $DIR/conf_disallowed_methods.rs:53:31 | LL | let same_name_as_module = select_all(vec![empty::<()>()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_fn` - --> $DIR/conf_disallowed_methods.rs:53:5 + --> $DIR/conf_disallowed_methods.rs:55:5 | LL | local_fn(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_mod::f` - --> $DIR/conf_disallowed_methods.rs:54:5 + --> $DIR/conf_disallowed_methods.rs:56:5 | LL | local_mod::f(); | ^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Struct::method` - --> $DIR/conf_disallowed_methods.rs:56:5 + --> $DIR/conf_disallowed_methods.rs:58:5 | LL | s.method(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method` - --> $DIR/conf_disallowed_methods.rs:57:5 + --> $DIR/conf_disallowed_methods.rs:59:5 | LL | s.provided_method(); | ^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method` - --> $DIR/conf_disallowed_methods.rs:58:5 + --> $DIR/conf_disallowed_methods.rs:60:5 | LL | s.implemented_method(); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 179b1266169ef..f267a67f40ee5 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,7 +1,7 @@ //@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)" //@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" -#![deny(clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::trivially_copy_pass_by_ref)] #[derive(Copy, Clone)] struct Foo(u8); diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index b3ef5928e8ea2..d2b55eff16dbf 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -4,11 +4,7 @@ error: this argument (N byte) is passed by reference, but would be more efficien LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` | -note: the lint level is defined here - --> $DIR/test.rs:4:9 - | -LL | #![deny(clippy::trivially_copy_pass_by_ref)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) --> $DIR/test.rs:14:20 diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index 569fd2c3553b1..38009627757c2 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,3 +1,3 @@ -//@error-pattern: unknown field `foobar`, expected one of +//@error-in-other-file: unknown field `foobar`, expected one of fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index b6038f031f3c3..6ba26e9773023 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,9 +1,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expected one of + accept-comment-above-attributes + accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args + allow-one-hash-in-raw-strings allow-print-in-tests + allow-private-module-inception allow-unwrap-in-tests + allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary @@ -24,6 +29,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect enforced-import-renames enum-variant-name-threshold enum-variant-size-threshold + excessive-nesting-threshold future-size-threshold ignore-interior-mutability large-error-threshold @@ -34,12 +40,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect max-struct-bools max-suggested-slice-pattern-length max-trait-bounds + min-ident-chars-threshold missing-docs-in-crate-items msrv pass-by-value-size-limit semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + stack-size-threshold standard-macro-braces suppress-restriction-lint-in-const third-party @@ -54,17 +62,22 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | foobar = 42 | ^^^^^^ error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of + accept-comment-above-attributes + accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args + allow-one-hash-in-raw-strings allow-print-in-tests + allow-private-module-inception allow-unwrap-in-tests + allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary @@ -85,6 +98,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect enforced-import-renames enum-variant-name-threshold enum-variant-size-threshold + excessive-nesting-threshold future-size-threshold ignore-interior-mutability large-error-threshold @@ -95,12 +109,14 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect max-struct-bools max-suggested-slice-pattern-length max-trait-bounds + min-ident-chars-threshold missing-docs-in-crate-items msrv pass-by-value-size-limit semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + stack-size-threshold standard-macro-braces suppress-restriction-lint-in-const third-party @@ -115,7 +131,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports - --> $DIR/clippy.toml:4:1 + --> $DIR/$DIR/clippy.toml:4:1 | LL | barfoo = 53 | ^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs new file mode 100644 index 0000000000000..1c591fc76f3e9 --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs @@ -0,0 +1,13 @@ +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; + +#[proc_macro] +pub fn unsafe_block(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(span); + TokenTree::Group(group) + }]) +} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml new file mode 100644 index 0000000000000..e6dbb3d37841b --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml @@ -0,0 +1,2 @@ +accept-comment-above-statement = true +accept-comment-above-attributes = true diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs new file mode 100644 index 0000000000000..33d63670958dc --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -0,0 +1,567 @@ +//@aux-build:proc_macro_unsafe.rs:proc-macro + +#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] +#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)] +#![feature(lint_reasons)] + +extern crate proc_macro_unsafe; + +// Valid comments + +fn nested_local() { + let _ = { + let _ = { + // SAFETY: + let _ = unsafe {}; + }; + }; +} + +fn deep_nest() { + let _ = { + let _ = { + // SAFETY: + let _ = unsafe {}; + + // Safety: + unsafe {}; + + let _ = { + let _ = { + let _ = { + let _ = { + let _ = { + // Safety: + let _ = unsafe {}; + + // SAFETY: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + + // SAFETY: + unsafe {}; +} + +fn local_tuple_expression() { + // Safety: + let _ = (42, unsafe {}); +} + +fn line_comment() { + // Safety: + unsafe {} +} + +fn line_comment_newlines() { + // SAFETY: + + unsafe {} +} + +fn line_comment_empty() { + // Safety: + // + // + // + unsafe {} +} + +fn line_comment_with_extras() { + // This is a description + // Safety: + unsafe {} +} + +fn block_comment() { + /* Safety: */ + unsafe {} +} + +fn block_comment_newlines() { + /* SAFETY: */ + + unsafe {} +} + +fn block_comment_with_extras() { + /* This is a description + * SAFETY: + */ + unsafe {} +} + +fn block_comment_terminator_same_line() { + /* This is a description + * Safety: */ + unsafe {} +} + +fn buried_safety() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + // laborum. Safety: + // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi + // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio + // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl + // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. + unsafe {} +} + +fn safety_with_prepended_text() { + // This is a test. safety: + unsafe {} +} + +fn local_line_comment() { + // Safety: + let _ = unsafe {}; +} + +fn local_block_comment() { + /* SAFETY: */ + let _ = unsafe {}; +} + +fn comment_array() { + // Safety: + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn comment_tuple() { + // sAFETY: + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn comment_unary() { + // SAFETY: + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn comment_match() { + // SAFETY: + let _ = match unsafe {} { + _ => {}, + }; +} + +fn comment_addr_of() { + // Safety: + let _ = &unsafe {}; +} + +fn comment_repeat() { + // Safety: + let _ = [unsafe {}; 5]; +} + +fn comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!( + // SAFETY: + unsafe {} + ); +} + +fn comment_macro_def() { + macro_rules! t { + () => { + // Safety: + unsafe {} + }; + } + + t!(); +} + +fn non_ascii_comment() { + // ॐ᧻໒ SaFeTy: ௵∰ + unsafe {}; +} + +fn local_commented_block() { + let _ = + // safety: + unsafe {}; +} + +fn local_nest() { + // safety: + let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})]; +} + +fn in_fn_call(x: *const u32) { + fn f(x: u32) {} + + // Safety: reason + f(unsafe { *x }); +} + +fn multi_in_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + // Safety: reason + f(unsafe { *x }, unsafe { *x }); +} + +fn in_multiline_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + f( + // Safety: reason + unsafe { *x }, + 0, + ); +} + +fn in_macro_call(x: *const u32) { + // Safety: reason + println!("{}", unsafe { *x }); +} + +fn in_multiline_macro_call(x: *const u32) { + println!( + "{}", + // Safety: reason + unsafe { *x }, + ); +} + +fn from_proc_macro() { + proc_macro_unsafe::unsafe_block!(token); +} + +fn in_closure(x: *const u32) { + // Safety: reason + let _ = || unsafe { *x }; +} + +// Invalid comments + +#[rustfmt::skip] +fn inline_block_comment() { + /* Safety: */ unsafe {} +} + +fn no_comment() { + unsafe {} +} + +fn no_comment_array() { + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn no_comment_tuple() { + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn no_comment_unary() { + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn no_comment_match() { + let _ = match unsafe {} { + _ => {}, + }; +} + +fn no_comment_addr_of() { + let _ = &unsafe {}; +} + +fn no_comment_repeat() { + let _ = [unsafe {}; 5]; +} + +fn local_no_comment() { + let _ = unsafe {}; +} + +fn no_comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!(unsafe {}); +} + +fn no_comment_macro_def() { + macro_rules! t { + () => { + unsafe {} + }; + } + + t!(); +} + +fn trailing_comment() { + unsafe {} // SAFETY: +} + +fn internal_comment() { + unsafe { + // SAFETY: + } +} + +fn interference() { + // SAFETY + + let _ = 42; + + unsafe {}; +} + +pub fn print_binary_tree() { + println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); +} + +mod unsafe_impl_smoke_test { + unsafe trait A {} + + // error: no safety comment + unsafe impl A for () {} + + // Safety: ok + unsafe impl A for (i32) {} + + mod sub_mod { + // error: + unsafe impl B for (u32) {} + unsafe trait B {} + } + + #[rustfmt::skip] + mod sub_mod2 { + // + // SAFETY: ok + // + + unsafe impl B for (u32) {} + unsafe trait B {} + } +} + +mod unsafe_impl_from_macro { + unsafe trait T {} + + // error + macro_rules! no_safety_comment { + ($t:ty) => { + unsafe impl T for $t {} + }; + } + + // ok + no_safety_comment!(()); + + // ok + macro_rules! with_safety_comment { + ($t:ty) => { + // SAFETY: + unsafe impl T for $t {} + }; + } + + // ok + with_safety_comment!((i32)); +} + +mod unsafe_impl_macro_and_not_macro { + unsafe trait T {} + + // error + macro_rules! no_safety_comment { + ($t:ty) => { + unsafe impl T for $t {} + }; + } + + // ok + no_safety_comment!(()); + + // error + unsafe impl T for (i32) {} + + // ok + no_safety_comment!(u32); + + // error + unsafe impl T for (bool) {} +} + +#[rustfmt::skip] +mod unsafe_impl_valid_comment { + unsafe trait SaFety {} + // SaFety: + unsafe impl SaFety for () {} + + unsafe trait MultiLineComment {} + // The following impl is safe + // ... + // Safety: reason + unsafe impl MultiLineComment for () {} + + unsafe trait NoAscii {} + // 安全 SAFETY: 以下のコードは安全です + unsafe impl NoAscii for () {} + + unsafe trait InlineAndPrecedingComment {} + // SAFETY: + /* comment */ unsafe impl InlineAndPrecedingComment for () {} + + unsafe trait BuriedSafety {} + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + // laborum. Safety: + // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi + // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio + // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl + // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. + unsafe impl BuriedSafety for () {} + + unsafe trait MultiLineBlockComment {} + /* This is a description + * Safety: */ + unsafe impl MultiLineBlockComment for () {} +} + +#[rustfmt::skip] +mod unsafe_impl_invalid_comment { + unsafe trait NoComment {} + + unsafe impl NoComment for () {} + + unsafe trait InlineComment {} + + /* SAFETY: */ unsafe impl InlineComment for () {} + + unsafe trait TrailingComment {} + + unsafe impl TrailingComment for () {} // SAFETY: + + unsafe trait Interference {} + // SAFETY: + const BIG_NUMBER: i32 = 1000000; + unsafe impl Interference for () {} +} + +unsafe trait ImplInFn {} + +fn impl_in_fn() { + // error + unsafe impl ImplInFn for () {} + + // SAFETY: ok + unsafe impl ImplInFn for (i32) {} +} + +unsafe trait CrateRoot {} + +// error +unsafe impl CrateRoot for () {} + +// SAFETY: ok +unsafe impl CrateRoot for (i32) {} + +fn issue_9142() { + // SAFETY: ok + let _ = + // we need this comment to avoid rustfmt putting + // it all on one line + unsafe {}; + + // SAFETY: this is more than one level away, so it should warn + let _ = { + if unsafe { true } { + todo!(); + } else { + let bar = unsafe {}; + todo!(); + bar + } + }; +} + +pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { + 1 +} + +pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { + 2 +} + +fn issue_10832() { + // Safety: A safety comment + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; +} + +fn issue_8679() { + // SAFETY: + #[allow(unsafe_code)] + unsafe {} + + // SAFETY: + #[expect(unsafe_code, reason = "totally safe")] + unsafe { + *std::ptr::null::() + }; + + // Safety: A safety comment + #[allow(unsafe_code)] + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment + #[allow(unsafe_code)] + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment + #[allow(unsafe_code)] + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // SAFETY: + #[allow(unsafe_code)] + // This also works I guess + unsafe {} +} + +fn main() {} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr new file mode 100644 index 0000000000000..9a0fd05938962 --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr @@ -0,0 +1,314 @@ +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:263:19 + | +LL | /* Safety: */ unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:267:5 + | +LL | unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:271:14 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:271:29 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:271:48 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:275:18 + | +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:275:37 + | +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:279:14 + | +LL | let _ = *unsafe { &42 }; + | ^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:284:19 + | +LL | let _ = match unsafe {} { + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:290:14 + | +LL | let _ = &unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:294:14 + | +LL | let _ = [unsafe {}; 5]; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:298:13 + | +LL | let _ = unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:308:8 + | +LL | t!(unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:314:13 + | +LL | unsafe {} + | ^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:322:5 + | +LL | unsafe {} // SAFETY: + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:326:5 + | +LL | unsafe { + | ^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:336:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:340:20 + | +LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:347:5 + | +LL | unsafe impl A for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:354:9 + | +LL | unsafe impl B for (u32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:375:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(()); + | ---------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:400:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(()); + | ---------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:408:5 + | +LL | unsafe impl T for (i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:400:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(u32); + | ----------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:414:5 + | +LL | unsafe impl T for (bool) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:460:5 + | +LL | unsafe impl NoComment for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:464:19 + | +LL | /* SAFETY: */ unsafe impl InlineComment for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:468:5 + | +LL | unsafe impl TrailingComment for () {} // SAFETY: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: constant item has unnecessary safety comment + --> $DIR/undocumented_unsafe_blocks.rs:472:5 + | +LL | const BIG_NUMBER: i32 = 1000000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider removing the safety comment + --> $DIR/undocumented_unsafe_blocks.rs:471:5 + | +LL | // SAFETY: + | ^^^^^^^^^^ + = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings` + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:473:5 + | +LL | unsafe impl Interference for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:480:5 + | +LL | unsafe impl ImplInFn for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:489:1 + | +LL | unsafe impl CrateRoot for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: statement has unnecessary safety comment + --> $DIR/undocumented_unsafe_blocks.rs:502:5 + | +LL | / let _ = { +LL | | if unsafe { true } { +LL | | todo!(); +LL | | } else { +... | +LL | | } +LL | | }; + | |______^ + | +help: consider removing the safety comment + --> $DIR/undocumented_unsafe_blocks.rs:501:5 + | +LL | // SAFETY: this is more than one level away, so it should warn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:503:12 + | +LL | if unsafe { true } { + | ^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:506:23 + | +LL | let bar = unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 35 previous errors + diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index 5d3e800caddfe..dde1c6d7c37d6 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -1,8 +1,13 @@ //@compile-flags: --test -#![allow(unused_mut, clippy::get_first, clippy::from_iter_instead_of_collect)] +#![allow( + unused_mut, + clippy::get_first, + clippy::from_iter_instead_of_collect, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] -#![deny(clippy::get_unwrap)] +#![warn(clippy::get_unwrap)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index 8a32750e3c92d..eb66a5cf50ba9 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -1,17 +1,13 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:35:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | -note: the lint level is defined here - --> $DIR/unwrap_used.rs:5:9 - | -LL | #![deny(clippy::get_unwrap)] - | ^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::get-unwrap` implied by `-D warnings` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:35:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,13 +16,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:36:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:36:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,13 +30,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:37:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:37:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,13 +44,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:38:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:38:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,13 +58,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:39:17 + --> $DIR/unwrap_used.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:39:17 + --> $DIR/unwrap_used.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,13 +72,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,13 +86,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:44:21 + --> $DIR/unwrap_used.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:44:22 + --> $DIR/unwrap_used.rs:49:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,13 +100,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:49:9 + --> $DIR/unwrap_used.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:49:10 + --> $DIR/unwrap_used.rs:54:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +114,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:50:9 + --> $DIR/unwrap_used.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:50:10 + --> $DIR/unwrap_used.rs:55:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,13 +128,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:51:9 + --> $DIR/unwrap_used.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:51:10 + --> $DIR/unwrap_used.rs:56:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,13 +142,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:52:9 + --> $DIR/unwrap_used.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:52:10 + --> $DIR/unwrap_used.rs:57:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,13 +156,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:64:17 + --> $DIR/unwrap_used.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:64:17 + --> $DIR/unwrap_used.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,13 +170,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:65:17 + --> $DIR/unwrap_used.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:65:17 + --> $DIR/unwrap_used.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,13 +184,13 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:72:13 + --> $DIR/unwrap_used.rs:77:13 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:90:17 + --> $DIR/unwrap_used.rs:95:17 | LL | let _ = Box::new([0]).get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]` diff --git a/tests/ui-toml/update-all-references.sh b/tests/ui-toml/update-all-references.sh index 4391499a1e1f8..d42043070261e 100755 --- a/tests/ui-toml/update-all-references.sh +++ b/tests/ui-toml/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index f0936b2608e9e..cc95a06817d69 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -1,9 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] +#![no_main] -fn main() {} +extern crate proc_macros; +use proc_macros::{external, with_span}; // Using clippy::needless_borrow just as a placeholder, it isn't relevant. @@ -20,6 +23,21 @@ struct T4; #[cfg_attr(panic = "unwind", expect(dead_code))] struct CfgT; +fn ignore_external() { + external! { + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + +fn ignore_proc_macro() { + with_span! { + span + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + fn ignore_inner_attr() { #![allow(unused)] // Should not lint } diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 2fb9e86126e55..2eb6ad304ea47 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -1,9 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] +#![no_main] -fn main() {} +extern crate proc_macros; +use proc_macros::{external, with_span}; // Using clippy::needless_borrow just as a placeholder, it isn't relevant. @@ -20,6 +23,21 @@ struct T4; #[cfg_attr(panic = "unwind", allow(dead_code))] struct CfgT; +fn ignore_external() { + external! { + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + +fn ignore_proc_macro() { + with_span! { + span + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + fn ignore_inner_attr() { #![allow(unused)] // Should not lint } diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index 681837e9ed770..d17fd86cb866c 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -1,5 +1,5 @@ error: #[allow] attribute found - --> $DIR/allow_attributes.rs:11:3 + --> $DIR/allow_attributes.rs:14:3 | LL | #[allow(dead_code)] | ^^^^^ help: replace it with: `expect` @@ -7,7 +7,7 @@ LL | #[allow(dead_code)] = note: `-D clippy::allow-attributes` implied by `-D warnings` error: #[allow] attribute found - --> $DIR/allow_attributes.rs:20:30 + --> $DIR/allow_attributes.rs:23:30 | LL | #[cfg_attr(panic = "unwind", allow(dead_code))] | ^^^^^ help: replace it with: `expect` diff --git a/tests/ui/allow_attributes_false_positive.rs b/tests/ui/allow_attributes_false_positive.rs deleted file mode 100644 index 5c3407628be27..0000000000000 --- a/tests/ui/allow_attributes_false_positive.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(clippy::allow_attributes)] -#![feature(lint_reasons)] -#![crate_type = "proc-macro"] - -fn main() {} diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 1a0d4e886576e..d223d56422177 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -1,9 +1,15 @@ +//@aux-build:proc_macros.rs:proc-macro #![feature(lint_reasons)] #![deny(clippy::allow_attributes_without_reason)] +#![allow(unfulfilled_lint_expectations)] + +extern crate proc_macros; +use proc_macros::{external, with_span}; // These should trigger the lint #[allow(dead_code)] #[allow(dead_code, deprecated)] +#[expect(dead_code)] // These should be fine #[allow(dead_code, reason = "This should be allowed")] #[warn(dyn_drop, reason = "Warnings can also have reasons")] @@ -11,4 +17,28 @@ #[deny(deref_nullptr)] #[forbid(deref_nullptr)] -fn main() {} +fn main() { + external! { + #[allow(dead_code)] + fn a() {} + } + with_span! { + span + #[allow(dead_code)] + fn b() {} + } +} + +// Make sure this is not triggered on `?` desugaring + +pub fn trigger_fp_option() -> Option<()> { + Some(())?; + None?; + Some(()) +} + +pub fn trigger_fp_result() -> Result<(), &'static str> { + Ok(())?; + Err("asdf")?; + Ok(()) +} diff --git a/tests/ui/allow_attributes_without_reason.stderr b/tests/ui/allow_attributes_without_reason.stderr index 23f17e9a7afb4..96f747d0026df 100644 --- a/tests/ui/allow_attributes_without_reason.stderr +++ b/tests/ui/allow_attributes_without_reason.stderr @@ -1,23 +1,39 @@ error: `allow` attribute without specifying a reason - --> $DIR/allow_attributes_without_reason.rs:5:1 + --> $DIR/allow_attributes_without_reason.rs:4:1 | -LL | #[allow(dead_code)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![allow(unfulfilled_lint_expectations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` note: the lint level is defined here - --> $DIR/allow_attributes_without_reason.rs:2:9 + --> $DIR/allow_attributes_without_reason.rs:3:9 | LL | #![deny(clippy::allow_attributes_without_reason)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow` attribute without specifying a reason - --> $DIR/allow_attributes_without_reason.rs:6:1 + --> $DIR/allow_attributes_without_reason.rs:10:1 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: `allow` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:11:1 | LL | #[allow(dead_code, deprecated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` -error: aborting due to 2 previous errors +error: `expect` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:12:1 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: aborting due to 4 previous errors diff --git a/tests/ui/almost_complete_range.fixed b/tests/ui/almost_complete_range.fixed index 5cd0dcce6f765..50a13f16b4456 100644 --- a/tests/ui/almost_complete_range.fixed +++ b/tests/ui/almost_complete_range.fixed @@ -1,6 +1,6 @@ //@run-rustfix //@edition:2018 -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/almost_complete_range.rs b/tests/ui/almost_complete_range.rs index db0bfc8afc39a..fd8223a2309c2 100644 --- a/tests/ui/almost_complete_range.rs +++ b/tests/ui/almost_complete_range.rs @@ -1,6 +1,6 @@ //@run-rustfix //@edition:2018 -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs new file mode 100644 index 0000000000000..ac786f68c123d --- /dev/null +++ b/tests/ui/arc_with_non_send_sync.rs @@ -0,0 +1,17 @@ +#![warn(clippy::arc_with_non_send_sync)] +#![allow(unused_variables)] +use std::cell::RefCell; +use std::sync::{Arc, Mutex}; + +fn foo(x: T) { + // Should not lint - purposefully ignoring generic args. + let a = Arc::new(x); +} + +fn main() { + // This is safe, as `i32` implements `Send` and `Sync`. + let a = Arc::new(42); + + // This is not safe, as `RefCell` does not implement `Sync`. + let b = Arc::new(RefCell::new(42)); +} diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr new file mode 100644 index 0000000000000..fc2fc5f93b13b --- /dev/null +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -0,0 +1,11 @@ +error: usage of `Arc` where `T` is not `Send` or `Sync` + --> $DIR/arc_with_non_send_sync.rs:16:13 + | +LL | let b = Arc::new(RefCell::new(42)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `Rc` instead or wrapping `T` in a std::sync type like `Mutex` + = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index f95af1017bcbb..4f38e50c81d55 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![allow( clippy::assign_op_pattern, @@ -466,4 +466,19 @@ pub fn issue_10767() { &3.5_f32 + &1.3_f32; } +pub fn issue_10792() { + struct One { + a: u32, + } + struct Two { + b: u32, + c: u64, + } + const ONE: One = One { a: 1 }; + const TWO: Two = Two { b: 2, c: 3 }; + let _ = 10 / ONE.a; + let _ = 10 / TWO.b; + let _ = 10 / TWO.c; +} + fn main() {} diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index 890bf0b0a7eb2..427842a51d9bd 100644 --- a/tests/ui/as_conversions.rs +++ b/tests/ui/as_conversions.rs @@ -1,10 +1,11 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::as_conversions)] -#![allow(clippy::borrow_as_ptr)] +#![allow(clippy::borrow_as_ptr, unused)] extern crate proc_macros; use proc_macros::external; +use proc_macros::with_span; fn main() { let i = 0u32 as u64; @@ -13,3 +14,11 @@ fn main() { external!(0u32 as u64); } + +with_span!( + span + + fn coverting() { + let x = 0u32 as u64; + } +); diff --git a/tests/ui/as_conversions.stderr b/tests/ui/as_conversions.stderr index 54037a6499787..ca41d1378aa09 100644 --- a/tests/ui/as_conversions.stderr +++ b/tests/ui/as_conversions.stderr @@ -1,5 +1,5 @@ error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:10:13 + --> $DIR/as_conversions.rs:11:13 | LL | let i = 0u32 as u64; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let i = 0u32 as u64; = note: `-D clippy::as-conversions` implied by `-D warnings` error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:12:13 + --> $DIR/as_conversions.rs:13:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64; = help: consider using a safe wrapper for this conversion error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:12:13 + --> $DIR/as_conversions.rs:13:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/as_ptr_cast_mut.rs b/tests/ui/as_ptr_cast_mut.rs index 0d1d9258433b2..7d71947e42814 100644 --- a/tests/ui/as_ptr_cast_mut.rs +++ b/tests/ui/as_ptr_cast_mut.rs @@ -1,6 +1,6 @@ #![allow(unused)] #![warn(clippy::as_ptr_cast_mut)] -#![allow(clippy::wrong_self_convention)] +#![allow(clippy::wrong_self_convention, clippy::unnecessary_cast)] struct MutPtrWrapper(Vec); impl MutPtrWrapper { diff --git a/tests/ui/asm_syntax.rs b/tests/ui/asm_syntax.rs index c93995f939acc..af02e202b17bb 100644 --- a/tests/ui/asm_syntax.rs +++ b/tests/ui/asm_syntax.rs @@ -1,5 +1,5 @@ -//@only-x86_64 -//@ignore-aarch64 +//@only-target-x86_64 +//@ignore-target-aarch64 #[warn(clippy::inline_asm_x86_intel_syntax)] mod warn_intel { diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed index ea8b895664c49..3152bd3cae1a6 100644 --- a/tests/ui/assertions_on_result_states.fixed +++ b/tests/ui/assertions_on_result_states.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::assertions_on_result_states)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::result::Result; diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs index 6fc20f8598872..42755e935aa41 100644 --- a/tests/ui/assertions_on_result_states.rs +++ b/tests/ui/assertions_on_result_states.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::assertions_on_result_states)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::result::Result; diff --git a/tests/ui/assertions_on_result_states.stderr b/tests/ui/assertions_on_result_states.stderr index 298d63c9c34fb..be581030cb67b 100644 --- a/tests/ui/assertions_on_result_states.stderr +++ b/tests/ui/assertions_on_result_states.stderr @@ -1,5 +1,5 @@ error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:24:5 + --> $DIR/assertions_on_result_states.rs:25:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` @@ -7,37 +7,37 @@ LL | assert!(r.is_ok()); = note: `-D clippy::assertions-on-result-states` implied by `-D warnings` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:42:5 + --> $DIR/assertions_on_result_states.rs:43:5 | LL | assert!(get_ok().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:45:5 + --> $DIR/assertions_on_result_states.rs:46:5 | LL | assert!(get_ok_macro!().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:58:5 + --> $DIR/assertions_on_result_states.rs:59:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:64:9 + --> $DIR/assertions_on_result_states.rs:65:9 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_err` - --> $DIR/assertions_on_result_states.rs:72:5 + --> $DIR/assertions_on_result_states.rs:73:5 | LL | assert!(r.is_err()); | ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()` error: called `assert!` with `Result::is_err` - --> $DIR/assertions_on_result_states.rs:82:5 + --> $DIR/assertions_on_result_states.rs:83:5 | LL | assert!(res.is_err()) | ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();` diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index b50682ea00c44..ef45e97d1de14 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -2,7 +2,7 @@ use core::num::Wrapping; -#[allow(dead_code, unused_assignments)] +#[allow(dead_code, unused_assignments, clippy::useless_vec)] #[warn(clippy::assign_op_pattern)] fn main() { let mut a = 5; diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 780d2d040f124..ae87afc485ed8 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -2,7 +2,7 @@ use core::num::Wrapping; -#[allow(dead_code, unused_assignments)] +#[allow(dead_code, unused_assignments, clippy::useless_vec)] #[warn(clippy::assign_op_pattern)] fn main() { let mut a = 5; diff --git a/tests/ui/auxiliary/extern_fake_libc.rs b/tests/ui/auxiliary/extern_fake_libc.rs new file mode 100644 index 0000000000000..eb5a5d2b83685 --- /dev/null +++ b/tests/ui/auxiliary/extern_fake_libc.rs @@ -0,0 +1,10 @@ +#![allow(nonstandard_style)] +#![allow(clippy::missing_safety_doc, unused)] + +type pid_t = i32; +pub unsafe fn getpid() -> pid_t { + pid_t::from(0) +} +pub fn getpid_SAFE_TRUTH() -> pid_t { + unsafe { getpid() } +} diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index e5bb906663c56..6b164967a28e4 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] //! Used to test that certain lints don't trigger in imported external macros - #[macro_export] macro_rules! try_err { () => { @@ -44,3 +43,10 @@ macro_rules! issue_10421 { b = a; }; } + +#[macro_export] +macro_rules! macro_with_panic { + () => { + panic!() + }; +} diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs index 7ed8a28dbd935..cab216b51ac71 100644 --- a/tests/ui/auxiliary/macro_use_helper.rs +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -1,3 +1,5 @@ +//@aux-build:macro_rules.rs + extern crate macro_rules; // STMT diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index d164dd0e54505..fdfe5fc418122 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -1,7 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] #![allow(incomplete_features)] #![allow(clippy::useless_conversion, clippy::uninlined_format_args)] diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index 5a924ca1830a4..37f0ec2b37d88 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -1,7 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(repr128, proc_macro_quote)] #![allow(incomplete_features)] #![allow(clippy::field_reassign_with_default)] @@ -90,70 +86,58 @@ pub fn extra_lifetime(_input: TokenStream) -> TokenStream { #[allow(unused)] #[proc_macro_derive(ArithmeticDerive)] pub fn arithmetic_derive(_: TokenStream) -> TokenStream { - >::from_iter( - [ - Ident::new("fn", Span::call_site()).into(), - Ident::new("_foo", Span::call_site()).into(), - Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), - Group::new( - Delimiter::Brace, - >::from_iter( - [ - Ident::new("let", Span::call_site()).into(), - Ident::new("mut", Span::call_site()).into(), - Ident::new("_n", Span::call_site()).into(), - Punct::new('=', Spacing::Alone).into(), - Literal::i32_unsuffixed(9).into(), - Punct::new(';', Spacing::Alone).into(), - Ident::new("_n", Span::call_site()).into(), - Punct::new('=', Spacing::Alone).into(), - Literal::i32_unsuffixed(9).into(), - Punct::new('/', Spacing::Alone).into(), - Literal::i32_unsuffixed(2).into(), - Punct::new(';', Spacing::Alone).into(), - Ident::new("_n", Span::call_site()).into(), - Punct::new('=', Spacing::Alone).into(), - Punct::new('-', Spacing::Alone).into(), - Ident::new("_n", Span::call_site()).into(), - Punct::new(';', Spacing::Alone).into(), - ] - .into_iter(), - ), - ) - .into(), - ] - .into_iter(), - ) + >::from_iter([ + Ident::new("fn", Span::call_site()).into(), + Ident::new("_foo", Span::call_site()).into(), + Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), + Group::new( + Delimiter::Brace, + >::from_iter([ + Ident::new("let", Span::call_site()).into(), + Ident::new("mut", Span::call_site()).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(9).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(9).into(), + Punct::new('/', Spacing::Alone).into(), + Literal::i32_unsuffixed(2).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Punct::new('-', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ]), + ) + .into(), + ]) } #[allow(unused)] #[proc_macro_derive(ShadowDerive)] pub fn shadow_derive(_: TokenStream) -> TokenStream { - >::from_iter( - [ - Ident::new("fn", Span::call_site()).into(), - Ident::new("_foo", Span::call_site()).into(), - Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), - Group::new( - Delimiter::Brace, - >::from_iter( - [ - Ident::new("let", Span::call_site()).into(), - Ident::new("_x", Span::call_site()).into(), - Punct::new('=', Spacing::Alone).into(), - Literal::i32_unsuffixed(2).into(), - Punct::new(';', Spacing::Alone).into(), - Ident::new("let", Span::call_site()).into(), - Ident::new("_x", Span::call_site()).into(), - Punct::new('=', Spacing::Alone).into(), - Ident::new("_x", Span::call_site()).into(), - Punct::new(';', Spacing::Alone).into(), - ] - .into_iter(), - ), - ) - .into(), - ] - .into_iter(), - ) + >::from_iter([ + Ident::new("fn", Span::call_site()).into(), + Ident::new("_foo", Span::call_site()).into(), + Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), + Group::new( + Delimiter::Brace, + >::from_iter([ + Ident::new("let", Span::call_site()).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(2).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("let", Span::call_site()).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ]), + ) + .into(), + ]) } diff --git a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs index f13b76e44b04f..79e8eff3aa101 100644 --- a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs +++ b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree}; diff --git a/tests/ui/auxiliary/proc_macro_unsafe.rs b/tests/ui/auxiliary/proc_macro_unsafe.rs index c2326678d0d52..1c591fc76f3e9 100644 --- a/tests/ui/auxiliary/proc_macro_unsafe.rs +++ b/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 94f075ed09cce..4d008c8cb59fc 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -1,10 +1,6 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(let_chains)] #![feature(proc_macro_span)] -#![allow(dead_code)] +#![allow(clippy::needless_if, dead_code)] extern crate proc_macro; diff --git a/tests/ui/blocks_in_if_conditions.fixed b/tests/ui/blocks_in_if_conditions.fixed index a9f18782e58b7..2a3867ac8fc0e 100644 --- a/tests/ui/blocks_in_if_conditions.fixed +++ b/tests/ui/blocks_in_if_conditions.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_if_conditions.rs b/tests/ui/blocks_in_if_conditions.rs index 0a70317c4d408..704d09fbad3d9 100644 --- a/tests/ui/blocks_in_if_conditions.rs +++ b/tests/ui/blocks_in_if_conditions.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_if_conditions_closure.rs b/tests/ui/blocks_in_if_conditions_closure.rs index 169589f6d4e70..d6d085d7fd14f 100644 --- a/tests/ui/blocks_in_if_conditions_closure.rs +++ b/tests/ui/blocks_in_if_conditions_closure.rs @@ -1,5 +1,10 @@ #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow( + unused, + clippy::let_and_return, + clippy::needless_if, + clippy::unnecessary_literal_unwrap +)] fn predicate bool, T>(pfn: F, val: T) -> bool { pfn(val) diff --git a/tests/ui/blocks_in_if_conditions_closure.stderr b/tests/ui/blocks_in_if_conditions_closure.stderr index 941d604dd5f91..5ac02e7504e8a 100644 --- a/tests/ui/blocks_in_if_conditions_closure.stderr +++ b/tests/ui/blocks_in_if_conditions_closure.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` - --> $DIR/blocks_in_if_conditions_closure.rs:18:17 + --> $DIR/blocks_in_if_conditions_closure.rs:23:17 | LL | |x| { | _________________^ @@ -11,7 +11,7 @@ LL | | }, = note: `-D clippy::blocks-in-if-conditions` implied by `-D warnings` 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` - --> $DIR/blocks_in_if_conditions_closure.rs:27:13 + --> $DIR/blocks_in_if_conditions_closure.rs:32:13 | LL | |x| { | _____________^ diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 670eef6a21d7e..d6774c0359842 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -1,5 +1,6 @@ //@run-rustfix +#![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] fn main() { diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 72851be635d0e..c0483fd737489 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,5 +1,6 @@ //@run-rustfix +#![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] fn main() { diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 31522d4a52519..f4dded365fba9 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,5 +1,5 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:7:8 + --> $DIR/bool_comparison.rs:8:8 | LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -7,127 +7,127 @@ LL | if x == true { = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:12:8 + --> $DIR/bool_comparison.rs:13:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:17:8 + --> $DIR/bool_comparison.rs:18:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:22:8 + --> $DIR/bool_comparison.rs:23:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:27:8 + --> $DIR/bool_comparison.rs:28:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:32:8 + --> $DIR/bool_comparison.rs:33:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:37:8 + --> $DIR/bool_comparison.rs:38:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:42:8 + --> $DIR/bool_comparison.rs:43:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:47:8 + --> $DIR/bool_comparison.rs:48:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:52:8 + --> $DIR/bool_comparison.rs:53:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:57:8 + --> $DIR/bool_comparison.rs:58:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:62:8 + --> $DIR/bool_comparison.rs:63:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:68:8 + --> $DIR/bool_comparison.rs:69:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:73:8 + --> $DIR/bool_comparison.rs:74:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:121:8 + --> $DIR/bool_comparison.rs:122:8 | LL | if a == !b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:122:8 + --> $DIR/bool_comparison.rs:123:8 | LL | if !a == b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:126:8 + --> $DIR/bool_comparison.rs:127:8 | LL | if b == !a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:127:8 + --> $DIR/bool_comparison.rs:128:8 | LL | if !b == a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:151:8 + --> $DIR/bool_comparison.rs:152:8 | LL | if false == m!(func) {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:152:8 + --> $DIR/bool_comparison.rs:153:8 | LL | if m!(func) == false {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:153:8 + --> $DIR/bool_comparison.rs:154:8 | LL | if true == m!(func) {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:154:8 + --> $DIR/bool_comparison.rs:155:8 | LL | if m!(func) == true {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index 3f440ce0045a9..996cc3650ff0a 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -1,9 +1,18 @@ //@run-rustfix #![warn(clippy::borrow_as_ptr)] +#![allow(clippy::useless_vec)] + +fn a() -> i32 { + 0 +} fn main() { let val = 1; let _p = std::ptr::addr_of!(val); + let _p = &0 as *const i32; + let _p = &a() as *const i32; + let vec = vec![1]; + let _p = &vec.len() as *const usize; let mut val_mut = 1; let _p_mut = std::ptr::addr_of_mut!(val_mut); diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index c1ca9180eef42..5eafaeb2fc306 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -1,9 +1,18 @@ //@run-rustfix #![warn(clippy::borrow_as_ptr)] +#![allow(clippy::useless_vec)] + +fn a() -> i32 { + 0 +} fn main() { let val = 1; let _p = &val as *const i32; + let _p = &0 as *const i32; + let _p = &a() as *const i32; + let vec = vec![1]; + let _p = &vec.len() as *const usize; let mut val_mut = 1; let _p_mut = &mut val_mut as *mut i32; diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr index be1ed73305674..c9990bb6f2266 100644 --- a/tests/ui/borrow_as_ptr.stderr +++ b/tests/ui/borrow_as_ptr.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:6:14 + --> $DIR/borrow_as_ptr.rs:11:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)` @@ -7,7 +7,7 @@ LL | let _p = &val as *const i32; = note: `-D clippy::borrow-as-ptr` implied by `-D warnings` error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:9:18 + --> $DIR/borrow_as_ptr.rs:18:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)` diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 755264617920e..b951ba04c37f4 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(dead_code, unused_variables)] diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index e319d365f7e77..52980e55fbea0 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(dead_code, unused_variables)] diff --git a/tests/ui/borrow_interior_mutable_const/enums.rs b/tests/ui/borrow_interior_mutable_const/enums.rs index 29b08ab36430d..da940a4cfb50b 100644 --- a/tests/ui/borrow_interior_mutable_const/enums.rs +++ b/tests/ui/borrow_interior_mutable_const/enums.rs @@ -1,6 +1,6 @@ //@aux-build:helper.rs -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] // this file (mostly) replicates its `declare` counterpart. Please see it for more discussions. @@ -19,7 +19,7 @@ const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; fn borrow_optional_cell() { - let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability + let _ = &UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &FROZEN_VARIANT; } @@ -34,11 +34,11 @@ trait AssocConsts { // This is the "suboptimal behavior" mentioned in `is_value_unfrozen` // caused by a similar reason to unfrozen types without any default values // get linted even if it has frozen variants'. - let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR: interior mutability // The lint ignores default values because an impl of this trait can set // an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`. - let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR: interior mutability } } @@ -47,9 +47,9 @@ impl AssocConsts for u64 { const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; fn function() { - let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &::TO_BE_FROZEN_VARIANT; - let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; } } @@ -67,11 +67,11 @@ trait AssocTypes { impl AssocTypes for u64 { type ToBeUnfrozen = AtomicUsize; - const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); const TO_BE_FROZEN_VARIANT: Option = None; fn function() { - let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &::TO_BE_FROZEN_VARIANT; } } @@ -83,19 +83,19 @@ enum BothOfCellAndGeneric { } impl BothOfCellAndGeneric { - const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); fn function() { - let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability - let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability + let _ = &Self::UNFROZEN_VARIANT; //~ ERROR: interior mutability + let _ = &Self::GENERIC_VARIANT; //~ ERROR: interior mutability let _ = &Self::FROZEN_VARIANT; } } fn main() { // constants defined in foreign crates - let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability + let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT; } diff --git a/tests/ui/borrow_interior_mutable_const/enums.stderr b/tests/ui/borrow_interior_mutable_const/enums.stderr index b0cab977a0384..b753ec92608a8 100644 --- a/tests/ui/borrow_interior_mutable_const/enums.stderr +++ b/tests/ui/borrow_interior_mutable_const/enums.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:22:14 | -LL | let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/enums.rs:3:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:37:18 | -LL | let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_FROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:41:18 | -LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior muta error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:50:18 | -LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &::TO_BE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR i error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:52:18 | -LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mu error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:74:18 | -LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &::TO_BE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR in error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:91:18 | -LL | let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &Self::UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:92:18 | -LL | let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability +LL | let _ = &Self::GENERIC_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:99:14 | -LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs index 7c57864245a94..0ea93dd84625c 100644 --- a/tests/ui/borrow_interior_mutable_const/others.rs +++ b/tests/ui/borrow_interior_mutable_const/others.rs @@ -1,4 +1,4 @@ -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)] #![allow(const_item_mutation)] @@ -51,14 +51,14 @@ impl std::ops::Deref for StaticRef { const CELL_REF: StaticRef<(UnsafeCell,)> = unsafe { StaticRef::new(std::ptr::null()) }; fn main() { - ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability - assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + ATOMIC.store(1, Ordering::SeqCst); //~ ERROR: interior mutability + assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR: interior mutability let _once = ONCE_INIT; - let _once_ref = &ONCE_INIT; //~ ERROR interior mutability - let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability - let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability - let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability + let _once_ref = &ONCE_INIT; //~ ERROR: interior mutability + let _once_ref_2 = &&ONCE_INIT; //~ ERROR: interior mutability + let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR: interior mutability + let _once_mut = &mut ONCE_INIT; //~ ERROR: interior mutability let _atomic_into_inner = ATOMIC.into_inner(); // these should be all fine. let _twice = (ONCE_INIT, ONCE_INIT); @@ -69,23 +69,23 @@ fn main() { let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0]; // referencing projection is still bad. - let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability - let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability - let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability - let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability - let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability + let _ = &ATOMIC_TUPLE; //~ ERROR: interior mutability + let _ = &ATOMIC_TUPLE.0; //~ ERROR: interior mutability + let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability + let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability + let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability let _ = &*ATOMIC_TUPLE.1; let _ = &ATOMIC_TUPLE.2; let _ = (&&&&ATOMIC_TUPLE).0; let _ = (&&&&ATOMIC_TUPLE).2; let _ = ATOMIC_TUPLE.0; - let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + let _ = ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability let _ = ATOMIC_TUPLE.1.into_iter(); let _ = ATOMIC_TUPLE.2; let _ = &{ ATOMIC_TUPLE }; - CELL.set(2); //~ ERROR interior mutability - assert_eq!(CELL.get(), 6); //~ ERROR interior mutability + CELL.set(2); //~ ERROR: interior mutability + assert_eq!(CELL.get(), 6); //~ ERROR: interior mutability assert_eq!(INTEGER, 8); assert!(STRING.is_empty()); diff --git a/tests/ui/borrow_interior_mutable_const/others.stderr b/tests/ui/borrow_interior_mutable_const/others.stderr index c87ad206c2ae2..200e04b8f6be5 100644 --- a/tests/ui/borrow_interior_mutable_const/others.stderr +++ b/tests/ui/borrow_interior_mutable_const/others.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:54:5 | -LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability +LL | ATOMIC.store(1, Ordering::SeqCst); | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/others.rs:1:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:55:16 | -LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability +LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:58:22 | -LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref = &ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:59:25 | -LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref_2 = &&ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:60:27 | -LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref_4 = &&&&ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:61:26 | -LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability +LL | let _once_mut = &mut ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:72:14 | -LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:73:14 | -LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE.0; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:74:19 | -LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability +LL | let _ = &(&&&&ATOMIC_TUPLE).0; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -74,7 +78,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:75:14 | -LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -82,7 +86,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:76:13 | -LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability +LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -90,7 +94,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:82:13 | -LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +LL | let _ = ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -98,7 +102,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:87:5 | -LL | CELL.set(2); //~ ERROR interior mutability +LL | CELL.set(2); | ^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -106,7 +110,7 @@ LL | CELL.set(2); //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:88:16 | -LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability +LL | assert_eq!(CELL.get(), 6); | ^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/borrow_interior_mutable_const/traits.rs b/tests/ui/borrow_interior_mutable_const/traits.rs index 06b5d62e8f9a8..4da3833cbf5a0 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.rs +++ b/tests/ui/borrow_interior_mutable_const/traits.rs @@ -1,4 +1,4 @@ -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] // this file replicates its `declare` counterpart. Please see it for more discussions. @@ -12,7 +12,7 @@ trait ConcreteTypes { const STRING: String; fn function() { - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::STRING; } } @@ -23,7 +23,7 @@ impl ConcreteTypes for u64 { fn function() { // Lint this again since implementers can choose not to borrow it. - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::STRING; } } @@ -48,7 +48,7 @@ impl GenericTypes for Vec { fn function() { let _ = &Self::TO_REMAIN_GENERIC; - let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable + let _ = &Self::TO_BE_CONCRETE; //~ ERROR: interior mutability } } @@ -83,8 +83,8 @@ impl AssocTypes for Vec { fn function() { let _ = &Self::TO_BE_FROZEN; - let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable - let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable + let _ = &Self::TO_BE_UNFROZEN; //~ ERROR: interior mutability + let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR: interior mutability let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM; } } @@ -106,7 +106,7 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR interior mutable + let _ = &Self::BOUNDED; //~ ERROR: interior mutability } } @@ -119,7 +119,7 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR interior mutable + let _ = &Self::BOUNDED; //~ ERROR: interior mutability } } @@ -148,8 +148,8 @@ impl SelfType for AtomicUsize { const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); fn function() { - let _ = &Self::SELF; //~ ERROR interior mutable - let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable + let _ = &Self::SELF; //~ ERROR: interior mutability + let _ = &Self::WRAPPED_SELF; //~ ERROR: interior mutability } } @@ -159,7 +159,7 @@ trait BothOfCellAndGeneric { fn function() { let _ = &Self::DIRECT; - let _ = &Self::INDIRECT; //~ ERROR interior mutable + let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } @@ -169,7 +169,7 @@ impl BothOfCellAndGeneric for Vec { fn function() { let _ = &Self::DIRECT; - let _ = &Self::INDIRECT; //~ ERROR interior mutable + let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } @@ -188,15 +188,15 @@ where const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); fn function() { - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::COW; let _ = &Self::GENERIC_TYPE; let _ = &Self::ASSOC_TYPE; - let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable + let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR: interior mutability } } fn main() { - u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability - assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability + u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR: interior mutability + assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR: interior mutability } diff --git a/tests/ui/borrow_interior_mutable_const/traits.stderr b/tests/ui/borrow_interior_mutable_const/traits.stderr index f34ae8814c335..add223acd68c7 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.stderr +++ b/tests/ui/borrow_interior_mutable_const/traits.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:15:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/traits.rs:1:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:26:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:51:18 | -LL | let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_CONCRETE; | ^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:86:18 | -LL | let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:87:18 | -LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable +LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:109:18 | -LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:122:18 | -LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:151:18 | -LL | let _ = &Self::SELF; //~ ERROR interior mutable +LL | let _ = &Self::SELF; | ^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &Self::SELF; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:152:18 | -LL | let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable +LL | let _ = &Self::WRAPPED_SELF; | ^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -74,7 +78,7 @@ LL | let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:162:18 | -LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable +LL | let _ = &Self::INDIRECT; | ^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -82,7 +86,7 @@ LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:172:18 | -LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable +LL | let _ = &Self::INDIRECT; | ^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -90,7 +94,7 @@ LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:191:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -98,7 +102,7 @@ LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:195:18 | -LL | let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED_ASSOC_TYPE; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -106,7 +110,7 @@ LL | let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:200:5 | -LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability +LL | u64::ATOMIC.store(5, Ordering::SeqCst); | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -114,7 +118,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:201:16 | -LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability +LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/builtin_type_shadow.rs b/tests/ui/builtin_type_shadow.rs index 69b8b6a0e68c3..c5addd53434c9 100644 --- a/tests/ui/builtin_type_shadow.rs +++ b/tests/ui/builtin_type_shadow.rs @@ -3,7 +3,7 @@ fn foo(a: u32) -> u32 { 42 - // ^ rustc's type error + //~^ ERROR: mismatched types } fn main() {} diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index d3ad26921bffa..4d168bfeab93a 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_borrow)] +#![allow(clippy::needless_borrow, clippy::useless_vec)] #[deny(clippy::naive_bytecount)] fn main() { diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index a86b85706a345..60a0eabf55b0b 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -41,6 +41,14 @@ fn main() { 1u32 as i32; 1u64 as i64; 1usize as isize; + 1usize as i8; // should not wrap, usize is never 8 bits + 1usize as i16; // wraps on 16 bit ptr size + 1usize as i32; // wraps on 32 bit ptr size + 1usize as i64; // wraps on 64 bit ptr size + 1u8 as isize; // should not wrap, isize is never 8 bits + 1u16 as isize; // wraps on 16 bit ptr size + 1u32 as isize; // wraps on 32 bit ptr size + 1u64 as isize; // wraps on 64 bit ptr size // Test clippy::cast_sign_loss 1i32 as u32; -1i32 as u32; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 65ecf1aa37aaa..de29af78ef30c 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -215,20 +215,110 @@ error: casting `usize` to `isize` may wrap around the value LL | 1usize as isize; | ^^^^^^^^^^^^^^^ -error: casting `i32` to `u32` may lose the sign of the value +error: casting `usize` to `i8` may truncate the value + --> $DIR/cast.rs:44:5 + | +LL | 1usize as i8; // should not wrap, usize is never 8 bits + | ^^^^^^^^^^^^ + | + = 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 | i8::try_from(1usize); // should not wrap, usize is never 8 bits + | ~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i16` may truncate the value + --> $DIR/cast.rs:45:5 + | +LL | 1usize as i16; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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 | i16::try_from(1usize); // wraps on 16 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers + --> $DIR/cast.rs:45:5 + | +LL | 1usize as i16; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + | + = note: `usize` and `isize` may be as small as 16 bits on some platforms + = 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 --> $DIR/cast.rs:46:5 | +LL | 1usize as i32; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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 | i32::try_from(1usize); // wraps on 32 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast.rs:46:5 + | +LL | 1usize as i32; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast.rs:47:5 + | +LL | 1usize as i64; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers + --> $DIR/cast.rs:49:5 + | +LL | 1u16 as isize; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + | + = note: `usize` and `isize` may be as small as 16 bits on some platforms + = 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 + --> $DIR/cast.rs:50:5 + | +LL | 1u32 as isize; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast.rs:51:5 + | +LL | 1u64 as isize; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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 | isize::try_from(1u64); // wraps on 64 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast.rs:51:5 + | +LL | 1u64 as isize; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `i32` to `u32` may lose the sign of the value + --> $DIR/cast.rs:54:5 + | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> $DIR/cast.rs:48:5 + --> $DIR/cast.rs:56:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> $DIR/cast.rs:115:5 + --> $DIR/cast.rs:123:5 | LL | (-99999999999i64).min(1) as i8; // should be linted because signed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +330,7 @@ LL | i8::try_from((-99999999999i64).min(1)); // should be linted because sig | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `u8` may truncate the value - --> $DIR/cast.rs:127:5 + --> $DIR/cast.rs:135:5 | LL | 999999u64.clamp(0, 256) as u8; // should still be linted | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,7 +342,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E2` to `u8` may truncate the value - --> $DIR/cast.rs:148:21 + --> $DIR/cast.rs:156:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -264,7 +354,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> $DIR/cast.rs:149:21 + --> $DIR/cast.rs:157:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -272,7 +362,7 @@ LL | let _ = Self::B as u8; = note: `-D clippy::cast-enum-truncation` implied by `-D warnings` error: casting `main::E5` to `i8` may truncate the value - --> $DIR/cast.rs:185:21 + --> $DIR/cast.rs:193:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -284,13 +374,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> $DIR/cast.rs:186:21 + --> $DIR/cast.rs:194:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> $DIR/cast.rs:200:21 + --> $DIR/cast.rs:208:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -302,7 +392,7 @@ LL | let _ = i16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:215:21 + --> $DIR/cast.rs:223:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -314,7 +404,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> $DIR/cast.rs:256:21 + --> $DIR/cast.rs:264:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -326,7 +416,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:264:13 + --> $DIR/cast.rs:272:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -338,7 +428,7 @@ LL | let c = u8::try_from(q >> 16); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:267:13 + --> $DIR/cast.rs:275:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -349,5 +439,5 @@ help: ... or use `try_from` and handle the error accordingly LL | let c = u8::try_from(q / 1000); | ~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 41 previous errors +error: aborting due to 51 previous errors diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index b77f01883bf38..27e03ebb7197d 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -1,4 +1,4 @@ -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::unnecessary_cast)] fn main() { let x: [i32; 3] = [1_i32, 2, 3]; diff --git a/tests/ui/cfg_features.rs b/tests/ui/cfg_features.rs new file mode 100644 index 0000000000000..bc4109c2c8964 --- /dev/null +++ b/tests/ui/cfg_features.rs @@ -0,0 +1,12 @@ +#![warn(clippy::maybe_misused_cfg)] + +fn main() { + #[cfg(features = "not-really-a-feature")] + let _ = 1 + 2; + + #[cfg(all(feature = "right", features = "wrong"))] + let _ = 1 + 2; + + #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + let _ = 1 + 2; +} diff --git a/tests/ui/cfg_features.stderr b/tests/ui/cfg_features.stderr new file mode 100644 index 0000000000000..00405985d48c7 --- /dev/null +++ b/tests/ui/cfg_features.stderr @@ -0,0 +1,28 @@ +error: feature may misspelled as features + --> $DIR/cfg_features.rs:4:11 + | +LL | #[cfg(features = "not-really-a-feature")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `feature = "not-really-a-feature"` + | + = note: `-D clippy::maybe-misused-cfg` implied by `-D warnings` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:7:34 + | +LL | #[cfg(all(feature = "right", features = "wrong"))] + | ^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong"` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:10:15 + | +LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong1"` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:10:59 + | +LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong2"` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/checked_unwrap/complex_conditionals.rs b/tests/ui/checked_unwrap/complex_conditionals.rs index ec082c73b44c0..16e54a7d969ef 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.rs +++ b/tests/ui/checked_unwrap/complex_conditionals.rs @@ -1,5 +1,9 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] fn test_complex_conditions() { let x: Result<(), ()> = Ok(()); diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index d44d5072e4850..c395c5ba06f2e 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:8:9 + --> $DIR/complex_conditionals.rs:12:9 | LL | if x.is_ok() && y.is_err() { | --------- the check is happening here @@ -14,7 +14,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:9:9 + --> $DIR/complex_conditionals.rs:13:9 | LL | if x.is_ok() && y.is_err() { | --------- because of this check @@ -29,7 +29,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:10:9 + --> $DIR/complex_conditionals.rs:14:9 | LL | if x.is_ok() && y.is_err() { | ---------- because of this check @@ -38,7 +38,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:11:9 + --> $DIR/complex_conditionals.rs:15:9 | LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here @@ -49,7 +49,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:25:9 + --> $DIR/complex_conditionals.rs:29:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -58,7 +58,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:26:9 + --> $DIR/complex_conditionals.rs:30:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -69,7 +69,7 @@ LL | x.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:27:9 + --> $DIR/complex_conditionals.rs:31:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -78,7 +78,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:28:9 + --> $DIR/complex_conditionals.rs:32:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -89,7 +89,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:32:9 + --> $DIR/complex_conditionals.rs:36:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -99,7 +99,7 @@ LL | x.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:33:9 + --> $DIR/complex_conditionals.rs:37:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -108,7 +108,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:34:9 + --> $DIR/complex_conditionals.rs:38:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -117,7 +117,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:35:9 + --> $DIR/complex_conditionals.rs:39:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -128,7 +128,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `z` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:36:9 + --> $DIR/complex_conditionals.rs:40:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here @@ -139,7 +139,7 @@ LL | z.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:37:9 + --> $DIR/complex_conditionals.rs:41:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check @@ -148,7 +148,7 @@ LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:45:9 + --> $DIR/complex_conditionals.rs:49:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -157,7 +157,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:46:9 + --> $DIR/complex_conditionals.rs:50:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -168,7 +168,7 @@ LL | x.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:47:9 + --> $DIR/complex_conditionals.rs:51:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -179,7 +179,7 @@ LL | y.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:48:9 + --> $DIR/complex_conditionals.rs:52:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -188,7 +188,7 @@ LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:49:9 + --> $DIR/complex_conditionals.rs:53:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check @@ -197,7 +197,7 @@ LL | z.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `z` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:50:9 + --> $DIR/complex_conditionals.rs:54:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/tests/ui/checked_unwrap/complex_conditionals_nested.rs index 043ea4148dc51..e417cf833cbb9 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.rs +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.rs @@ -1,5 +1,9 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] fn test_nested() { fn nested() { diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index 542ab53300c02..049a69d93bfe9 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/complex_conditionals_nested.rs:8:13 + --> $DIR/complex_conditionals_nested.rs:12:13 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals_nested.rs:10:13 + --> $DIR/complex_conditionals_nested.rs:14:13 | LL | if x.is_some() { | ----------- because of this check diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index 82dce81979fd9..61042bb90d27a 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -1,6 +1,10 @@ #![feature(lint_reasons)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] macro_rules! m { ($a:expr) => { diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index ef68827422233..93809f6551add 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:40:9 + --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:41:9 + --> $DIR/simple_conditionals.rs:45:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -22,7 +22,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:43:9 + --> $DIR/simple_conditionals.rs:47:9 | LL | if x.is_some() { | ----------- because of this check @@ -37,7 +37,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:44:9 + --> $DIR/simple_conditionals.rs:48:9 | LL | if x.is_some() { | ----------- because of this check @@ -46,7 +46,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:47:9 + --> $DIR/simple_conditionals.rs:51:9 | LL | if x.is_none() { | ----------- because of this check @@ -54,7 +54,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_none` - --> $DIR/simple_conditionals.rs:49:9 + --> $DIR/simple_conditionals.rs:53:9 | LL | if x.is_none() { | -------------- help: try: `if let Some(..) = x` @@ -63,7 +63,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:8:13 + --> $DIR/simple_conditionals.rs:12:13 | LL | if $a.is_some() { | --------------- help: try: `if let Some(..) = x` @@ -76,7 +76,7 @@ LL | m!(x); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:57:9 + --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -84,7 +84,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:58:9 + --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -93,7 +93,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:59:9 + --> $DIR/simple_conditionals.rs:63:9 | LL | if x.is_ok() { | --------- because of this check @@ -102,7 +102,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:61:9 + --> $DIR/simple_conditionals.rs:65:9 | LL | if x.is_ok() { | --------- because of this check @@ -111,7 +111,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:62:9 + --> $DIR/simple_conditionals.rs:66:9 | LL | if x.is_ok() { | --------- because of this check @@ -120,7 +120,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:63:9 + --> $DIR/simple_conditionals.rs:67:9 | LL | if x.is_ok() { | ------------ help: try: `if let Err(..) = x` @@ -129,7 +129,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:66:9 + --> $DIR/simple_conditionals.rs:70:9 | LL | if x.is_err() { | ---------- because of this check @@ -137,7 +137,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:67:9 + --> $DIR/simple_conditionals.rs:71:9 | LL | if x.is_err() { | ------------- help: try: `if let Err(..) = x` @@ -146,7 +146,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:69:9 + --> $DIR/simple_conditionals.rs:73:9 | LL | if x.is_err() { | ------------- help: try: `if let Ok(..) = x` @@ -155,7 +155,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:70:9 + --> $DIR/simple_conditionals.rs:74:9 | LL | if x.is_err() { | ---------- because of this check diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index 8f9f2a0db8c43..b7c186bef7724 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,3 +1,5 @@ +#![allow(clippy::incorrect_clone_impl_on_copy_type)] + use std::fmt; use std::marker::PhantomData; diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index b6e09ab319086..34bd2233440bf 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -2,6 +2,7 @@ #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] +#![allow(clippy::useless_vec)] fn main() { // yay diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index fa9e1a996139d..fa8444937b6b1 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -2,6 +2,7 @@ #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] +#![allow(clippy::useless_vec)] fn main() { // yay diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr index e0361acd95607..3ce482006e949 100644 --- a/tests/ui/cloned_instead_of_copied.stderr +++ b/tests/ui/cloned_instead_of_copied.stderr @@ -1,5 +1,5 @@ error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:8:24 + --> $DIR/cloned_instead_of_copied.rs:9:24 | LL | let _ = [1].iter().cloned(); | ^^^^^^ help: try: `copied` @@ -7,43 +7,43 @@ LL | let _ = [1].iter().cloned(); = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:9:31 + --> $DIR/cloned_instead_of_copied.rs:10:31 | LL | let _ = vec!["hi"].iter().cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:10:22 + --> $DIR/cloned_instead_of_copied.rs:11:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:11:34 + --> $DIR/cloned_instead_of_copied.rs:12:34 | LL | let _ = Box::new([1].iter()).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:12:32 + --> $DIR/cloned_instead_of_copied.rs:13:32 | LL | let _ = Box::new(Some(&1)).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:28:22 + --> $DIR/cloned_instead_of_copied.rs:29:22 | LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:33:24 + --> $DIR/cloned_instead_of_copied.rs:34:24 | LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:34:22 + --> $DIR/cloned_instead_of_copied.rs:35:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed index 3bf3deb9b9182..118346348564b 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed @@ -1,5 +1,10 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 +#![allow( + unused, + clippy::needless_if, + clippy::redundant_clone, + clippy::derive_partial_eq_without_eq +)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. macro_rules! impl_types { diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/tests/ui/cmp_owned/asymmetric_partial_eq.rs index 10107dc8f86d3..3a25d53a5d080 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.rs +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.rs @@ -1,5 +1,10 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 +#![allow( + unused, + clippy::needless_if, + clippy::redundant_clone, + clippy::derive_partial_eq_without_eq +)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. macro_rules! impl_types { diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr index 43bf8851fc620..4714a0daaa68a 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr @@ -1,5 +1,5 @@ error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:42:12 + --> $DIR/asymmetric_partial_eq.rs:47:12 | LL | if borrowed.to_owned() == owned {} | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` @@ -7,7 +7,7 @@ LL | if borrowed.to_owned() == owned {} = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:43:21 + --> $DIR/asymmetric_partial_eq.rs:48:21 | LL | if owned == borrowed.to_owned() {} | ---------^^^^^^^^^^^^^^^^^^^ @@ -15,13 +15,13 @@ LL | if owned == borrowed.to_owned() {} | help: try: `borrowed == owned` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:61:21 + --> $DIR/asymmetric_partial_eq.rs:66:21 | LL | if owned == borrowed.to_owned() {} | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:62:12 + --> $DIR/asymmetric_partial_eq.rs:67:12 | LL | if borrowed.to_owned() == owned {} | ^^^^^^^^^^^^^^^^^^^--------- @@ -29,7 +29,7 @@ LL | if borrowed.to_owned() == owned {} | help: try: `owned == borrowed` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:88:20 + --> $DIR/asymmetric_partial_eq.rs:93:20 | LL | if "Hi" == borrowed.to_string() {} | --------^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | if "Hi" == borrowed.to_string() {} | help: try: `borrowed == "Hi"` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:89:12 + --> $DIR/asymmetric_partial_eq.rs:94:12 | LL | if borrowed.to_string() == "Hi" {} | ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index 76f90ab2a9d11..bf1a58588a856 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -31,7 +31,7 @@ struct Foo; impl PartialEq for Foo { // Allow this here, because it emits the lint // without a suggestion. This is tested in - // `tests/ui/cmp_owned/without_suggestion.rs` + // `$DIR/without_suggestion.rs` #[allow(clippy::cmp_owned)] fn eq(&self, other: &Self) -> bool { self.to_owned() == *other diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 5824631fa83ba..d867246301abd 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -39,6 +39,14 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions +error: the function has a cognitive complexity of (2/1) + --> $DIR/cognitive_complexity.rs:178:4 + | +LL | fn dont_warn_on_tests() { + | ^^^^^^^^^^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + error: the function has a cognitive complexity of (2/1) --> $DIR/cognitive_complexity.rs:186:4 | @@ -151,5 +159,5 @@ LL | pub async fn async_method() { | = help: you could split it up into multiple smaller functions -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index 8302cec45e781..c4116cd8520c0 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] +#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 5913dcf41cafc..8f51d0ee508ff 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] +#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index c6514a559340c..e305e1d7a8710 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -2,6 +2,7 @@ #![allow( clippy::assertions_on_constants, clippy::equatable_if_let, + clippy::needless_if, clippy::nonminimal_bool, clippy::eq_op )] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 2c85b68df632c..7c52959d3b51b 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -2,6 +2,7 @@ #![allow( clippy::assertions_on_constants, clippy::equatable_if_let, + clippy::needless_if, clippy::nonminimal_bool, clippy::eq_op )] diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index c687bae1acc52..4a1a9e8a60aee 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,5 +1,5 @@ error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:14:5 + --> $DIR/collapsible_if.rs:15:5 | LL | / if x == "hello" { LL | | if y == "world" { @@ -17,7 +17,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:20:5 + --> $DIR/collapsible_if.rs:21:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -34,7 +34,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:26:5 + --> $DIR/collapsible_if.rs:27:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -51,7 +51,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:32:5 + --> $DIR/collapsible_if.rs:33:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -68,7 +68,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:38:5 + --> $DIR/collapsible_if.rs:39:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -85,7 +85,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:44:5 + --> $DIR/collapsible_if.rs:45:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -102,7 +102,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:100:5 + --> $DIR/collapsible_if.rs:101:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible @@ -119,7 +119,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:159:5 + --> $DIR/collapsible_if.rs:160:5 | LL | / if matches!(true, true) { LL | | if matches!(true, true) {} @@ -127,7 +127,7 @@ LL | | } | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:164:5 + --> $DIR/collapsible_if.rs:165:5 | LL | / if matches!(true, true) && truth() { LL | | if matches!(true, true) {} diff --git a/tests/ui/collection_is_never_read.rs b/tests/ui/collection_is_never_read.rs index 2c1a42a72c149..e02c1c57230ad 100644 --- a/tests/ui/collection_is_never_read.rs +++ b/tests/ui/collection_is_never_read.rs @@ -1,4 +1,4 @@ -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] #![warn(clippy::collection_is_never_read)] use std::collections::{HashMap, HashSet}; diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed index dd2615ab25cf1..c92dd509ebb2d 100644 --- a/tests/ui/comparison_to_empty.fixed +++ b/tests/ui/comparison_to_empty.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::comparison_to_empty)] +#![allow(clippy::useless_vec)] fn main() { // Disallow comparisons to empty diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs index 5462784c6ac8a..b3489714380aa 100644 --- a/tests/ui/comparison_to_empty.rs +++ b/tests/ui/comparison_to_empty.rs @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::comparison_to_empty)] +#![allow(clippy::useless_vec)] fn main() { // Disallow comparisons to empty diff --git a/tests/ui/comparison_to_empty.stderr b/tests/ui/comparison_to_empty.stderr index f69d6bd5255df..cc09b17eb8951 100644 --- a/tests/ui/comparison_to_empty.stderr +++ b/tests/ui/comparison_to_empty.stderr @@ -1,5 +1,5 @@ error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:8:13 + --> $DIR/comparison_to_empty.rs:9:13 | LL | let _ = s == ""; | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` @@ -7,19 +7,19 @@ LL | let _ = s == ""; = note: `-D clippy::comparison-to-empty` implied by `-D warnings` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:9:13 + --> $DIR/comparison_to_empty.rs:10:13 | LL | let _ = s != ""; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:12:13 + --> $DIR/comparison_to_empty.rs:13:13 | LL | let _ = v == []; | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:13:13 + --> $DIR/comparison_to_empty.rs:14:13 | LL | let _ = v != []; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()` diff --git a/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/tests/ui/crashes/auxiliary/proc_macro_crash.rs index 66419656a327a..5dffddc119aa3 100644 --- a/tests/ui/crashes/auxiliary/proc_macro_crash.rs +++ b/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -1,13 +1,5 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic -// ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro -// crates. If we don't set this, compiletest will override the `crate_type` attribute below and -// compile this as dylib. Removing this then causes the test to fail because a `dylib` crate can't -// contain a proc-macro. - #![feature(repr128)] #![allow(incomplete_features)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/crashes/ice-10148.rs b/tests/ui/crashes/ice-10148.rs index c7f0224820ed0..0df22f41374f1 100644 --- a/tests/ui/crashes/ice-10148.rs +++ b/tests/ui/crashes/ice-10148.rs @@ -1,4 +1,4 @@ -//@aux-build:../../auxiliary/proc_macros.rs +//@aux-build:../auxiliary/proc_macros.rs:proc-macro extern crate proc_macros; diff --git a/tests/ui/crashes/ice-10645.rs b/tests/ui/crashes/ice-10645.rs index 4d8698d383ba5..6e126aff7512e 100644 --- a/tests/ui/crashes/ice-10645.rs +++ b/tests/ui/crashes/ice-10645.rs @@ -1,4 +1,4 @@ -// compile-flags: --cap-lints=warn +//@compile-flags: --cap-lints=warn // https://github.com/rust-lang/rust-clippy/issues/10645 #![warn(clippy::future_not_send)] diff --git a/tests/ui/crashes/ice-10645.stderr b/tests/ui/crashes/ice-10645.stderr index fc084e30d7fe8..0055fe061e2aa 100644 --- a/tests/ui/crashes/ice-10645.stderr +++ b/tests/ui/crashes/ice-10645.stderr @@ -1,4 +1,4 @@ -error: future cannot be sent between threads safely +warning: future cannot be sent between threads safely --> $DIR/ice-10645.rs:5:35 | LL | pub async fn bar<'a, T: 'a>(_: T) {} @@ -12,5 +12,5 @@ LL | pub async fn bar<'a, T: 'a>(_: T) {} = note: `T` doesn't implement `std::marker::Send` = note: `-D clippy::future-not-send` implied by `-D warnings` -error: aborting due to previous error +warning: 1 warning emitted diff --git a/tests/ui/crashes/ice-10912.rs b/tests/ui/crashes/ice-10912.rs new file mode 100644 index 0000000000000..69d7f2f395fff --- /dev/null +++ b/tests/ui/crashes/ice-10912.rs @@ -0,0 +1,4 @@ +#![warn(clippy::unreadable_literal)] +fn f2() -> impl Sized { && 3.14159265358979323846E } + +fn main() {} diff --git a/tests/ui/crashes/ice-10912.stderr b/tests/ui/crashes/ice-10912.stderr new file mode 100644 index 0000000000000..a74ce731577d0 --- /dev/null +++ b/tests/ui/crashes/ice-10912.stderr @@ -0,0 +1,16 @@ +error: expected at least one digit in exponent + --> $DIR/ice-10912.rs:2:28 + | +LL | fn f2() -> impl Sized { && 3.14159265358979323846E } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: long literal lacking separators + --> $DIR/ice-10912.rs:2:28 + | +LL | fn f2() -> impl Sized { && 3.14159265358979323846E } + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider: `3.141_592_653_589_793_238_46` + | + = note: `-D clippy::unreadable-literal` implied by `-D warnings` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index 81af88962a64d..19ab03418eed3 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/tests/ui/crashes/ice-1782.rs @@ -1,4 +1,5 @@ #![allow(dead_code, unused_variables)] +#![allow(clippy::unnecessary_cast)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` /// diff --git a/tests/ui/crashes/ice-2774.stderr b/tests/ui/crashes/ice-2774.stderr index c5ea0b16d1be4..a166ccb3ee8fa 100644 --- a/tests/ui/crashes/ice-2774.stderr +++ b/tests/ui/crashes/ice-2774.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/ice-2774.rs:15:1 + --> $DIR/ice-2774.rs:15:28 | LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` help: elide the lifetimes diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs index b402052882adc..21cd9d337cdd0 100644 --- a/tests/ui/crashes/ice-3462.rs +++ b/tests/ui/crashes/ice-3462.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(clippy::disallowed_names, clippy::equatable_if_let)] +#![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)] #![allow(unused)] /// Test for https://github.com/rust-lang/rust-clippy/issues/3462 diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs index 3106a2e721694..268c5ba0ad0f6 100644 --- a/tests/ui/crashes/ice-3741.rs +++ b/tests/ui/crashes/ice-3741.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_crash.rs +//@aux-build:proc_macro_crash.rs:proc-macro #![warn(clippy::suspicious_else_formatting)] diff --git a/tests/ui/crashes/ice-4968.rs b/tests/ui/crashes/ice-4968.rs index ac724ac93e3f2..50473868005e0 100644 --- a/tests/ui/crashes/ice-4968.rs +++ b/tests/ui/crashes/ice-4968.rs @@ -1,5 +1,3 @@ -//@check-pass - // Test for https://github.com/rust-lang/rust-clippy/issues/4968 #![warn(clippy::unsound_collection_transmute)] diff --git a/tests/ui/crashes/ice-5497.rs b/tests/ui/crashes/ice-5497.rs index 0769bce5fc809..f77f691c19276 100644 --- a/tests/ui/crashes/ice-5497.rs +++ b/tests/ui/crashes/ice-5497.rs @@ -7,5 +7,5 @@ pub trait Foo { impl Foo for Vec { const OOB: i32 = [1][1] + T::OOB; - //~^ ERROR operation will panic + //~^ ERROR: operation will panic } diff --git a/tests/ui/crashes/ice-5579.rs b/tests/ui/crashes/ice-5579.rs index e1842c73f0e31..8ab36bbf93cbf 100644 --- a/tests/ui/crashes/ice-5579.rs +++ b/tests/ui/crashes/ice-5579.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_literal_unwrap)] + trait IsErr { fn is_err(&self, err: &str) -> bool; } diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr index db34e6bfa7b2f..97390af3e89ed 100644 --- a/tests/ui/crashes/ice-6250.stderr +++ b/tests/ui/crashes/ice-6250.stderr @@ -1,9 +1,3 @@ -error[E0601]: `main` function not found in crate `ice_6250` - --> $DIR/ice-6250.rs:16:2 - | -LL | } - | ^ consider adding a `main` function to `$DIR/ice-6250.rs` - error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:14 | @@ -24,7 +18,6 @@ help: consider adding `let` LL | let Some(reference) = cache.data.get(key) { | +++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0601. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/crashes/ice-6251.stderr b/tests/ui/crashes/ice-6251.stderr index 8da2965c63512..68a5766c90c0e 100644 --- a/tests/ui/crashes/ice-6251.stderr +++ b/tests/ui/crashes/ice-6251.stderr @@ -1,9 +1,3 @@ -error[E0601]: `main` function not found in crate `ice_6251` - --> $DIR/ice-6251.rs:6:2 - | -LL | } - | ^ consider adding a `main` function to `$DIR/ice-6251.rs` - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/ice-6251.rs:4:45 | @@ -35,7 +29,7 @@ LL | fn bug() -> impl Iterator { = note: expected type `usize` found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0308, E0601. +Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/crashes/ice-6255.rs b/tests/ui/crashes/ice-6255.rs index ccde6aa2b0f77..b6555ac5c4072 100644 --- a/tests/ui/crashes/ice-6255.rs +++ b/tests/ui/crashes/ice-6255.rs @@ -4,7 +4,6 @@ macro_rules! define_other_core { ( ) => { extern crate std as core; - //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` }; } @@ -13,3 +12,4 @@ fn main() { } define_other_core!(); +//~^ ERROR: macro-expanded `extern crate` items cannot shadow names passed with `--extern` diff --git a/tests/ui/crashes/ice-6256.rs b/tests/ui/crashes/ice-6256.rs index f9ee3e058c111..1d336b3cdc0c8 100644 --- a/tests/ui/crashes/ice-6256.rs +++ b/tests/ui/crashes/ice-6256.rs @@ -10,6 +10,6 @@ impl dyn TT { #[rustfmt::skip] fn main() { - let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types - //[nll]~^ ERROR: borrowed data escapes outside of closure + let f = |x: &dyn TT| x.func(); + //~^ ERROR: borrowed data escapes outside of closure } diff --git a/tests/ui/crashes/ice-6256.stderr b/tests/ui/crashes/ice-6256.stderr index 9cfcccf1e3cd9..671933157c809 100644 --- a/tests/ui/crashes/ice-6256.stderr +++ b/tests/ui/crashes/ice-6256.stderr @@ -1,7 +1,7 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/ice-6256.rs:13:26 | -LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types +LL | let f = |x: &dyn TT| x.func(); | - - ^^^^^^^^ | | | | | | | `x` escapes the closure body here diff --git a/tests/ui/crashes/ice-7169.rs b/tests/ui/crashes/ice-7169.rs index 82095febc194a..b203252f0a14a 100644 --- a/tests/ui/crashes/ice-7169.rs +++ b/tests/ui/crashes/ice-7169.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_if)] + #[derive(Default)] struct A { a: Vec>, diff --git a/tests/ui/crashes/ice-7169.stderr b/tests/ui/crashes/ice-7169.stderr index 5a9cd32380a19..84e0af3f0d0a9 100644 --- a/tests/ui/crashes/ice-7169.stderr +++ b/tests/ui/crashes/ice-7169.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/ice-7169.rs:8:12 + --> $DIR/ice-7169.rs:10:12 | LL | if let Ok(_) = Ok::<_, ()>(A::::default()) {} | -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::::default()).is_ok()` diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index a5373cdcae120..a2683b3ce3402 100644 --- a/tests/ui/crashes/ice-7410.rs +++ b/tests/ui/crashes/ice-7410.rs @@ -1,6 +1,6 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-macos -//@ignore-windows +//@ignore-target-apple +//@ignore-target-windows #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/crashes/ice-96721.rs b/tests/ui/crashes/ice-96721.rs index 4b3fb76401082..ca68ba3d03a51 100644 --- a/tests/ui/crashes/ice-96721.rs +++ b/tests/ui/crashes/ice-96721.rs @@ -4,7 +4,7 @@ macro_rules! foo { }; } -#[path = foo!()] //~ ERROR malformed `path` attribute +#[path = foo!()] //~ ERROR: malformed `path` attribute mod abc {} fn main() {} diff --git a/tests/ui/crashes/ice-96721.stderr b/tests/ui/crashes/ice-96721.stderr index 78c567b8e772e..712bd14c685f0 100644 --- a/tests/ui/crashes/ice-96721.stderr +++ b/tests/ui/crashes/ice-96721.stderr @@ -1,7 +1,7 @@ error: malformed `path` attribute input --> $DIR/ice-96721.rs:7:1 | -LL | #[path = foo!()] //~ ERROR malformed `path` attribute +LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` error: aborting due to previous error diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr index 0b0e0ad2684a9..37484f5ebd702 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr +++ b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes_impl_trait.rs:15:5 + --> $DIR/needless_lifetimes_impl_trait.rs:15:12 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | note: the lint level is defined here --> $DIR/needless_lifetimes_impl_trait.rs:1:9 diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index d6cd594d7c971..aa76688d80101 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,4 +1,4 @@ -//@ignore-macos +//@ignore-target-apple #![feature(rustc_attrs)] diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr deleted file mode 100644 index 3d79a115cb301..0000000000000 --- a/tests/ui/crate_level_checks/entrypoint_recursion.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: recursing into entrypoint `a` - --> $DIR/entrypoint_recursion.rs:10:5 - | -LL | a(); - | ^ - | - = help: consider using another function for this recursion - = note: `-D clippy::main-recursion` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs index a382135bb6951..32eba9695920c 100644 --- a/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,5 +1,5 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-macos +//@ignore-target-apple #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs index 10788d4048164..6c63c098916b7 100644 --- a/tests/ui/dbg_macro.rs +++ b/tests/ui/dbg_macro.rs @@ -1,4 +1,3 @@ -//@compile-flags: --test #![warn(clippy::dbg_macro)] fn foo(n: u32) -> u32 { diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr index 530e766331777..3d29262595902 100644 --- a/tests/ui/dbg_macro.stderr +++ b/tests/ui/dbg_macro.stderr @@ -1,5 +1,5 @@ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:5:22 + --> $DIR/dbg_macro.rs:4:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:10:8 + --> $DIR/dbg_macro.rs:9:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if n <= 1 { | ~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:11:9 + --> $DIR/dbg_macro.rs:10:9 | LL | dbg!(1) | ^^^^^^^ @@ -33,7 +33,7 @@ LL | 1 | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:13:9 + --> $DIR/dbg_macro.rs:12:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:18:5 + --> $DIR/dbg_macro.rs:17:5 | LL | dbg!(42); | ^^^^^^^^ @@ -55,7 +55,7 @@ LL | 42; | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:19:5 + --> $DIR/dbg_macro.rs:18:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | dbg!(dbg!(42)); | ~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:20:14 + --> $DIR/dbg_macro.rs:19:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | foo(3) + factorial(4); | ~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:21:5 + --> $DIR/dbg_macro.rs:20:5 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | (1, 2, dbg!(3, 4)); | ~~~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:22:5 + --> $DIR/dbg_macro.rs:21:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:42:5 + --> $DIR/dbg_macro.rs:41:5 | LL | dbg!(); | ^^^^^^^ @@ -111,7 +111,7 @@ LL + | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:44:13 + --> $DIR/dbg_macro.rs:43:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -122,7 +122,7 @@ LL | let _ = (); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:45:9 + --> $DIR/dbg_macro.rs:44:9 | LL | bar(dbg!()); | ^^^^^^ @@ -133,7 +133,7 @@ LL | bar(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:46:10 + --> $DIR/dbg_macro.rs:45:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -144,7 +144,7 @@ LL | foo!(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:47:16 + --> $DIR/dbg_macro.rs:46:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -155,7 +155,7 @@ LL | foo2!(foo!(())); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:68:9 + --> $DIR/dbg_macro.rs:67:9 | LL | dbg!(2); | ^^^^^^^ @@ -166,7 +166,7 @@ LL | 2; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:74:5 + --> $DIR/dbg_macro.rs:73:5 | LL | dbg!(1); | ^^^^^^^ @@ -177,7 +177,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:79:5 + --> $DIR/dbg_macro.rs:78:5 | LL | dbg!(1); | ^^^^^^^ @@ -188,7 +188,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:85:9 + --> $DIR/dbg_macro.rs:84:9 | LL | dbg!(1); | ^^^^^^^ diff --git a/tests/ui/declare_interior_mutable_const/enums.rs b/tests/ui/declare_interior_mutable_const/enums.rs index f44518694b89c..a88bf7b21b8b7 100644 --- a/tests/ui/declare_interior_mutable_const/enums.rs +++ b/tests/ui/declare_interior_mutable_const/enums.rs @@ -9,7 +9,7 @@ enum OptionalCell { } // a constant with enums should be linted only when the used variant is unfrozen (#3962). -const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable +const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR: interior mutable const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; const fn unfrozen_variant() -> OptionalCell { @@ -20,7 +20,7 @@ const fn frozen_variant() -> OptionalCell { OptionalCell::Frozen } -const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable +const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR: interior mutable const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant(); enum NestedInnermost { @@ -43,10 +43,11 @@ struct NestedOutermost { // a constant with enums should be linted according to its value, no matter how structs involve. const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { + //~^ ERROR: interior mutable outer: NestedOuter::NestedInner(NestedInner { inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)), }), -}; //~ ERROR interior mutable +}; const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost { outer: NestedOuter::NestedInner(NestedInner { inner: NestedInnermost::Frozen, @@ -56,11 +57,11 @@ const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost { trait AssocConsts { // When there's no default value, lint it only according to its type. // Further details are on the corresponding code (`NonCopyConst::check_trait_item`). - const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable - const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable + const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable // Lint default values accordingly. - const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable + const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR: interior mutable const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; } @@ -86,7 +87,7 @@ trait AssocTypes { impl AssocTypes for u64 { type ToBeUnfrozen = AtomicUsize; - const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR: interior mutable const TO_BE_FROZEN_VARIANT: Option = None; } @@ -98,25 +99,25 @@ enum BothOfCellAndGeneric { } impl BothOfCellAndGeneric { - const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR: interior mutable // This is a false positive. The argument about this is on `is_value_unfrozen_raw` - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); // This is what is likely to be a false negative when one tries to fix // the `GENERIC_VARIANT` false positive. - const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable + const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR: interior mutable } // associated types here is basically the same as the one above. trait BothOfCellAndGenericWithAssocType { type AssocType; - const UNFROZEN_VARIANT: BothOfCellAndGeneric = - BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = //~ ERROR: interior mutable + BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); } diff --git a/tests/ui/declare_interior_mutable_const/enums.stderr b/tests/ui/declare_interior_mutable_const/enums.stderr index 84198d5461578..6070df749ca98 100644 --- a/tests/ui/declare_interior_mutable_const/enums.stderr +++ b/tests/ui/declare_interior_mutable_const/enums.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/enums.rs:12:1 | -LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable +LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -11,7 +11,7 @@ LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(tru error: a `const` item should never be interior mutable --> $DIR/enums.rs:23:1 | -LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable +LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -24,65 +24,66 @@ LL | const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { | | | _make this a static item (maybe with lazy_static) | | +LL | | LL | | outer: NestedOuter::NestedInner(NestedInner { LL | | inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)), LL | | }), -LL | | }; //~ ERROR interior mutable +LL | | }; | |__^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:59:5 + --> $DIR/enums.rs:60:5 | -LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:60:5 + --> $DIR/enums.rs:61:5 | -LL | const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable +LL | const TO_BE_FROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:63:5 + --> $DIR/enums.rs:64:5 | -LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable +LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:89:5 + --> $DIR/enums.rs:90:5 | -LL | const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:101:5 + --> $DIR/enums.rs:102:5 | -LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mut... +LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:104:5 + --> $DIR/enums.rs:105:5 | -LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable +LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:110:5 + --> $DIR/enums.rs:111:5 | -LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable +LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:117:5 + --> $DIR/enums.rs:118:5 | LL | / const UNFROZEN_VARIANT: BothOfCellAndGeneric = -LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable +LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | |____________________________________________________________________^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:119:5 + --> $DIR/enums.rs:120:5 | -LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mu... +LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs index 896596b567922..1cec2980652c1 100644 --- a/tests/ui/declare_interior_mutable_const/others.rs +++ b/tests/ui/declare_interior_mutable_const/others.rs @@ -6,17 +6,17 @@ use std::fmt::Display; use std::sync::atomic::AtomicUsize; use std::sync::Once; -const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable -const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable +const CELL: Cell = Cell::new(6); //~ ERROR: interior mutable const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); -//~^ ERROR interior mutable +//~^ ERROR: interior mutable macro_rules! declare_const { ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; } -declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +declare_const!(_ONCE: Once = Once::new()); //~ ERROR: interior mutable // const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492. @@ -24,12 +24,12 @@ const INTEGER: u8 = 8; const STRING: String = String::new(); const STR: &str = "012345"; const COW: Cow = Cow::Borrowed("abcdef"); -//^ note: a const item of Cow is used in the `postgres` package. +// note: a const item of Cow is used in the `postgres` package. const NO_ANN: &dyn Display = &70; static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING); -//^ there should be no lints on this line +// there should be no lints on the line above line mod issue_8493 { use std::cell::Cell; @@ -40,7 +40,7 @@ mod issue_8493 { macro_rules! issue_8493 { () => { - const _BAZ: Cell = Cell::new(0); //~ ERROR interior mutable + const _BAZ: Cell = Cell::new(0); static _FOOBAR: () = { thread_local! { static _VAR: Cell = const { Cell::new(0) }; @@ -49,7 +49,7 @@ mod issue_8493 { }; } - issue_8493!(); + issue_8493!(); //~ ERROR: interior mutable } fn main() {} diff --git a/tests/ui/declare_interior_mutable_const/others.stderr b/tests/ui/declare_interior_mutable_const/others.stderr index 1fd6d7322a76c..0259f6a4a286b 100644 --- a/tests/ui/declare_interior_mutable_const/others.stderr +++ b/tests/ui/declare_interior_mutable_const/others.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/others.rs:9:1 | -LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -11,7 +11,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable error: a `const` item should never be interior mutable --> $DIR/others.rs:10:1 | -LL | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +LL | const CELL: Cell = Cell::new(6); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -30,7 +30,7 @@ error: a `const` item should never be interior mutable LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +LL | declare_const!(_ONCE: Once = Once::new()); | ----------------------------------------- in this macro invocation | = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable error: a `const` item should never be interior mutable --> $DIR/others.rs:43:13 | -LL | const _BAZ: Cell = Cell::new(0); //~ ERROR interior mutable +LL | const _BAZ: Cell = Cell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | issue_8493!(); diff --git a/tests/ui/declare_interior_mutable_const/traits.rs b/tests/ui/declare_interior_mutable_const/traits.rs index 256a336db821d..a6ccdd2707989 100644 --- a/tests/ui/declare_interior_mutable_const/traits.rs +++ b/tests/ui/declare_interior_mutable_const/traits.rs @@ -12,10 +12,10 @@ macro_rules! declare_const { // a constant whose type is a concrete type should be linted at the definition site. trait ConcreteTypes { - const ATOMIC: AtomicUsize; //~ ERROR interior mutable + const ATOMIC: AtomicUsize; //~ ERROR: interior mutable const INTEGER: u64; const STRING: String; - declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable + declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR: interior mutable } impl ConcreteTypes for u64 { @@ -40,7 +40,7 @@ trait GenericTypes { impl GenericTypes for u64 { const TO_REMAIN_GENERIC: T = T::DEFAULT; - const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable + const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR: interior mutable } // a helper type used below @@ -65,8 +65,8 @@ impl AssocTypes for Vec { type ToBeGenericParam = T; const TO_BE_FROZEN: Self::ToBeFrozen = 12; - const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable - const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable + const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR: interior mutable + const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR: interior mutable const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper = Wrapper(T::DEFAULT); } @@ -85,7 +85,7 @@ where T: AssocTypesHelper, { const NOT_BOUNDED: T::NotToBeBounded; - const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable + const BOUNDED: T::ToBeBounded; //~ ERROR: interior mutable } impl AssocTypesFromGenericParam for u64 @@ -113,8 +113,8 @@ impl SelfType for u64 { impl SelfType for AtomicUsize { // this (interior mutable `Self` const) exists in `parking_lot`. // `const_trait_impl` will replace it in the future, hopefully. - const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable - const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR interior mutable + const SELF: Self = AtomicUsize::new(17); //~ ERROR: interior mutable + const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR: interior mutable } // Even though a constant contains a generic type, if it also have an interior mutable type, @@ -122,7 +122,7 @@ impl SelfType for AtomicUsize { trait BothOfCellAndGeneric { // this is a false negative in the current implementation. const DIRECT: Cell; - const INDIRECT: Cell<*const T>; //~ ERROR interior mutable + const INDIRECT: Cell<*const T>; //~ ERROR: interior mutable } impl BothOfCellAndGeneric for u64 { @@ -138,13 +138,13 @@ impl Local where T: ConstDefault + AssocTypesHelper, { - const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable + const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR: interior mutable const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy"); const GENERIC_TYPE: T = T::DEFAULT; const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED; - const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable + const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR: interior mutable } fn main() {} diff --git a/tests/ui/declare_interior_mutable_const/traits.stderr b/tests/ui/declare_interior_mutable_const/traits.stderr index 7debe059ff4ee..ef62919dfead3 100644 --- a/tests/ui/declare_interior_mutable_const/traits.stderr +++ b/tests/ui/declare_interior_mutable_const/traits.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/traits.rs:15:5 | -LL | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings` @@ -12,7 +12,7 @@ error: a `const` item should never be interior mutable LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable +LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); | ---------------------------------------------------------- in this macro invocation | = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -20,55 +20,55 @@ LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR i error: a `const` item should never be interior mutable --> $DIR/traits.rs:43:5 | -LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable +LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:68:5 | -LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:69:5 | -LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable +LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:88:5 | -LL | const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable +LL | const BOUNDED: T::ToBeBounded; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:116:5 | -LL | const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable +LL | const SELF: Self = AtomicUsize::new(17); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:117:5 | -LL | const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR interior mutable +LL | const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:125:5 | -LL | const INDIRECT: Cell<*const T>; //~ ERROR interior mutable +LL | const INDIRECT: Cell<*const T>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:141:5 | -LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:147:5 | -LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable +LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 11 previous errors diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index f7819068ac5ab..da0816830b85f 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -1,4 +1,4 @@ -//@ignore-macos +//@ignore-target-apple #![feature(no_core, lang_items, start)] #![no_core] diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed index 9520efe6329b1..02eb78060130f 100644 --- a/tests/ui/default_numeric_fallback_f64.fixed +++ b/tests/ui/default_numeric_fallback_f64.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::default_numeric_fallback)] #![allow( diff --git a/tests/ui/default_numeric_fallback_f64.rs b/tests/ui/default_numeric_fallback_f64.rs index cacbdb4a95bf4..79a9669833fad 100644 --- a/tests/ui/default_numeric_fallback_f64.rs +++ b/tests/ui/default_numeric_fallback_f64.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::default_numeric_fallback)] #![allow( diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed index fbabb8bcf8e33..23272d07eec66 100644 --- a/tests/ui/default_numeric_fallback_i32.fixed +++ b/tests/ui/default_numeric_fallback_i32.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs index 7bfc390e4bfab..fb149141609dc 100644 --- a/tests/ui/default_numeric_fallback_i32.rs +++ b/tests/ui/default_numeric_fallback_i32.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed index bf5dca976416d..14eb6d572cfac 100644 --- a/tests/ui/default_trait_access.fixed +++ b/tests/ui/default_trait_access.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![deny(clippy::default_trait_access)] #![allow(dead_code, unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 5e8e9ce85b1c5..aa2ced0a7f035 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![deny(clippy::default_trait_access)] #![allow(dead_code, unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed index b27d3bc100283..0ecca1b8ffaaa 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro -#![allow(clippy::return_self_not_must_use)] +#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] extern crate proc_macros; diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 825090c7c122e..9f91310e61f3e 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro -#![allow(clippy::return_self_not_must_use)] +#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] extern crate proc_macros; diff --git a/tests/ui/deref_addrof_macro.rs b/tests/ui/deref_addrof_macro.rs index c7e60f3650603..ce4b94a73bd25 100644 --- a/tests/ui/deref_addrof_macro.rs +++ b/tests/ui/deref_addrof_macro.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::deref_addrof)] diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index aa0efb85c297a..a10f3d0107076 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -268,4 +268,25 @@ impl Default for OtherGenericType { } } +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::::default() adjusts to Box + inner: Box::::default(), + } + } + } +} + fn main() {} diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 8dc999ad58602..18cef1c5be895 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -304,4 +304,25 @@ impl Default for OtherGenericType { } } +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::::default() adjusts to Box + inner: Box::::default(), + } + } + } +} + fn main() {} diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 6e0ce55f57d93..e01079bc977be 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] diff --git a/tests/ui/disallowed_names.rs b/tests/ui/disallowed_names.rs index e937c49f3897f..5889f04439ff4 100644 --- a/tests/ui/disallowed_names.rs +++ b/tests/ui/disallowed_names.rs @@ -1,5 +1,6 @@ #![allow( dead_code, + clippy::needless_if, clippy::similar_names, clippy::single_match, clippy::toplevel_ref_arg, diff --git a/tests/ui/disallowed_names.stderr b/tests/ui/disallowed_names.stderr index 78cb55096ff0c..9ab68b641f137 100644 --- a/tests/ui/disallowed_names.stderr +++ b/tests/ui/disallowed_names.stderr @@ -1,5 +1,5 @@ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:11:9 + --> $DIR/disallowed_names.rs:12:9 | LL | fn test(foo: ()) {} | ^^^ @@ -7,79 +7,79 @@ LL | fn test(foo: ()) {} = note: `-D clippy::disallowed-names` implied by `-D warnings` error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:14:9 + --> $DIR/disallowed_names.rs:15:9 | LL | let foo = 42; | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:15:9 + --> $DIR/disallowed_names.rs:16:9 | LL | let baz = 42; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:16:9 + --> $DIR/disallowed_names.rs:17:9 | LL | let quux = 42; | ^^^^ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:27:10 + --> $DIR/disallowed_names.rs:28:10 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:27:20 + --> $DIR/disallowed_names.rs:28:20 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:27:26 + --> $DIR/disallowed_names.rs:28:26 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^^ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:32:19 + --> $DIR/disallowed_names.rs:33:19 | LL | fn issue_1647(mut foo: u8) { | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:33:13 + --> $DIR/disallowed_names.rs:34:13 | LL | let mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:34:21 + --> $DIR/disallowed_names.rs:35:21 | LL | if let Some(mut quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:38:13 + --> $DIR/disallowed_names.rs:39:13 | LL | let ref baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:39:21 + --> $DIR/disallowed_names.rs:40:21 | LL | if let Some(ref quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:43:17 + --> $DIR/disallowed_names.rs:44:17 | LL | let ref mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:44:25 + --> $DIR/disallowed_names.rs:45:25 | LL | if let Some(ref mut quux) = Some(42) {} | ^^^^ diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index e8f992e6ddedb..9b1619baf0e6c 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,5 +1,6 @@ #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::overly_complex_bool_expr)] +#![allow(clippy::nonminimal_bool)] #[allow(clippy::empty_loop)] fn diverge() -> ! { loop {} @@ -21,6 +22,7 @@ fn main() { } #[allow(dead_code, unused_variables)] +#[rustfmt::skip] fn foobar() { loop { let x = match 5 { @@ -35,6 +37,20 @@ fn foobar() { 99 => return, _ => true || panic!("boo"), }, + // lint blocks as well + 15 => true || { return; }, + 16 => false || { return; }, + // ... and when it's a single expression + 17 => true || { return }, + 18 => false || { return }, + // ... but not when there's both an expression and a statement + 19 => true || { _ = 1; return }, + 20 => false || { _ = 1; return }, + // ... or multiple statements + 21 => true || { _ = 1; return; }, + 22 => false || { _ = 1; return; }, + 23 => true || { return; true }, + 24 => true || { return; true }, _ => true || break, }; } diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 51a3b0d972e68..243a5cf5369ad 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,5 +1,5 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:19:10 + --> $DIR/diverging_sub_expression.rs:20:10 | LL | b || diverge(); | ^^^^^^^^^ @@ -7,34 +7,66 @@ LL | b || diverge(); = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:20:10 + --> $DIR/diverging_sub_expression.rs:21:10 | LL | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:29:26 + --> $DIR/diverging_sub_expression.rs:31:26 | LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:30:26 + --> $DIR/diverging_sub_expression.rs:32:26 | LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:33:26 + --> $DIR/diverging_sub_expression.rs:35:26 | LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:38:26 + --> $DIR/diverging_sub_expression.rs:38:30 + | +LL | _ => true || panic!("boo"), + | ^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:41:29 + | +LL | 15 => true || { return; }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:42:30 + | +LL | 16 => false || { return; }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:44:29 + | +LL | 17 => true || { return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:45:30 + | +LL | 18 => false || { return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:54:26 | LL | _ => true || break, | ^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index d3aa2816cb6d3..14444df4c10ec 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -60,6 +60,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript +/// WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index d1e7d8017d7d1..542d33b13a4c5 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -60,6 +60,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript +/// WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index 6c67c903c7508..94ef43afc08f3 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -132,7 +132,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:74:5 + --> $DIR/doc-fixable.rs:75:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:91:5 + --> $DIR/doc-fixable.rs:92:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:99:8 + --> $DIR/doc-fixable.rs:100:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | /// ## `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:102:7 + --> $DIR/doc-fixable.rs:103:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | /// # `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:104:22 + --> $DIR/doc-fixable.rs:105:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | /// Not a title #897 `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:105:5 + --> $DIR/doc-fixable.rs:106:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +198,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:112:5 + --> $DIR/doc-fixable.rs:113:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:125:5 + --> $DIR/doc-fixable.rs:126:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -220,7 +220,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:136:43 + --> $DIR/doc-fixable.rs:137:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -231,7 +231,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:141:5 + --> $DIR/doc-fixable.rs:142:5 | LL | And BarQuz too. | ^^^^^^ @@ -242,7 +242,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:142:1 + --> $DIR/doc-fixable.rs:143:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:147:43 + --> $DIR/doc-fixable.rs:148:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -264,7 +264,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:152:5 + --> $DIR/doc-fixable.rs:153:5 | LL | And BarQuz too. | ^^^^^^ @@ -275,7 +275,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:153:1 + --> $DIR/doc-fixable.rs:154:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -286,7 +286,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:164:5 + --> $DIR/doc-fixable.rs:165:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:183:22 + --> $DIR/doc-fixable.rs:184:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs new file mode 100644 index 0000000000000..f1a2c0575ee5e --- /dev/null +++ b/tests/ui/doc/needless_doctest_main.rs @@ -0,0 +1,20 @@ +#![warn(clippy::needless_doctest_main)] +//! issue 10491: +//! ```rust,no_test +//! use std::collections::HashMap; +//! +//! fn main() { +//! let mut m = HashMap::new(); +//! m.insert(1u32, 2u32); +//! } +//! ``` + +/// some description here +/// ```rust,no_test +/// fn main() { +/// foo() +/// } +/// ``` +fn foo() {} + +fn main() {} diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index 0c8eac5ccffc3..d21b046f167ef 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::let_unit_value)] diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index c80ff671a5db7..f8ca92ef0b34b 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -1,4 +1,5 @@ //@run-rustfix +#![allow(clippy::needless_if)] fn main() { let x = 1; diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index bc78694aa6806..47ff87bea0ab0 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -1,4 +1,5 @@ //@run-rustfix +#![allow(clippy::needless_if)] fn main() { let x = 1; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 05ef4e25f7f87..4df1c28ac4871 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,5 +1,5 @@ error: this binary expression can be simplified - --> $DIR/double_comparison.rs:6:8 + --> $DIR/double_comparison.rs:7:8 | LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` @@ -7,43 +7,43 @@ LL | if x == y || x < y { = note: `-D clippy::double-comparisons` implied by `-D warnings` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:9:8 + --> $DIR/double_comparison.rs:10:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:12:8 + --> $DIR/double_comparison.rs:13:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:15:8 + --> $DIR/double_comparison.rs:16:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:18:8 + --> $DIR/double_comparison.rs:19:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:21:8 + --> $DIR/double_comparison.rs:22:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:24:8 + --> $DIR/double_comparison.rs:25:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:27:8 + --> $DIR/double_comparison.rs:28:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/drain_collect.fixed b/tests/ui/drain_collect.fixed new file mode 100644 index 0000000000000..11001bd319f31 --- /dev/null +++ b/tests/ui/drain_collect.fixed @@ -0,0 +1,77 @@ +//@run-rustfix + +#![deny(clippy::drain_collect)] +#![allow(dead_code)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { + std::mem::take(b) +} + +fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { + b.drain().collect() +} + +fn hashmap(b: &mut HashMap) -> HashMap { + std::mem::take(b) +} + +fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { + b.drain().collect() +} + +fn hashset(b: &mut HashSet) -> HashSet { + std::mem::take(b) +} + +fn hashset_dont_lint(b: &mut HashSet) -> Vec { + b.drain().collect() +} + +fn vecdeque(b: &mut VecDeque) -> VecDeque { + std::mem::take(b) +} + +fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { + b.drain(..).collect() +} + +fn vec(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec2(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec3(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec4(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec_no_reborrow() -> Vec { + let mut b = vec![1, 2, 3]; + std::mem::take(&mut b) +} + +fn vec_dont_lint(b: &mut Vec) -> HashSet { + b.drain(..).collect() +} + +fn string(b: &mut String) -> String { + std::mem::take(b) +} + +fn string_dont_lint(b: &mut String) -> HashSet { + b.drain(..).collect() +} + +fn not_whole_length(v: &mut Vec) -> Vec { + v.drain(1..).collect() +} + +fn main() {} diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs new file mode 100644 index 0000000000000..373a3ca3506da --- /dev/null +++ b/tests/ui/drain_collect.rs @@ -0,0 +1,77 @@ +//@run-rustfix + +#![deny(clippy::drain_collect)] +#![allow(dead_code)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { + b.drain().collect() +} + +fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { + b.drain().collect() +} + +fn hashmap(b: &mut HashMap) -> HashMap { + b.drain().collect() +} + +fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { + b.drain().collect() +} + +fn hashset(b: &mut HashSet) -> HashSet { + b.drain().collect() +} + +fn hashset_dont_lint(b: &mut HashSet) -> Vec { + b.drain().collect() +} + +fn vecdeque(b: &mut VecDeque) -> VecDeque { + b.drain(..).collect() +} + +fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { + b.drain(..).collect() +} + +fn vec(b: &mut Vec) -> Vec { + b.drain(..).collect() +} + +fn vec2(b: &mut Vec) -> Vec { + b.drain(0..).collect() +} + +fn vec3(b: &mut Vec) -> Vec { + b.drain(..b.len()).collect() +} + +fn vec4(b: &mut Vec) -> Vec { + b.drain(0..b.len()).collect() +} + +fn vec_no_reborrow() -> Vec { + let mut b = vec![1, 2, 3]; + b.drain(..).collect() +} + +fn vec_dont_lint(b: &mut Vec) -> HashSet { + b.drain(..).collect() +} + +fn string(b: &mut String) -> String { + b.drain(..).collect() +} + +fn string_dont_lint(b: &mut String) -> HashSet { + b.drain(..).collect() +} + +fn not_whole_length(v: &mut Vec) -> Vec { + v.drain(1..).collect() +} + +fn main() {} diff --git a/tests/ui/drain_collect.stderr b/tests/ui/drain_collect.stderr new file mode 100644 index 0000000000000..0792f0254cb54 --- /dev/null +++ b/tests/ui/drain_collect.stderr @@ -0,0 +1,68 @@ +error: you seem to be trying to move all elements into a new `BinaryHeap` + --> $DIR/drain_collect.rs:9:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + | +note: the lint level is defined here + --> $DIR/drain_collect.rs:3:9 + | +LL | #![deny(clippy::drain_collect)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: you seem to be trying to move all elements into a new `HashMap` + --> $DIR/drain_collect.rs:17:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `HashSet` + --> $DIR/drain_collect.rs:25:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:33:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:41:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:45:5 + | +LL | b.drain(0..).collect() + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:49:5 + | +LL | b.drain(..b.len()).collect() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:53:5 + | +LL | b.drain(0..b.len()).collect() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:58:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `String` + --> $DIR/drain_collect.rs:66:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 879b3ac398e45..eb5e2266540c9 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -43,7 +43,7 @@ fn main() { if bla1() { println!("if"); } else if bla2() { - //~ ERROR else if without else + //~^ ERROR: `if` expression with an `else if`, but without a final `else` println!("else if"); } @@ -52,7 +52,7 @@ fn main() { } else if bla2() { println!("else if 1"); } else if bla3() { - //~ ERROR else if without else + //~^ ERROR: `if` expression with an `else if`, but without a final `else` println!("else if 2"); } } diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 90ccfb4fad641..11baf75441ae2 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -3,7 +3,7 @@ error: `if` expression with an `else if`, but without a final `else` | LL | } else if bla2() { | ____________^ -LL | | //~ ERROR else if without else +LL | | LL | | println!("else if"); LL | | } | |_____^ @@ -16,7 +16,7 @@ error: `if` expression with an `else if`, but without a final `else` | LL | } else if bla3() { | ____________^ -LL | | //~ ERROR else if without else +LL | | LL | | println!("else if 2"); LL | | } | |_____^ diff --git a/tests/ui/empty_line_after_doc_comments.rs b/tests/ui/empty_line_after_doc_comments.rs index e843770f57854..83db2a07d334e 100644 --- a/tests/ui/empty_line_after_doc_comments.rs +++ b/tests/ui/empty_line_after_doc_comments.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs:proc-macro #![warn(clippy::empty_line_after_doc_comments)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 269e66ea0a816..b2d7ddae42746 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs:proc-macro #![warn(clippy::empty_line_after_outer_attr)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/empty_loop.rs b/tests/ui/empty_loop.rs index 54e8fb4907c0f..f1a55415c8d50 100644 --- a/tests/ui/empty_loop.rs +++ b/tests/ui/empty_loop.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::empty_loop)] diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index d564b2d24f5c4..f9ab443dfd94a 100644 --- a/tests/ui/empty_loop_no_std.rs +++ b/tests/ui/empty_loop_no_std.rs @@ -1,5 +1,5 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-macos +//@ignore-target-apple #![warn(clippy::empty_loop)] #![feature(lang_items, start, libc)] diff --git a/tests/ui/endian_bytes.rs b/tests/ui/endian_bytes.rs new file mode 100644 index 0000000000000..6bf014fc80951 --- /dev/null +++ b/tests/ui/endian_bytes.rs @@ -0,0 +1,127 @@ +#![allow(unused)] +#![allow(clippy::diverging_sub_expression)] +#![no_main] + +macro_rules! fn_body { + () => { + 2u8.to_ne_bytes(); + 2i8.to_ne_bytes(); + 2u16.to_ne_bytes(); + 2i16.to_ne_bytes(); + 2u32.to_ne_bytes(); + 2i32.to_ne_bytes(); + 2u64.to_ne_bytes(); + 2i64.to_ne_bytes(); + 2u128.to_ne_bytes(); + 2i128.to_ne_bytes(); + 2.0f32.to_ne_bytes(); + 2.0f64.to_ne_bytes(); + 2usize.to_ne_bytes(); + 2isize.to_ne_bytes(); + u8::from_ne_bytes(todo!()); + i8::from_ne_bytes(todo!()); + u16::from_ne_bytes(todo!()); + i16::from_ne_bytes(todo!()); + u32::from_ne_bytes(todo!()); + i32::from_ne_bytes(todo!()); + u64::from_ne_bytes(todo!()); + i64::from_ne_bytes(todo!()); + u128::from_ne_bytes(todo!()); + i128::from_ne_bytes(todo!()); + usize::from_ne_bytes(todo!()); + isize::from_ne_bytes(todo!()); + f32::from_ne_bytes(todo!()); + f64::from_ne_bytes(todo!()); + + 2u8.to_le_bytes(); + 2i8.to_le_bytes(); + 2u16.to_le_bytes(); + 2i16.to_le_bytes(); + 2u32.to_le_bytes(); + 2i32.to_le_bytes(); + 2u64.to_le_bytes(); + 2i64.to_le_bytes(); + 2u128.to_le_bytes(); + 2i128.to_le_bytes(); + 2.0f32.to_le_bytes(); + 2.0f64.to_le_bytes(); + 2usize.to_le_bytes(); + 2isize.to_le_bytes(); + u8::from_le_bytes(todo!()); + i8::from_le_bytes(todo!()); + u16::from_le_bytes(todo!()); + i16::from_le_bytes(todo!()); + u32::from_le_bytes(todo!()); + i32::from_le_bytes(todo!()); + u64::from_le_bytes(todo!()); + i64::from_le_bytes(todo!()); + u128::from_le_bytes(todo!()); + i128::from_le_bytes(todo!()); + usize::from_le_bytes(todo!()); + isize::from_le_bytes(todo!()); + f32::from_le_bytes(todo!()); + f64::from_le_bytes(todo!()); + }; +} + +// bless breaks if I use fn_body too much (oops) +macro_rules! fn_body_smol { + () => { + 2u8.to_ne_bytes(); + u8::from_ne_bytes(todo!()); + + 2u8.to_le_bytes(); + u8::from_le_bytes(todo!()); + + 2u8.to_be_bytes(); + u8::from_be_bytes(todo!()); + }; +} + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +fn host() { fn_body!(); } + +#[rustfmt::skip] +#[warn(clippy::little_endian_bytes)] +fn little() { fn_body!(); } + +#[rustfmt::skip] +#[warn(clippy::big_endian_bytes)] +fn big() { fn_body!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn host_encourage_little() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn host_encourage_big() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn no_help() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::little_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn little_encourage_host() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn little_encourage_big() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::big_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn big_encourage_host() { fn_body_smol!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn big_encourage_little() { fn_body_smol!(); } diff --git a/tests/ui/endian_bytes.stderr b/tests/ui/endian_bytes.stderr new file mode 100644 index 0000000000000..5e64ea5b5ab8b --- /dev/null +++ b/tests/ui/endian_bytes.stderr @@ -0,0 +1,1031 @@ +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:7:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: `-D clippy::host-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:8:9 + | +LL | 2i8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u16::to_ne_bytes` method + --> $DIR/endian_bytes.rs:9:9 + | +LL | 2u16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i16::to_ne_bytes` method + --> $DIR/endian_bytes.rs:10:9 + | +LL | 2i16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u32::to_ne_bytes` method + --> $DIR/endian_bytes.rs:11:9 + | +LL | 2u32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i32::to_ne_bytes` method + --> $DIR/endian_bytes.rs:12:9 + | +LL | 2i32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u64::to_ne_bytes` method + --> $DIR/endian_bytes.rs:13:9 + | +LL | 2u64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i64::to_ne_bytes` method + --> $DIR/endian_bytes.rs:14:9 + | +LL | 2i64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u128::to_ne_bytes` method + --> $DIR/endian_bytes.rs:15:9 + | +LL | 2u128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i128::to_ne_bytes` method + --> $DIR/endian_bytes.rs:16:9 + | +LL | 2i128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `f32::to_ne_bytes` method + --> $DIR/endian_bytes.rs:17:9 + | +LL | 2.0f32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `f64::to_ne_bytes` method + --> $DIR/endian_bytes.rs:18:9 + | +LL | 2.0f64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `usize::to_ne_bytes` method + --> $DIR/endian_bytes.rs:19:9 + | +LL | 2usize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `isize::to_ne_bytes` method + --> $DIR/endian_bytes.rs:20:9 + | +LL | 2isize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:21:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i8::from_ne_bytes` + --> $DIR/endian_bytes.rs:22:9 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u16::from_ne_bytes` + --> $DIR/endian_bytes.rs:23:9 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i16::from_ne_bytes` + --> $DIR/endian_bytes.rs:24:9 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u32::from_ne_bytes` + --> $DIR/endian_bytes.rs:25:9 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i32::from_ne_bytes` + --> $DIR/endian_bytes.rs:26:9 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u64::from_ne_bytes` + --> $DIR/endian_bytes.rs:27:9 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i64::from_ne_bytes` + --> $DIR/endian_bytes.rs:28:9 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u128::from_ne_bytes` + --> $DIR/endian_bytes.rs:29:9 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i128::from_ne_bytes` + --> $DIR/endian_bytes.rs:30:9 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `usize::from_ne_bytes` + --> $DIR/endian_bytes.rs:31:9 + | +LL | usize::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `isize::from_ne_bytes` + --> $DIR/endian_bytes.rs:32:9 + | +LL | isize::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `f32::from_ne_bytes` + --> $DIR/endian_bytes.rs:33:9 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `f64::from_ne_bytes` + --> $DIR/endian_bytes.rs:34:9 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation + | + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:36:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: `-D clippy::little-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i8::to_le_bytes` method + --> $DIR/endian_bytes.rs:37:9 + | +LL | 2i8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u16::to_le_bytes` method + --> $DIR/endian_bytes.rs:38:9 + | +LL | 2u16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i16::to_le_bytes` method + --> $DIR/endian_bytes.rs:39:9 + | +LL | 2i16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u32::to_le_bytes` method + --> $DIR/endian_bytes.rs:40:9 + | +LL | 2u32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i32::to_le_bytes` method + --> $DIR/endian_bytes.rs:41:9 + | +LL | 2i32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u64::to_le_bytes` method + --> $DIR/endian_bytes.rs:42:9 + | +LL | 2u64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i64::to_le_bytes` method + --> $DIR/endian_bytes.rs:43:9 + | +LL | 2i64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u128::to_le_bytes` method + --> $DIR/endian_bytes.rs:44:9 + | +LL | 2u128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `i128::to_le_bytes` method + --> $DIR/endian_bytes.rs:45:9 + | +LL | 2i128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `f32::to_le_bytes` method + --> $DIR/endian_bytes.rs:46:9 + | +LL | 2.0f32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `f64::to_le_bytes` method + --> $DIR/endian_bytes.rs:47:9 + | +LL | 2.0f64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `usize::to_le_bytes` method + --> $DIR/endian_bytes.rs:48:9 + | +LL | 2usize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `isize::to_le_bytes` method + --> $DIR/endian_bytes.rs:49:9 + | +LL | 2isize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:50:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i8::from_le_bytes` + --> $DIR/endian_bytes.rs:51:9 + | +LL | i8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u16::from_le_bytes` + --> $DIR/endian_bytes.rs:52:9 + | +LL | u16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i16::from_le_bytes` + --> $DIR/endian_bytes.rs:53:9 + | +LL | i16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u32::from_le_bytes` + --> $DIR/endian_bytes.rs:54:9 + | +LL | u32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i32::from_le_bytes` + --> $DIR/endian_bytes.rs:55:9 + | +LL | i32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u64::from_le_bytes` + --> $DIR/endian_bytes.rs:56:9 + | +LL | u64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i64::from_le_bytes` + --> $DIR/endian_bytes.rs:57:9 + | +LL | i64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u128::from_le_bytes` + --> $DIR/endian_bytes.rs:58:9 + | +LL | u128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `i128::from_le_bytes` + --> $DIR/endian_bytes.rs:59:9 + | +LL | i128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `usize::from_le_bytes` + --> $DIR/endian_bytes.rs:60:9 + | +LL | usize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `isize::from_le_bytes` + --> $DIR/endian_bytes.rs:61:9 + | +LL | isize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `f32::from_le_bytes` + --> $DIR/endian_bytes.rs:62:9 + | +LL | f32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `f64::from_le_bytes` + --> $DIR/endian_bytes.rs:63:9 + | +LL | f64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_be_bytes` method + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_le_bytes` instead + = note: `-D clippy::big-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_be_bytes` method + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_be_bytes` method + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_le_bytes` method + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_be_bytes` method + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_ne_bytes` method + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the `u8::to_be_bytes` method + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the function `u8::from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation + | + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 86 previous errors + diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index f17556ea90709..abe42a2305f52 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -1,4 +1,4 @@ -//@ignore-x86 +//@ignore-target-x86 #![warn(clippy::enum_clike_unportable_variant)] #![allow(unused, non_upper_case_globals)] diff --git a/tests/ui/eprint_with_newline.rs b/tests/ui/eprint_with_newline.rs index de5e121be8774..8389806c838e1 100644 --- a/tests/ui/eprint_with_newline.rs +++ b/tests/ui/eprint_with_newline.rs @@ -44,7 +44,7 @@ fn main() { // Don't warn on CRLF (#4208) eprint!("\r\n"); eprint!("foo\r\n"); - eprint!("\\r\n"); //~ ERROR + eprint!("\\r\n"); eprint!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/eprint_with_newline.stderr b/tests/ui/eprint_with_newline.stderr index 0eefb9f0ca978..0a6bdf15df8ee 100644 --- a/tests/ui/eprint_with_newline.stderr +++ b/tests/ui/eprint_with_newline.stderr @@ -62,13 +62,13 @@ LL + eprintln!(); error: using `eprint!()` with a format string that ends in a single newline --> $DIR/eprint_with_newline.rs:28:5 | -LL | eprint!("//n"); // should fail +LL | eprint!("///n"); // should fail | ^^^^^^^^^^^^^^^ | help: use `eprintln!` instead | -LL - eprint!("//n"); // should fail -LL + eprintln!("/"); // should fail +LL - eprint!("///n"); // should fail +LL + eprintln!("//"); // should fail | error: using `eprint!()` with a format string that ends in a single newline @@ -104,13 +104,13 @@ LL ~ error: using `eprint!()` with a format string that ends in a single newline --> $DIR/eprint_with_newline.rs:47:5 | -LL | eprint!("/r/n"); //~ ERROR +LL | eprint!("//r/n"); | ^^^^^^^^^^^^^^^^ | help: use `eprintln!` instead | -LL - eprint!("/r/n"); //~ ERROR -LL + eprintln!("/r"); //~ ERROR +LL - eprint!("//r/n"); +LL + eprintln!("//r"); | error: aborting due to 9 previous errors diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index cdd33ebe582ff..e973e5ba2fb1e 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,5 +1,3 @@ -//@compile-flags: --test - #![warn(clippy::eq_op)] #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)] #![allow(clippy::suspicious_xor_used_as_pow)] @@ -12,6 +10,8 @@ fn main() { let _ = false != false; let _ = 1.5 < 1.5; let _ = 1u64 >= 1u64; + let x = f32::NAN; + let _ = x != x; // casts, methods, parentheses let _ = (1u32 as u64) & (1u32 as u64); diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index d365ab27edc28..c7fa253bdca26 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,5 +1,5 @@ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:9:13 + --> $DIR/eq_op.rs:7:13 | LL | let _ = 1 == 1; | ^^^^^^ @@ -7,29 +7,37 @@ LL | let _ = 1 == 1; = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:10:13 + --> $DIR/eq_op.rs:8:13 | LL | let _ = "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:12:13 + --> $DIR/eq_op.rs:10:13 | LL | let _ = false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:13:13 + --> $DIR/eq_op.rs:11:13 | LL | let _ = 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:14:13 + --> $DIR/eq_op.rs:12:13 | LL | let _ = 1u64 >= 1u64; | ^^^^^^^^^^^^ +error: equal expressions as operands to `!=` + --> $DIR/eq_op.rs:14:13 + | +LL | let _ = x != x; + | ^^^^^^ + | + = note: if you intended to check if the operand is NaN, use `.is_nan()` instead + error: equal expressions as operands to `&` --> $DIR/eq_op.rs:17:13 | @@ -168,5 +176,5 @@ error: equal expressions as operands to `==` LL | (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: aborting due to 29 previous errors diff --git a/tests/ui/eq_op_macros.rs b/tests/ui/eq_op_macros.rs index 6b5b31a1a2ef1..4824067722890 100644 --- a/tests/ui/eq_op_macros.rs +++ b/tests/ui/eq_op_macros.rs @@ -1,4 +1,5 @@ #![warn(clippy::eq_op)] +#![allow(clippy::useless_vec)] // lint also in macro definition macro_rules! assert_in_macro_def { diff --git a/tests/ui/eq_op_macros.stderr b/tests/ui/eq_op_macros.stderr index cd9f1826e59bf..cb9b0c01862bf 100644 --- a/tests/ui/eq_op_macros.stderr +++ b/tests/ui/eq_op_macros.stderr @@ -1,5 +1,5 @@ error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:7:20 + --> $DIR/eq_op_macros.rs:8:20 | LL | assert_eq!(a, a); | ^^^^ @@ -11,7 +11,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:8:20 + --> $DIR/eq_op_macros.rs:9:20 | LL | assert_ne!(a, a); | ^^^^ @@ -22,7 +22,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:9:26 + --> $DIR/eq_op_macros.rs:10:26 | LL | debug_assert_eq!(a, a); | ^^^^ @@ -33,7 +33,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:10:26 + --> $DIR/eq_op_macros.rs:11:26 | LL | debug_assert_ne!(a, a); | ^^^^ @@ -44,49 +44,49 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:22:16 + --> $DIR/eq_op_macros.rs:23:16 | LL | assert_eq!(a, a); | ^^^^ error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:23:16 + --> $DIR/eq_op_macros.rs:24:16 | LL | assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:30:16 + --> $DIR/eq_op_macros.rs:31:16 | LL | assert_ne!(a, a); | ^^^^ error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:31:16 + --> $DIR/eq_op_macros.rs:32:16 | LL | assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:38:22 + --> $DIR/eq_op_macros.rs:39:22 | LL | debug_assert_eq!(a, a); | ^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:39:22 + --> $DIR/eq_op_macros.rs:40:22 | LL | debug_assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:46:22 + --> $DIR/eq_op_macros.rs:47:22 | LL | debug_assert_ne!(a, a); | ^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:47:22 + --> $DIR/eq_op_macros.rs:48:22 | LL | debug_assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index 53e62760bef4d..6cc070fb5526d 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -1,7 +1,12 @@ //@run-rustfix -//@aux-build:proc_macros.rs - -#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] +//@aux-build:proc_macros.rs:proc-macro + +#![allow( + unused_variables, + dead_code, + clippy::derive_partial_eq_without_eq, + clippy::needless_if +)] #![warn(clippy::equatable_if_let)] extern crate proc_macros; diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index 55918a5bb1196..f00a129bef1a0 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -1,7 +1,12 @@ //@run-rustfix -//@aux-build:proc_macros.rs - -#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] +//@aux-build:proc_macros.rs:proc-macro + +#![allow( + unused_variables, + dead_code, + clippy::derive_partial_eq_without_eq, + clippy::needless_if +)] #![warn(clippy::equatable_if_let)] extern crate proc_macros; diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index a72d87bb7ba96..649495dded7df 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -1,5 +1,5 @@ error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:60:8 + --> $DIR/equatable_if_let.rs:65:8 | LL | if let 2 = a {} | ^^^^^^^^^ help: try: `a == 2` @@ -7,79 +7,79 @@ LL | if let 2 = a {} = note: `-D clippy::equatable-if-let` implied by `-D warnings` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:61:8 + --> $DIR/equatable_if_let.rs:66:8 | LL | if let Ordering::Greater = a.cmp(&b) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:62:8 + --> $DIR/equatable_if_let.rs:67:8 | LL | if let Some(2) = c {} | ^^^^^^^^^^^^^^^ help: try: `c == Some(2)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:63:8 + --> $DIR/equatable_if_let.rs:68:8 | LL | if let Struct { a: 2, b: false } = d {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:64:8 + --> $DIR/equatable_if_let.rs:69:8 | LL | if let Enum::TupleVariant(32, 64) = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:65:8 + --> $DIR/equatable_if_let.rs:70:8 | LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:66:8 + --> $DIR/equatable_if_let.rs:71:8 | LL | if let Enum::UnitVariant = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:67:8 + --> $DIR/equatable_if_let.rs:72:8 | LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:76:8 + --> $DIR/equatable_if_let.rs:81:8 | LL | if let NotPartialEq::A = f {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:77:8 + --> $DIR/equatable_if_let.rs:82:8 | LL | if let NotStructuralEq::A = g {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:78:8 + --> $DIR/equatable_if_let.rs:83:8 | LL | if let Some(NotPartialEq::A) = Some(f) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:79:8 + --> $DIR/equatable_if_let.rs:84:8 | LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:80:8 + --> $DIR/equatable_if_let.rs:85:8 | LL | if let NoPartialEqStruct { a: 2, b: false } = h {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:82:8 + --> $DIR/equatable_if_let.rs:87:8 | LL | if let inline!("abc") = "abc" { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")` diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index 6ade6f5468917..46e2816da5226 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::unnecessary_literal_unwrap)] struct MyTypeNonDebug; diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index a93fb59493fec..b9446034d50a2 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::unnecessary_literal_unwrap)] struct MyTypeNonDebug; diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index b1baf462c0f88..bf44bcb564ecc 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -7,7 +7,8 @@ clippy::no_effect, clippy::option_map_unit_fn, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] use std::path::{Path, PathBuf}; @@ -46,6 +47,12 @@ fn main() { // issue #7224 let _: Option> = Some(0).map(|_| vec![]); + + // issue #10684 + fn test(x: impl Fn(usize, usize) -> T) -> T { + x(1, 2) + } + test(|start, end| start..=end); } trait TestTrait { diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index e113c3d6cd6b2..b2af4bf095373 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -7,7 +7,8 @@ clippy::no_effect, clippy::option_map_unit_fn, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] use std::path::{Path, PathBuf}; @@ -46,6 +47,12 @@ fn main() { // issue #7224 let _: Option> = Some(0).map(|_| vec![]); + + // issue #10684 + fn test(x: impl Fn(usize, usize) -> T) -> T { + x(1, 2) + } + test(|start, end| start..=end); } trait TestTrait { diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index a521fb868607a..0ac0b901df446 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:28:27 + --> $DIR/eta.rs:29:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -7,31 +7,31 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:32:40 + --> $DIR/eta.rs:33:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:33:35 + --> $DIR/eta.rs:34:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: redundant closure - --> $DIR/eta.rs:34:26 + --> $DIR/eta.rs:35:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:41:27 + --> $DIR/eta.rs:42:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:87:51 + --> $DIR/eta.rs:94:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -39,121 +39,121 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:88:51 + --> $DIR/eta.rs:95:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:90:42 + --> $DIR/eta.rs:97:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:94:29 + --> $DIR/eta.rs:101:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:95:27 + --> $DIR/eta.rs:102:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:97:65 + --> $DIR/eta.rs:104:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:160:22 + --> $DIR/eta.rs:167:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:167:27 + --> $DIR/eta.rs:174:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:172:27 + --> $DIR/eta.rs:179:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:204:28 + --> $DIR/eta.rs:211:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:205:28 + --> $DIR/eta.rs:212:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:206:28 + --> $DIR/eta.rs:213:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:213:21 + --> $DIR/eta.rs:220:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:217:21 + --> $DIR/eta.rs:224:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> $DIR/eta.rs:310:18 + --> $DIR/eta.rs:317:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:313:19 + --> $DIR/eta.rs:320:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:317:26 + --> $DIR/eta.rs:324:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> $DIR/eta.rs:329:19 + --> $DIR/eta.rs:336:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> $DIR/eta.rs:332:19 + --> $DIR/eta.rs:339:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> $DIR/eta.rs:335:17 + --> $DIR/eta.rs:342:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> $DIR/eta.rs:339:17 + --> $DIR/eta.rs:346:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 0a07957386c23..7bb4da453c1cb 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -1,6 +1,12 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal)] +#![allow( + dead_code, + overflowing_literals, + unused_variables, + clippy::print_literal, + clippy::useless_vec +)] fn main() { // Consts @@ -66,4 +72,11 @@ fn main() { // issue #7745 let _ = 0_f64; + + // issue #9910 + const INF1: f32 = 1.0e+33f32; + const INF2: f64 = 1.0e+3300f64; + const NEG_INF1: f32 = -1.0e+33f32; + const NEG_INF2: f64 = -1.0e+3300f64; + const NEG_INF3: f32 = -3.40282357e+38_f32; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 62a832caa67b6..e8d6ab6870a4e 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,6 +1,12 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal)] +#![allow( + dead_code, + overflowing_literals, + unused_variables, + clippy::print_literal, + clippy::useless_vec +)] fn main() { // Consts @@ -66,4 +72,11 @@ fn main() { // issue #7745 let _ = 1.000_000_000_000_001e-324_f64; + + // issue #9910 + const INF1: f32 = 1.0e+33f32; + const INF2: f64 = 1.0e+3300f64; + const NEG_INF1: f32 = -1.0e+33f32; + const NEG_INF2: f64 = -1.0e+3300f64; + const NEG_INF3: f32 = -3.40282357e+38_f32; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 42d9d4de193c4..348ad183d7d7f 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,5 +1,5 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:15:26 + --> $DIR/excessive_precision.rs:21:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32` @@ -7,85 +7,85 @@ LL | const BAD32_1: f32 = 0.123_456_789_f32; = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:16:26 + --> $DIR/excessive_precision.rs:22:26 | LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:17:26 + --> $DIR/excessive_precision.rs:23:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:18:29 + --> $DIR/excessive_precision.rs:24:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:22:26 + --> $DIR/excessive_precision.rs:28:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:25:22 + --> $DIR/excessive_precision.rs:31:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:36:22 + --> $DIR/excessive_precision.rs:42:22 | LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:37:26 + --> $DIR/excessive_precision.rs:43:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision - --> $DIR/excessive_precision.rs:38:21 + --> $DIR/excessive_precision.rs:44:21 | LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:36 + --> $DIR/excessive_precision.rs:54:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:49:36 + --> $DIR/excessive_precision.rs:55:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:53:24 + --> $DIR/excessive_precision.rs:59:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:56:27 + --> $DIR/excessive_precision.rs:62:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:65:13 + --> $DIR/excessive_precision.rs:71:13 | LL | let _ = 2.225_073_858_507_201_1e-308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64` error: float has excessive precision - --> $DIR/excessive_precision.rs:68:13 + --> $DIR/excessive_precision.rs:74:13 | LL | let _ = 1.000_000_000_000_001e-324_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64` diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index d742595e14d4c..1588579bb0f2f 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -1,4 +1,5 @@ #![warn(clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn expect_option() { let opt = Some(0); diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index c08e0dbbf7449..be340340d4773 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> $DIR/expect.rs:5:13 + --> $DIR/expect.rs:6:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.expect(""); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `expect()` on a `Result` value - --> $DIR/expect.rs:10:13 + --> $DIR/expect.rs:11:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = res.expect(""); = help: if this value is an `Err`, it will panic error: used `expect_err()` on a `Result` value - --> $DIR/expect.rs:11:13 + --> $DIR/expect.rs:12:13 | LL | let _ = res.expect_err(""); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed index 8e97054fb6bca..73c6c97de84b1 100644 --- a/tests/ui/expect_fun_call.fixed +++ b/tests/ui/expect_fun_call.fixed @@ -1,6 +1,10 @@ //@run-rustfix #![warn(clippy::expect_fun_call)] -#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] +#![allow( + clippy::to_string_in_format_args, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 31e6bcc7ff643..a786138631c8d 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -1,6 +1,10 @@ //@run-rustfix #![warn(clippy::expect_fun_call)] -#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] +#![allow( + clippy::to_string_in_format_args, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index cb55e32aee02e..36fb0e5de1567 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:34:26 + --> $DIR/expect_fun_call.rs:38:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` @@ -7,85 +7,85 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:37:26 + --> $DIR/expect_fun_call.rs:41:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:40:37 + --> $DIR/expect_fun_call.rs:44:37 | LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:50:25 + --> $DIR/expect_fun_call.rs:54:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:53:25 + --> $DIR/expect_fun_call.rs:57:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:65:17 + --> $DIR/expect_fun_call.rs:69:17 | LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:86:21 + --> $DIR/expect_fun_call.rs:90:21 | LL | Some("foo").expect(&get_string()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:87:21 + --> $DIR/expect_fun_call.rs:91:21 | LL | Some("foo").expect(get_string().as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:88:21 + --> $DIR/expect_fun_call.rs:92:21 | LL | Some("foo").expect(get_string().as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:90:21 + --> $DIR/expect_fun_call.rs:94:21 | LL | Some("foo").expect(get_static_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:91:21 + --> $DIR/expect_fun_call.rs:95:21 | LL | Some("foo").expect(get_non_static_str(&0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:95:16 + --> $DIR/expect_fun_call.rs:99:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:101:17 + --> $DIR/expect_fun_call.rs:105:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:105:20 + --> $DIR/expect_fun_call.rs:109:20 | LL | format_capture.expect(&format!("{error_code}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}"))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:108:30 + --> $DIR/expect_fun_call.rs:112:30 | LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index 0415e33b3fa10..2460f33434d12 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(lint_reasons)] //! This file tests the `#[expect]` attribute implementation for tool lints. The same //! file is used to test clippy and rustdoc. Any changes to this file should be synced @@ -12,6 +11,7 @@ //! This test can't cover every lint from Clippy, rustdoc and potentially other //! tools that will be developed. This therefore only tests a small subset of lints #![expect(rustdoc::missing_crate_level_docs)] +#![allow(clippy::needless_if)] mod rustc_ok { //! See diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 46565a97f0059..e02b8f62b3dd0 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -1,5 +1,5 @@ #![warn(clippy::explicit_counter_loop)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { let mut vec = vec![1, 2, 3, 4]; @@ -23,6 +23,54 @@ fn main() { for _v in vec { _index += 1; } + + let vec = [1, 2, 3, 4]; + // Potential false positives + let mut _index = 0; + _index = 1; + for _v in &vec { + _index += 1 + } + + let mut _index = 0; + _index += 1; + for _v in &vec { + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + _index = 1; + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + let mut _index = 0; + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + _index += 1; + _index = 0; + } + + let mut _index = 0; + if true { + _index = 1 + }; + for _v in &vec { + _index += 1 + } + + let mut _index = 1; + if false { + _index = 0 + }; + for _v in &vec { + _index += 1 + } } mod issue_1219 { diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index d3f3c626bbdfd..0677e4d78c8be 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -25,31 +25,31 @@ LL | for _v in vec { | ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:62:9 + --> $DIR/explicit_counter_loop.rs:110:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:73:9 + --> $DIR/explicit_counter_loop.rs:121:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:131:9 + --> $DIR/explicit_counter_loop.rs:179:9 | LL | for _i in 3..10 { | ^^^^^^^^^^^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()` error: the variable `idx_usize` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:171:9 + --> $DIR/explicit_counter_loop.rs:219:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_usize, _item) in slice.iter().enumerate()` error: the variable `idx_u32` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:183:9 + --> $DIR/explicit_counter_loop.rs:231:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_u32, _item) in (0_u32..).zip(slice.iter())` diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 60482c66da7c4..4d72b58cdf867 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -1,12 +1,14 @@ //@run-rustfix #![warn(clippy::explicit_deref_methods)] -#![allow(unused_variables)] +#![allow(unused_variables, unused_must_use)] #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::no_effect, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap )] use std::ops::{Deref, DerefMut}; @@ -28,6 +30,22 @@ impl Deref for CustomVec { } } +struct Aaa; + +impl Deref for Aaa { + type Target = (); + + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +impl DerefMut for Aaa { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!(); + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -58,6 +76,17 @@ fn main() { let opt_a = Some(a.clone()); let b = &*opt_a.unwrap(); + // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified + // syntax + + Aaa::deref(&Aaa); + Aaa::deref_mut(&mut Aaa); + ::deref(&Aaa); + ::deref_mut(&mut Aaa); + let mut aaa = Aaa; + Aaa::deref(&aaa); + Aaa::deref_mut(&mut aaa); + // following should not require linting let cv = CustomVec(vec![0, 42]); diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index e3613e216bb22..fcd945de33860 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -1,12 +1,14 @@ //@run-rustfix #![warn(clippy::explicit_deref_methods)] -#![allow(unused_variables)] +#![allow(unused_variables, unused_must_use)] #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::no_effect, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap )] use std::ops::{Deref, DerefMut}; @@ -28,6 +30,22 @@ impl Deref for CustomVec { } } +struct Aaa; + +impl Deref for Aaa { + type Target = (); + + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +impl DerefMut for Aaa { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!(); + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -58,6 +76,17 @@ fn main() { let opt_a = Some(a.clone()); let b = opt_a.unwrap().deref(); + // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified + // syntax + + Aaa::deref(&Aaa); + Aaa::deref_mut(&mut Aaa); + ::deref(&Aaa); + ::deref_mut(&mut Aaa); + let mut aaa = Aaa; + Aaa::deref(&aaa); + Aaa::deref_mut(&mut aaa); + // following should not require linting let cv = CustomVec(vec![0, 42]); diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index 4b10ed1377b0d..d025035b78942 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -1,5 +1,5 @@ error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:36:19 + --> $DIR/explicit_deref_methods.rs:54:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try this: `&*a` @@ -7,67 +7,67 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:38:23 + --> $DIR/explicit_deref_methods.rs:56:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try this: `&mut **a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:41:39 + --> $DIR/explicit_deref_methods.rs:59:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:41:50 + --> $DIR/explicit_deref_methods.rs:59:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:43:20 + --> $DIR/explicit_deref_methods.rs:61:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:46:11 + --> $DIR/explicit_deref_methods.rs:64:11 | LL | match a.deref() { | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:50:28 + --> $DIR/explicit_deref_methods.rs:68:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:52:13 + --> $DIR/explicit_deref_methods.rs:70:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:54:28 + --> $DIR/explicit_deref_methods.rs:72:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:56:19 + --> $DIR/explicit_deref_methods.rs:74:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:59:13 + --> $DIR/explicit_deref_methods.rs:77:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:85:31 + --> $DIR/explicit_deref_methods.rs:114:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try this: `&*a` diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed new file mode 100644 index 0000000000000..dcef634031143 --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.fixed @@ -0,0 +1,69 @@ +//@run-rustfix +#![warn(clippy::explicit_into_iter_loop)] + +fn main() { + // Issue #4958 + fn _takes_iterator(iterator: &T) + where + for<'a> &'a T: IntoIterator, + { + for _ in iterator {} + } + + struct T; + impl IntoIterator for &T { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut t = T; + for _ in &t {} + + let r = &t; + for _ in r {} + + // No suggestion for this. + // We'd have to suggest `for _ in *rr {}` which is less clear. + let rr = &&t; + for _ in rr.into_iter() {} + + let mr = &mut t; + for _ in &*mr {} + + struct U; + impl IntoIterator for &mut U { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut u = U; + for _ in &mut u {} + + let mr = &mut u; + for _ in &mut *mr {} + + // Issue #6900 + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter(self) -> I { + unimplemented!() + } + } + + struct I(T); + impl Iterator for I { + type Item = T; + fn next(&mut self) -> Option { + unimplemented!() + } + } + + for _ in S.into_iter::() {} +} diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs new file mode 100644 index 0000000000000..bc048ed302bff --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.rs @@ -0,0 +1,69 @@ +//@run-rustfix +#![warn(clippy::explicit_into_iter_loop)] + +fn main() { + // Issue #4958 + fn _takes_iterator(iterator: &T) + where + for<'a> &'a T: IntoIterator, + { + for _ in iterator.into_iter() {} + } + + struct T; + impl IntoIterator for &T { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut t = T; + for _ in t.into_iter() {} + + let r = &t; + for _ in r.into_iter() {} + + // No suggestion for this. + // We'd have to suggest `for _ in *rr {}` which is less clear. + let rr = &&t; + for _ in rr.into_iter() {} + + let mr = &mut t; + for _ in mr.into_iter() {} + + struct U; + impl IntoIterator for &mut U { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut u = U; + for _ in u.into_iter() {} + + let mr = &mut u; + for _ in mr.into_iter() {} + + // Issue #6900 + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter(self) -> I { + unimplemented!() + } + } + + struct I(T); + impl Iterator for I { + type Item = T; + fn next(&mut self) -> Option { + unimplemented!() + } + } + + for _ in S.into_iter::() {} +} diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr new file mode 100644 index 0000000000000..fa89b884fa0fc --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.stderr @@ -0,0 +1,40 @@ +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:10:18 + | +LL | for _ in iterator.into_iter() {} + | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` + | + = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:23:14 + | +LL | for _ in t.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:26:14 + | +LL | for _ in r.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:34:14 + | +LL | for _ in mr.into_iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*mr` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:46:14 + | +LL | for _ in u.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut u` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:49:14 + | +LL | for _ in mr.into_iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed new file mode 100644 index 0000000000000..746ef813c0481 --- /dev/null +++ b/tests/ui/explicit_iter_loop.fixed @@ -0,0 +1,154 @@ +//@run-rustfix +#![deny(clippy::explicit_iter_loop)] +#![allow( + clippy::linkedlist, + clippy::similar_names, + clippy::needless_borrow, + clippy::deref_addrof, + dead_code +)] + +use core::slice; +use std::collections::*; + +fn main() { + let mut vec = vec![1, 2, 3, 4]; + + for _ in &vec {} + for _ in &mut vec {} + + let rvec = &vec; + for _ in rvec {} + + let rmvec = &mut vec; + for _ in &*rmvec {} + for _ in &mut *rmvec {} + + for _ in &vec {} // these are fine + for _ in &mut vec {} // these are fine + + for _ in &[1, 2, 3] {} + + for _ in &*(&mut [1, 2, 3]) {} + + for _ in &[0; 32] {} + for _ in &[0; 33] {} + + let ll: LinkedList<()> = LinkedList::new(); + for _ in &ll {} + let rll = ≪ + for _ in rll {} + + let vd: VecDeque<()> = VecDeque::new(); + for _ in &vd {} + let rvd = &vd; + for _ in rvd {} + + let bh: BinaryHeap<()> = BinaryHeap::new(); + for _ in &bh {} + + let hm: HashMap<(), ()> = HashMap::new(); + for _ in &hm {} + + let bt: BTreeMap<(), ()> = BTreeMap::new(); + for _ in &bt {} + + let hs: HashSet<()> = HashSet::new(); + for _ in &hs {} + + let bs: BTreeSet<()> = BTreeSet::new(); + for _ in &bs {} + + struct NoIntoIter(); + impl NoIntoIter { + fn iter(&self) -> slice::Iter { + unimplemented!() + } + + fn iter_mut(&mut self) -> slice::IterMut { + unimplemented!() + } + } + let mut x = NoIntoIter(); + for _ in x.iter() {} // no error + for _ in x.iter_mut() {} // no error + + struct IntoIterDiffTy; + impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } + } + let x = IntoIterDiffTy; + for _ in x.iter() {} + + struct IntoIterDiffSig; + impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } + } + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + struct IntoIterDiffLt<'a>(&'a ()); + impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } + } + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + struct CustomType; + impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } + } + let mut x = CustomType; + for _ in &x {} + for _ in &mut x {} + + let r = &x; + for _ in r {} +} diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs new file mode 100644 index 0000000000000..fba230ee0eeaa --- /dev/null +++ b/tests/ui/explicit_iter_loop.rs @@ -0,0 +1,154 @@ +//@run-rustfix +#![deny(clippy::explicit_iter_loop)] +#![allow( + clippy::linkedlist, + clippy::similar_names, + clippy::needless_borrow, + clippy::deref_addrof, + dead_code +)] + +use core::slice; +use std::collections::*; + +fn main() { + let mut vec = vec![1, 2, 3, 4]; + + for _ in vec.iter() {} + for _ in vec.iter_mut() {} + + let rvec = &vec; + for _ in rvec.iter() {} + + let rmvec = &mut vec; + for _ in rmvec.iter() {} + for _ in rmvec.iter_mut() {} + + for _ in &vec {} // these are fine + for _ in &mut vec {} // these are fine + + for _ in [1, 2, 3].iter() {} + + for _ in (&mut [1, 2, 3]).iter() {} + + for _ in [0; 32].iter() {} + for _ in [0; 33].iter() {} + + let ll: LinkedList<()> = LinkedList::new(); + for _ in ll.iter() {} + let rll = ≪ + for _ in rll.iter() {} + + let vd: VecDeque<()> = VecDeque::new(); + for _ in vd.iter() {} + let rvd = &vd; + for _ in rvd.iter() {} + + let bh: BinaryHeap<()> = BinaryHeap::new(); + for _ in bh.iter() {} + + let hm: HashMap<(), ()> = HashMap::new(); + for _ in hm.iter() {} + + let bt: BTreeMap<(), ()> = BTreeMap::new(); + for _ in bt.iter() {} + + let hs: HashSet<()> = HashSet::new(); + for _ in hs.iter() {} + + let bs: BTreeSet<()> = BTreeSet::new(); + for _ in bs.iter() {} + + struct NoIntoIter(); + impl NoIntoIter { + fn iter(&self) -> slice::Iter { + unimplemented!() + } + + fn iter_mut(&mut self) -> slice::IterMut { + unimplemented!() + } + } + let mut x = NoIntoIter(); + for _ in x.iter() {} // no error + for _ in x.iter_mut() {} // no error + + struct IntoIterDiffTy; + impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } + } + let x = IntoIterDiffTy; + for _ in x.iter() {} + + struct IntoIterDiffSig; + impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } + } + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + struct IntoIterDiffLt<'a>(&'a ()); + impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } + } + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + struct CustomType; + impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } + } + let mut x = CustomType; + for _ in x.iter() {} + for _ in x.iter_mut() {} + + let r = &x; + for _ in r.iter() {} +} diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr new file mode 100644 index 0000000000000..94a264dcea8d5 --- /dev/null +++ b/tests/ui/explicit_iter_loop.stderr @@ -0,0 +1,142 @@ +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:17:14 + | +LL | for _ in vec.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` + | +note: the lint level is defined here + --> $DIR/explicit_iter_loop.rs:2:9 + | +LL | #![deny(clippy::explicit_iter_loop)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:18:14 + | +LL | for _ in vec.iter_mut() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:21:14 + | +LL | for _ in rvec.iter() {} + | ^^^^^^^^^^^ help: to write this more concisely, try: `rvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:24:14 + | +LL | for _ in rmvec.iter() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:25:14 + | +LL | for _ in rmvec.iter_mut() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:30:14 + | +LL | for _ in [1, 2, 3].iter() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:32:14 + | +LL | for _ in (&mut [1, 2, 3]).iter() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])` + +error: the method `iter` doesn't need a mutable reference + --> $DIR/explicit_iter_loop.rs:32:14 + | +LL | for _ in (&mut [1, 2, 3]).iter() {} + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:34:14 + | +LL | for _ in [0; 32].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:35:14 + | +LL | for _ in [0; 33].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:38:14 + | +LL | for _ in ll.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&ll` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:40:14 + | +LL | for _ in rll.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `rll` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:43:14 + | +LL | for _ in vd.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&vd` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:45:14 + | +LL | for _ in rvd.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `rvd` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:48:14 + | +LL | for _ in bh.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bh` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:51:14 + | +LL | for _ in hm.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hm` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:54:14 + | +LL | for _ in bt.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bt` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:57:14 + | +LL | for _ in hs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hs` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:60:14 + | +LL | for _ in bs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bs` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:149:14 + | +LL | for _ in x.iter() {} + | ^^^^^^^^ help: to write this more concisely, try: `&x` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:150:14 + | +LL | for _ in x.iter_mut() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:153:14 + | +LL | for _ in r.iter() {} + | ^^^^^^^^ help: to write this more concisely, try: `r` + +error: aborting due to 22 previous errors + diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index cdfaf8d3afea8..50abe89da893a 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![allow( unused, diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed index adcd1f6d4076c..8420df6634d90 100644 --- a/tests/ui/extra_unused_type_parameters.fixed +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] +extern crate proc_macros; +use proc_macros::with_span; + fn unused_ty(x: u8) { unimplemented!() } @@ -102,4 +106,12 @@ mod issue10319 { } } +with_span!( + span + + fn should_not_lint(x: u8) { + unimplemented!() + } +); + fn main() {} diff --git a/tests/ui/extra_unused_type_parameters.rs b/tests/ui/extra_unused_type_parameters.rs index c4c5227ac9187..f63535d7ae6ee 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] +extern crate proc_macros; +use proc_macros::with_span; + fn unused_ty(x: u8) { unimplemented!() } @@ -102,4 +106,12 @@ mod issue10319 { } } +with_span!( + span + + fn should_not_lint(x: u8) { + unimplemented!() + } +); + fn main() {} diff --git a/tests/ui/extra_unused_type_parameters.stderr b/tests/ui/extra_unused_type_parameters.stderr index c042a5a2290e5..b5277d49861c9 100644 --- a/tests/ui/extra_unused_type_parameters.stderr +++ b/tests/ui/extra_unused_type_parameters.stderr @@ -1,5 +1,5 @@ error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:6:13 + --> $DIR/extra_unused_type_parameters.rs:10:13 | LL | fn unused_ty(x: u8) { | ^^^ help: consider removing the parameter @@ -7,19 +7,19 @@ LL | fn unused_ty(x: u8) { = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings` error: type parameters go unused in function definition: T, U - --> $DIR/extra_unused_type_parameters.rs:10:16 + --> $DIR/extra_unused_type_parameters.rs:14:16 | LL | fn unused_multi(x: u8) { | ^^^^^^ help: consider removing the parameters error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:14:21 + --> $DIR/extra_unused_type_parameters.rs:18:21 | LL | fn unused_with_lt<'a, T>(x: &'a u8) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: T, V - --> $DIR/extra_unused_type_parameters.rs:26:19 + --> $DIR/extra_unused_type_parameters.rs:30:19 | LL | fn unused_bounded(x: U) { | ^^^^^^^^^^^^ ^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL + fn unused_bounded(x: U) { | error: type parameters go unused in function definition: A, D, E - --> $DIR/extra_unused_type_parameters.rs:30:16 + --> $DIR/extra_unused_type_parameters.rs:34:16 | LL | fn some_unused, E>(b: B, c: C) { | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,19 +43,19 @@ LL + fn some_unused(b: B, c: C) { | error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:55:22 + --> $DIR/extra_unused_type_parameters.rs:59:22 | LL | fn unused_ty_impl(&self) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: A, B - --> $DIR/extra_unused_type_parameters.rs:77:17 + --> $DIR/extra_unused_type_parameters.rs:81:17 | LL | fn unused_opaque(dummy: impl Default) { | ^^^^^^ help: consider removing the parameters error: type parameter `U` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:90:56 + --> $DIR/extra_unused_type_parameters.rs:94:56 | LL | fn unused_with_priv_trait_bound() { | ^^^ help: consider removing the parameter diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs index 2045b1eebcd7f..d6df114b8d262 100644 --- a/tests/ui/field_reassign_with_default.rs +++ b/tests/ui/field_reassign_with_default.rs @@ -1,5 +1,5 @@ -//@aux-build:proc_macro_derive.rs -//@aux-build:proc_macros.rs +//@aux-build:proc_macro_derive.rs:proc-macro +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::field_reassign_with_default)] diff --git a/tests/ui/filetype_is_file.rs b/tests/ui/filetype_is_file.rs index 5de8fe8cdd7b0..d3ad36e40b53c 100644 --- a/tests/ui/filetype_is_file.rs +++ b/tests/ui/filetype_is_file.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_if)] #![warn(clippy::filetype_is_file)] fn main() -> std::io::Result<()> { diff --git a/tests/ui/filetype_is_file.stderr b/tests/ui/filetype_is_file.stderr index e51a90d6cfd24..36142deb3092a 100644 --- a/tests/ui/filetype_is_file.stderr +++ b/tests/ui/filetype_is_file.stderr @@ -1,5 +1,5 @@ error: `FileType::is_file()` only covers regular files - --> $DIR/filetype_is_file.rs:8:8 + --> $DIR/filetype_is_file.rs:9:8 | LL | if fs::metadata("foo.txt")?.file_type().is_file() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | if fs::metadata("foo.txt")?.file_type().is_file() { = note: `-D clippy::filetype-is-file` implied by `-D warnings` error: `!FileType::is_file()` only denies regular files - --> $DIR/filetype_is_file.rs:13:8 + --> $DIR/filetype_is_file.rs:14:8 | LL | if !fs::metadata("foo.txt")?.file_type().is_file() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | if !fs::metadata("foo.txt")?.file_type().is_file() { = help: use `FileType::is_dir()` instead error: `FileType::is_file()` only covers regular files - --> $DIR/filetype_is_file.rs:18:9 + --> $DIR/filetype_is_file.rs:19:9 | LL | if !fs::metadata("foo.txt")?.file_type().is_file().bitor(true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/find_map.rs b/tests/ui/find_map.rs index 88d3b0e749001..bbd395d50ef22 100644 --- a/tests/ui/find_map.rs +++ b/tests/ui/find_map.rs @@ -1,4 +1,5 @@ #![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::useless_vec)] #[derive(Debug, Copy, Clone)] enum Flavor { diff --git a/tests/ui/fn_null_check.rs b/tests/ui/fn_null_check.rs index df5bc8420d57b..dfdea100c8fd7 100644 --- a/tests/ui/fn_null_check.rs +++ b/tests/ui/fn_null_check.rs @@ -1,6 +1,7 @@ #![allow(unused)] #![warn(clippy::fn_null_check)] #![allow(clippy::cmp_null)] +#![allow(clippy::needless_if)] #![allow(clippy::ptr_eq)] #![allow(clippy::zero_ptr)] diff --git a/tests/ui/fn_null_check.stderr b/tests/ui/fn_null_check.stderr index 660dd32397922..5b9f48a961caf 100644 --- a/tests/ui/fn_null_check.stderr +++ b/tests/ui/fn_null_check.stderr @@ -1,5 +1,5 @@ error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:13:8 + --> $DIR/fn_null_check.rs:14:8 | LL | if (fn_ptr as *mut ()).is_null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | if (fn_ptr as *mut ()).is_null() {} = note: `-D clippy::fn-null-check` implied by `-D warnings` error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:14:8 + --> $DIR/fn_null_check.rs:15:8 | LL | if (fn_ptr as *const u8).is_null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | if (fn_ptr as *const u8).is_null() {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:15:8 + --> $DIR/fn_null_check.rs:16:8 | LL | if (fn_ptr as *const ()) == std::ptr::null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | if (fn_ptr as *const ()) == std::ptr::null() {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:16:8 + --> $DIR/fn_null_check.rs:17:8 | LL | if (fn_ptr as *const ()) == (0 as *const ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | if (fn_ptr as *const ()) == (0 as *const ()) {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:17:8 + --> $DIR/fn_null_check.rs:18:8 | LL | if (fn_ptr as *const ()) == ZPTR {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed deleted file mode 100644 index f578c98da1534..0000000000000 --- a/tests/ui/for_loop_fixable.fixed +++ /dev/null @@ -1,309 +0,0 @@ -//@run-rustfix -#![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args)] - -use std::collections::*; - -#[warn(clippy::all)] -struct Unrelated(Vec); -impl Unrelated { - fn next(&self) -> std::slice::Iter { - self.0.iter() - } - - fn iter(&self) -> std::slice::Iter { - self.0.iter() - } -} - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow( - clippy::linkedlist, - clippy::unnecessary_mut_passed, - clippy::similar_names, - clippy::needless_borrow -)] -#[allow(unused_variables)] -fn main() { - let mut vec = vec![1, 2, 3, 4]; - - // See #601 - for i in 0..10 { - // no error, id_col does not exist outside the loop - let mut id_col = vec![0f64; 10]; - id_col[i] = 1f64; - } - - for _v in &vec {} - - for _v in &mut vec {} - - let out_vec = vec![1, 2, 3]; - for _v in out_vec {} - - for _v in &vec {} // these are fine - for _v in &mut vec {} // these are fine - - for _v in &[1, 2, 3] {} - - for _v in (&mut [1, 2, 3]).iter() {} // no error - - for _v in &[0; 32] {} - - for _v in [0; 33].iter() {} // no error - - let ll: LinkedList<()> = LinkedList::new(); - for _v in &ll {} - - let vd: VecDeque<()> = VecDeque::new(); - for _v in &vd {} - - let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in &bh {} - - let hm: HashMap<(), ()> = HashMap::new(); - for _v in &hm {} - - let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in &bt {} - - let hs: HashSet<()> = HashSet::new(); - for _v in &hs {} - - let bs: BTreeSet<()> = BTreeSet::new(); - for _v in &bs {} - - let u = Unrelated(vec![]); - for _v in u.next() {} // no error - for _v in u.iter() {} // no error - - let mut out = vec![]; - vec.iter().cloned().map(|x| out.push(x)).collect::>(); - let _y = vec.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine - - // Loop with explicit counter variable - - // Potential false positives - let mut _index = 0; - _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - _index += 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - if true { - _index = 1 - } - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - let mut _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index *= 2; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index = 1; - _index += 1 - } - - let mut _index = 0; - - for _v in &vec { - let mut _index = 0; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index = 0; - } - - let mut _index = 0; - for _v in &vec { - for _x in 0..1 { - _index += 1; - } - _index += 1 - } - - let mut _index = 0; - for x in &vec { - if *x == 1 { - _index += 1 - } - } - - let mut _index = 0; - if true { - _index = 1 - }; - for _v in &vec { - _index += 1 - } - - let mut _index = 1; - if false { - _index = 0 - }; - for _v in &vec { - _index += 1 - } - - let mut index = 0; - { - let mut _x = &mut index; - } - for _v in &vec { - _index += 1 - } - - let mut index = 0; - for _v in &vec { - index += 1 - } - println!("index: {}", index); - - fn f(_: &T, _: &T) -> bool { - unimplemented!() - } - fn g(_: &mut [T], _: usize, _: usize) { - unimplemented!() - } - for i in 1..vec.len() { - if f(&vec[i - 1], &vec[i]) { - g(&mut vec, i - 1, i); - } - } - - for mid in 1..vec.len() { - let (_, _) = vec.split_at(mid); - } -} - -fn partition(v: &mut [T]) -> usize { - let pivot = v.len() - 1; - let mut i = 0; - for j in 0..pivot { - if v[j] <= v[pivot] { - v.swap(i, j); - i += 1; - } - } - v.swap(i, pivot); - i -} - -#[warn(clippy::needless_range_loop)] -pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { - // Same source and destination - don't trigger lint - for i in 0..dst.len() { - dst[d + i] = dst[s + i]; - } -} - -mod issue_2496 { - pub trait Handle { - fn new_for_index(index: usize) -> Self; - fn index(&self) -> usize; - } - - pub fn test() -> H { - for x in 0..5 { - let next_handle = H::new_for_index(x); - println!("{}", next_handle.index()); - } - unimplemented!() - } -} - -// explicit_into_iter_loop bad suggestions -#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)] -mod issue_4958 { - fn takes_iterator(iterator: &T) - where - for<'a> &'a T: IntoIterator, - { - for i in iterator { - println!("{}", i); - } - } - - struct T; - impl IntoIterator for &T { - type Item = (); - type IntoIter = std::vec::IntoIter; - fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() - } - } - - fn more_tests() { - let t = T; - let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in &t {} - - for _ in r {} - - // No suggestion for this. - // We'd have to suggest `for _ in *rr {}` which is less clear. - for _ in rr.into_iter() {} - } -} - -// explicit_into_iter_loop -#[warn(clippy::explicit_into_iter_loop)] -mod issue_6900 { - struct S; - impl S { - #[allow(clippy::should_implement_trait)] - pub fn into_iter(self) -> I { - unimplemented!() - } - } - - struct I(T); - impl Iterator for I { - type Item = T; - fn next(&mut self) -> Option { - unimplemented!() - } - } - - fn f() { - for _ in S.into_iter::() { - unimplemented!() - } - } -} diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs deleted file mode 100644 index 42bc6de0c7dda..0000000000000 --- a/tests/ui/for_loop_fixable.rs +++ /dev/null @@ -1,309 +0,0 @@ -//@run-rustfix -#![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args)] - -use std::collections::*; - -#[warn(clippy::all)] -struct Unrelated(Vec); -impl Unrelated { - fn next(&self) -> std::slice::Iter { - self.0.iter() - } - - fn iter(&self) -> std::slice::Iter { - self.0.iter() - } -} - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow( - clippy::linkedlist, - clippy::unnecessary_mut_passed, - clippy::similar_names, - clippy::needless_borrow -)] -#[allow(unused_variables)] -fn main() { - let mut vec = vec![1, 2, 3, 4]; - - // See #601 - for i in 0..10 { - // no error, id_col does not exist outside the loop - let mut id_col = vec![0f64; 10]; - id_col[i] = 1f64; - } - - for _v in vec.iter() {} - - for _v in vec.iter_mut() {} - - let out_vec = vec![1, 2, 3]; - for _v in out_vec.into_iter() {} - - for _v in &vec {} // these are fine - for _v in &mut vec {} // these are fine - - for _v in [1, 2, 3].iter() {} - - for _v in (&mut [1, 2, 3]).iter() {} // no error - - for _v in [0; 32].iter() {} - - for _v in [0; 33].iter() {} // no error - - let ll: LinkedList<()> = LinkedList::new(); - for _v in ll.iter() {} - - let vd: VecDeque<()> = VecDeque::new(); - for _v in vd.iter() {} - - let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in bh.iter() {} - - let hm: HashMap<(), ()> = HashMap::new(); - for _v in hm.iter() {} - - let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in bt.iter() {} - - let hs: HashSet<()> = HashSet::new(); - for _v in hs.iter() {} - - let bs: BTreeSet<()> = BTreeSet::new(); - for _v in bs.iter() {} - - let u = Unrelated(vec![]); - for _v in u.next() {} // no error - for _v in u.iter() {} // no error - - let mut out = vec![]; - vec.iter().cloned().map(|x| out.push(x)).collect::>(); - let _y = vec.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine - - // Loop with explicit counter variable - - // Potential false positives - let mut _index = 0; - _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - _index += 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - if true { - _index = 1 - } - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - let mut _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index *= 2; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index = 1; - _index += 1 - } - - let mut _index = 0; - - for _v in &vec { - let mut _index = 0; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index = 0; - } - - let mut _index = 0; - for _v in &vec { - for _x in 0..1 { - _index += 1; - } - _index += 1 - } - - let mut _index = 0; - for x in &vec { - if *x == 1 { - _index += 1 - } - } - - let mut _index = 0; - if true { - _index = 1 - }; - for _v in &vec { - _index += 1 - } - - let mut _index = 1; - if false { - _index = 0 - }; - for _v in &vec { - _index += 1 - } - - let mut index = 0; - { - let mut _x = &mut index; - } - for _v in &vec { - _index += 1 - } - - let mut index = 0; - for _v in &vec { - index += 1 - } - println!("index: {}", index); - - fn f(_: &T, _: &T) -> bool { - unimplemented!() - } - fn g(_: &mut [T], _: usize, _: usize) { - unimplemented!() - } - for i in 1..vec.len() { - if f(&vec[i - 1], &vec[i]) { - g(&mut vec, i - 1, i); - } - } - - for mid in 1..vec.len() { - let (_, _) = vec.split_at(mid); - } -} - -fn partition(v: &mut [T]) -> usize { - let pivot = v.len() - 1; - let mut i = 0; - for j in 0..pivot { - if v[j] <= v[pivot] { - v.swap(i, j); - i += 1; - } - } - v.swap(i, pivot); - i -} - -#[warn(clippy::needless_range_loop)] -pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { - // Same source and destination - don't trigger lint - for i in 0..dst.len() { - dst[d + i] = dst[s + i]; - } -} - -mod issue_2496 { - pub trait Handle { - fn new_for_index(index: usize) -> Self; - fn index(&self) -> usize; - } - - pub fn test() -> H { - for x in 0..5 { - let next_handle = H::new_for_index(x); - println!("{}", next_handle.index()); - } - unimplemented!() - } -} - -// explicit_into_iter_loop bad suggestions -#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)] -mod issue_4958 { - fn takes_iterator(iterator: &T) - where - for<'a> &'a T: IntoIterator, - { - for i in iterator.into_iter() { - println!("{}", i); - } - } - - struct T; - impl IntoIterator for &T { - type Item = (); - type IntoIter = std::vec::IntoIter; - fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() - } - } - - fn more_tests() { - let t = T; - let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in t.into_iter() {} - - for _ in r.into_iter() {} - - // No suggestion for this. - // We'd have to suggest `for _ in *rr {}` which is less clear. - for _ in rr.into_iter() {} - } -} - -// explicit_into_iter_loop -#[warn(clippy::explicit_into_iter_loop)] -mod issue_6900 { - struct S; - impl S { - #[allow(clippy::should_implement_trait)] - pub fn into_iter(self) -> I { - unimplemented!() - } - } - - struct I(T); - impl Iterator for I { - type Item = T; - fn next(&mut self) -> Option { - unimplemented!() - } - } - - fn f() { - for _ in S.into_iter::() { - unimplemented!() - } - } -} diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr deleted file mode 100644 index ddfe66d675f91..0000000000000 --- a/tests/ui/for_loop_fixable.stderr +++ /dev/null @@ -1,96 +0,0 @@ -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:43:15 - | -LL | for _v in vec.iter() {} - | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` - | - = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:45:15 - | -LL | for _v in vec.iter_mut() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:48:15 - | -LL | for _v in out_vec.into_iter() {} - | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` - | - = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:53:15 - | -LL | for _v in [1, 2, 3].iter() {} - | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:57:15 - | -LL | for _v in [0; 32].iter() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:62:15 - | -LL | for _v in ll.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&ll` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:65:15 - | -LL | for _v in vd.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&vd` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:68:15 - | -LL | for _v in bh.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bh` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:71:15 - | -LL | for _v in hm.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hm` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:74:15 - | -LL | for _v in bt.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bt` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:77:15 - | -LL | for _v in hs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hs` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:80:15 - | -LL | for _v in bs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bs` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:255:18 - | -LL | for i in iterator.into_iter() { - | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:275:18 - | -LL | for _ in t.into_iter() {} - | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:277:18 - | -LL | for _ in r.into_iter() {} - | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` - -error: aborting due to 15 previous errors - diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs deleted file mode 100644 index 55fb3788a8b1a..0000000000000 --- a/tests/ui/for_loop_unfixable.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Tests from for_loop.rs that don't have suggestions - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)] -#[allow(for_loops_over_fallibles)] -fn main() { - let vec = vec![1, 2, 3, 4]; - - for _v in vec.iter().next() {} -} diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr deleted file mode 100644 index 50a86eaa68f7d..0000000000000 --- a/tests/ui/for_loop_unfixable.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_unfixable.rs:15:15 - | -LL | for _v in vec.iter().next() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-next-loop` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 9288956f51306..2e24e07ea268f 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -6,7 +6,9 @@ clippy::redundant_clone, clippy::to_string_in_format_args, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::needless_raw_string_hashes, + clippy::useless_vec )] struct Foo(pub String); diff --git a/tests/ui/format.rs b/tests/ui/format.rs index b2b817e0f4c43..0e64a310b01e2 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -6,7 +6,9 @@ clippy::redundant_clone, clippy::to_string_in_format_args, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::needless_raw_string_hashes, + clippy::useless_vec )] struct Foo(pub String); diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 0ef0ac655d394..78a11a3354f6b 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,5 +1,5 @@ error: useless use of `format!` - --> $DIR/format.rs:19:5 + --> $DIR/format.rs:21:5 | LL | format!("foo"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` @@ -7,19 +7,19 @@ LL | format!("foo"); = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:20:5 + --> $DIR/format.rs:22:5 | LL | format!("{{}}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:21:5 + --> $DIR/format.rs:23:5 | LL | format!("{{}} abc {{}}"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:22:5 + --> $DIR/format.rs:24:5 | LL | / format!( LL | | r##"foo {{}} @@ -34,67 +34,67 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> $DIR/format.rs:27:13 + --> $DIR/format.rs:29:13 | LL | let _ = format!(""); | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` error: useless use of `format!` - --> $DIR/format.rs:29:5 + --> $DIR/format.rs:31:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:37:5 + --> $DIR/format.rs:39:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:67:5 + --> $DIR/format.rs:69:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> $DIR/format.rs:69:5 + --> $DIR/format.rs:71:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> $DIR/format.rs:73:18 + --> $DIR/format.rs:75:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> $DIR/format.rs:77:22 + --> $DIR/format.rs:79:22 | LL | let _s: String = format!("{}", &*v.join("/n")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()` error: useless use of `format!` - --> $DIR/format.rs:83:13 + --> $DIR/format.rs:85:13 | LL | let _ = format!("{x}"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:85:13 + --> $DIR/format.rs:87:13 | LL | let _ = format!("{y}", y = x); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:89:13 + --> $DIR/format.rs:91:13 | LL | let _ = format!("{abc}"); | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()` error: useless use of `format!` - --> $DIR/format.rs:91:13 + --> $DIR/format.rs:93:13 | LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` diff --git a/tests/ui/format_push_string.rs b/tests/ui/format_push_string.rs index 4db13d650eb18..89423ffe1cf8c 100644 --- a/tests/ui/format_push_string.rs +++ b/tests/ui/format_push_string.rs @@ -5,3 +5,32 @@ fn main() { string += &format!("{:?}", 1234); string.push_str(&format!("{:?}", 5678)); } + +mod issue9493 { + pub fn u8vec_to_hex(vector: &Vec, upper: bool) -> String { + let mut hex = String::with_capacity(vector.len() * 2); + for byte in vector { + hex += &(if upper { + format!("{byte:02X}") + } else { + format!("{byte:02x}") + }); + } + hex + } + + pub fn other_cases() { + let mut s = String::new(); + // if let + s += &(if let Some(_a) = Some(1234) { + format!("{}", 1234) + } else { + format!("{}", 1234) + }); + // match + s += &(match Some(1234) { + Some(_) => format!("{}", 1234), + None => format!("{}", 1234), + }); + } +} diff --git a/tests/ui/format_push_string.stderr b/tests/ui/format_push_string.stderr index d7be9a5f206c1..76762c4a1d1f7 100644 --- a/tests/ui/format_push_string.stderr +++ b/tests/ui/format_push_string.stderr @@ -15,5 +15,40 @@ LL | string.push_str(&format!("{:?}", 5678)); | = help: consider using `write!` to avoid the extra allocation -error: aborting due to 2 previous errors +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:13:13 + | +LL | / hex += &(if upper { +LL | | format!("{byte:02X}") +LL | | } else { +LL | | format!("{byte:02x}") +LL | | }); + | |______________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:25:9 + | +LL | / s += &(if let Some(_a) = Some(1234) { +LL | | format!("{}", 1234) +LL | | } else { +LL | | format!("{}", 1234) +LL | | }); + | |__________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:31:9 + | +LL | / s += &(match Some(1234) { +LL | | Some(_) => format!("{}", 1234), +LL | | None => format!("{}", 1234), +LL | | }); + | |__________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: aborting due to 5 previous errors diff --git a/tests/ui/from_iter_instead_of_collect.fixed b/tests/ui/from_iter_instead_of_collect.fixed index 915ff4fb079d2..1671987cb673e 100644 --- a/tests/ui/from_iter_instead_of_collect.fixed +++ b/tests/ui/from_iter_instead_of_collect.fixed @@ -2,6 +2,7 @@ #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] +#![allow(clippy::useless_vec)] use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; diff --git a/tests/ui/from_iter_instead_of_collect.rs b/tests/ui/from_iter_instead_of_collect.rs index e926f8c529df3..48509b32f1092 100644 --- a/tests/ui/from_iter_instead_of_collect.rs +++ b/tests/ui/from_iter_instead_of_collect.rs @@ -2,6 +2,7 @@ #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] +#![allow(clippy::useless_vec)] use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; diff --git a/tests/ui/from_iter_instead_of_collect.stderr b/tests/ui/from_iter_instead_of_collect.stderr index 8aa3c3c01f818..8f08ac8c3ff43 100644 --- a/tests/ui/from_iter_instead_of_collect.stderr +++ b/tests/ui/from_iter_instead_of_collect.stderr @@ -1,5 +1,5 @@ error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:18:9 + --> $DIR/from_iter_instead_of_collect.rs:19:9 | LL | >::from_iter(iter.into_iter().copied()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::()` @@ -7,85 +7,85 @@ LL | >::from_iter(iter.into_iter().copied()) = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:24:13 + --> $DIR/from_iter_instead_of_collect.rs:25:13 | LL | let _ = Vec::from_iter(iter_expr); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:26:13 + --> $DIR/from_iter_instead_of_collect.rs:27:13 | LL | let _ = HashMap::::from_iter(vec![5, 5, 5, 5].iter().enumerate()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:31:19 + --> $DIR/from_iter_instead_of_collect.rs:32:19 | LL | assert_eq!(a, Vec::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:32:19 + --> $DIR/from_iter_instead_of_collect.rs:33:19 | LL | assert_eq!(a, Vec::::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:34:17 + --> $DIR/from_iter_instead_of_collect.rs:35:17 | LL | let mut b = VecDeque::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:37:17 + --> $DIR/from_iter_instead_of_collect.rs:38:17 | LL | let mut b = VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:42:21 + --> $DIR/from_iter_instead_of_collect.rs:43:21 | LL | let mut b = collections::VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:47:14 + --> $DIR/from_iter_instead_of_collect.rs:48:14 | LL | let bm = BTreeMap::from_iter(values.iter().cloned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:48:19 + --> $DIR/from_iter_instead_of_collect.rs:49:19 | LL | let mut bar = BTreeMap::from_iter(bm.range(0..2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:51:19 + --> $DIR/from_iter_instead_of_collect.rs:52:19 | LL | let mut bts = BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:55:17 + --> $DIR/from_iter_instead_of_collect.rs:56:17 | LL | let _ = collections::BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:56:17 + --> $DIR/from_iter_instead_of_collect.rs:57:17 | LL | let _ = collections::BTreeSet::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:59:15 + --> $DIR/from_iter_instead_of_collect.rs:60:15 | LL | for _i in Vec::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:60:15 + --> $DIR/from_iter_instead_of_collect.rs:61:15 | LL | for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 204019130ede3..d96b68a9159a7 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -60,6 +60,15 @@ impl From for A { } } +struct PathInExpansion; + +impl From for String { + fn from(val: PathInExpansion) -> Self { + // non self/Self paths in expansions are fine + panic!() + } +} + #[clippy::msrv = "1.40"] fn msrv_1_40() { struct FromOverInto(Vec); diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 46e02847e3084..da8fe04f47605 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -60,6 +60,15 @@ impl From for A { } } +struct PathInExpansion; + +impl Into for PathInExpansion { + fn into(self) -> String { + // non self/Self paths in expansions are fine + panic!() + } +} + #[clippy::msrv = "1.40"] fn msrv_1_40() { struct FromOverInto(Vec); diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 6039f86fe6703..498b00de5adb6 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -59,7 +59,21 @@ LL ~ val.0 | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:78:5 + --> $DIR/from_over_into.rs:65:1 + | +LL | impl Into for PathInExpansion { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `impl From for Foreign` is allowed by the orphan rules, for more information see + https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence +help: replace the `Into` implementation with `From` + | +LL ~ impl From for String { +LL ~ fn from(val: PathInExpansion) -> Self { + | + +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> $DIR/from_over_into.rs:87:5 | LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,5 +85,5 @@ LL ~ fn from(val: Vec) -> Self { LL ~ FromOverInto(val) | -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index 3b280b7488ae7..c769e38eb33a0 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -3,14 +3,14 @@ struct InMacro(String); macro_rules! in_macro { - ($e:ident) => { - $e + () => { + Self::new() }; } impl Into for String { fn into(self) -> InMacro { - InMacro(in_macro!(self)) + InMacro(in_macro!()) } } @@ -32,4 +32,14 @@ impl Into for ContainsVal { } } +pub struct Lval(T); + +pub struct Rval(T); + +impl Into> for Lval { + fn into(self) -> Rval { + Rval(self) + } +} + fn main() {} diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index 251f1d84e74e3..2ab9b9d6b17cc 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -25,5 +25,13 @@ LL | impl Into for ContainsVal { https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence = help: replace the `Into` implementation with `From` -error: aborting due to 3 previous errors +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> $DIR/from_over_into_unfixable.rs:39:1 + | +LL | impl Into> for Lval { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: replace the `Into` implementation with `From>` + +error: aborting due to 4 previous errors diff --git a/tests/ui/from_raw_with_void_ptr.rs b/tests/ui/from_raw_with_void_ptr.rs index 8484da2415ab3..95ef6425fad9a 100644 --- a/tests/ui/from_raw_with_void_ptr.rs +++ b/tests/ui/from_raw_with_void_ptr.rs @@ -1,4 +1,5 @@ #![warn(clippy::from_raw_with_void_ptr)] +#![allow(clippy::unnecessary_cast)] use std::ffi::c_void; use std::rc::Rc; diff --git a/tests/ui/from_raw_with_void_ptr.stderr b/tests/ui/from_raw_with_void_ptr.stderr index 96e4af12ba386..1963d08014b15 100644 --- a/tests/ui/from_raw_with_void_ptr.stderr +++ b/tests/ui/from_raw_with_void_ptr.stderr @@ -1,60 +1,60 @@ error: creating a `Box` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:10:22 + --> $DIR/from_raw_with_void_ptr.rs:11:22 | LL | let _ = unsafe { Box::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:10:36 + --> $DIR/from_raw_with_void_ptr.rs:11:36 | LL | let _ = unsafe { Box::from_raw(ptr) }; | ^^^ = note: `-D clippy::from-raw-with-void-ptr` implied by `-D warnings` error: creating a `Rc` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:21:22 + --> $DIR/from_raw_with_void_ptr.rs:22:22 | LL | let _ = unsafe { Rc::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:21:35 + --> $DIR/from_raw_with_void_ptr.rs:22:35 | LL | let _ = unsafe { Rc::from_raw(ptr) }; | ^^^ error: creating a `Arc` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:25:22 + --> $DIR/from_raw_with_void_ptr.rs:26:22 | LL | let _ = unsafe { Arc::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:25:36 + --> $DIR/from_raw_with_void_ptr.rs:26:36 | LL | let _ = unsafe { Arc::from_raw(ptr) }; | ^^^ error: creating a `Weak` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:29:22 + --> $DIR/from_raw_with_void_ptr.rs:30:22 | LL | let _ = unsafe { std::rc::Weak::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:29:46 + --> $DIR/from_raw_with_void_ptr.rs:30:46 | LL | let _ = unsafe { std::rc::Weak::from_raw(ptr) }; | ^^^ error: creating a `Weak` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:33:22 + --> $DIR/from_raw_with_void_ptr.rs:34:22 | LL | let _ = unsafe { std::sync::Weak::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:33:48 + --> $DIR/from_raw_with_void_ptr.rs:34:48 | LL | let _ = unsafe { std::sync::Weak::from_raw(ptr) }; | ^^^ diff --git a/tests/ui/get_first.fixed b/tests/ui/get_first.fixed index ef132b7961177..a29c0918a6dd8 100644 --- a/tests/ui/get_first.fixed +++ b/tests/ui/get_first.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::get_first)] +#![allow(clippy::useless_vec)] use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::VecDeque; diff --git a/tests/ui/get_first.rs b/tests/ui/get_first.rs index 4d8722356144e..2062f3ec23a04 100644 --- a/tests/ui/get_first.rs +++ b/tests/ui/get_first.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::get_first)] +#![allow(clippy::useless_vec)] use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::VecDeque; diff --git a/tests/ui/get_first.stderr b/tests/ui/get_first.stderr index 466beff9c92df..4e267ba9a3b48 100644 --- a/tests/ui/get_first.stderr +++ b/tests/ui/get_first.stderr @@ -1,5 +1,5 @@ error: accessing first element with `x.get(0)` - --> $DIR/get_first.rs:19:13 + --> $DIR/get_first.rs:20:13 | LL | let _ = x.get(0); // Use x.first() | ^^^^^^^^ help: try: `x.first()` @@ -7,13 +7,13 @@ LL | let _ = x.get(0); // Use x.first() = note: `-D clippy::get-first` implied by `-D warnings` error: accessing first element with `y.get(0)` - --> $DIR/get_first.rs:24:13 + --> $DIR/get_first.rs:25:13 | LL | let _ = y.get(0); // Use y.first() | ^^^^^^^^ help: try: `y.first()` error: accessing first element with `z.get(0)` - --> $DIR/get_first.rs:29:13 + --> $DIR/get_first.rs:30:13 | LL | let _ = z.get(0); // Use z.first() | ^^^^^^^^ help: try: `z.first()` diff --git a/tests/ui/get_last_with_len.fixed b/tests/ui/get_last_with_len.fixed index a58dfda798855..01a83e5bf343f 100644 --- a/tests/ui/get_last_with_len.fixed +++ b/tests/ui/get_last_with_len.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::get_last_with_len)] -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] use std::collections::VecDeque; diff --git a/tests/ui/get_last_with_len.rs b/tests/ui/get_last_with_len.rs index d626656c78f95..d82484b46d3ff 100644 --- a/tests/ui/get_last_with_len.rs +++ b/tests/ui/get_last_with_len.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::get_last_with_len)] -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] use std::collections::VecDeque; diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 4950c47ddeb80..56ee37f02d26d 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -1,6 +1,11 @@ //@run-rustfix -#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] +#![allow( + unused_mut, + clippy::from_iter_instead_of_collect, + clippy::get_first, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] @@ -65,3 +70,42 @@ fn main() { let _ = some_vec[0..1].to_vec(); } } +mod issue9909 { + #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] + + fn reduced() { + let f = &[1, 2, 3]; + + // include a borrow in the suggestion, even if the argument is not just a numeric literal + let _x: &i32 = &f[1 + 2]; + + // don't include a borrow here + let _x = f[1 + 2].to_string(); + + // don't include a borrow here + let _x = f[1 + 2].abs(); + } + + // original code: + fn linidx(row: usize, col: usize) -> usize { + row * 1 + col * 3 + } + + fn main_() { + let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0]; + + for i in 0..2 { + for j in i + 1..3 { + if mat[linidx(j, 3)] > mat[linidx(i, 3)] { + for k in 0..4 { + let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); + let a = x.last_mut().unwrap(); + let b = &mut rest[linidx(j, k) - linidx(i, k) - 1]; + ::std::mem::swap(a, b); + } + } + } + } + assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat); + } +} diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 6b1e8edb7bd2f..af3a619adc5e9 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -1,6 +1,11 @@ //@run-rustfix -#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] +#![allow( + unused_mut, + clippy::from_iter_instead_of_collect, + clippy::get_first, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] @@ -65,3 +70,42 @@ fn main() { let _ = some_vec.get_mut(0..1).unwrap().to_vec(); } } +mod issue9909 { + #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] + + fn reduced() { + let f = &[1, 2, 3]; + + // include a borrow in the suggestion, even if the argument is not just a numeric literal + let _x: &i32 = f.get(1 + 2).unwrap(); + + // don't include a borrow here + let _x = f.get(1 + 2).unwrap().to_string(); + + // don't include a borrow here + let _x = f.get(1 + 2).unwrap().abs(); + } + + // original code: + fn linidx(row: usize, col: usize) -> usize { + row * 1 + col * 3 + } + + fn main_() { + let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0]; + + for i in 0..2 { + for j in i + 1..3 { + if mat[linidx(j, 3)] > mat[linidx(i, 3)] { + for k in 0..4 { + let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); + let a = x.last_mut().unwrap(); + let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + ::std::mem::swap(a, b); + } + } + } + } + assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat); + } +} diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 6dee4d5b4b624..fd961420dc41d 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,17 +1,17 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:35:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | note: the lint level is defined here - --> $DIR/get_unwrap.rs:5:9 + --> $DIR/get_unwrap.rs:10:9 | LL | #![deny(clippy::get_unwrap)] | ^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:35:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,13 +20,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,13 +48,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,13 +62,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,13 +76,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,13 +90,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:44:21 + --> $DIR/get_unwrap.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:44:22 + --> $DIR/get_unwrap.rs:49:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,13 +104,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:49:9 + --> $DIR/get_unwrap.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:49:10 + --> $DIR/get_unwrap.rs:54:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +118,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:50:9 + --> $DIR/get_unwrap.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:50:10 + --> $DIR/get_unwrap.rs:55:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,13 +132,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:51:9 + --> $DIR/get_unwrap.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:51:10 + --> $DIR/get_unwrap.rs:56:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,13 +146,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:52:9 + --> $DIR/get_unwrap.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:52:10 + --> $DIR/get_unwrap.rs:57:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,13 +160,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:64:17 + --> $DIR/get_unwrap.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:64:17 + --> $DIR/get_unwrap.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,18 +174,42 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message -error: aborting due to 26 previous errors +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:80:24 + | +LL | let _x: &i32 = f.get(1 + 2).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:83:18 + | +LL | let _x = f.get(1 + 2).unwrap().to_string(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:86:18 + | +LL | let _x = f.get(1 + 2).unwrap().abs(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:103:33 + | +LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` + +error: aborting due to 30 previous errors diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 07d2002eb27f8..dad4543f84c09 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -21,6 +21,7 @@ fn foo() -> bool { fn if_same_then_else() { if true { + //~^ ERROR: this `if` has identical blocks Foo { bar: 42 }; 0..10; ..; @@ -29,7 +30,6 @@ fn if_same_then_else() { 0..=10; foo(); } else { - //~ ERROR same body as `if` block Foo { bar: 42 }; 0..10; ..; @@ -65,16 +65,16 @@ fn if_same_then_else() { } let _ = if true { + //~^ ERROR: this `if` has identical blocks 0.0 } else { - //~ ERROR same body as `if` block 0.0 }; let _ = if true { + //~^ ERROR: this `if` has identical blocks -0.0 } else { - //~ ERROR same body as `if` block -0.0 }; @@ -88,13 +88,14 @@ fn if_same_then_else() { } let _ = if true { + //~^ ERROR: this `if` has identical blocks 42 } else { - //~ ERROR same body as `if` block 42 }; if true { + //~^ ERROR: this `if` has identical blocks let bar = if true { 42 } else { 43 }; while foo() { @@ -102,7 +103,6 @@ fn if_same_then_else() { } bar + 1; } else { - //~ ERROR same body as `if` block let bar = if true { 42 } else { 43 }; while foo() { diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index fb23b81d36d72..a34fc565590b0 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -3,22 +3,22 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | Foo { bar: 42 }; LL | | 0..10; -LL | | ..; ... | LL | | foo(); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:31:12 + --> $DIR/if_same_then_else.rs:32:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | Foo { bar: 42 }; LL | | 0..10; +LL | | ..; ... | LL | | foo(); LL | | } @@ -30,16 +30,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | 0.0 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:69:12 + --> $DIR/if_same_then_else.rs:70:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | 0.0 LL | | }; | |_____^ @@ -49,16 +49,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | -0.0 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:76:12 + --> $DIR/if_same_then_else.rs:77:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | -0.0 LL | | }; | |_____^ @@ -68,16 +68,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | 42 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:92:12 + --> $DIR/if_same_then_else.rs:93:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | 42 LL | | }; | |_____^ @@ -87,22 +87,22 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | let bar = if true { 42 } else { 43 }; LL | | -LL | | while foo() { ... | LL | | bar + 1; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:104:12 + --> $DIR/if_same_then_else.rs:105:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | let bar = if true { 42 } else { 43 }; LL | | +LL | | while foo() { ... | LL | | bar + 1; LL | | } diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 58167f4446dba..0b171f21d0cc4 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -5,6 +5,7 @@ clippy::equatable_if_let, clippy::collapsible_if, clippy::ifs_same_cond, + clippy::needless_if, clippy::needless_return, clippy::single_element_loop, clippy::branches_sharing_code @@ -12,6 +13,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { if true { + //~^ ERROR: this `if` has identical blocks for _ in &[42] { let foo: &Option<_> = &Some::(42); if foo.is_some() { @@ -21,7 +23,6 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } } } else { - //~ ERROR same body as `if` block for _ in &[42] { let bar: &Option<_> = &Some::(42); if bar.is_some() { @@ -33,16 +34,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } if true { + //~^ ERROR: this `if` has identical blocks if let Some(a) = Some(42) {} } else { - //~ ERROR same body as `if` block if let Some(a) = Some(42) {} } if true { + //~^ ERROR: this `if` has identical blocks if let (1, .., 3) = (1, 2, 3) {} } else { - //~ ERROR same body as `if` block if let (1, .., 3) = (1, 2, 3) {} } @@ -90,16 +91,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> { // Same NaNs let _ = if true { + //~^ ERROR: this `if` has identical blocks f32::NAN } else { - //~ ERROR same body as `if` block f32::NAN }; if true { + //~^ ERROR: this `if` has identical blocks Ok("foo")?; } else { - //~ ERROR same body as `if` block Ok("foo")?; } @@ -121,6 +122,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { let foo = "bar"; return Ok(&foo[0..]); } else if true { + //~^ ERROR: this `if` has identical blocks let foo = ""; return Ok(&foo[0..]); } else { diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr index 704cfd9669ac8..56e5f3e45b22c 100644 --- a/tests/ui/if_same_then_else2.stderr +++ b/tests/ui/if_same_then_else2.stderr @@ -1,24 +1,24 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:14:13 + --> $DIR/if_same_then_else2.rs:15:13 | LL | if true { | _____________^ +LL | | LL | | for _ in &[42] { LL | | let foo: &Option<_> = &Some::(42); -LL | | if foo.is_some() { ... | LL | | } LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:23:12 + --> $DIR/if_same_then_else2.rs:25:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | for _ in &[42] { LL | | let bar: &Option<_> = &Some::(42); +LL | | if bar.is_some() { ... | LL | | } LL | | } @@ -26,93 +26,94 @@ LL | | } = note: `-D clippy::if-same-then-else` implied by `-D warnings` error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:35:13 + --> $DIR/if_same_then_else2.rs:36:13 | LL | if true { | _____________^ +LL | | LL | | if let Some(a) = Some(42) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:37:12 + --> $DIR/if_same_then_else2.rs:39:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | if let Some(a) = Some(42) {} LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:42:13 + --> $DIR/if_same_then_else2.rs:43:13 | LL | if true { | _____________^ +LL | | LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:44:12 + --> $DIR/if_same_then_else2.rs:46:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:92:21 + --> $DIR/if_same_then_else2.rs:93:21 | LL | let _ = if true { | _____________________^ +LL | | LL | | f32::NAN LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:94:12 + --> $DIR/if_same_then_else2.rs:96:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | f32::NAN LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:99:13 + --> $DIR/if_same_then_else2.rs:100:13 | LL | if true { | _____________^ +LL | | LL | | Ok("foo")?; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:101:12 + --> $DIR/if_same_then_else2.rs:103:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | Ok("foo")?; LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:123:20 + --> $DIR/if_same_then_else2.rs:124:20 | LL | } else if true { | ____________________^ +LL | | LL | | let foo = ""; LL | | return Ok(&foo[0..]); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:126:12 + --> $DIR/if_same_then_else2.rs:128:12 | LL | } else { | ____________^ diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index f62da157d1b94..5c338e3c5c8f2 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -1,5 +1,10 @@ #![warn(clippy::ifs_same_cond)] -#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] // all empty blocks +#![allow( + clippy::if_same_then_else, + clippy::comparison_chain, + clippy::needless_if, + clippy::needless_else +)] // all empty blocks fn ifs_same_cond() { let a = 0; @@ -7,18 +12,18 @@ fn ifs_same_cond() { if b { } else if b { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } if a == 1 { } else if a == 1 { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } if 2 * a == 1 { } else if 2 * a == 2 { } else if 2 * a == 1 { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } else if a == 1 { } @@ -47,6 +52,7 @@ fn issue10272() { let a = String::from("ha"); if a.contains("ah") { } else if a.contains("ah") { + //~^ ERROR: this `if` has the same condition as a previous `if` // Trigger this lint } else if a.contains("ha") { } else if a == "wow" { diff --git a/tests/ui/ifs_same_cond.stderr b/tests/ui/ifs_same_cond.stderr index 9519f6904cb1e..8d70934476cbc 100644 --- a/tests/ui/ifs_same_cond.stderr +++ b/tests/ui/ifs_same_cond.stderr @@ -1,48 +1,48 @@ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:9:15 + --> $DIR/ifs_same_cond.rs:14:15 | LL | } else if b { | ^ | note: same as this - --> $DIR/ifs_same_cond.rs:8:8 + --> $DIR/ifs_same_cond.rs:13:8 | LL | if b { | ^ = note: `-D clippy::ifs-same-cond` implied by `-D warnings` error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:14:15 + --> $DIR/ifs_same_cond.rs:19:15 | LL | } else if a == 1 { | ^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:13:8 + --> $DIR/ifs_same_cond.rs:18:8 | LL | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:20:15 + --> $DIR/ifs_same_cond.rs:25:15 | LL | } else if 2 * a == 1 { | ^^^^^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:18:8 + --> $DIR/ifs_same_cond.rs:23:8 | LL | if 2 * a == 1 { | ^^^^^^^^^^ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:49:15 + --> $DIR/ifs_same_cond.rs:54:15 | LL | } else if a.contains("ah") { | ^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:48:8 + --> $DIR/ifs_same_cond.rs:53:8 | LL | if a.contains("ah") { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index ca7c12213728b..7ed7bf94a4b3c 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![deny(clippy::implicit_hasher)] #![allow(unused)] diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed index 620d45e6828cc..d84346e8789d5 100644 --- a/tests/ui/inconsistent_struct_constructor.fixed +++ b/tests/ui/inconsistent_struct_constructor.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] diff --git a/tests/ui/inconsistent_struct_constructor.rs b/tests/ui/inconsistent_struct_constructor.rs index 10ffadcb2ba90..87fba7448e3a3 100644 --- a/tests/ui/inconsistent_struct_constructor.rs +++ b/tests/ui/inconsistent_struct_constructor.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.fixed b/tests/ui/incorrect_clone_impl_on_copy_type.fixed new file mode 100644 index 0000000000000..ac482dcda1eee --- /dev/null +++ b/tests/ui/incorrect_clone_impl_on_copy_type.fixed @@ -0,0 +1,97 @@ +//@run-rustfix +#![allow(clippy::clone_on_copy, unused)] +#![no_main] + +// lint + +struct A(u32); + +impl Clone for A { + fn clone(&self) -> Self { *self } + + +} + +impl Copy for A {} + +// do not lint + +struct B(u32); + +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for B {} + +// do not lint derived (clone's implementation is `*self` here anyway) + +#[derive(Clone, Copy)] +struct C(u32); + +// do not lint derived (fr this time) + +struct D(u32); + +#[automatically_derived] +impl Clone for D { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for D {} + +// do not lint if clone is not manually implemented + +struct E(u32); + +#[automatically_derived] +impl Clone for E { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for E {} + +// lint since clone is not derived + +#[derive(Copy)] +struct F(u32); + +impl Clone for F { + fn clone(&self) -> Self { *self } + + +} + +// do not lint since copy has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Clone for Uwu
{ + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for Uwu {} diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.rs b/tests/ui/incorrect_clone_impl_on_copy_type.rs new file mode 100644 index 0000000000000..00775874ff585 --- /dev/null +++ b/tests/ui/incorrect_clone_impl_on_copy_type.rs @@ -0,0 +1,107 @@ +//@run-rustfix +#![allow(clippy::clone_on_copy, unused)] +#![no_main] + +// lint + +struct A(u32); + +impl Clone for A { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for A {} + +// do not lint + +struct B(u32); + +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for B {} + +// do not lint derived (clone's implementation is `*self` here anyway) + +#[derive(Clone, Copy)] +struct C(u32); + +// do not lint derived (fr this time) + +struct D(u32); + +#[automatically_derived] +impl Clone for D { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for D {} + +// do not lint if clone is not manually implemented + +struct E(u32); + +#[automatically_derived] +impl Clone for E { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for E {} + +// lint since clone is not derived + +#[derive(Copy)] +struct F(u32); + +impl Clone for F { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +// do not lint since copy has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Clone for Uwu { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + +impl Copy for Uwu {} diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/tests/ui/incorrect_clone_impl_on_copy_type.stderr new file mode 100644 index 0000000000000..0021841aa860f --- /dev/null +++ b/tests/ui/incorrect_clone_impl_on_copy_type.stderr @@ -0,0 +1,40 @@ +error: incorrect implementation of `clone` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:10:29 + | +LL | fn clone(&self) -> Self { + | _____________________________^ +LL | | Self(self.0) +LL | | } + | |_____^ help: change this to: `{ *self }` + | + = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default + +error: incorrect implementation of `clone_from` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:14:5 + | +LL | / fn clone_from(&mut self, source: &Self) { +LL | | source.clone(); +LL | | *self = source.clone(); +LL | | } + | |_____^ help: remove this + +error: incorrect implementation of `clone` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:81:29 + | +LL | fn clone(&self) -> Self { + | _____________________________^ +LL | | Self(self.0) +LL | | } + | |_____^ help: change this to: `{ *self }` + +error: incorrect implementation of `clone_from` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:85:5 + | +LL | / fn clone_from(&mut self, source: &Self) { +LL | | source.clone(); +LL | | *self = source.clone(); +LL | | } + | |_____^ help: remove this + +error: aborting due to 4 previous errors + diff --git a/tests/ui/indexing_slicing_index.rs b/tests/ui/indexing_slicing_index.rs index 26abc9edb5e44..16f9e47e8532c 100644 --- a/tests/ui/indexing_slicing_index.rs +++ b/tests/ui/indexing_slicing_index.rs @@ -3,7 +3,12 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + unconditional_panic, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::useless_vec +)] const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index 8fd77913a3fd9..f4357c1d592d0 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -1,5 +1,5 @@ error: indexing may panic - --> $DIR/indexing_slicing_index.rs:9:20 + --> $DIR/indexing_slicing_index.rs:14:20 | LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic - --> $DIR/indexing_slicing_index.rs:10:24 + --> $DIR/indexing_slicing_index.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ @@ -18,19 +18,19 @@ LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. = note: the suggestion might not be applicable in constant blocks error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/indexing_slicing_index.rs:31:14 + --> $DIR/indexing_slicing_index.rs:36:14 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant used - --> $DIR/indexing_slicing_index.rs:31:5 + --> $DIR/indexing_slicing_index.rs:36:5 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/indexing_slicing_index.rs:22:5 + --> $DIR/indexing_slicing_index.rs:27:5 | LL | x[index]; | ^^^^^^^^ @@ -38,7 +38,7 @@ LL | x[index]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:30:14 + --> $DIR/indexing_slicing_index.rs:35:14 | LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restri = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> $DIR/indexing_slicing_index.rs:31:14 + --> $DIR/indexing_slicing_index.rs:36:14 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restr = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> $DIR/indexing_slicing_index.rs:38:5 + --> $DIR/indexing_slicing_index.rs:43:5 | LL | v[0]; | ^^^^ @@ -64,7 +64,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:39:5 + --> $DIR/indexing_slicing_index.rs:44:5 | LL | v[10]; | ^^^^^ @@ -72,7 +72,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:40:5 + --> $DIR/indexing_slicing_index.rs:45:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:46:5 + --> $DIR/indexing_slicing_index.rs:51:5 | LL | v[N]; | ^^^^ @@ -88,7 +88,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:47:5 + --> $DIR/indexing_slicing_index.rs:52:5 | LL | v[M]; | ^^^^ @@ -96,7 +96,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed - --> $DIR/indexing_slicing_index.rs:10:24 + --> $DIR/indexing_slicing_index.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 diff --git a/tests/ui/indexing_slicing_slice.rs b/tests/ui/indexing_slicing_slice.rs index 7b107db39f022..939b6ac36bde8 100644 --- a/tests/ui/indexing_slicing_slice.rs +++ b/tests/ui/indexing_slicing_slice.rs @@ -2,7 +2,7 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)] fn main() { let x = [1, 2, 3, 4]; diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index 9f550acb1577c..af197e33fd835 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -11,35 +11,35 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).iter(); //~ WARN equivalent to .iter() - let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ WARN equivalent to .iter() - let _ = std::rc::Rc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() - let _ = std::sync::Arc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() + let _ = (&vec![1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ ERROR: equivalent to `.iter() + let _ = std::rc::Rc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() + let _ = std::sync::Arc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() - let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() - let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR equivalent to .iter_mut() + let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Some(4)).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Some(5)).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&Ok::<_, i32>(6)).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Err::(7)).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&Vec::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Vec::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&BTreeMap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut BTreeMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&VecDeque::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut VecDeque::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&LinkedList::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut LinkedList::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&HashMap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut HashMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&Some(4)).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Some(5)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Ok::<_, i32>(6)).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Err::(7)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Vec::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Vec::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&BTreeMap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut BTreeMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&VecDeque::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut VecDeque::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&LinkedList::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut LinkedList::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&HashMap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut HashMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeSet::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&BinaryHeap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&HashSet::::new()).iter(); //~ WARN equivalent to .iter() - let _ = std::path::Path::new("12/34").iter(); //~ WARN equivalent to .iter() - let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR equivalent to .iter() + let _ = (&BTreeSet::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BinaryHeap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&HashSet::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::Path::new("12/34").iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR: equivalent to `.iter() - let _ = (&[1, 2, 3]).iter().next(); //~ WARN equivalent to .iter() + let _ = (&[1, 2, 3]).iter().next(); //~ ERROR: equivalent to `.iter() } diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 3381ae04dcecd..3ac13d7dd3e1d 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -11,35 +11,35 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() - let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() - let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() - let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + let _ = (&vec![1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() + let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&Some(4)).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Some(5)).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Ok::<_, i32>(6)).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Err::(7)).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() - let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() + let _ = (&BTreeSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BinaryHeap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&HashSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::Path::new("12/34").into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() + let _ = (&[1, 2, 3]).into_iter().next(); //~ ERROR: equivalent to `.iter() } diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 28003b365bbd5..06014a93f8c18 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,7 +1,7 @@ error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:14:30 | -LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&vec![1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` | = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` @@ -9,157 +9,157 @@ LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:15:46 | -LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() +LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:16:41 | -LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:17:44 | -LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:19:32 | -LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:20:36 | -LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:21:40 | -LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() +LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Option` --> $DIR/into_iter_on_ref.rs:23:24 | -LL | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Some(4)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Option` --> $DIR/into_iter_on_ref.rs:24:28 | -LL | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Some(5)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Result` --> $DIR/into_iter_on_ref.rs:25:32 | -LL | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Ok::<_, i32>(6)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Result` --> $DIR/into_iter_on_ref.rs:26:37 | -LL | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Err::(7)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:27:34 | -LL | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:28:38 | -LL | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeMap` --> $DIR/into_iter_on_ref.rs:29:44 | -LL | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `BTreeMap` --> $DIR/into_iter_on_ref.rs:30:48 | -LL | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `VecDeque` --> $DIR/into_iter_on_ref.rs:31:39 | -LL | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `VecDeque` --> $DIR/into_iter_on_ref.rs:32:43 | -LL | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `LinkedList` --> $DIR/into_iter_on_ref.rs:33:41 | -LL | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `LinkedList` --> $DIR/into_iter_on_ref.rs:34:45 | -LL | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashMap` --> $DIR/into_iter_on_ref.rs:35:43 | -LL | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `HashMap` --> $DIR/into_iter_on_ref.rs:36:47 | -LL | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeSet` --> $DIR/into_iter_on_ref.rs:38:39 | -LL | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BinaryHeap` --> $DIR/into_iter_on_ref.rs:39:41 | -LL | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BinaryHeap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashSet` --> $DIR/into_iter_on_ref.rs:40:38 | -LL | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Path` --> $DIR/into_iter_on_ref.rs:41:43 | -LL | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::path::Path::new("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `PathBuf` --> $DIR/into_iter_on_ref.rs:42:47 | -LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = std::path::PathBuf::from("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:44:26 | -LL | let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() +LL | let _ = (&[1, 2, 3]).into_iter().next(); | ^^^^^^^^^ help: call directly: `iter` error: aborting due to 27 previous errors diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs index 586d13647d15e..0b07de1144ce7 100644 --- a/tests/ui/issue-3145.rs +++ b/tests/ui/issue-3145.rs @@ -1,3 +1,3 @@ fn main() { - println!("{}" a); //~ERROR expected `,`, found `a` + println!("{}" a); //~ERROR: expected `,`, found `a` } diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index a35032aa150dc..d7c2c88a20470 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,7 +1,7 @@ error: expected `,`, found `a` --> $DIR/issue-3145.rs:2:19 | -LL | println!("{}" a); //~ERROR expected `,`, found `a` +LL | println!("{}" a); | ^ expected `,` error: aborting due to previous error diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index fd553aa4538ad..5b60646ef21df 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -1,16 +1,16 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/issue_4266.rs:4:1 + --> $DIR/issue_4266.rs:4:16 | LL | async fn sink1<'a>(_: &'a str) {} // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: the following explicit lifetimes could be elided: 'a - --> $DIR/issue_4266.rs:8:1 + --> $DIR/issue_4266.rs:8:21 | LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ error: methods called `new` usually take no `self` --> $DIR/issue_4266.rs:28:22 diff --git a/tests/ui/items_after_test_module/block_module.stderr b/tests/ui/items_after_test_module/block_module.stderr index 597f1b9510c56..1b6257471618c 100644 --- a/tests/ui/items_after_test_module/block_module.stderr +++ b/tests/ui/items_after_test_module/block_module.stderr @@ -1,17 +1,2 @@ -error: items were found after the testing module - --> $DIR/block_module.rs:13:1 - | -LL | / mod tests { -LL | | #[test] -LL | | fn hi() {} -LL | | } -... | -LL | | () => {}; -LL | | } - | |_^ - | - = help: move the items to before the testing module was defined - = note: `-D clippy::items-after-test-module` implied by `-D warnings` - -error: aborting due to previous error +error: Option 'test' given more than once diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index 88f08bb991b8d..2baea06f84ba9 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![allow(unused)] +#![allow(clippy::useless_vec)] use std::collections::HashSet; use std::collections::VecDeque; diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index d3438b7f51a2c..9eac94eb8d975 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -1,6 +1,7 @@ //@run-rustfix #![allow(unused)] +#![allow(clippy::useless_vec)] use std::collections::HashSet; use std::collections::VecDeque; diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr index b2cc497bf433a..b38cf547dc5fb 100644 --- a/tests/ui/iter_cloned_collect.stderr +++ b/tests/ui/iter_cloned_collect.stderr @@ -1,5 +1,5 @@ error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:10:27 + --> $DIR/iter_cloned_collect.rs:11:27 | LL | let v2: Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` @@ -7,13 +7,13 @@ LL | let v2: Vec = v.iter().cloned().collect(); = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:15:38 + --> $DIR/iter_cloned_collect.rs:16:38 | LL | let _: Vec = vec![1, 2, 3].iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:20:24 + --> $DIR/iter_cloned_collect.rs:21:24 | LL | .to_bytes() | ________________________^ @@ -23,13 +23,13 @@ LL | | .collect(); | |______________________^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:28:24 + --> $DIR/iter_cloned_collect.rs:29:24 | LL | let _: Vec<_> = arr.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:31:26 + --> $DIR/iter_cloned_collect.rs:32:26 | LL | let _: Vec = v.iter().copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` diff --git a/tests/ui/iter_count.fixed b/tests/ui/iter_count.fixed index 4367a12f820d5..b6208201409f1 100644 --- a/tests/ui/iter_count.fixed +++ b/tests/ui/iter_count.fixed @@ -7,7 +7,8 @@ array_into_iter, unused_mut, clippy::into_iter_on_ref, - clippy::unnecessary_operation + clippy::unnecessary_operation, + clippy::useless_vec )] extern crate option_helpers; diff --git a/tests/ui/iter_count.rs b/tests/ui/iter_count.rs index 8c7543cf03b39..fb2161312098a 100644 --- a/tests/ui/iter_count.rs +++ b/tests/ui/iter_count.rs @@ -7,7 +7,8 @@ array_into_iter, unused_mut, clippy::into_iter_on_ref, - clippy::unnecessary_operation + clippy::unnecessary_operation, + clippy::useless_vec )] extern crate option_helpers; diff --git a/tests/ui/iter_count.stderr b/tests/ui/iter_count.stderr index 2e3d7fc35de9c..f9aee0b7846d3 100644 --- a/tests/ui/iter_count.stderr +++ b/tests/ui/iter_count.stderr @@ -1,5 +1,5 @@ error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:54:6 + --> $DIR/iter_count.rs:55:6 | LL | &vec[..].iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` @@ -7,145 +7,145 @@ LL | &vec[..].iter().count(); = note: `-D clippy::iter-count` implied by `-D warnings` error: called `.iter().count()` on a `Vec` - --> $DIR/iter_count.rs:55:5 + --> $DIR/iter_count.rs:56:5 | LL | vec.iter().count(); | ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:56:5 + --> $DIR/iter_count.rs:57:5 | LL | boxed_slice.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()` error: called `.iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:57:5 + --> $DIR/iter_count.rs:58:5 | LL | vec_deque.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:58:5 + --> $DIR/iter_count.rs:59:5 | LL | hash_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:59:5 + --> $DIR/iter_count.rs:60:5 | LL | hash_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:60:5 + --> $DIR/iter_count.rs:61:5 | LL | b_tree_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:61:5 + --> $DIR/iter_count.rs:62:5 | LL | b_tree_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:62:5 + --> $DIR/iter_count.rs:63:5 | LL | linked_list.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:63:5 + --> $DIR/iter_count.rs:64:5 | LL | binary_heap.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` error: called `.iter_mut().count()` on a `Vec` - --> $DIR/iter_count.rs:65:5 + --> $DIR/iter_count.rs:66:5 | LL | vec.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter_mut().count()` on a `slice` - --> $DIR/iter_count.rs:66:6 + --> $DIR/iter_count.rs:67:6 | LL | &vec[..].iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.iter_mut().count()` on a `VecDeque` - --> $DIR/iter_count.rs:67:5 + --> $DIR/iter_count.rs:68:5 | LL | vec_deque.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter_mut().count()` on a `HashMap` - --> $DIR/iter_count.rs:68:5 + --> $DIR/iter_count.rs:69:5 | LL | hash_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter_mut().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:69:5 + --> $DIR/iter_count.rs:70:5 | LL | b_tree_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter_mut().count()` on a `LinkedList` - --> $DIR/iter_count.rs:70:5 + --> $DIR/iter_count.rs:71:5 | LL | linked_list.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `slice` - --> $DIR/iter_count.rs:72:6 + --> $DIR/iter_count.rs:73:6 | LL | &vec[..].into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.into_iter().count()` on a `Vec` - --> $DIR/iter_count.rs:73:5 + --> $DIR/iter_count.rs:74:5 | LL | vec.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.into_iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:74:5 + --> $DIR/iter_count.rs:75:5 | LL | vec_deque.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.into_iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:75:5 + --> $DIR/iter_count.rs:76:5 | LL | hash_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.into_iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:76:5 + --> $DIR/iter_count.rs:77:5 | LL | hash_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.into_iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:77:5 + --> $DIR/iter_count.rs:78:5 | LL | b_tree_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.into_iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:78:5 + --> $DIR/iter_count.rs:79:5 | LL | b_tree_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.into_iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:79:5 + --> $DIR/iter_count.rs:80:5 | LL | linked_list.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:80:5 + --> $DIR/iter_count.rs:81:5 | LL | binary_heap.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` diff --git a/tests/ui/iter_next_loop.rs b/tests/ui/iter_next_loop.rs new file mode 100644 index 0000000000000..548b799de44e8 --- /dev/null +++ b/tests/ui/iter_next_loop.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, unused, for_loops_over_fallibles)] +#![warn(clippy::iter_next_loop)] + +fn main() { + let x = [1, 2, 3, 4]; + for _ in vec.iter().next() {} + + struct Unrelated(&'static [u8]); + impl Unrelated { + fn next(&self) -> std::slice::Iter { + self.0.iter() + } + } + let u = Unrelated(&[0]); + for _v in u.next() {} // no error +} diff --git a/tests/ui/iter_next_loop.stderr b/tests/ui/iter_next_loop.stderr new file mode 100644 index 0000000000000..5bba0e635bba6 --- /dev/null +++ b/tests/ui/iter_next_loop.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected value, found macro `vec` + --> $DIR/iter_next_loop.rs:6:14 + | +LL | for _ in vec.iter().next() {} + | ^^^ not a value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/iter_next_slice.fixed b/tests/ui/iter_next_slice.fixed index d862abc34e0bb..702edccdbad0d 100644 --- a/tests/ui/iter_next_slice.fixed +++ b/tests/ui/iter_next_slice.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::iter_next_slice)] +#![allow(clippy::useless_vec)] fn main() { // test code goes here diff --git a/tests/ui/iter_next_slice.rs b/tests/ui/iter_next_slice.rs index da6fc46e42874..30bfc72de1793 100644 --- a/tests/ui/iter_next_slice.rs +++ b/tests/ui/iter_next_slice.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::iter_next_slice)] +#![allow(clippy::useless_vec)] fn main() { // test code goes here diff --git a/tests/ui/iter_next_slice.stderr b/tests/ui/iter_next_slice.stderr index d8b89061ff895..0db8201a1325c 100644 --- a/tests/ui/iter_next_slice.stderr +++ b/tests/ui/iter_next_slice.stderr @@ -1,5 +1,5 @@ error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:9:13 + --> $DIR/iter_next_slice.rs:10:13 | LL | let _ = s.iter().next(); | ^^^^^^^^^^^^^^^ help: try calling: `s.first()` @@ -7,19 +7,19 @@ LL | let _ = s.iter().next(); = note: `-D clippy::iter-next-slice` implied by `-D warnings` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:12:13 + --> $DIR/iter_next_slice.rs:13:13 | LL | let _ = s[2..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:15:13 + --> $DIR/iter_next_slice.rs:16:13 | LL | let _ = v[5..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:18:13 + --> $DIR/iter_next_slice.rs:19:13 | LL | let _ = v.iter().next(); | ^^^^^^^^^^^^^^^ help: try calling: `v.first()` diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs index e7fb97d4fbc8a..7c567bb81d88a 100644 --- a/tests/ui/iter_nth.rs +++ b/tests/ui/iter_nth.rs @@ -1,6 +1,7 @@ //@aux-build:option_helpers.rs #![warn(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #[macro_use] extern crate option_helpers; diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr index a0fe353bcf75c..24be814548a29 100644 --- a/tests/ui/iter_nth.stderr +++ b/tests/ui/iter_nth.stderr @@ -1,5 +1,5 @@ -error: called `.iter().nth()` on a Vec - --> $DIR/iter_nth.rs:33:23 +error: called `.iter().nth()` on a `Vec` + --> $DIR/iter_nth.rs:34:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice - --> $DIR/iter_nth.rs:34:26 + --> $DIR/iter_nth.rs:35:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,23 +16,23 @@ LL | let bad_slice = &some_vec[..].iter().nth(3); = help: calling `.get()` is both faster and more readable error: called `.iter().nth()` on a slice - --> $DIR/iter_nth.rs:35:31 + --> $DIR/iter_nth.rs:36:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: calling `.get()` is both faster and more readable -error: called `.iter().nth()` on a VecDeque - --> $DIR/iter_nth.rs:36:29 +error: called `.iter().nth()` on a `VecDeque` + --> $DIR/iter_nth.rs:37:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: calling `.get()` is both faster and more readable -error: called `.iter_mut().nth()` on a Vec - --> $DIR/iter_nth.rs:41:23 +error: called `.iter_mut().nth()` on a `Vec` + --> $DIR/iter_nth.rs:42:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,15 +40,15 @@ LL | let bad_vec = some_vec.iter_mut().nth(3); = help: calling `.get_mut()` is both faster and more readable error: called `.iter_mut().nth()` on a slice - --> $DIR/iter_nth.rs:44:26 + --> $DIR/iter_nth.rs:45:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: calling `.get_mut()` is both faster and more readable -error: called `.iter_mut().nth()` on a VecDeque - --> $DIR/iter_nth.rs:47:29 +error: called `.iter_mut().nth()` on a `VecDeque` + --> $DIR/iter_nth.rs:48:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/iter_nth_zero.fixed b/tests/ui/iter_nth_zero.fixed index 587b0d1d366a7..91f4a7ba0d2fc 100644 --- a/tests/ui/iter_nth_zero.fixed +++ b/tests/ui/iter_nth_zero.fixed @@ -29,3 +29,18 @@ fn main() { let mut iter2 = s3.iter(); let _unwrapped = iter2.next().unwrap(); } + +struct Issue9820; + +impl Iterator for Issue9820 { + type Item = (); + + fn nth(&mut self, _n: usize) -> Option { + todo!() + } + + // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect + fn next(&mut self) -> Option { + self.nth(0) + } +} diff --git a/tests/ui/iter_nth_zero.rs b/tests/ui/iter_nth_zero.rs index 93b576ec56fed..160a895bb7b4e 100644 --- a/tests/ui/iter_nth_zero.rs +++ b/tests/ui/iter_nth_zero.rs @@ -29,3 +29,18 @@ fn main() { let mut iter2 = s3.iter(); let _unwrapped = iter2.nth(0).unwrap(); } + +struct Issue9820; + +impl Iterator for Issue9820 { + type Item = (); + + fn nth(&mut self, _n: usize) -> Option { + todo!() + } + + // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect + fn next(&mut self) -> Option { + self.nth(0) + } +} diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed index bf576e9cbfb34..2874513c049b8 100644 --- a/tests/ui/iter_overeager_cloned.fixed +++ b/tests/ui/iter_overeager_cloned.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] -#![allow(dead_code, clippy::let_unit_value)] +#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs index df42d88eff00d..26f39734a5124 100644 --- a/tests/ui/iter_overeager_cloned.rs +++ b/tests/ui/iter_overeager_cloned.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] -#![allow(dead_code, clippy::let_unit_value)] +#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed index 8f2cefc430434..b888d965e8d7e 100644 --- a/tests/ui/iter_skip_next.fixed +++ b/tests/ui/iter_skip_next.fixed @@ -4,6 +4,7 @@ #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #![allow(unused_mut, dead_code)] extern crate option_helpers; diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 71d83384f3a05..e44efdebc4718 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -4,6 +4,7 @@ #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #![allow(unused_mut, dead_code)] extern crate option_helpers; diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index ca6970b27f16c..4ee26e088ce35 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:16:28 + --> $DIR/iter_skip_next.rs:17:28 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` @@ -7,37 +7,37 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:17:36 + --> $DIR/iter_skip_next.rs:18:36 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:18:20 + --> $DIR/iter_skip_next.rs:19:20 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:19:33 + --> $DIR/iter_skip_next.rs:20:33 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:27:26 + --> $DIR/iter_skip_next.rs:28:26 | LL | let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:29:29 + --> $DIR/iter_skip_next.rs:30:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:35:29 + --> $DIR/iter_skip_next.rs:36:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed index 24a95c4d0fee4..7a8c677010104 100644 --- a/tests/ui/iter_with_drain.fixed +++ b/tests/ui/iter_with_drain.fixed @@ -2,7 +2,7 @@ // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing -#![allow(clippy::needless_collect)] +#![allow(clippy::needless_collect, clippy::drain_collect)] #![warn(clippy::iter_with_drain)] use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs index a118c981ee3f5..cf3a935c349a4 100644 --- a/tests/ui/iter_with_drain.rs +++ b/tests/ui/iter_with_drain.rs @@ -2,7 +2,7 @@ // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing -#![allow(clippy::needless_collect)] +#![allow(clippy::needless_collect, clippy::drain_collect)] #![warn(clippy::iter_with_drain)] use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/tests/ui/iterator_step_by_zero.rs b/tests/ui/iterator_step_by_zero.rs index 13d1cfd428185..33ec78e9a4160 100644 --- a/tests/ui/iterator_step_by_zero.rs +++ b/tests/ui/iterator_step_by_zero.rs @@ -1,3 +1,4 @@ +#![allow(clippy::useless_vec)] #[warn(clippy::iterator_step_by_zero)] fn main() { let _ = vec!["A", "B", "B"].iter().step_by(0); diff --git a/tests/ui/iterator_step_by_zero.stderr b/tests/ui/iterator_step_by_zero.stderr index d792aea11dfa0..b470e2ed2eab9 100644 --- a/tests/ui/iterator_step_by_zero.stderr +++ b/tests/ui/iterator_step_by_zero.stderr @@ -1,5 +1,5 @@ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:3:13 + --> $DIR/iterator_step_by_zero.rs:4:13 | LL | let _ = vec!["A", "B", "B"].iter().step_by(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | let _ = vec!["A", "B", "B"].iter().step_by(0); = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:4:13 + --> $DIR/iterator_step_by_zero.rs:5:13 | LL | let _ = "XXX".chars().step_by(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:5:13 + --> $DIR/iterator_step_by_zero.rs:6:13 | LL | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:14:13 + --> $DIR/iterator_step_by_zero.rs:15:13 | LL | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:15:13 + --> $DIR/iterator_step_by_zero.rs:16:13 | LL | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:18:13 + --> $DIR/iterator_step_by_zero.rs:19:13 | LL | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:22:13 + --> $DIR/iterator_step_by_zero.rs:23:13 | LL | let _ = v1.iter().step_by(2 / 3); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index ea8bc5b4aca1f..e677cc9a7b95c 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs index 4a8ba995da556..e0f6b3d9d3b44 100644 --- a/tests/ui/large_futures.rs +++ b/tests/ui/large_futures.rs @@ -1,5 +1,6 @@ #![feature(generators)] #![warn(clippy::large_futures)] +#![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] #![allow(clippy::manual_async_fn)] diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr index 67e0fceff6ef3..5bcf054884e41 100644 --- a/tests/ui/large_futures.stderr +++ b/tests/ui/large_futures.stderr @@ -1,5 +1,5 @@ error: large future with a size of 16385 bytes - --> $DIR/large_futures.rs:10:9 + --> $DIR/large_futures.rs:11:9 | LL | big_fut([0u8; 1024 * 16]).await; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))` @@ -7,37 +7,37 @@ LL | big_fut([0u8; 1024 * 16]).await; = note: `-D clippy::large-futures` implied by `-D warnings` error: large future with a size of 16386 bytes - --> $DIR/large_futures.rs:12:5 + --> $DIR/large_futures.rs:13:5 | LL | f.await | ^ help: consider `Box::pin` on it: `Box::pin(f)` error: large future with a size of 16387 bytes - --> $DIR/large_futures.rs:16:9 + --> $DIR/large_futures.rs:17:9 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 16387 bytes - --> $DIR/large_futures.rs:20:13 + --> $DIR/large_futures.rs:21:13 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 65540 bytes - --> $DIR/large_futures.rs:27:5 + --> $DIR/large_futures.rs:28:5 | LL | foo().await; | ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())` error: large future with a size of 49159 bytes - --> $DIR/large_futures.rs:28:5 + --> $DIR/large_futures.rs:29:5 | LL | calls_fut(fut).await; | ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))` error: large future with a size of 65540 bytes - --> $DIR/large_futures.rs:40:5 + --> $DIR/large_futures.rs:41:5 | LL | / async { LL | | let x = [0i32; 1024 * 16]; @@ -56,7 +56,7 @@ LL + }) | error: large future with a size of 65540 bytes - --> $DIR/large_futures.rs:51:13 + --> $DIR/large_futures.rs:52:13 | LL | / async { LL | | let x = [0i32; 1024 * 16]; diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs new file mode 100644 index 0000000000000..cd9d0c8a67a8a --- /dev/null +++ b/tests/ui/large_stack_frames.rs @@ -0,0 +1,44 @@ +#![allow(unused, incomplete_features)] +#![warn(clippy::large_stack_frames)] +#![feature(unsized_locals)] + +use std::hint::black_box; + +fn generic() { + let x = T::default(); + black_box(&x); +} + +fn unsized_local() { + let x: dyn std::fmt::Display = *(Box::new(1) as Box); + black_box(&x); +} + +struct ArrayDefault([u8; N]); + +impl Default for ArrayDefault { + fn default() -> Self { + Self([0; N]) + } +} + +fn many_small_arrays() { + let x = [0u8; 500_000]; + let x2 = [0u8; 500_000]; + let x3 = [0u8; 500_000]; + let x4 = [0u8; 500_000]; + let x5 = [0u8; 500_000]; + black_box((&x, &x2, &x3, &x4, &x5)); +} + +fn large_return_value() -> ArrayDefault<1_000_000> { + Default::default() +} + +fn large_fn_arg(x: ArrayDefault<1_000_000>) { + black_box(&x); +} + +fn main() { + generic::>(); +} diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr new file mode 100644 index 0000000000000..d57df8596fe56 --- /dev/null +++ b/tests/ui/large_stack_frames.stderr @@ -0,0 +1,37 @@ +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:25:1 + | +LL | / fn many_small_arrays() { +LL | | let x = [0u8; 500_000]; +LL | | let x2 = [0u8; 500_000]; +LL | | let x3 = [0u8; 500_000]; +... | +LL | | black_box((&x, &x2, &x3, &x4, &x5)); +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + = note: `-D clippy::large-stack-frames` implied by `-D warnings` + +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:34:1 + | +LL | / fn large_return_value() -> ArrayDefault<1_000_000> { +LL | | Default::default() +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:38:1 + | +LL | / fn large_fn_arg(x: ArrayDefault<1_000_000>) { +LL | | black_box(&x); +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + +error: aborting due to 3 previous errors + diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index 2c22abd7e4b14..fafee6a0d41d5 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::len_without_is_empty)] +#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index a011ff976448b..6a9006c477999 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::len_without_is_empty)] +#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs index 2c313ff35d59d..431d83778e34f 100644 --- a/tests/ui/let_underscore_untyped.rs +++ b/tests/ui/let_underscore_untyped.rs @@ -1,4 +1,4 @@ -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::let_underscore_untyped)] diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index 7c1835e8cd18f..8214176cfd576 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -1,19 +1,42 @@ +//@aux-build: proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::let_with_type_underscore)] -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_late_init)] + +extern crate proc_macros; fn func() -> &'static str { "" } +#[rustfmt::skip] fn main() { // Will lint let x: _ = 1; let _: _ = 2; let x: _ = func(); + let x: _; + x = (); let x = 1; // Will not lint, Rust infers this to an integer before Clippy let x = func(); let x: Vec<_> = Vec::::new(); let x: [_; 1] = [1]; + let x : _ = 1; + + // Do not lint from procedural macros + proc_macros::with_span! { + span + let x: _ = (); + // Late initialization + let x: _; + x = (); + // Ensure weird formatting will not break it (hopefully) + let x : _ = 1; + let x +: _ = 1; + let x : + _; + x = (); + }; } diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr index 16bf83c708fe8..a749552c7fac8 100644 --- a/tests/ui/let_with_type_underscore.stderr +++ b/tests/ui/let_with_type_underscore.stderr @@ -1,39 +1,63 @@ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:11:5 + --> $DIR/let_with_type_underscore.rs:15:5 | LL | let x: _ = 1; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:11:10 + --> $DIR/let_with_type_underscore.rs:15:10 | LL | let x: _ = 1; | ^^^ = note: `-D clippy::let-with-type-underscore` implied by `-D warnings` error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:12:5 + --> $DIR/let_with_type_underscore.rs:16:5 | LL | let _: _ = 2; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:12:10 + --> $DIR/let_with_type_underscore.rs:16:10 | LL | let _: _ = 2; | ^^^ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:13:5 + --> $DIR/let_with_type_underscore.rs:17:5 | LL | let x: _ = func(); | ^^^^^^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:13:10 + --> $DIR/let_with_type_underscore.rs:17:10 | LL | let x: _ = func(); | ^^^ -error: aborting due to 3 previous errors +error: variable declared with type underscore + --> $DIR/let_with_type_underscore.rs:18:5 + | +LL | let x: _; + | ^^^^^^^^^ + | +help: remove the explicit type `_` declaration + --> $DIR/let_with_type_underscore.rs:18:10 + | +LL | let x: _; + | ^^^ + +error: variable declared with type underscore + --> $DIR/let_with_type_underscore.rs:25:5 + | +LL | let x : _ = 1; + | ^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + --> $DIR/let_with_type_underscore.rs:25:10 + | +LL | let x : _ = 1; + | ^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed index a208857561030..e19f4980cd70d 100644 --- a/tests/ui/lossy_float_literal.fixed +++ b/tests/ui/lossy_float_literal.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::lossy_float_literal)] +#![allow(overflowing_literals, unused)] fn main() { // Lossy whole-number float literals @@ -32,4 +33,7 @@ fn main() { let _: f64 = 1e99; let _: f64 = 1E99; let _: f32 = 0.1; + + const INF1: f32 = 1000000000000000000000000000000000f32; + const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32; } diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs index 1a75f214c856f..a2a1cfb317e11 100644 --- a/tests/ui/lossy_float_literal.rs +++ b/tests/ui/lossy_float_literal.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::lossy_float_literal)] +#![allow(overflowing_literals, unused)] fn main() { // Lossy whole-number float literals @@ -32,4 +33,7 @@ fn main() { let _: f64 = 1e99; let _: f64 = 1E99; let _: f32 = 0.1; + + const INF1: f32 = 1000000000000000000000000000000000f32; + const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32; } diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr index d2193c0c81955..2d72b16430c40 100644 --- a/tests/ui/lossy_float_literal.stderr +++ b/tests/ui/lossy_float_literal.stderr @@ -1,5 +1,5 @@ error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:6:18 + --> $DIR/lossy_float_literal.rs:7:18 | LL | let _: f32 = 16_777_217.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` @@ -7,61 +7,61 @@ LL | let _: f32 = 16_777_217.0; = note: `-D clippy::lossy-float-literal` implied by `-D warnings` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:7:18 + --> $DIR/lossy_float_literal.rs:8:18 | LL | let _: f32 = 16_777_219.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:8:18 + --> $DIR/lossy_float_literal.rs:9:18 | LL | let _: f32 = 16_777_219.; | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:9:18 + --> $DIR/lossy_float_literal.rs:10:18 | LL | let _: f32 = 16_777_219.000; | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:10:13 + --> $DIR/lossy_float_literal.rs:11:13 | LL | let _ = 16_777_219f32; | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:11:19 + --> $DIR/lossy_float_literal.rs:12:19 | LL | let _: f32 = -16_777_219.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:12:18 + --> $DIR/lossy_float_literal.rs:13:18 | LL | let _: f64 = 9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:13:18 + --> $DIR/lossy_float_literal.rs:14:18 | LL | let _: f64 = 9_007_199_254_740_993.; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:14:18 + --> $DIR/lossy_float_literal.rs:15:18 | LL | let _: f64 = 9_007_199_254_740_993.00; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:15:13 + --> $DIR/lossy_float_literal.rs:16:13 | LL | let _ = 9_007_199_254_740_993f64; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:16:19 + --> $DIR/lossy_float_literal.rs:17:19 | LL | let _: f64 = -9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index b4dabe3cae5d3..53b6a0250f99a 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix //@ignore-32bit diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 925a2c61f8d20..a40fa389895aa 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix //@ignore-32bit diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 6fd338cef8688..67a833e85e046 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,28 +1,28 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:25:5 + --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:21:5 + --> $DIR/macro_use_imports.rs:23:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:23:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 + --> $DIR/macro_use_imports.rs:21:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: aborting due to 4 previous errors diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs index b9677851b92de..3971aadbef853 100644 --- a/tests/ui/macro_use_imports_expect.rs +++ b/tests/ui/macro_use_imports_expect.rs @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@ignore-32bit #![feature(lint_reasons)] diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed index ab9b375dc03d5..d8dde0236eae1 100644 --- a/tests/ui/manual_assert.edition2018.fixed +++ b/tests/ui/manual_assert.edition2018.fixed @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed index ab9b375dc03d5..d8dde0236eae1 100644 --- a/tests/ui/manual_assert.edition2021.fixed +++ b/tests/ui/manual_assert.edition2021.fixed @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index eac52d1b5de57..0f87d6e2d2c93 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index e458f0d254f66..e609b4b1bdb03 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::manual_async_fn)] -#![allow(unused)] +#![allow(clippy::needless_pub_self, unused)] use std::future::Future; diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index dd5ca1c9b5b7e..6c1a9edaa110d 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::manual_async_fn)] -#![allow(unused)] +#![allow(clippy::needless_pub_self, unused)] use std::future::Future; diff --git a/tests/ui/manual_filter.fixed b/tests/ui/manual_filter.fixed index 755caa664d59a..5e3b12e510b84 100644 --- a/tests/ui/manual_filter.fixed +++ b/tests/ui/manual_filter.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::manual_filter)] -#![allow(unused_variables, dead_code)] +#![allow(unused_variables, dead_code, clippy::useless_vec)] fn main() { Some(0).filter(|&x| x <= 0); diff --git a/tests/ui/manual_filter.rs b/tests/ui/manual_filter.rs index faccfe9db12a6..b81604b0372b5 100644 --- a/tests/ui/manual_filter.rs +++ b/tests/ui/manual_filter.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::manual_filter)] -#![allow(unused_variables, dead_code)] +#![allow(unused_variables, dead_code, clippy::useless_vec)] fn main() { match Some(0) { diff --git a/tests/ui/manual_filter_map.fixed b/tests/ui/manual_filter_map.fixed index 831323089e7f2..9dd376df2b48a 100644 --- a/tests/ui/manual_filter_map.fixed +++ b/tests/ui/manual_filter_map.fixed @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_filter_map.rs b/tests/ui/manual_filter_map.rs index 2692303d31382..6dd1e066aebdb 100644 --- a/tests/ui/manual_filter_map.rs +++ b/tests/ui/manual_filter_map.rs @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_filter_map.stderr b/tests/ui/manual_filter_map.stderr index 6e5bbe8f2aaf5..882468b0f5f19 100644 --- a/tests/ui/manual_filter_map.stderr +++ b/tests/ui/manual_filter_map.stderr @@ -1,5 +1,5 @@ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:8:19 + --> $DIR/manual_filter_map.rs:9:19 | LL | let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))` @@ -7,19 +7,19 @@ LL | let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap = note: `-D clippy::manual-filter-map` implied by `-D warnings` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:11:19 + --> $DIR/manual_filter_map.rs:12:19 | LL | let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:14:19 + --> $DIR/manual_filter_map.rs:15:19 | LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:17:10 + --> $DIR/manual_filter_map.rs:18:10 | LL | .filter(|&x| to_ref(to_opt(x)).is_some()) | __________^ @@ -27,7 +27,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:20:10 + --> $DIR/manual_filter_map.rs:21:10 | LL | .filter(|x| to_ref(to_opt(*x)).is_some()) | __________^ @@ -35,7 +35,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:24:10 + --> $DIR/manual_filter_map.rs:25:10 | LL | .filter(|&x| to_ref(to_res(x)).is_ok()) | __________^ @@ -43,7 +43,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:27:10 + --> $DIR/manual_filter_map.rs:28:10 | LL | .filter(|x| to_ref(to_res(*x)).is_ok()) | __________^ @@ -51,7 +51,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:33:27 + --> $DIR/manual_filter_map.rs:34:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` @@ -59,67 +59,67 @@ LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap() = note: `-D clippy::manual-find-map` implied by `-D warnings` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:34:28 + --> $DIR/manual_filter_map.rs:35:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:35:31 + --> $DIR/manual_filter_map.rs:36:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:36:31 + --> $DIR/manual_filter_map.rs:37:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:38:30 + --> $DIR/manual_filter_map.rs:39:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:39:31 + --> $DIR/manual_filter_map.rs:40:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:40:32 + --> $DIR/manual_filter_map.rs:41:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:41:31 + --> $DIR/manual_filter_map.rs:42:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:42:32 + --> $DIR/manual_filter_map.rs:43:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:43:35 + --> $DIR/manual_filter_map.rs:44:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:44:35 + --> $DIR/manual_filter_map.rs:45:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:92:10 + --> $DIR/manual_filter_map.rs:93:10 | LL | .filter(|f| f.option_field.is_some()) | __________^ @@ -127,7 +127,7 @@ LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.option_field.clone())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:97:10 + --> $DIR/manual_filter_map.rs:98:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ @@ -135,7 +135,7 @@ LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.cloned())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:102:10 + --> $DIR/manual_filter_map.rs:103:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ @@ -143,7 +143,7 @@ LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.copied())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:107:10 + --> $DIR/manual_filter_map.rs:108:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -151,7 +151,7 @@ LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.result_field.clone().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:112:10 + --> $DIR/manual_filter_map.rs:113:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -159,7 +159,7 @@ LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_ref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:117:10 + --> $DIR/manual_filter_map.rs:118:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -167,7 +167,7 @@ LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:122:10 + --> $DIR/manual_filter_map.rs:123:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -175,7 +175,7 @@ LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:127:10 + --> $DIR/manual_filter_map.rs:128:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -183,7 +183,7 @@ LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:132:10 + --> $DIR/manual_filter_map.rs:133:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ diff --git a/tests/ui/manual_find_map.fixed b/tests/ui/manual_find_map.fixed index 554613a30a9ea..0c8eebf04b5c0 100644 --- a/tests/ui/manual_find_map.fixed +++ b/tests/ui/manual_find_map.fixed @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_find_map.rs b/tests/ui/manual_find_map.rs index d6245758f9d09..b2feb48a839b7 100644 --- a/tests/ui/manual_find_map.rs +++ b/tests/ui/manual_find_map.rs @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_find_map.stderr b/tests/ui/manual_find_map.stderr index c1ac499f7c601..693a06bb5590b 100644 --- a/tests/ui/manual_find_map.stderr +++ b/tests/ui/manual_find_map.stderr @@ -1,5 +1,5 @@ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:8:19 + --> $DIR/manual_find_map.rs:9:19 | LL | let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))` @@ -7,19 +7,19 @@ LL | let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap() = note: `-D clippy::manual-find-map` implied by `-D warnings` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:11:19 + --> $DIR/manual_find_map.rs:12:19 | LL | let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:14:19 + --> $DIR/manual_find_map.rs:15:19 | LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:17:10 + --> $DIR/manual_find_map.rs:18:10 | LL | .find(|&x| to_ref(to_opt(x)).is_some()) | __________^ @@ -27,7 +27,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:20:10 + --> $DIR/manual_find_map.rs:21:10 | LL | .find(|x| to_ref(to_opt(*x)).is_some()) | __________^ @@ -35,7 +35,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:24:10 + --> $DIR/manual_find_map.rs:25:10 | LL | .find(|&x| to_ref(to_res(x)).is_ok()) | __________^ @@ -43,7 +43,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:27:10 + --> $DIR/manual_find_map.rs:28:10 | LL | .find(|x| to_ref(to_res(*x)).is_ok()) | __________^ @@ -51,91 +51,91 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:33:26 + --> $DIR/manual_find_map.rs:34:26 | LL | iter::>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:34:27 + --> $DIR/manual_find_map.rs:35:27 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| *x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:35:28 + --> $DIR/manual_find_map.rs:36:28 | LL | iter::<&&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| **x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:36:27 + --> $DIR/manual_find_map.rs:37:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:37:28 + --> $DIR/manual_find_map.rs:38:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:38:31 + --> $DIR/manual_find_map.rs:39:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:39:31 + --> $DIR/manual_find_map.rs:40:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:41:30 + --> $DIR/manual_find_map.rs:42:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:42:31 + --> $DIR/manual_find_map.rs:43:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:43:32 + --> $DIR/manual_find_map.rs:44:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:44:31 + --> $DIR/manual_find_map.rs:45:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:45:32 + --> $DIR/manual_find_map.rs:46:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:46:35 + --> $DIR/manual_find_map.rs:47:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:47:35 + --> $DIR/manual_find_map.rs:48:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:95:10 + --> $DIR/manual_find_map.rs:96:10 | LL | .find(|f| f.option_field.is_some()) | __________^ @@ -143,7 +143,7 @@ LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.option_field.clone())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:100:10 + --> $DIR/manual_find_map.rs:101:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ @@ -151,7 +151,7 @@ LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:105:10 + --> $DIR/manual_find_map.rs:106:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ @@ -159,7 +159,7 @@ LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.copied())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:110:10 + --> $DIR/manual_find_map.rs:111:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -167,7 +167,7 @@ LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.result_field.clone().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:115:10 + --> $DIR/manual_find_map.rs:116:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -175,7 +175,7 @@ LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_ref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:120:10 + --> $DIR/manual_find_map.rs:121:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -183,7 +183,7 @@ LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:125:10 + --> $DIR/manual_find_map.rs:126:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -191,7 +191,7 @@ LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:130:10 + --> $DIR/manual_find_map.rs:131:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -199,7 +199,7 @@ LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:135:10 + --> $DIR/manual_find_map.rs:136:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 351ea0e4f509e..46241afec9472 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -4,7 +4,8 @@ clippy::unused_unit, clippy::let_unit_value, clippy::match_single_binding, - clippy::never_loop + clippy::never_loop, + clippy::needless_if )] #![warn(clippy::manual_let_else)] @@ -127,8 +128,8 @@ fn fire() { return; }; - // Tuples supported for the identity block and pattern - let v = if let (Some(v_some), w_some) = (g(), 0) { + // Tuples supported with multiple bindings + let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { (w_some, v_some) } else { return; @@ -160,6 +161,30 @@ fn fire() { }; // dot dot works let v = if let Variant::A(.., a) = e() { a } else { return }; + + // () is preserved: a bit of an edge case but make sure it stays around + let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; + + // Tuple structs work + let w = if let Some(S { v: x }) = Some(S { v: 0 }) { + x + } else { + return; + }; + + // Field init shorthand is suggested + let v = if let Some(S { v: x }) = Some(S { v: 0 }) { + x + } else { + return; + }; + + // Multi-field structs also work + let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { + (x, v, w) + } else { + return; + }; } fn not_fire() { @@ -284,4 +309,23 @@ fn not_fire() { }; 1 }; + + // This would require creation of a suggestion of the form + // let v @ (Some(_), _) = (...) else { return }; + // Which is too advanced for our code, so we just bail. + let v = if let (Some(v_some), w_some) = (g(), 0) { + (w_some, v_some) + } else { + return; + }; +} + +struct S { + v: T, +} + +struct U { + v: T, + w: T, + x: T, } diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 0e87679713474..1eada4f992ec5 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` - --> $DIR/manual_let_else.rs:24:5 + --> $DIR/manual_let_else.rs:25:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -7,7 +7,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = note: `-D clippy::manual-let-else` implied by `-D warnings` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:25:5 + --> $DIR/manual_let_else.rs:26:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -24,7 +24,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:31:5 + --> $DIR/manual_let_else.rs:32:5 | LL | / let v = if let Some(v) = g() { LL | | // Blocks around the identity should have no impact @@ -45,25 +45,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:44:9 + --> $DIR/manual_let_else.rs:45: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` - --> $DIR/manual_let_else.rs:45:9 + --> $DIR/manual_let_else.rs:46: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` - --> $DIR/manual_let_else.rs:49:5 + --> $DIR/manual_let_else.rs:50: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` - --> $DIR/manual_let_else.rs:52:5 + --> $DIR/manual_let_else.rs:53:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -80,7 +80,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:59:5 + --> $DIR/manual_let_else.rs:60:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -97,7 +97,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:66:5 + --> $DIR/manual_let_else.rs:67:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -116,7 +116,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:76:5 + --> $DIR/manual_let_else.rs:77:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -138,13 +138,13 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:86:5 + --> $DIR/manual_let_else.rs:87:5 | LL | let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:89:5 + --> $DIR/manual_let_else.rs:90:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -165,7 +165,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:98:5 + --> $DIR/manual_let_else.rs:99:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -186,7 +186,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:107:5 + --> $DIR/manual_let_else.rs:108:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -215,7 +215,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:124:5 + --> $DIR/manual_let_else.rs:125:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | v_some @@ -232,9 +232,9 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:131:5 + --> $DIR/manual_let_else.rs:132:5 | -LL | / let v = if let (Some(v_some), w_some) = (g(), 0) { +LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | (w_some, v_some) LL | | } else { LL | | return; @@ -243,13 +243,13 @@ LL | | }; | help: consider writing | -LL ~ let (Some(v_some), w_some) = (g(), 0) else { +LL ~ let (Some(S { v }), w) = (g().map(|_| S { v: 0 }), 0) else { LL + return; LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:140:13 + --> $DIR/manual_let_else.rs:141:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -260,19 +260,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` - --> $DIR/manual_let_else.rs:149:5 + --> $DIR/manual_let_else.rs:150: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` - --> $DIR/manual_let_else.rs:152:5 + --> $DIR/manual_let_else.rs:153: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` - --> $DIR/manual_let_else.rs:156:5 + --> $DIR/manual_let_else.rs:157:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | b @@ -289,13 +289,70 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:162:5 + --> $DIR/manual_let_else.rs:163: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` - --> $DIR/manual_let_else.rs:272:5 + --> $DIR/manual_let_else.rs:166: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` + --> $DIR/manual_let_else.rs:169:5 + | +LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { +LL | | x +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(S { v: w }) = Some(S { v: 0 }) else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:176:5 + | +LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { +LL | | x +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(S { v }) = Some(S { v: 0 }) else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:183:5 + | +LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { +LL | | (x, v, w) +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(U { v: S { v }, w, x }) = None::>> else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:297:5 | LL | / let _ = match ff { LL | | Some(value) => value, @@ -303,5 +360,5 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 22 previous errors +error: aborting due to 26 previous errors diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index dfca3b023cd58..73ff69eec4ed7 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -1,5 +1,9 @@ #![allow(unused_braces, unused_variables, dead_code)] -#![allow(clippy::collapsible_else_if, clippy::let_unit_value)] +#![allow( + clippy::collapsible_else_if, + clippy::let_unit_value, + clippy::redundant_at_rest_pattern +)] #![warn(clippy::manual_let_else)] // Ensure that we don't conflict with match -> if let lints #![warn(clippy::single_match_else, clippy::single_match)] @@ -72,6 +76,11 @@ fn fire() { _ => return, }; + let _value = match Some(build_enum()) { + Some(Variant::Bar(v) | Variant::Baz(v)) => v, + _ => return, + }; + let data = [1_u8, 2, 3, 4, 0, 0, 0, 0]; let data = match data.as_slice() { [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index 13ed35bc1d5db..3fd9a637605b5 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:32:5 + --> $DIR/manual_let_else_match.rs:36:5 | LL | / let v = match g() { LL | | Some(v_some) => v_some, @@ -10,7 +10,7 @@ LL | | }; = note: `-D clippy::manual-let-else` implied by `-D warnings` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:37:5 + --> $DIR/manual_let_else_match.rs:41:5 | LL | / let v = match g() { LL | | Some(v_some) => v_some, @@ -19,7 +19,7 @@ LL | | }; | |______^ help: consider writing: `let Some(v) = g() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:44:9 + --> $DIR/manual_let_else_match.rs:48:9 | LL | / let v = match h() { LL | | (Some(v), None) | (None, Some(v)) => v, @@ -28,7 +28,7 @@ LL | | }; | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:49:9 + --> $DIR/manual_let_else_match.rs:53:9 | LL | / let v = match build_enum() { LL | | Variant::Bar(v) | Variant::Baz(v) => v, @@ -37,7 +37,7 @@ LL | | }; | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:57:5 + --> $DIR/manual_let_else_match.rs:61:5 | LL | / let v = match f() { LL | | Ok(v) => v, @@ -46,7 +46,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:63:5 + --> $DIR/manual_let_else_match.rs:67:5 | LL | / let v = match f().map_err(|_| ()) { LL | | Ok(v) => v, @@ -55,7 +55,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:70:5 + --> $DIR/manual_let_else_match.rs:74:5 | LL | / let _value = match f { LL | | Variant::Bar(v) | Variant::Baz(v) => v, @@ -64,7 +64,16 @@ LL | | }; | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:76:5 + --> $DIR/manual_let_else_match.rs:79:5 + | +LL | / let _value = match Some(build_enum()) { +LL | | Some(Variant::Bar(v) | Variant::Baz(v)) => v, +LL | | _ => return, +LL | | }; + | |______^ help: consider writing: `let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return };` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_match.rs:85:5 | LL | / let data = match data.as_slice() { LL | | [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, @@ -72,5 +81,5 @@ LL | | _ => return, LL | | }; | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/manual_memcpy/without_loop_counters.rs b/tests/ui/manual_memcpy/without_loop_counters.rs index ea0535d076b81..4d5c70f19a064 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/tests/ui/manual_memcpy/without_loop_counters.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_range_loop, clippy::manual_memcpy)] +#![allow(clippy::useless_vec)] const LOOP_OFFSET: usize = 5000; diff --git a/tests/ui/manual_memcpy/without_loop_counters.stderr b/tests/ui/manual_memcpy/without_loop_counters.stderr index c163ae061dfc9..1c6a7d5c04e0a 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.stderr +++ b/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -1,5 +1,5 @@ error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:7:5 + --> $DIR/without_loop_counters.rs:8:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i]; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:12:5 + --> $DIR/without_loop_counters.rs:13:5 | LL | / for i in 0..src.len() { LL | | dst[i + 10] = src[i]; @@ -17,7 +17,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:17:5 + --> $DIR/without_loop_counters.rs:18:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i + 10]; @@ -25,7 +25,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:22:5 + --> $DIR/without_loop_counters.rs:23:5 | LL | / for i in 11..src.len() { LL | | dst[i] = src[i - 10]; @@ -33,7 +33,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:27:5 + --> $DIR/without_loop_counters.rs:28:5 | LL | / for i in 0..dst.len() { LL | | dst[i] = src[i]; @@ -41,7 +41,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:40:5 + --> $DIR/without_loop_counters.rs:41:5 | LL | / for i in 10..256 { LL | | dst[i] = src[i - 5]; @@ -56,7 +56,7 @@ LL + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); | error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:52:5 + --> $DIR/without_loop_counters.rs:53:5 | LL | / for i in 10..LOOP_OFFSET { LL | | dst[i + LOOP_OFFSET] = src[i - some_var]; @@ -64,7 +64,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:65:5 + --> $DIR/without_loop_counters.rs:66:5 | LL | / for i in 0..src_vec.len() { LL | | dst_vec[i] = src_vec[i]; @@ -72,7 +72,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:94:5 + --> $DIR/without_loop_counters.rs:95:5 | LL | / for i in from..from + src.len() { LL | | dst[i] = src[i - from]; @@ -80,7 +80,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:98:5 + --> $DIR/without_loop_counters.rs:99:5 | LL | / for i in from..from + 3 { LL | | dst[i] = src[i - from]; @@ -88,7 +88,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:103:5 + --> $DIR/without_loop_counters.rs:104:5 | LL | / for i in 0..5 { LL | | dst[i - 0] = src[i]; @@ -96,7 +96,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src[..5]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:108:5 + --> $DIR/without_loop_counters.rs:109:5 | LL | / for i in 0..0 { LL | | dst[i] = src[i]; @@ -104,7 +104,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:131:5 + --> $DIR/without_loop_counters.rs:132:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i].clone(); diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed new file mode 100644 index 0000000000000..9eee8f371874a --- /dev/null +++ b/tests/ui/manual_range_patterns.fixed @@ -0,0 +1,35 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + let f = 6; + + let _ = matches!(f, 1..=10); + let _ = matches!(f, 1..=10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing + let _ = matches!(f, | 4); + let _ = matches!(f, 4 | 5); + let _ = matches!(f, 1 | 2147483647); + let _ = matches!(f, 0 | 2147483647); + let _ = matches!(f, -2147483647 | 2147483647); + let _ = matches!(f, 1 | (2..=4)); + let _ = matches!(f, 1 | (2..4)); + let _ = matches!(f, 1..=48324729); + let _ = matches!(f, 0..=48324730); + let _ = matches!(f, 0..=3); + #[allow(clippy::match_like_matches_macro)] + let _ = match f { + 1..=10 => true, + _ => false, + }; + + macro_rules! mac { + ($e:expr) => { + matches!($e, 1..=10) + }; + } + mac!(f); +} diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs new file mode 100644 index 0000000000000..10743a7d04c66 --- /dev/null +++ b/tests/ui/manual_range_patterns.rs @@ -0,0 +1,35 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + let f = 6; + + let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing + let _ = matches!(f, | 4); + let _ = matches!(f, 4 | 5); + let _ = matches!(f, 1 | 2147483647); + let _ = matches!(f, 0 | 2147483647); + let _ = matches!(f, -2147483647 | 2147483647); + let _ = matches!(f, 1 | (2..=4)); + let _ = matches!(f, 1 | (2..4)); + let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); + let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); + let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); + #[allow(clippy::match_like_matches_macro)] + let _ = match f { + 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, + _ => false, + }; + + macro_rules! mac { + ($e:expr) => { + matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) + }; + } + mac!(f); +} diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr new file mode 100644 index 0000000000000..bc9e335016457 --- /dev/null +++ b/tests/ui/manual_range_patterns.stderr @@ -0,0 +1,51 @@ +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:10:25 + | +LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + | + = note: `-D clippy::manual-range-patterns` implied by `-D warnings` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:11:25 + | +LL | let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:20:25 + | +LL | let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:21:25 + | +LL | let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:22:25 + | +LL | let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:25:9 + | +LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:31:26 + | +LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` +... +LL | mac!(f); + | ------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index f2e44e56f0205..594a76897bbe2 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::manual_rem_euclid)] #![allow(clippy::let_with_type_underscore)] diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index b2329c33a47d5..d5f98e71517ee 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::manual_rem_euclid)] #![allow(clippy::let_with_type_underscore)] diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed index ac85bd8d3acac..5b9629f4bc10f 100644 --- a/tests/ui/manual_slice_size_calculation.fixed +++ b/tests/ui/manual_slice_size_calculation.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::manual_slice_size_calculation)] diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs index 1f824b12bc263..297887a9cfc82 100644 --- a/tests/ui/manual_slice_size_calculation.rs +++ b/tests/ui/manual_slice_size_calculation.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::manual_slice_size_calculation)] diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs new file mode 100644 index 0000000000000..4521e9fa1a502 --- /dev/null +++ b/tests/ui/manual_try_fold.rs @@ -0,0 +1,100 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::unnecessary_fold, unused)] +#![warn(clippy::manual_try_fold)] +#![feature(try_trait_v2)] + +use std::ops::ControlFlow; +use std::ops::FromResidual; +use std::ops::Try; + +#[macro_use] +extern crate proc_macros; + +// Test custom `Try` with more than 1 argument +struct NotOption(i32, i32); + +impl FromResidual for NotOption { + fn from_residual(_: R) -> Self { + todo!() + } +} + +impl Try for NotOption { + type Output = (); + type Residual = (); + + fn from_output(_: Self::Output) -> Self { + todo!() + } + + fn branch(self) -> ControlFlow { + todo!() + } +} + +// Test custom `Try` with only 1 argument +#[derive(Default)] +struct NotOptionButWorse(i32); + +impl FromResidual for NotOptionButWorse { + fn from_residual(_: R) -> Self { + todo!() + } +} + +impl Try for NotOptionButWorse { + type Output = (); + type Residual = (); + + fn from_output(_: Self::Output) -> Self { + todo!() + } + + fn branch(self) -> ControlFlow { + todo!() + } +} + +fn main() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); + [1, 2, 3] + .iter() + .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); + [1, 2, 3] + .iter() + .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); + // Do not lint + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + [1, 2, 3].iter().fold(0i32, |sum, i| sum + i); + [1, 2, 3] + .iter() + .fold(NotOptionButWorse::default(), |sum, i| NotOptionButWorse::default()); + external! { + [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap(); + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + } + with_span! { + span + [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap(); + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + } +} + +#[clippy::msrv = "1.26.0"] +fn msrv_too_low() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); +} + +#[clippy::msrv = "1.27.0"] +fn msrv_juust_right() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); +} diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr new file mode 100644 index 0000000000000..a0cf5b3b5fc8a --- /dev/null +++ b/tests/ui/manual_try_fold.stderr @@ -0,0 +1,28 @@ +error: usage of `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:61:10 + | +LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` + | + = note: `-D clippy::manual-try-fold` implied by `-D warnings` + +error: usage of `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:65:10 + | +LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)` + +error: usage of `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:68:10 + | +LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` + +error: usage of `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:98:10 + | +LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index c17634bffe303..20560b87c1a59 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps)] +#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index 6d49a6949fa98..5dbc57565bff3 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps)] +#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] fn option_unwrap_or() { // int case diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index d7474f3571912..50c0eb1a81081 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -4,7 +4,8 @@ clippy::clone_on_copy, clippy::iter_cloned_collect, clippy::many_single_char_names, - clippy::redundant_clone + clippy::redundant_clone, + clippy::useless_vec )] fn main() { diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 74978ae8006d7..91a084f2844dd 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -4,7 +4,8 @@ clippy::clone_on_copy, clippy::iter_cloned_collect, clippy::many_single_char_names, - clippy::redundant_clone + clippy::redundant_clone, + clippy::useless_vec )] fn main() { diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index d84a5bf8d4de6..d768af1f48c97 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 - --> $DIR/map_clone.rs:11:22 + --> $DIR/map_clone.rs:12: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()` @@ -7,31 +7,31 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: you are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:12:26 + --> $DIR/map_clone.rs:13: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 - --> $DIR/map_clone.rs:13:23 + --> $DIR/map_clone.rs:14: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 - --> $DIR/map_clone.rs:15:26 + --> $DIR/map_clone.rs:16: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 - --> $DIR/map_clone.rs:16:25 + --> $DIR/map_clone.rs:17: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 - --> $DIR/map_clone.rs:27:29 + --> $DIR/map_clone.rs:28:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index cb25d8567aa01..bb36cb2c598b7 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -56,6 +56,10 @@ fn option_methods() { .unwrap_or_else(|| 0 ); + + // Check for `map(f).unwrap_or(false)` use. + let _ = opt.map(|x| x > 5).unwrap_or(false); + } #[rustfmt::skip] @@ -94,3 +98,46 @@ fn msrv_1_41() { let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); } + +#[clippy::msrv = "1.69"] +fn msrv_1_69() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + +#[clippy::msrv = "1.70"] +fn msrv_1_70() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + +mod issue_10579 { + // Different variations of the same issue. + fn v1() { + let x = vec![1, 2, 3, 0]; + let y = x.strip_suffix(&[0]).map(|s| s.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v2() { + let x = vec![1, 2, 3, 0]; + let y = Some(()).map(|_| x.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v3() { + let x = vec![1, 2, 3, 0]; + let xref = &x; + let y = Some(()).map(|_| xref.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v4() { + struct VecInStruct { + v: Vec, + } + let s = VecInStruct { v: vec![1, 2, 3, 0] }; + + let y = Some(()).map(|_| s.v.clone()).unwrap_or(s.v); + println!("{y:?}"); + } +} diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index 41781b050fa20..9f4a4a9ae6bf4 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -126,8 +126,20 @@ LL | | 0 LL | | ); | |_________^ +error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead + --> $DIR/map_unwrap_or.rs:61:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_some_and()` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.is_some_and(|x| x > 5); + | + error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:67:13 + --> $DIR/map_unwrap_or.rs:71:13 | LL | let _ = res.map(|x| { | _____________^ @@ -137,7 +149,7 @@ LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:71:13 + --> $DIR/map_unwrap_or.rs:75:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -147,10 +159,34 @@ LL | | }); | |__________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:95:13 + --> $DIR/map_unwrap_or.rs:99:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 12 previous errors +error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead + --> $DIR/map_unwrap_or.rs:106:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.map_or(false, |x| x > 5); + | + +error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead + --> $DIR/map_unwrap_or.rs:113:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_some_and()` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.is_some_and(|x| x > 5); + | + +error: aborting due to 15 previous errors diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index 30415e3b94dc4..cf9c279cd2f16 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -1,4 +1,5 @@ #![warn(clippy::match_on_vec_items)] +#![allow(clippy::redundant_at_rest_pattern, clippy::useless_vec)] fn match_with_wildcard() { let arr = vec![0, 1, 2, 3]; diff --git a/tests/ui/match_on_vec_items.stderr b/tests/ui/match_on_vec_items.stderr index 49446d715abe2..9b1f052867e0f 100644 --- a/tests/ui/match_on_vec_items.stderr +++ b/tests/ui/match_on_vec_items.stderr @@ -1,5 +1,5 @@ error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:9:11 + --> $DIR/match_on_vec_items.rs:10:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` @@ -7,43 +7,43 @@ LL | match arr[idx] { = note: `-D clippy::match-on-vec-items` implied by `-D warnings` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:16:11 + --> $DIR/match_on_vec_items.rs:17:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:29:11 + --> $DIR/match_on_vec_items.rs:30:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:36:11 + --> $DIR/match_on_vec_items.rs:37:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:49:11 + --> $DIR/match_on_vec_items.rs:50:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:56:11 + --> $DIR/match_on_vec_items.rs:57:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:69:11 + --> $DIR/match_on_vec_items.rs:70:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:76:11 + --> $DIR/match_on_vec_items.rs:77:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs index b4097fa96045e..b78c1fd06d44d 100644 --- a/tests/ui/match_overlapping_arm.rs +++ b/tests/ui/match_overlapping_arm.rs @@ -1,7 +1,7 @@ #![feature(exclusive_range_pattern)] #![warn(clippy::match_overlapping_arm)] #![allow(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let)] +#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)] /// Tests for match_overlapping_arm diff --git a/tests/ui/match_same_arms.rs b/tests/ui/match_same_arms.rs index 3914b45464c71..fad6a7db988c4 100644 --- a/tests/ui/match_same_arms.rs +++ b/tests/ui/match_same_arms.rs @@ -8,29 +8,30 @@ pub enum Abc { fn match_same_arms() { let _ = match Abc::A { - Abc::A => 0, + Abc::A => 0, //~ ERROR: this match arm has an identical body to the `_` wildcard arm Abc::B => 1, - _ => 0, //~ ERROR match arms have same body + _ => 0, }; match (1, 2, 3) { - (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body + (1, .., 3) => 42, //~ ERROR: this match arm has an identical body to another arm + (.., 3) => 42, _ => 0, }; let _ = match 42 { 42 => 1, - 51 => 1, //~ ERROR match arms have same body - 41 => 2, - 52 => 2, //~ ERROR match arms have same body + 51 => 1, //~ ERROR: this match arm has an identical body to another arm + 41 => 2, //~ ERROR: this match arm has an identical body to another arm + 52 => 2, _ => 0, }; let _ = match 42 { 1 => 2, - 2 => 2, //~ ERROR 2nd matched arms have same body - 3 => 2, //~ ERROR 3rd matched arms have same body + 2 => 2, //~ ERROR: this match arm has an identical body to another arm + //~^ ERROR: this match arm has an identical body to another arm + 3 => 2, //~ ERROR: this match arm has an identical body to another arm 4 => 3, _ => 0, }; @@ -48,6 +49,7 @@ mod issue4244 { match self { CommandInfo::BuiltIn { name, .. } => name.to_string(), CommandInfo::External { name, .. } => name.to_string(), + //~^ ERROR: this match arm has an identical body to another arm } } } diff --git a/tests/ui/match_same_arms.stderr b/tests/ui/match_same_arms.stderr index db85b5964e842..88b9a20a3726f 100644 --- a/tests/ui/match_same_arms.stderr +++ b/tests/ui/match_same_arms.stderr @@ -8,7 +8,7 @@ LL | Abc::A => 0, note: `_` wildcard arm here --> $DIR/match_same_arms.rs:13:9 | -LL | _ => 0, //~ ERROR match arms have same body +LL | _ => 0, | ^^^^^^ = note: `-D clippy::match-same-arms` implied by `-D warnings` @@ -24,13 +24,13 @@ LL | (1, .., 3) => 42, note: other arm here --> $DIR/match_same_arms.rs:18:9 | -LL | (.., 3) => 42, //~ ERROR match arms have same body +LL | (.., 3) => 42, | ^^^^^^^^^^^^^ error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:24:9 | -LL | 51 => 1, //~ ERROR match arms have same body +LL | 51 => 1, | --^^^^^ | | | help: try merging the arm patterns: `51 | 42` @@ -54,13 +54,13 @@ LL | 41 => 2, note: other arm here --> $DIR/match_same_arms.rs:26:9 | -LL | 52 => 2, //~ ERROR match arms have same body +LL | 52 => 2, | ^^^^^^^ error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:32:9 | -LL | 2 => 2, //~ ERROR 2nd matched arms have same body +LL | 2 => 2, | -^^^^^ | | | help: try merging the arm patterns: `2 | 1` @@ -73,9 +73,9 @@ LL | 1 => 2, | ^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms.rs:33:9 + --> $DIR/match_same_arms.rs:34:9 | -LL | 3 => 2, //~ ERROR 3rd matched arms have same body +LL | 3 => 2, | -^^^^^ | | | help: try merging the arm patterns: `3 | 1` @@ -90,20 +90,20 @@ LL | 1 => 2, error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:32:9 | -LL | 2 => 2, //~ ERROR 2nd matched arms have same body +LL | 2 => 2, | -^^^^^ | | | help: try merging the arm patterns: `2 | 3` | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms.rs:33:9 + --> $DIR/match_same_arms.rs:34:9 | -LL | 3 => 2, //~ ERROR 3rd matched arms have same body +LL | 3 => 2, | ^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms.rs:50:17 + --> $DIR/match_same_arms.rs:51:17 | LL | CommandInfo::External { name, .. } => name.to_string(), | ----------------------------------^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | CommandInfo::External { name, .. } => name.to_string(), | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms.rs:49:17 + --> $DIR/match_same_arms.rs:50:17 | LL | CommandInfo::BuiltIn { name, .. } => name.to_string(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index 60b2975be0454..b1b9a6ae3e8ab 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -13,6 +13,7 @@ fn foo() -> bool { fn match_same_arms() { let _ = match 42 { 42 => { + //~^ ERROR: this match arm has an identical body to the `_` wildcard arm foo(); let mut a = 42 + [23].len() as i32; if true { @@ -22,7 +23,6 @@ fn match_same_arms() { a }, _ => { - //~ ERROR match arms have same body foo(); let mut a = 42 + [23].len() as i32; if true { @@ -35,13 +35,13 @@ fn match_same_arms() { let _ = match 42 { 42 => foo(), - 51 => foo(), //~ ERROR match arms have same body + 51 => foo(), //~ ERROR: this match arm has an identical body to another arm _ => true, }; let _ = match Some(42) { Some(_) => 24, - None => 24, //~ ERROR match arms have same body + None => 24, //~ ERROR: this match arm has an identical body to another arm }; let _ = match Some(42) { @@ -63,13 +63,13 @@ fn match_same_arms() { match (Some(42), Some(42)) { (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), //~ ERROR match arms have same body + (None, Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm _ => (), } match (Some(42), Some(42)) { - (Some(a), ..) => bar(a), - (.., Some(a)) => bar(a), //~ ERROR match arms have same body + (Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (.., Some(a)) => bar(a), _ => (), } @@ -102,7 +102,7 @@ fn match_same_arms() { } match (x, Some(1i32)) { - (Ok(x), Some(_)) => println!("ok {}", x), + (Ok(x), Some(_)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm (Ok(_), Some(x)) => println!("ok {}", x), _ => println!("err"), } @@ -118,7 +118,7 @@ fn match_same_arms() { match x { Ok(_tmp) => println!("ok"), Ok(3) => println!("ok"), - Ok(_) => println!("ok"), + Ok(_) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm Err(_) => { unreachable!(); }, @@ -146,6 +146,7 @@ fn match_same_arms() { empty!(0); }, 1 => { + //~^ ERROR: this match arm has an identical body to another arm empty!(0); }, x => { @@ -195,7 +196,7 @@ fn main() { // Suggest moving `Foo::Z(_)` up. let _ = match Foo::X(0) { - Foo::X(0) => 1, + Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm Foo::X(_) | Foo::Y(_) => 2, Foo::Z(_) => 1, _ => 0, @@ -205,7 +206,7 @@ fn main() { let _ = match Foo::X(0) { Foo::X(0) => 1, Foo::Y(_) | Foo::Z(0) => 2, - Foo::Z(_) => 1, + Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm _ => 0, }; @@ -228,7 +229,7 @@ fn main() { Some(Bar { x: 0, y: 5, .. }) => 1, Some(Bar { y: 10, z: 0, .. }) => 2, None => 50, - Some(Bar { y: 0, x: 5, .. }) => 1, + Some(Bar { y: 0, x: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm _ => 200, }; diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 8fb461bd28667..7f0c70745ac0b 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -2,9 +2,9 @@ error: this match arm has an identical body to the `_` wildcard arm --> $DIR/match_same_arms2.rs:15:9 | LL | / 42 => { +LL | | LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; -LL | | if true { ... | LL | | a LL | | }, @@ -12,12 +12,12 @@ LL | | }, | = help: or try changing either arm body note: `_` wildcard arm here - --> $DIR/match_same_arms2.rs:24:9 + --> $DIR/match_same_arms2.rs:25:9 | LL | / _ => { -LL | | //~ ERROR match arms have same body LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { ... | LL | | a LL | | }, @@ -27,7 +27,7 @@ LL | | }, error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:38:9 | -LL | 51 => foo(), //~ ERROR match arms have same body +LL | 51 => foo(), | --^^^^^^^^^ | | | help: try merging the arm patterns: `51 | 42` @@ -42,7 +42,7 @@ LL | 42 => foo(), error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:44:9 | -LL | None => 24, //~ ERROR match arms have same body +LL | None => 24, | ----^^^^^^ | | | help: try merging the arm patterns: `None | Some(_)` @@ -57,7 +57,7 @@ LL | Some(_) => 24, error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:66:9 | -LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +LL | (None, Some(a)) => bar(a), | ---------------^^^^^^^^^^ | | | help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)` @@ -81,7 +81,7 @@ LL | (Some(a), ..) => bar(a), note: other arm here --> $DIR/match_same_arms2.rs:72:9 | -LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +LL | (.., Some(a)) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm @@ -121,6 +121,7 @@ LL | 1 => { | ^ help: try merging the arm patterns: `1 | 0` | _________| | | +LL | | LL | | empty!(0); LL | | }, | |_________^ @@ -135,7 +136,7 @@ LL | | }, | |_________^ error: match expression looks like `matches!` macro - --> $DIR/match_same_arms2.rs:166:16 + --> $DIR/match_same_arms2.rs:167:16 | LL | let _ans = match x { | ________________^ @@ -148,7 +149,7 @@ LL | | }; = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:198:9 + --> $DIR/match_same_arms2.rs:199:9 | LL | Foo::X(0) => 1, | ---------^^^^^ @@ -157,13 +158,13 @@ LL | Foo::X(0) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:200:9 + --> $DIR/match_same_arms2.rs:201:9 | LL | Foo::Z(_) => 1, | ^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:208:9 + --> $DIR/match_same_arms2.rs:209:9 | LL | Foo::Z(_) => 1, | ---------^^^^^ @@ -172,13 +173,13 @@ LL | Foo::Z(_) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:206:9 + --> $DIR/match_same_arms2.rs:207:9 | LL | Foo::X(0) => 1, | ^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:231:9 + --> $DIR/match_same_arms2.rs:232:9 | LL | Some(Bar { y: 0, x: 5, .. }) => 1, | ----------------------------^^^^^ @@ -187,13 +188,13 @@ LL | Some(Bar { y: 0, x: 5, .. }) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:228:9 + --> $DIR/match_same_arms2.rs:229:9 | LL | Some(Bar { x: 0, y: 5, .. }) => 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:245:9 + --> $DIR/match_same_arms2.rs:246:9 | LL | 1 => cfg!(not_enable), | -^^^^^^^^^^^^^^^^^^^^ @@ -202,7 +203,7 @@ LL | 1 => cfg!(not_enable), | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:244:9 + --> $DIR/match_same_arms2.rs:245:9 | LL | 0 => cfg!(not_enable), | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms_non_exhaustive.rs b/tests/ui/match_same_arms_non_exhaustive.rs new file mode 100644 index 0000000000000..07421173a3381 --- /dev/null +++ b/tests/ui/match_same_arms_non_exhaustive.rs @@ -0,0 +1,58 @@ +#![feature(non_exhaustive_omitted_patterns_lint)] +#![warn(clippy::match_same_arms)] +#![no_main] + +use std::sync::atomic::Ordering; // #[non_exhaustive] enum + +pub fn f(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + #[deny(non_exhaustive_omitted_patterns)] + _ => panic!(), + } +} + +mod f { + #![deny(non_exhaustive_omitted_patterns)] + + use super::*; + + pub fn f(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } + } +} + +// Below should still lint + +pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } +} + +mod g { + use super::*; + + pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } + } +} diff --git a/tests/ui/match_same_arms_non_exhaustive.stderr b/tests/ui/match_same_arms_non_exhaustive.stderr new file mode 100644 index 0000000000000..088f7d5c06242 --- /dev/null +++ b/tests/ui/match_same_arms_non_exhaustive.stderr @@ -0,0 +1,29 @@ +error: this match arm has an identical body to the `_` wildcard arm + --> $DIR/match_same_arms_non_exhaustive.rs:41:9 + | +LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm + | + = help: or try changing either arm body +note: `_` wildcard arm here + --> $DIR/match_same_arms_non_exhaustive.rs:42:9 + | +LL | _ => panic!(), + | ^^^^^^^^^^^^^ + = note: `-D clippy::match-same-arms` implied by `-D warnings` + +error: this match arm has an identical body to the `_` wildcard arm + --> $DIR/match_same_arms_non_exhaustive.rs:54:13 + | +LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm + | + = help: or try changing either arm body +note: `_` wildcard arm here + --> $DIR/match_same_arms_non_exhaustive.rs:55:13 + | +LL | _ => panic!(), + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 7c29bb08e64da..f59ff456bf298 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -5,7 +5,8 @@ clippy::let_unit_value, clippy::no_effect, clippy::toplevel_ref_arg, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Point { diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index c068d5e17c33d..e293bc33c8a93 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -5,7 +5,8 @@ clippy::let_unit_value, clippy::no_effect, clippy::toplevel_ref_arg, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Point { diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 9d16af76c6af9..8998786de7eaf 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -1,5 +1,5 @@ error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:33:5 + --> $DIR/match_single_binding.rs:34:5 | LL | / match (a, b, c) { LL | | (x, y, z) => { @@ -18,7 +18,7 @@ LL + } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:39:5 + --> $DIR/match_single_binding.rs:40:5 | LL | / match (a, b, c) { LL | | (x, y, z) => println!("{} {} {}", x, y, z), @@ -32,7 +32,7 @@ LL + println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:56:5 + --> $DIR/match_single_binding.rs:57:5 | LL | / match a { LL | | _ => println!("whatever"), @@ -40,7 +40,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("whatever");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:60:5 + --> $DIR/match_single_binding.rs:61:5 | LL | / match a { LL | | _ => { @@ -59,7 +59,7 @@ LL + } | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:67:5 + --> $DIR/match_single_binding.rs:68:5 | LL | / match a { LL | | _ => { @@ -81,7 +81,7 @@ LL + } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:77:5 + --> $DIR/match_single_binding.rs:78:5 | LL | / match p { LL | | Point { x, y } => println!("Coords: ({}, {})", x, y), @@ -95,7 +95,7 @@ LL + println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:81:5 + --> $DIR/match_single_binding.rs:82:5 | LL | / match p { LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), @@ -109,7 +109,7 @@ LL + println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:86:5 + --> $DIR/match_single_binding.rs:87:5 | LL | / match x { LL | | ref r => println!("Got a reference to {}", r), @@ -123,7 +123,7 @@ LL + println!("Got a reference to {}", r); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:91:5 + --> $DIR/match_single_binding.rs:92:5 | LL | / match x { LL | | ref mut mr => println!("Got a mutable reference to {}", mr), @@ -137,7 +137,7 @@ LL + println!("Got a mutable reference to {}", mr); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:95:5 + --> $DIR/match_single_binding.rs:96:5 | LL | / let product = match coords() { LL | | Point { x, y } => x * y, @@ -151,7 +151,7 @@ LL + let product = x * y; | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:103:18 + --> $DIR/match_single_binding.rs:104:18 | LL | .map(|i| match i.unwrap() { | __________________^ @@ -168,7 +168,7 @@ LL ~ }) | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:129:5 + --> $DIR/match_single_binding.rs:130:5 | LL | / match x { LL | | // => @@ -177,7 +177,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("Not an array index start")` error: this assignment could be simplified - --> $DIR/match_single_binding.rs:138:5 + --> $DIR/match_single_binding.rs:139:5 | LL | / val = match val.split_at(idx) { LL | | (pre, suf) => { @@ -197,7 +197,7 @@ LL ~ }; | error: this match could be replaced by its scrutinee and body - --> $DIR/match_single_binding.rs:151:16 + --> $DIR/match_single_binding.rs:152:16 | LL | let _ = || match side_effects() { | ________________^ @@ -214,7 +214,7 @@ LL ~ }; | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:157:5 + --> $DIR/match_single_binding.rs:158:5 | LL | / match r { LL | | x => match x { @@ -239,7 +239,7 @@ LL ~ }; | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:170:5 + --> $DIR/match_single_binding.rs:171:5 | LL | / match 1 { LL | | _ => (), @@ -247,7 +247,7 @@ LL | | } | |_____^ help: consider using the match body instead: `();` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:174:13 + --> $DIR/match_single_binding.rs:175:13 | LL | let a = match 1 { | _____________^ @@ -256,7 +256,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:178:5 + --> $DIR/match_single_binding.rs:179:5 | LL | / match 1 { LL | | _ => side_effects(), @@ -264,7 +264,7 @@ LL | | } | |_____^ help: consider using the match body instead: `side_effects();` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:182:13 + --> $DIR/match_single_binding.rs:183:13 | LL | let b = match 1 { | _____________^ @@ -273,7 +273,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:186:5 + --> $DIR/match_single_binding.rs:187:5 | LL | / match 1 { LL | | _ => println!("1"), @@ -281,7 +281,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("1");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:190:13 + --> $DIR/match_single_binding.rs:191:13 | LL | let c = match 1 { | _____________^ @@ -290,7 +290,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `println!("1")` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:195:9 + --> $DIR/match_single_binding.rs:196:9 | LL | / match 1 { LL | | _ => (), @@ -298,7 +298,7 @@ LL | | }, | |_________^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:198:9 + --> $DIR/match_single_binding.rs:199:9 | LL | / match 1 { LL | | _ => side_effects(), @@ -306,7 +306,7 @@ LL | | }, | |_________^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:201:9 + --> $DIR/match_single_binding.rs:202:9 | LL | / match 1 { LL | | _ => println!("1"), diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index edb9d87d032ec..b6c8d9e53d80e 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -19,5 +19,8 @@ fn main() { let eight: Vec = vec![8]; forgetSomething(eight); + let string = String::new(); + std::mem::forget(string); + std::mem::forget(7); } diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index a90d8b1655dc4..8004b2aa8db7a 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -4,6 +4,7 @@ error: usage of `mem::forget` on `Drop` type LL | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | + = note: argument has type `std::sync::Arc` = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of `mem::forget` on `Drop` type @@ -11,12 +12,24 @@ error: usage of `mem::forget` on `Drop` type | LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: argument has type `std::rc::Rc` error: usage of `mem::forget` on `Drop` type --> $DIR/mem_forget.rs:20:5 | LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: argument has type `std::vec::Vec` + +error: usage of `mem::forget` on type with `Drop` fields + --> $DIR/mem_forget.rs:23:5 + | +LL | std::mem::forget(string); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: argument has type `std::string::String` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/mem_replace_macro.rs b/tests/ui/mem_replace_macro.rs index 132873858b7c5..e53342f2ed368 100644 --- a/tests/ui/mem_replace_macro.rs +++ b/tests/ui/mem_replace_macro.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::mem_replace_with_default)] extern crate proc_macros; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index e0e2cac30a286..589eab5cdfc54 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -18,6 +18,7 @@ clippy::wrong_self_convention, clippy::unused_async, clippy::unused_self, + clippy::useless_vec, unused )] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 4643e09e27028..73ec48643e063 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:105:5 + --> $DIR/methods.rs:106:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:126:13 + --> $DIR/methods.rs:127:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/tests/ui/methods_fixable.fixed b/tests/ui/methods_fixable.fixed index dcbed5a4d997f..ce5d19a8b6e8e 100644 --- a/tests/ui/methods_fixable.fixed +++ b/tests/ui/methods_fixable.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::filter_next)] +#![allow(clippy::useless_vec)] /// Checks implementation of `FILTER_NEXT` lint. fn main() { diff --git a/tests/ui/methods_fixable.rs b/tests/ui/methods_fixable.rs index 3a976d235276a..0615817ec925d 100644 --- a/tests/ui/methods_fixable.rs +++ b/tests/ui/methods_fixable.rs @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::filter_next)] +#![allow(clippy::useless_vec)] /// Checks implementation of `FILTER_NEXT` lint. fn main() { diff --git a/tests/ui/methods_fixable.stderr b/tests/ui/methods_fixable.stderr index 852f48e32d678..187714c75fb95 100644 --- a/tests/ui/methods_fixable.stderr +++ b/tests/ui/methods_fixable.stderr @@ -1,5 +1,5 @@ error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods_fixable.rs:10:13 + --> $DIR/methods_fixable.rs:11:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)` diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs new file mode 100644 index 0000000000000..b5b9e66aa7a02 --- /dev/null +++ b/tests/ui/min_ident_chars.rs @@ -0,0 +1,84 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(irrefutable_let_patterns, nonstandard_style, unused)] +#![warn(clippy::min_ident_chars)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +struct A { + a: u32, + i: u32, + A: u32, + I: u32, +} + +struct B(u32); + +struct O { + o: u32, +} + +struct i; + +enum C { + D, + E, + F, + j, +} + +struct Vec4 { + x: u32, + y: u32, + z: u32, + w: u32, +} + +struct AA(T, E); + +fn main() { + // Allowed idents + let w = 1; + // Ok, not this one + // let i = 1; + let j = 1; + let n = 1; + let z = 1; + let y = 1; + let z = 1; + // Implicitly disallowed idents + let h = 1; + let e = 2; + let l = 3; + let l = 4; + let o = 6; + // 2 len does not lint + let hi = 0; + // Lint + let (h, o, w) = (1, 2, 3); + for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + let you = Vec4 { x: 1, y: 2, z: 3, w: 4 }; + while let (d, o, _i, n, g) = (true, true, false, false, true) {} + let today = true; + // Ideally this wouldn't lint, but this would (likely) require global analysis, outta scope + // of this lint regardless + let o = 1; + let o = O { o }; + + for j in 0..1000 {} + for _ in 0..10 {} + + // Do not lint code from external macros + external! { for j in 0..1000 {} } + // Do not lint code from procedural macros + with_span! { + span + for j in 0..1000 {} + } +} + +fn b() {} +fn wrong_pythagoras(a: f32, b: f32) -> f32 { + a * a + a * b +} diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr new file mode 100644 index 0000000000000..66a63f6575656 --- /dev/null +++ b/tests/ui/min_ident_chars.stderr @@ -0,0 +1,178 @@ +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:9:8 + | +LL | struct A { + | ^ + | + = note: `-D clippy::min-ident-chars` implied by `-D warnings` + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:10:5 + | +LL | a: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:12:5 + | +LL | A: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:13:5 + | +LL | I: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:16:8 + | +LL | struct B(u32); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:18:8 + | +LL | struct O { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:19:5 + | +LL | o: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:24:6 + | +LL | enum C { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:25:5 + | +LL | D, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:26:5 + | +LL | E, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:27:5 + | +LL | F, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:51:9 + | +LL | let h = 1; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:52:9 + | +LL | let e = 2; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:53:9 + | +LL | let l = 3; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:54:9 + | +LL | let l = 4; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:55:9 + | +LL | let o = 6; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:59:10 + | +LL | let (h, o, w) = (1, 2, 3); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:59:13 + | +LL | let (h, o, w) = (1, 2, 3); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:10 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:14 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:17 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:16 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:19 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:29 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:66:9 + | +LL | let o = 1; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:67:9 + | +LL | let o = O { o }; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:81:4 + | +LL | fn b() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:82:21 + | +LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:82:29 + | +LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { + | ^ + +error: aborting due to 29 previous errors + diff --git a/tests/ui/missing_assert_message.rs b/tests/ui/missing_assert_message.rs index 89404ca882718..af1358f61b5cb 100644 --- a/tests/ui/missing_assert_message.rs +++ b/tests/ui/missing_assert_message.rs @@ -7,8 +7,6 @@ macro_rules! bar { }; } -fn main() {} - // Should trigger warning fn asserts_without_message() { assert!(foo()); @@ -66,9 +64,14 @@ fn asserts_without_message_but_inside_a_test_function() { debug_assert_ne!(foo(), foo()); } +fn foo() -> bool { + true +} + // Should not trigger warning #[cfg(test)] mod tests { + use super::foo; fn asserts_without_message_but_inside_a_test_module() { assert!(foo()); assert_eq!(foo(), foo()); @@ -78,7 +81,3 @@ mod tests { debug_assert_ne!(foo(), foo()); } } - -fn foo() -> bool { - true -} diff --git a/tests/ui/missing_assert_message.stderr b/tests/ui/missing_assert_message.stderr index ecd0380127797..33a5c1f8e0526 100644 --- a/tests/ui/missing_assert_message.stderr +++ b/tests/ui/missing_assert_message.stderr @@ -1,5 +1,5 @@ error: assert without any message - --> $DIR/missing_assert_message.rs:14:5 + --> $DIR/missing_assert_message.rs:12:5 | LL | assert!(foo()); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | assert!(foo()); = note: `-D clippy::missing-assert-message` implied by `-D warnings` error: assert without any message - --> $DIR/missing_assert_message.rs:15:5 + --> $DIR/missing_assert_message.rs:13:5 | LL | assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:16:5 + --> $DIR/missing_assert_message.rs:14:5 | LL | assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:17:5 + --> $DIR/missing_assert_message.rs:15:5 | LL | debug_assert!(foo()); | ^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | debug_assert!(foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:18:5 + --> $DIR/missing_assert_message.rs:16:5 | LL | debug_assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | debug_assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:19:5 + --> $DIR/missing_assert_message.rs:17:5 | LL | debug_assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | debug_assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:24:5 + --> $DIR/missing_assert_message.rs:22:5 | LL | assert!(bar!(true)); | ^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | assert!(bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:25:5 + --> $DIR/missing_assert_message.rs:23:5 | LL | assert!(bar!(true, false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | assert!(bar!(true, false)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:26:5 + --> $DIR/missing_assert_message.rs:24:5 | LL | assert_eq!(bar!(true), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | assert_eq!(bar!(true), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:27:5 + --> $DIR/missing_assert_message.rs:25:5 | LL | assert_ne!(bar!(true, true), bar!(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | assert_ne!(bar!(true, true), bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:32:5 + --> $DIR/missing_assert_message.rs:30:5 | LL | assert!(foo(),); | ^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:33:5 + --> $DIR/missing_assert_message.rs:31:5 | LL | assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:34:5 + --> $DIR/missing_assert_message.rs:32:5 | LL | assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | assert_ne!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:35:5 + --> $DIR/missing_assert_message.rs:33:5 | LL | debug_assert!(foo(),); | ^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | debug_assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:36:5 + --> $DIR/missing_assert_message.rs:34:5 | LL | debug_assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | debug_assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:37:5 + --> $DIR/missing_assert_message.rs:35:5 | LL | debug_assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index 5db73a7b8ead4..06e0535247982 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -3,7 +3,7 @@ //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. //@aux-build:helper.rs -//@aux-build:../../auxiliary/proc_macros.rs +//@aux-build:../auxiliary/proc_macros.rs:proc-macro #![warn(clippy::missing_const_for_fn)] #![feature(start)] @@ -13,7 +13,7 @@ extern crate proc_macros; use proc_macros::with_span; -struct Game; +struct Game; // You just lost. // This should not be linted because it's already const const fn already_const() -> i32 { @@ -44,7 +44,6 @@ static Y: u32 = 0; // refer to a static variable fn get_y() -> u32 { Y - //~^ ERROR E0013 } // Don't lint entrypoint functions @@ -126,3 +125,43 @@ with_span! { span fn dont_check_in_proc_macro() {} } + +// Do not lint `String` has `Vec`, which cannot be dropped in const contexts +fn a(this: String) {} + +enum A { + F(String), + N, +} + +// Same here. +fn b(this: A) {} + +// Minimized version of `a`. +fn c(this: Vec) {} + +struct F(A); + +// Do not lint +fn f(this: F) {} + +// Do not lint +fn g(this: T) {} + +struct Issue10617(String); + +impl Issue10617 { + // Do not lint + pub fn name(self) -> String { + self.0 + } +} + +union U { + f: u32, +} + +// Do not lint because accessing union fields from const functions is unstable +fn h(u: U) -> u32 { + unsafe { u.f } +} 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 0246c8622ed3a..b1980b1b523fd 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,7 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return)] +#![feature(const_mut_refs)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -87,3 +89,14 @@ fn msrv_1_46() -> i32 { // Should not be const fn main() {} + +struct D; + +impl const Drop for D { + fn drop(&mut self) { + todo!(); + } +} + +// Lint this, since it can be dropped in const contexts +fn d(this: D) {} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 955e1ed263408..7be2cc0ca9306 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:12:5 + --> $DIR/could_be_const.rs:14:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:16:5 + --> $DIR/could_be_const.rs:18:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | b @@ -17,7 +17,7 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:22:1 + --> $DIR/could_be_const.rs:24:1 | LL | / fn one() -> i32 { LL | | 1 @@ -25,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:27:1 + --> $DIR/could_be_const.rs:29:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -34,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:33:1 + --> $DIR/could_be_const.rs:35:1 | LL | / fn string() -> String { LL | | String::new() @@ -42,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:38:1 + --> $DIR/could_be_const.rs:40:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -50,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:43:1 + --> $DIR/could_be_const.rs:45:1 | LL | / fn generic(t: T) -> T { LL | | t @@ -58,7 +58,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:51:1 + --> $DIR/could_be_const.rs:53:1 | LL | / fn generic_arr(t: [T; 1]) -> T { LL | | t[0] @@ -66,7 +66,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:64:9 + --> $DIR/could_be_const.rs:66:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B @@ -74,7 +74,7 @@ LL | | } | |_________^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:73:5 + --> $DIR/could_be_const.rs:75:5 | LL | / fn const_fn_stabilized_before_msrv(byte: u8) { LL | | byte.is_ascii_digit(); @@ -82,12 +82,18 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:84:1 + --> $DIR/could_be_const.rs:86:1 | LL | / fn msrv_1_46() -> i32 { LL | | 46 LL | | } | |_^ -error: aborting due to 11 previous errors +error: this could be a `const fn` + --> $DIR/could_be_const.rs:102:1 + | +LL | fn d(this: D) {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index bf587e774f743..cff1706a8426e 100644 --- a/tests/ui/missing_doc.rs +++ b/tests/ui/missing_doc.rs @@ -1,5 +1,5 @@ //@needs-asm-support -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the diff --git a/tests/ui/missing_doc_impl.rs b/tests/ui/missing_doc_impl.rs index 520ddbe16b829..2d45132f968eb 100644 --- a/tests/ui/missing_doc_impl.rs +++ b/tests/ui/missing_doc_impl.rs @@ -1,4 +1,4 @@ -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::missing_docs_in_private_items)] #![allow(dead_code)] diff --git a/tests/ui/missing_inline_proc_macro.rs b/tests/ui/missing_inline_proc_macro.rs index 3c68fb905f12d..e47a198c6aeaf 100644 --- a/tests/ui/missing_inline_proc_macro.rs +++ b/tests/ui/missing_inline_proc_macro.rs @@ -1,5 +1,4 @@ #![warn(clippy::missing_inline_in_public_items)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 7dc44529206d5..0e1533fc1ab10 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -1,5 +1,12 @@ +//@aux-build:macro_rules.rs #![warn(clippy::missing_panics_doc)] -#![allow(clippy::option_map_unit_fn)] +#![allow(clippy::option_map_unit_fn, clippy::unnecessary_literal_unwrap)] + +#[macro_use] +extern crate macro_rules; + +use macro_rules::macro_with_panic; + fn main() {} /// This needs to be documented @@ -13,11 +20,6 @@ pub fn panic() { panic!("This function panics") } -/// This needs to be documented -pub fn todo() { - todo!() -} - /// This needs to be documented pub fn inner_body(opt: Option) { opt.map(|x| { @@ -76,15 +78,6 @@ pub fn inner_body_documented(opt: Option) { }); } -/// This is documented -/// -/// # Panics -/// -/// We still need to do this part -pub fn todo_documented() { - todo!() -} - /// This is documented /// /// # Panics @@ -114,6 +107,11 @@ pub fn assert_ne_documented() { assert_ne!(x, 0); } +/// `todo!()` is fine +pub fn todo() { + todo!() +} + /// This is okay because it is private fn unwrap_private() { let result = Err("Hi"); @@ -125,11 +123,6 @@ fn panic_private() { panic!("This function panics") } -/// This is okay because it is private -fn todo_private() { - todo!() -} - /// This is okay because it is private fn inner_body_private(opt: Option) { opt.map(|x| { @@ -151,3 +144,50 @@ pub fn debug_assertions() { debug_assert_eq!(1, 2); debug_assert_ne!(1, 2); } + +// all function must be triggered the lint. +// `pub` is required, because the lint does not consider unreachable items +pub mod issue10240 { + pub fn option_unwrap(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.unwrap() + } + + pub fn option_expect(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.expect("passed an empty thing") + } + + pub fn result_unwrap(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.unwrap() + } + + pub fn result_expect(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.expect("passed an empty thing") + } + + pub fn last_unwrap(v: &[u32]) -> u32 { + *v.last().unwrap() + } + + pub fn last_expect(v: &[u32]) -> u32 { + *v.last().expect("passed an empty thing") + } +} + +fn from_external_macro_should_not_lint() { + macro_with_panic!() +} + +macro_rules! some_macro_that_panics { + () => { + panic!() + }; +} + +fn from_declared_macro_should_lint_at_macrosite() { + // Not here. + some_macro_that_panics!() +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 183c262ce0b51..3dbe2dfbd88fd 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -1,87 +1,147 @@ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:6:1 + --> $DIR/missing_panics_doc.rs:13:1 | LL | pub fn unwrap() { | ^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:8:5 + --> $DIR/missing_panics_doc.rs:15:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ = note: `-D clippy::missing-panics-doc` implied by `-D warnings` error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:12:1 + --> $DIR/missing_panics_doc.rs:19:1 | LL | pub fn panic() { | ^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:13:5 + --> $DIR/missing_panics_doc.rs:20:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:17:1 - | -LL | pub fn todo() { - | ^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:18:5 - | -LL | todo!() - | ^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:22:1 + --> $DIR/missing_panics_doc.rs:24:1 | LL | pub fn inner_body(opt: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:25:13 + --> $DIR/missing_panics_doc.rs:27:13 | LL | panic!() | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:31:1 + --> $DIR/missing_panics_doc.rs:33:1 | LL | pub fn unreachable_and_panic() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:32:39 + --> $DIR/missing_panics_doc.rs:34:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:36:1 + --> $DIR/missing_panics_doc.rs:38:1 | LL | pub fn assert_eq() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:38:5 + --> $DIR/missing_panics_doc.rs:40:5 | LL | assert_eq!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:42:1 + --> $DIR/missing_panics_doc.rs:44:1 | LL | pub fn assert_ne() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:44:5 + --> $DIR/missing_panics_doc.rs:46:5 | LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:151:5 + | +LL | pub fn option_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:153:9 + | +LL | o.unwrap() + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:156:5 + | +LL | pub fn option_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:158:9 + | +LL | o.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:161:5 + | +LL | pub fn result_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:163:9 + | +LL | res.unwrap() + | ^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:166:5 + | +LL | pub fn result_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:168:9 + | +LL | res.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:171:5 + | +LL | pub fn last_unwrap(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:172:10 + | +LL | *v.last().unwrap() + | ^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:175:5 + | +LL | pub fn last_expect(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:176:10 + | +LL | *v.last().expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index 62cfeafdc49fb..9c2ffcb02ea11 100644 --- a/tests/ui/mistyped_literal_suffix.fixed +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow( dead_code, diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index f83b7c3dbda5e..a0a1e96a775d2 100644 --- a/tests/ui/mistyped_literal_suffix.rs +++ b/tests/ui/mistyped_literal_suffix.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow( dead_code, diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index a23aba9164a5c..802c3ec39b64b 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,5 +1,17 @@ #![warn(clippy::module_inception)] +pub mod foo2 { + pub mod bar2 { + pub mod bar2 { + pub mod foo2 {} + } + pub mod foo2 {} + } + pub mod foo2 { + pub mod bar2 {} + } +} + mod foo { mod bar { mod bar { diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index 77564dce9eb48..ebb8e296f4646 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,8 +1,8 @@ error: module has the same name as its containing module --> $DIR/module_inception.rs:5:9 | -LL | / mod bar { -LL | | mod foo {} +LL | / pub mod bar2 { +LL | | pub mod foo2 {} LL | | } | |_________^ | @@ -11,10 +11,26 @@ LL | | } error: module has the same name as its containing module --> $DIR/module_inception.rs:10:5 | +LL | / pub mod foo2 { +LL | | pub mod bar2 {} +LL | | } + | |_____^ + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:17:9 + | +LL | / mod bar { +LL | | mod foo {} +LL | | } + | |_________^ + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:22:5 + | LL | / mod foo { LL | | mod bar {} LL | | } | |_____^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs index 4ef6f0ca92f2d..23ad36bb47304 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.rs +++ b/tests/ui/multiple_unsafe_ops_per_block.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![allow(deref_nullptr)] #![allow(clippy::unnecessary_operation)] diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed index 4f7cf4e56d152..c460fd7c6b0d5 100644 --- a/tests/ui/must_use_unit.fixed +++ b/tests/ui/must_use_unit.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::must_use_unit)] #![allow(clippy::unused_unit)] diff --git a/tests/ui/must_use_unit.rs b/tests/ui/must_use_unit.rs index 3a814ce16859e..fe95624f79960 100644 --- a/tests/ui/must_use_unit.rs +++ b/tests/ui/must_use_unit.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::must_use_unit)] #![allow(clippy::unused_unit)] diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index d838098de113e..b721342836771 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::mut_mut)] #![allow(unused)] #![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)] diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.rs b/tests/ui/needless_arbitrary_self_type_unfixable.rs index 00871f9f450ca..876f16a3854d9 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs:proc-macro #![warn(clippy::needless_arbitrary_self_type)] diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed index bf1911881c8a9..7d0e556528fa1 100644 --- a/tests/ui/needless_bool/fixable.fixed +++ b/tests/ui/needless_bool/fixable.fixed @@ -7,6 +7,7 @@ clippy::no_effect, clippy::if_same_then_else, clippy::equatable_if_let, + clippy::needless_if, clippy::needless_return, clippy::self_named_constructors )] diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs index a6c465d4fbd11..88bfe8af73373 100644 --- a/tests/ui/needless_bool/fixable.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -7,6 +7,7 @@ clippy::no_effect, clippy::if_same_then_else, clippy::equatable_if_let, + clippy::needless_if, clippy::needless_return, clippy::self_named_constructors )] diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr index fa906374fb3ba..1476aea439ff2 100644 --- a/tests/ui/needless_bool/fixable.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:41:5 + --> $DIR/fixable.rs:42:5 | LL | / if x { LL | | true @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:46:5 + --> $DIR/fixable.rs:47:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:51:5 + --> $DIR/fixable.rs:52:5 | LL | / if x && y { LL | | false @@ -31,7 +31,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:59:5 + --> $DIR/fixable.rs:60:5 | LL | / if a == b { LL | | false @@ -41,7 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a != b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:64:5 + --> $DIR/fixable.rs:65:5 | LL | / if a != b { LL | | false @@ -51,7 +51,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a == b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:69:5 + --> $DIR/fixable.rs:70:5 | LL | / if a < b { LL | | false @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a >= b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:74:5 + --> $DIR/fixable.rs:75:5 | LL | / if a <= b { LL | | false @@ -71,7 +71,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a > b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:79:5 + --> $DIR/fixable.rs:80:5 | LL | / if a > b { LL | | false @@ -81,7 +81,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a <= b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:84:5 + --> $DIR/fixable.rs:85:5 | LL | / if a >= b { LL | | false @@ -91,7 +91,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a < b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:112:5 + --> $DIR/fixable.rs:113:5 | LL | / if x { LL | | return true; @@ -101,7 +101,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:120:5 + --> $DIR/fixable.rs:121:5 | LL | / if x { LL | | return false; @@ -111,7 +111,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:128:5 + --> $DIR/fixable.rs:129:5 | LL | / if x && y { LL | | return true; @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:136:5 + --> $DIR/fixable.rs:137:5 | LL | / if x && y { LL | | return false; @@ -131,7 +131,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:144:8 + --> $DIR/fixable.rs:145:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -139,25 +139,25 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/fixable.rs:148:8 + --> $DIR/fixable.rs:149:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:158:8 + --> $DIR/fixable.rs:159:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/fixable.rs:159:8 + --> $DIR/fixable.rs:160:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:168:12 + --> $DIR/fixable.rs:169:12 | LL | } else if returns_bool() { | ____________^ @@ -168,7 +168,7 @@ LL | | }; | |_____^ help: you can reduce it to: `{ !returns_bool() }` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:181:5 + --> $DIR/fixable.rs:182:5 | LL | / if unsafe { no(4) } & 1 != 0 { LL | | true @@ -178,13 +178,13 @@ LL | | }; | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:186:30 + --> $DIR/fixable.rs:187:30 | LL | let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:189:9 + --> $DIR/fixable.rs:190:9 | LL | if unsafe { no(4) } & 1 != 0 { true } else { false } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 425e6eb6200ec..80cdb4e472d41 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -4,7 +4,8 @@ unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, - clippy::unnecessary_to_owned + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 3f7fa4a9d7dc4..99f735127eb8e 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -4,7 +4,8 @@ unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, - clippy::unnecessary_to_owned + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index d26c317124b8d..f85b4fb46a650 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:15:15 + --> $DIR/needless_borrow.rs:16:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -7,211 +7,211 @@ LL | let _ = x(&&a); // warn = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:19:13 + --> $DIR/needless_borrow.rs:20:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:31:13 + --> $DIR/needless_borrow.rs:32:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:33:15 + --> $DIR/needless_borrow.rs:34:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:39:27 + --> $DIR/needless_borrow.rs:40:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:46:15 + --> $DIR/needless_borrow.rs:47:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:47:15 + --> $DIR/needless_borrow.rs:48:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:48:15 + --> $DIR/needless_borrow.rs:49:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:49:15 + --> $DIR/needless_borrow.rs:50:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:52:11 + --> $DIR/needless_borrow.rs:53:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:59:13 + --> $DIR/needless_borrow.rs:60:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:60:13 + --> $DIR/needless_borrow.rs:61:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:61:23 + --> $DIR/needless_borrow.rs:62:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:62:23 + --> $DIR/needless_borrow.rs:63:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:71:14 + --> $DIR/needless_borrow.rs:72:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:77:14 + --> $DIR/needless_borrow.rs:78:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:89:13 + --> $DIR/needless_borrow.rs:90:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:91:22 + --> $DIR/needless_borrow.rs:92:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:101:5 + --> $DIR/needless_borrow.rs:102:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:110:5 + --> $DIR/needless_borrow.rs:111:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:135:51 + --> $DIR/needless_borrow.rs:136:51 | LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:136:44 + --> $DIR/needless_borrow.rs:137:44 | LL | let _ = std::path::Path::new(".").join(&&"."); | ^^^^^ help: change this to: `"."` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:137:23 + --> $DIR/needless_borrow.rs:138:23 | LL | deref_target_is_x(&X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:138:26 + --> $DIR/needless_borrow.rs:139:26 | LL | multiple_constraints(&[[""]]); | ^^^^^^^ help: change this to: `[[""]]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:139:45 + --> $DIR/needless_borrow.rs:140:45 | LL | multiple_constraints_normalizes_to_same(&X, X); | ^^ help: change this to: `X` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:140:32 + --> $DIR/needless_borrow.rs:141:32 | LL | let _ = Some("").unwrap_or(&""); | ^^^ help: change this to: `""` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:141:33 + --> $DIR/needless_borrow.rs:142:33 | LL | let _ = std::fs::write("x", &"".to_string()); | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:190:13 + --> $DIR/needless_borrow.rs:191:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:199:13 + --> $DIR/needless_borrow.rs:200:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:283:20 + --> $DIR/needless_borrow.rs:284:20 | LL | takes_iter(&mut x) | ^^^^^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:297:55 + --> $DIR/needless_borrow.rs:298:55 | LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:335:37 + --> $DIR/needless_borrow.rs:336:37 | LL | let _ = std::fs::write("x", &arg); | ^^^^ help: change this to: `arg` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:336:37 + --> $DIR/needless_borrow.rs:337:37 | LL | let _ = std::fs::write("x", &loc); | ^^^^ help: change this to: `loc` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:354:15 + --> $DIR/needless_borrow.rs:355:15 | LL | debug(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:363:15 + --> $DIR/needless_borrow.rs:364:15 | LL | use_x(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:457:13 + --> $DIR/needless_borrow.rs:458:13 | LL | foo(&a); | ^^ help: change this to: `a` diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed index 6663520da8a1d..59a38425b0680 100644 --- a/tests/ui/needless_borrowed_ref.fixed +++ b/tests/ui/needless_borrowed_ref.fixed @@ -5,7 +5,8 @@ unused, irrefutable_let_patterns, non_shorthand_field_patterns, - clippy::needless_borrow + clippy::needless_borrow, + clippy::needless_if )] fn main() {} diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 6c8efd2ce1804..e48b19cb19db8 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -5,7 +5,8 @@ unused, irrefutable_let_patterns, non_shorthand_field_patterns, - clippy::needless_borrow + clippy::needless_borrow, + clippy::needless_if )] fn main() {} diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 8d0f0c258dd26..35497a01ec220 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,5 +1,5 @@ error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:31:34 + --> $DIR/needless_borrowed_ref.rs:32:34 | LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ @@ -12,7 +12,7 @@ LL + let _ = v.iter_mut().filter(|a| a.is_empty()); | error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:35:17 + --> $DIR/needless_borrowed_ref.rs:36:17 | LL | if let Some(&ref v) = thingy {} | ^^^^^^ @@ -24,7 +24,7 @@ LL + if let Some(v) = thingy {} | error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:37:14 + --> $DIR/needless_borrowed_ref.rs:38:14 | LL | if let &[&ref a, ref b] = slice_of_refs {} | ^^^^^^ @@ -36,7 +36,7 @@ LL + if let &[a, ref b] = slice_of_refs {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:39:9 + --> $DIR/needless_borrowed_ref.rs:40:9 | LL | let &[ref a, ..] = &array; | ^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + let [a, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:40:9 + --> $DIR/needless_borrowed_ref.rs:41:9 | LL | let &[ref a, ref b, ..] = &array; | ^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + let [a, b, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:42:12 + --> $DIR/needless_borrowed_ref.rs:43:12 | LL | if let &[ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL + if let [a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:43:12 + --> $DIR/needless_borrowed_ref.rs:44:12 | LL | if let &[ref a, ref b] = &vec[..] {} | ^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL + if let [a, b] = &vec[..] {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:45:12 + --> $DIR/needless_borrowed_ref.rs:46:12 | LL | if let &[ref a, ref b, ..] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + if let [a, b, ..] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:46:12 + --> $DIR/needless_borrowed_ref.rs:47:12 | LL | if let &[ref a, .., ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + if let [a, .., b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:47:12 + --> $DIR/needless_borrowed_ref.rs:48:12 | LL | if let &[.., ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + if let [.., a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:49:12 + --> $DIR/needless_borrowed_ref.rs:50:12 | LL | if let &[ref a, _] = slice {} | ^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL + if let [a, _] = slice {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:51:12 + --> $DIR/needless_borrowed_ref.rs:52:12 | LL | if let &(ref a, ref b, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + if let (a, b, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:52:12 + --> $DIR/needless_borrowed_ref.rs:53:12 | LL | if let &(ref a, _, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL + if let (a, _, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:53:12 + --> $DIR/needless_borrowed_ref.rs:54:12 | LL | if let &(ref a, ..) = &tuple {} | ^^^^^^^^^^^^ @@ -168,7 +168,7 @@ LL + if let (a, ..) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:55:12 + --> $DIR/needless_borrowed_ref.rs:56:12 | LL | if let &TupleStruct(ref a, ..) = &tuple_struct {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -180,7 +180,7 @@ LL + if let TupleStruct(a, ..) = &tuple_struct {} | error: dereferencing a struct pattern where every field's pattern takes a reference - --> $DIR/needless_borrowed_ref.rs:57:12 + --> $DIR/needless_borrowed_ref.rs:58:12 | LL | if let &Struct { | ____________^ @@ -199,7 +199,7 @@ LL ~ c: renamed, | error: dereferencing a struct pattern where every field's pattern takes a reference - --> $DIR/needless_borrowed_ref.rs:64:12 + --> $DIR/needless_borrowed_ref.rs:65:12 | LL | if let &Struct { ref a, b: _, .. } = &s {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index b7e80af501547..0f0aaad17b453 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::suspicious_map, clippy::iter_count)] +#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; @@ -70,6 +70,11 @@ fn main() { bar((0..10).collect::>(), (0..10)); baz((0..10), (), ('a'..='z')) } + + let values = [1, 2, 3, 4]; + let mut out = vec![]; + values.iter().cloned().map(|x| out.push(x)).collect::>(); + let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 680b6fa5b55f5..4f48f24b17b84 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::suspicious_map, clippy::iter_count)] +#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; @@ -70,6 +70,11 @@ fn main() { bar((0..10).collect::>(), (0..10).collect::>()); baz((0..10), (), ('a'..='z').collect::>()) } + + let values = [1, 2, 3, 4]; + let mut out = vec![]; + values.iter().cloned().map(|x| out.push(x)).collect::>(); + let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index fe4209e99b2f5..d3d856c2c659c 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,4 +1,5 @@ -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] +#![allow(clippy::needless_if, clippy::uninlined_format_args)] #![warn(clippy::needless_collect)] use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 790d725907f32..8f84c5596889c 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:8:39 + --> $DIR/needless_collect_indirect.rs:9:39 | LL | let indirect_iter = sample.iter().collect::>(); | ^^^^^^^ @@ -14,7 +14,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::>(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:10:38 + --> $DIR/needless_collect_indirect.rs:11:38 | LL | let indirect_len = sample.iter().collect::>(); | ^^^^^^^ @@ -28,7 +28,7 @@ LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:12:40 + --> $DIR/needless_collect_indirect.rs:13:40 | LL | let indirect_empty = sample.iter().collect::>(); | ^^^^^^^ @@ -42,7 +42,7 @@ LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:14:43 + --> $DIR/needless_collect_indirect.rs:15:43 | LL | let indirect_contains = sample.iter().collect::>(); | ^^^^^^^ @@ -56,7 +56,7 @@ LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:26:48 + --> $DIR/needless_collect_indirect.rs:27:48 | LL | let non_copy_contains = sample.into_iter().collect::>(); | ^^^^^^^ @@ -70,7 +70,7 @@ LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:55:51 + --> $DIR/needless_collect_indirect.rs:56:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ @@ -84,7 +84,7 @@ LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:60:55 + --> $DIR/needless_collect_indirect.rs:61:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ @@ -98,7 +98,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:65:57 + --> $DIR/needless_collect_indirect.rs:66:57 | LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ @@ -112,7 +112,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:70:57 + --> $DIR/needless_collect_indirect.rs:71:57 | LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); | ^^^^^^^ @@ -126,7 +126,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:130:59 + --> $DIR/needless_collect_indirect.rs:131:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -143,7 +143,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:155:59 + --> $DIR/needless_collect_indirect.rs:156:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -160,7 +160,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:184:63 + --> $DIR/needless_collect_indirect.rs:185:63 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -177,7 +177,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:220:59 + --> $DIR/needless_collect_indirect.rs:221:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -195,7 +195,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:245:26 + --> $DIR/needless_collect_indirect.rs:246:26 | LL | let w = v.iter().collect::>(); | ^^^^^^^ @@ -211,7 +211,7 @@ LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:267:30 + --> $DIR/needless_collect_indirect.rs:268:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -227,7 +227,7 @@ LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:289:30 + --> $DIR/needless_collect_indirect.rs:290:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed new file mode 100644 index 0000000000000..5e6e140c2db38 --- /dev/null +++ b/tests/ui/needless_if.fixed @@ -0,0 +1,93 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(let_chains)] +#![allow( + clippy::blocks_in_if_conditions, + clippy::if_same_then_else, + clippy::ifs_same_cond, + clippy::let_unit_value, + clippy::needless_else, + clippy::no_effect, + clippy::nonminimal_bool, + clippy::short_circuit_statement, + clippy::unnecessary_operation, + unused +)] +#![warn(clippy::needless_if)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +fn maybe_side_effect() -> bool { + true +} + +fn main() { + // Lint + + // Do not remove the condition + maybe_side_effect(); + // Do not lint + if (true) { + } else { + } + ({ + return; + }); + // Do not lint if `else if` is present + if (true) { + } else if (true) { + } + // Do not lint `if let` or let chains + if let true = true {} + if let true = true && true {} + if true && let true = true {} + // Can lint nested `if let`s + ({ + if let true = true && true { true } else { false } + } && true); + external! { if (true) {} } + with_span! { + span + if (true) {} + } + + if true { + // comment + } + + if true { + #[cfg(any())] + foo; + } + + macro_rules! empty_expansion { + () => {}; + } + + if true { + empty_expansion!(); + } + + macro_rules! empty_repetition { + ($($t:tt)*) => { + if true { + $($t)* + } + } + } + + empty_repetition!(); + + // Must be placed into an expression context to not be interpreted as a block + ({ maybe_side_effect() }); + // Would be a block followed by `&&true` - a double reference to `true` + ({ maybe_side_effect() } && true); + + // Don't leave trailing attributes + #[allow(unused)] + true; + + let () = if maybe_side_effect() {}; +} diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs new file mode 100644 index 0000000000000..eb28ce73be8f9 --- /dev/null +++ b/tests/ui/needless_if.rs @@ -0,0 +1,94 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(let_chains)] +#![allow( + clippy::blocks_in_if_conditions, + clippy::if_same_then_else, + clippy::ifs_same_cond, + clippy::let_unit_value, + clippy::needless_else, + clippy::no_effect, + clippy::nonminimal_bool, + clippy::short_circuit_statement, + clippy::unnecessary_operation, + unused +)] +#![warn(clippy::needless_if)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +fn maybe_side_effect() -> bool { + true +} + +fn main() { + // Lint + if (true) {} + // Do not remove the condition + if maybe_side_effect() {} + // Do not lint + if (true) { + } else { + } + if { + return; + } {} + // Do not lint if `else if` is present + if (true) { + } else if (true) { + } + // Do not lint `if let` or let chains + if let true = true {} + if let true = true && true {} + if true && let true = true {} + // Can lint nested `if let`s + if { + if let true = true && true { true } else { false } + } && true + {} + external! { if (true) {} } + with_span! { + span + if (true) {} + } + + if true { + // comment + } + + if true { + #[cfg(any())] + foo; + } + + macro_rules! empty_expansion { + () => {}; + } + + if true { + empty_expansion!(); + } + + macro_rules! empty_repetition { + ($($t:tt)*) => { + if true { + $($t)* + } + } + } + + empty_repetition!(); + + // Must be placed into an expression context to not be interpreted as a block + if { maybe_side_effect() } {} + // Would be a block followed by `&&true` - a double reference to `true` + if { maybe_side_effect() } && true {} + + // Don't leave trailing attributes + #[allow(unused)] + if true {} + + let () = if maybe_side_effect() {}; +} diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr new file mode 100644 index 0000000000000..5cb42c36921d2 --- /dev/null +++ b/tests/ui/needless_if.stderr @@ -0,0 +1,65 @@ +error: this `if` branch is empty + --> $DIR/needless_if.rs:28:5 + | +LL | if (true) {} + | ^^^^^^^^^^^^ help: you can remove it + | + = note: `-D clippy::needless-if` implied by `-D warnings` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:30:5 + | +LL | if maybe_side_effect() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:35:5 + | +LL | / if { +LL | | return; +LL | | } {} + | |________^ + | +help: you can remove it + | +LL ~ ({ +LL + return; +LL + }); + | + +error: this `if` branch is empty + --> $DIR/needless_if.rs:47:5 + | +LL | / if { +LL | | if let true = true && true { true } else { false } +LL | | } && true +LL | | {} + | |______^ + | +help: you can remove it + | +LL ~ ({ +LL + if let true = true && true { true } else { false } +LL + } && true); + | + +error: this `if` branch is empty + --> $DIR/needless_if.rs:85:5 + | +LL | if { maybe_side_effect() } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:87:5 + | +LL | if { maybe_side_effect() } && true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:91:5 + | +LL | if true {} + | ^^^^^^^^^^ help: you can remove it: `true;` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index 92f7b3f777a19..933dd8bed2a26 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow(unused)] #![allow( @@ -8,7 +8,8 @@ clippy::let_and_return, clippy::let_unit_value, clippy::nonminimal_bool, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] extern crate proc_macros; diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index be378c42f95d6..ba3a04e0825eb 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow(unused)] #![allow( @@ -8,7 +8,8 @@ clippy::let_and_return, clippy::let_unit_value, clippy::nonminimal_bool, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] extern crate proc_macros; diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index eff782f8bf104..78ba8e11c575c 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -1,5 +1,5 @@ error: unneeded late initialization - --> $DIR/needless_late_init.rs:27:5 + --> $DIR/needless_late_init.rs:28:5 | LL | let a; | ^^^^^^ created here @@ -13,7 +13,7 @@ LL | let a = "zero"; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:30:5 + --> $DIR/needless_late_init.rs:31:5 | LL | let b; | ^^^^^^ created here @@ -27,7 +27,7 @@ LL | let b = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:31:5 + --> $DIR/needless_late_init.rs:32:5 | LL | let c; | ^^^^^^ created here @@ -41,7 +41,7 @@ LL | let c = 2; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:35:5 + --> $DIR/needless_late_init.rs:36:5 | LL | let d: usize; | ^^^^^^^^^^^^^ created here @@ -54,7 +54,7 @@ LL | let d: usize = 1; | ~~~~~~~~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:38:5 + --> $DIR/needless_late_init.rs:39:5 | LL | let e; | ^^^^^^ created here @@ -67,7 +67,7 @@ LL | let e = format!("{}", d); | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:43:5 + --> $DIR/needless_late_init.rs:44:5 | LL | let a; | ^^^^^^ @@ -88,7 +88,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:52:5 + --> $DIR/needless_late_init.rs:53:5 | LL | let b; | ^^^^^^ @@ -109,7 +109,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:59:5 + --> $DIR/needless_late_init.rs:60:5 | LL | let d; | ^^^^^^ @@ -130,7 +130,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:67:5 + --> $DIR/needless_late_init.rs:68:5 | LL | let e; | ^^^^^^ @@ -151,7 +151,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:74:5 + --> $DIR/needless_late_init.rs:75:5 | LL | let f; | ^^^^^^ @@ -167,7 +167,7 @@ LL + 1 => "three", | error: unneeded late initialization - --> $DIR/needless_late_init.rs:80:5 + --> $DIR/needless_late_init.rs:81:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:88:5 + --> $DIR/needless_late_init.rs:89:5 | LL | let x; | ^^^^^^ created here @@ -201,7 +201,7 @@ LL | let x = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:92:5 + --> $DIR/needless_late_init.rs:93:5 | LL | let x; | ^^^^^^ created here @@ -215,7 +215,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:96:5 + --> $DIR/needless_late_init.rs:97:5 | LL | let x; | ^^^^^^ created here @@ -229,7 +229,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:115:5 + --> $DIR/needless_late_init.rs:116:5 | LL | let a; | ^^^^^^ @@ -250,7 +250,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:132:5 + --> $DIR/needless_late_init.rs:133:5 | LL | let a; | ^^^^^^ diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index 7b99042f7449b..302a3f9edbecb 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 6fcf1efc2ee67..b15477c92e814 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index 86acc4e00469f..0da67b600a3f5 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:18:1 + --> $DIR/needless_lifetimes.rs:18:23 | LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` help: elide the lifetimes @@ -12,10 +12,10 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {} | error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:20:1 + --> $DIR/needless_lifetimes.rs:20:24 | LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -24,10 +24,10 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:30:1 + --> $DIR/needless_lifetimes.rs:30:15 | LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -36,10 +36,10 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:42:1 + --> $DIR/needless_lifetimes.rs:42:31 | LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -48,10 +48,10 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:49:1 + --> $DIR/needless_lifetimes.rs:49:27 | LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -60,10 +60,10 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:66:1 + --> $DIR/needless_lifetimes.rs:66:26 | LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -72,10 +72,10 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:73:1 + --> $DIR/needless_lifetimes.rs:73:22 | LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -84,10 +84,10 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:82:1 + --> $DIR/needless_lifetimes.rs:82:21 | LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -96,10 +96,10 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:87:1 + --> $DIR/needless_lifetimes.rs:87:28 | LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -108,10 +108,10 @@ LL + fn where_clause_without_lt(x: &u8, _y: u8) -> Result<&u8, ()> | error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:99:1 + --> $DIR/needless_lifetimes.rs:99:21 | LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -120,10 +120,10 @@ LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:123:1 + --> $DIR/needless_lifetimes.rs:123:15 | LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -132,10 +132,10 @@ LL + fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> | error: the following explicit lifetimes could be elided: 's - --> $DIR/needless_lifetimes.rs:153:5 + --> $DIR/needless_lifetimes.rs:153:21 | LL | fn self_and_out<'s>(&'s self) -> &'s u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -144,10 +144,10 @@ LL + fn self_and_out(&self) -> &u8 { | error: the following explicit lifetimes could be elided: 't - --> $DIR/needless_lifetimes.rs:160:5 + --> $DIR/needless_lifetimes.rs:160:30 | LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -156,10 +156,10 @@ LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 { | error: the following explicit lifetimes could be elided: 's - --> $DIR/needless_lifetimes.rs:167:5 + --> $DIR/needless_lifetimes.rs:167:26 | LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -168,10 +168,10 @@ LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 { | error: the following explicit lifetimes could be elided: 's, 't - --> $DIR/needless_lifetimes.rs:171:5 + --> $DIR/needless_lifetimes.rs:171:29 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -180,10 +180,10 @@ LL + fn distinct_self_and_in(&self, _x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:190:1 + --> $DIR/needless_lifetimes.rs:190:19 | LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -192,10 +192,10 @@ LL + fn struct_with_lt(_foo: Foo<'_>) -> &str { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:208:1 + --> $DIR/needless_lifetimes.rs:208:25 | LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -204,10 +204,10 @@ LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:216:1 + --> $DIR/needless_lifetimes.rs:216:21 | LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -216,10 +216,10 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:231:1 + --> $DIR/needless_lifetimes.rs:231:22 | LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -228,10 +228,10 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:237:1 + --> $DIR/needless_lifetimes.rs:237:18 | LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -240,10 +240,10 @@ LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:255:1 + --> $DIR/needless_lifetimes.rs:255:24 | LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -252,10 +252,10 @@ LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:263:1 + --> $DIR/needless_lifetimes.rs:263:20 | LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -264,10 +264,10 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:267:1 + --> $DIR/needless_lifetimes.rs:267:30 | LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^ | help: elide the lifetimes | @@ -276,10 +276,10 @@ LL + fn named_input_elided_output(_arg: &str) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:275:1 + --> $DIR/needless_lifetimes.rs:275:19 | LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -288,10 +288,10 @@ LL + fn trait_bound_ok>(_: &u8, _: T) { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:311:1 + --> $DIR/needless_lifetimes.rs:311:24 | LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -300,10 +300,10 @@ LL + fn out_return_type_lts(e: &str) -> Cow<'_> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:318:9 + --> $DIR/needless_lifetimes.rs:318:24 | LL | fn needless_lt<'a>(x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -312,10 +312,10 @@ LL + fn needless_lt(x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:322:9 + --> $DIR/needless_lifetimes.rs:322:24 | LL | fn needless_lt<'a>(_x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -324,10 +324,10 @@ LL + fn needless_lt(_x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:335:9 + --> $DIR/needless_lifetimes.rs:335:16 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -336,10 +336,10 @@ LL + fn baz(&self) -> impl Foo + '_ { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:367:5 + --> $DIR/needless_lifetimes.rs:367:55 | LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -348,10 +348,10 @@ LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(& | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:376:5 + --> $DIR/needless_lifetimes.rs:376:26 | LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -360,10 +360,10 @@ LL + fn generics_elidable &i32>(i: &i32, f: T) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:388:5 + --> $DIR/needless_lifetimes.rs:388:32 | LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -372,10 +372,10 @@ LL + fn where_clause_elidadable(i: &i32, f: T) -> &i32 | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:403:5 + --> $DIR/needless_lifetimes.rs:403:28 | LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -384,10 +384,10 @@ LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:416:5 + --> $DIR/needless_lifetimes.rs:416:28 | LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -396,10 +396,10 @@ LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:419:5 + --> $DIR/needless_lifetimes.rs:419:28 | LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -408,10 +408,10 @@ LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:441:9 + --> $DIR/needless_lifetimes.rs:441:21 | LL | fn implicit<'a>(&'a self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -420,10 +420,10 @@ LL + fn implicit(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:444:9 + --> $DIR/needless_lifetimes.rs:444:25 | LL | fn implicit_mut<'a>(&'a mut self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -432,10 +432,10 @@ LL + fn implicit_mut(&mut self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:455:9 + --> $DIR/needless_lifetimes.rs:455:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -444,10 +444,10 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:461:9 + --> $DIR/needless_lifetimes.rs:461:21 | LL | fn implicit<'a>(&'a self) -> &'a (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -456,10 +456,10 @@ LL + fn implicit(&self) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:462:9 + --> $DIR/needless_lifetimes.rs:462:30 | LL | fn implicit_provided<'a>(&'a self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -468,10 +468,10 @@ LL + fn implicit_provided(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:471:9 + --> $DIR/needless_lifetimes.rs:471:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -480,10 +480,10 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:472:9 + --> $DIR/needless_lifetimes.rs:472:40 | LL | fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -492,10 +492,10 @@ LL + fn lifetime_elsewhere_provided(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:481:5 + --> $DIR/needless_lifetimes.rs:481:12 | LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -504,10 +504,10 @@ LL + fn foo(x: &u8, y: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:483:5 + --> $DIR/needless_lifetimes.rs:483:12 | LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -516,10 +516,10 @@ LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:490:5 + --> $DIR/needless_lifetimes.rs:490:18 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -528,10 +528,10 @@ LL + fn one_input(x: &u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:495:5 + --> $DIR/needless_lifetimes.rs:495:42 | LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -540,10 +540,10 @@ LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:511:9 + --> $DIR/needless_lifetimes.rs:511:22 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: elide the lifetimes diff --git a/tests/ui/needless_option_as_deref.fixed b/tests/ui/needless_option_as_deref.fixed index 70015fccf9ee5..ec981ad97e3d3 100644 --- a/tests/ui/needless_option_as_deref.fixed +++ b/tests/ui/needless_option_as_deref.fixed @@ -2,6 +2,7 @@ #![allow(unused)] #![warn(clippy::needless_option_as_deref)] +#![allow(clippy::useless_vec)] fn main() { // should lint diff --git a/tests/ui/needless_option_as_deref.rs b/tests/ui/needless_option_as_deref.rs index e2e35360cb36b..6360874f62365 100644 --- a/tests/ui/needless_option_as_deref.rs +++ b/tests/ui/needless_option_as_deref.rs @@ -2,6 +2,7 @@ #![allow(unused)] #![warn(clippy::needless_option_as_deref)] +#![allow(clippy::useless_vec)] fn main() { // should lint diff --git a/tests/ui/needless_option_as_deref.stderr b/tests/ui/needless_option_as_deref.stderr index bc07db5b38ed3..20d28a968c917 100644 --- a/tests/ui/needless_option_as_deref.stderr +++ b/tests/ui/needless_option_as_deref.stderr @@ -1,5 +1,5 @@ error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:8:29 + --> $DIR/needless_option_as_deref.rs:9:29 | LL | let _: Option<&usize> = Some(&1).as_deref(); | ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)` @@ -7,13 +7,13 @@ LL | let _: Option<&usize> = Some(&1).as_deref(); = note: `-D clippy::needless-option-as-deref` implied by `-D warnings` error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:9:33 + --> $DIR/needless_option_as_deref.rs:10:33 | LL | let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)` error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:13:13 + --> $DIR/needless_option_as_deref.rs:14:13 | LL | let _ = x.as_deref_mut(); | ^^^^^^^^^^^^^^^^ help: try this: `x` diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 78a0e92d17979..c603163c145f2 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,4 +1,3 @@ -#![crate_type = "proc-macro"] #![warn(clippy::needless_pass_by_value)] extern crate proc_macro; diff --git a/tests/ui/needless_pub_self.fixed b/tests/ui/needless_pub_self.fixed new file mode 100644 index 0000000000000..672b4c318a8da --- /dev/null +++ b/tests/ui/needless_pub_self.fixed @@ -0,0 +1,33 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![warn(clippy::needless_pub_self)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + + fn a() {} + fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + fn f() {} +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/needless_pub_self.rs b/tests/ui/needless_pub_self.rs new file mode 100644 index 0000000000000..5ac1edf8e9907 --- /dev/null +++ b/tests/ui/needless_pub_self.rs @@ -0,0 +1,33 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![warn(clippy::needless_pub_self)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/needless_pub_self.stderr b/tests/ui/needless_pub_self.stderr new file mode 100644 index 0000000000000..3aa2feb5ecd82 --- /dev/null +++ b/tests/ui/needless_pub_self.stderr @@ -0,0 +1,22 @@ +error: unnecessary `pub(self)` + --> $DIR/needless_pub_self.rs:13:1 + | +LL | pub(self) fn a() {} + | ^^^^^^^^^ help: remove it + | + = note: `-D clippy::needless-pub-self` implied by `-D warnings` + +error: unnecessary `pub(in self)` + --> $DIR/needless_pub_self.rs:14:1 + | +LL | pub(in self) fn b() {} + | ^^^^^^^^^^^^ help: remove it + +error: unnecessary `pub(self)` + --> $DIR/needless_pub_self.rs:20:5 + | +LL | pub(self) fn f() {} + | ^^^^^^^^^ help: remove it + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 921801138a9b6..a16ef5a5bca95 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -1,5 +1,9 @@ #![warn(clippy::needless_range_loop)] -#![allow(clippy::uninlined_format_args)] +#![allow( + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap, + clippy::useless_vec +)] static STATIC: [usize; 4] = [0, 1, 8, 16]; const CONST: [usize; 4] = [0, 1, 8, 16]; @@ -82,6 +86,29 @@ fn main() { for i in 0..2 { println!("{}", test[i]); } + + // See #601 + for i in 0..10 { + // no error, id_col does not exist outside the loop + let mut id_col = [0f64; 10]; + id_col[i] = 1f64; + } + + fn f(_: &T, _: &T) -> bool { + unimplemented!() + } + fn g(_: &mut [T], _: usize, _: usize) { + unimplemented!() + } + for i in 1..vec.len() { + if f(&vec[i - 1], &vec[i]) { + g(&mut vec, i - 1, i); + } + } + + for mid in 1..vec.len() { + let (_, _) = vec.split_at(mid); + } } struct Test { @@ -94,3 +121,38 @@ impl std::ops::Index for Test { &self.inner[index] } } + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { + // Same source and destination - don't trigger lint + for i in 0..dst.len() { + dst[d + i] = dst[s + i]; + } +} + +mod issue_2496 { + pub trait Handle { + fn new_for_index(index: usize) -> Self; + fn index(&self) -> usize; + } + + pub fn test() -> H { + for x in 0..5 { + let next_handle = H::new_for_index(x); + println!("{}", next_handle.index()); + } + unimplemented!() + } +} diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index cffa19bec3a66..8ca6b880ceae7 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:11:14 + --> $DIR/needless_range_loop.rs:15:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | for in &vec { | ~~~~~~ ~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:20:14 + --> $DIR/needless_range_loop.rs:24:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | for in &vec { | ~~~~~~ ~~~~ error: the loop variable `j` is only used to index `STATIC` - --> $DIR/needless_range_loop.rs:25:14 + --> $DIR/needless_range_loop.rs:29:14 | LL | for j in 0..4 { | ^^^^ @@ -33,7 +33,7 @@ LL | for in &STATIC { | ~~~~~~ ~~~~~~~ error: the loop variable `j` is only used to index `CONST` - --> $DIR/needless_range_loop.rs:29:14 + --> $DIR/needless_range_loop.rs:33:14 | LL | for j in 0..4 { | ^^^^ @@ -44,7 +44,7 @@ LL | for in &CONST { | ~~~~~~ ~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:33:14 + --> $DIR/needless_range_loop.rs:37:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | for (i, ) in vec.iter().enumerate() { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec2` - --> $DIR/needless_range_loop.rs:41:14 + --> $DIR/needless_range_loop.rs:45:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | for in vec2.iter().take(vec.len()) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:45:14 + --> $DIR/needless_range_loop.rs:49:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | for in vec.iter().skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:49:14 + --> $DIR/needless_range_loop.rs:53:14 | LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | for in vec.iter().take(MAX_LEN) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:53:14 + --> $DIR/needless_range_loop.rs:57:14 | LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | for in vec.iter().take(MAX_LEN + 1) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:57:14 + --> $DIR/needless_range_loop.rs:61:14 | LL | for i in 5..10 { | ^^^^^ @@ -110,7 +110,7 @@ LL | for in vec.iter().take(10).skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:61:14 + --> $DIR/needless_range_loop.rs:65:14 | LL | for i in 5..=10 { | ^^^^^^ @@ -121,7 +121,7 @@ LL | for in vec.iter().take(10 + 1).skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:65:14 + --> $DIR/needless_range_loop.rs:69:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | for (i, ) in vec.iter().enumerate().skip(5) { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:69:14 + --> $DIR/needless_range_loop.rs:73:14 | LL | for i in 5..10 { | ^^^^^ @@ -143,7 +143,7 @@ LL | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:74:14 + --> $DIR/needless_range_loop.rs:78:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ diff --git a/tests/ui/needless_range_loop2.rs b/tests/ui/needless_range_loop2.rs index 7633316e0f877..516d99a3532af 100644 --- a/tests/ui/needless_range_loop2.rs +++ b/tests/ui/needless_range_loop2.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_range_loop)] +#![allow(clippy::useless_vec)] fn calc_idx(i: usize) -> usize { (i + i + 20) % 4 diff --git a/tests/ui/needless_range_loop2.stderr b/tests/ui/needless_range_loop2.stderr index 1e6ec5e667aa0..8c4f5d954a975 100644 --- a/tests/ui/needless_range_loop2.stderr +++ b/tests/ui/needless_range_loop2.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `ns` - --> $DIR/needless_range_loop2.rs:10:14 + --> $DIR/needless_range_loop2.rs:11:14 | LL | for i in 3..10 { | ^^^^^ @@ -11,7 +11,7 @@ LL | for in ns.iter().take(10).skip(3) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `ms` - --> $DIR/needless_range_loop2.rs:31:14 + --> $DIR/needless_range_loop2.rs:32:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | for in &mut ms { | ~~~~~~ ~~~~~~~ error: the loop variable `i` is only used to index `ms` - --> $DIR/needless_range_loop2.rs:37:14 + --> $DIR/needless_range_loop2.rs:38:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for in &mut ms { | ~~~~~~ ~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop2.rs:61:14 + --> $DIR/needless_range_loop2.rs:62:14 | LL | for i in x..x + 4 { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | for in vec.iter_mut().skip(x).take(4) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop2.rs:68:14 + --> $DIR/needless_range_loop2.rs:69:14 | LL | for i in x..=x + 4 { | ^^^^^^^^^ @@ -55,7 +55,7 @@ LL | for in vec.iter_mut().skip(x).take(4 + 1) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:74:14 + --> $DIR/needless_range_loop2.rs:75:14 | LL | for i in 0..3 { | ^^^^ @@ -66,7 +66,7 @@ LL | for in &arr { | ~~~~~~ ~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:78:14 + --> $DIR/needless_range_loop2.rs:79:14 | LL | for i in 0..2 { | ^^^^ @@ -77,7 +77,7 @@ LL | for in arr.iter().take(2) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:82:14 + --> $DIR/needless_range_loop2.rs:83:14 | LL | for i in 1..3 { | ^^^^ diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed new file mode 100644 index 0000000000000..6438e46977bbd --- /dev/null +++ b/tests/ui/needless_raw_string.fixed @@ -0,0 +1,16 @@ +//@run-rustfix +#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] +#![warn(clippy::needless_raw_strings)] +#![feature(c_str_literals)] + +fn main() { + "aaa"; + r#""aaa""#; + r#"\s"#; + b"aaa"; + br#""aaa""#; + br#"\s"#; + c"aaa"; + cr#""aaa""#; + cr#"\s"#; +} diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs new file mode 100644 index 0000000000000..f7ddc68265edf --- /dev/null +++ b/tests/ui/needless_raw_string.rs @@ -0,0 +1,16 @@ +//@run-rustfix +#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] +#![warn(clippy::needless_raw_strings)] +#![feature(c_str_literals)] + +fn main() { + r#"aaa"#; + r#""aaa""#; + r#"\s"#; + br#"aaa"#; + br#""aaa""#; + br#"\s"#; + cr#"aaa"#; + cr#""aaa""#; + cr#"\s"#; +} diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr new file mode 100644 index 0000000000000..0179978b7b08c --- /dev/null +++ b/tests/ui/needless_raw_string.stderr @@ -0,0 +1,22 @@ +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:7:5 + | +LL | r#"aaa"#; + | ^^^^^^^^ help: try: `"aaa"` + | + = note: `-D clippy::needless-raw-strings` implied by `-D warnings` + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:10:5 + | +LL | br#"aaa"#; + | ^^^^^^^^^ help: try: `b"aaa"` + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:13:5 + | +LL | cr#"aaa"#; + | ^^^^^^^^^ help: try: `c"aaa"` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed new file mode 100644 index 0000000000000..e4d7d8fb017a9 --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -0,0 +1,19 @@ +//@run-rustfix +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] +#![feature(c_str_literals)] + +fn main() { + r#"aaa"#; + r#"Hello "world"!"#; + r####" "### "## "# "####; + r###" "aa" "# "## "###; + br#"aaa"#; + br#"Hello "world"!"#; + br####" "### "## "# "####; + br###" "aa" "# "## "###; + cr#"aaa"#; + cr#"Hello "world"!"#; + cr####" "### "## "# "####; + cr###" "aa" "# "## "###; +} diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs new file mode 100644 index 0000000000000..e2d85c52e78cc --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.rs @@ -0,0 +1,19 @@ +//@run-rustfix +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] +#![feature(c_str_literals)] + +fn main() { + r#"aaa"#; + r##"Hello "world"!"##; + r######" "### "## "# "######; + r######" "aa" "# "## "######; + br#"aaa"#; + br##"Hello "world"!"##; + br######" "### "## "# "######; + br######" "aa" "# "## "######; + cr#"aaa"#; + cr##"Hello "world"!"##; + cr######" "### "## "# "######; + cr######" "aa" "# "## "######; +} diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr new file mode 100644 index 0000000000000..dff47a2d04212 --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.stderr @@ -0,0 +1,58 @@ +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:8:5 + | +LL | r##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `r#"Hello "world"!"#` + | + = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:9:5 + | +LL | r######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:10:5 + | +LL | r######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r###" "aa" "# "## "###` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:12:5 + | +LL | br##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `br#"Hello "world"!"#` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:13:5 + | +LL | br######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:14:5 + | +LL | br######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:16:5 + | +LL | cr##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:17:5 + | +LL | cr######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:18:5 + | +LL | cr######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 29821ff96fc0f..eb179f30e75e2 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,4 +1,6 @@ +#![feature(inline_const)] #![allow( + clippy::eq_op, clippy::single_match, unused_assignments, unused_variables, @@ -295,6 +297,42 @@ pub fn test24() { } } +// Do not lint, we can evaluate `true` to always succeed thus can short-circuit before the `return` +pub fn test25() { + loop { + 'label: { + if const { true } { + break 'label; + } + return; + } + } +} + +pub fn test26() { + loop { + 'label: { + if 1 == 1 { + break 'label; + } + return; + } + } +} + +pub fn test27() { + loop { + 'label: { + let x = true; + // Lints because we cannot prove it's always `true` + if x { + break 'label; + } + return; + } + } +} + fn main() { test1(); test2(); diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 704d448644e28..0446c09cd5bcc 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,5 +1,5 @@ error: this loop never actually loops - --> $DIR/never_loop.rs:10:5 + --> $DIR/never_loop.rs:12:5 | LL | / loop { LL | | // clippy::never_loop @@ -13,7 +13,7 @@ LL | | } = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops - --> $DIR/never_loop.rs:32:5 + --> $DIR/never_loop.rs:34:5 | LL | / loop { LL | | // never loops @@ -23,7 +23,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:52:5 + --> $DIR/never_loop.rs:54:5 | LL | / loop { LL | | // never loops @@ -35,7 +35,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:54:9 + --> $DIR/never_loop.rs:56:9 | LL | / while i == 0 { LL | | // never loops @@ -44,7 +44,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:66:9 + --> $DIR/never_loop.rs:68:9 | LL | / loop { LL | | // never loops @@ -56,7 +56,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:102:5 + --> $DIR/never_loop.rs:104:5 | LL | / while let Some(y) = x { LL | | // never loops @@ -65,7 +65,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:109:5 + --> $DIR/never_loop.rs:111:5 | LL | / for x in 0..10 { LL | | // never loops @@ -82,7 +82,7 @@ LL | if let Some(x) = (0..10).next() { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: this loop never actually loops - --> $DIR/never_loop.rs:157:5 + --> $DIR/never_loop.rs:159:5 | LL | / 'outer: while a { LL | | // never loops @@ -94,7 +94,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:172:9 + --> $DIR/never_loop.rs:174:9 | LL | / while false { LL | | break 'label; @@ -102,7 +102,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:223:13 + --> $DIR/never_loop.rs:225:13 | LL | let _ = loop { | _____________^ @@ -115,7 +115,7 @@ LL | | }; | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:244:5 + --> $DIR/never_loop.rs:246:5 | LL | / 'a: loop { LL | | 'b: { @@ -126,8 +126,16 @@ LL | | } LL | | } | |_____^ +error: sub-expression diverges + --> $DIR/never_loop.rs:249:17 + | +LL | break 'a; + | ^^^^^^^^ + | + = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` + error: this loop never actually loops - --> $DIR/never_loop.rs:278:13 + --> $DIR/never_loop.rs:280:13 | LL | / for _ in 0..20 { LL | | break 'block; @@ -139,5 +147,17 @@ help: if you need the first element of the iterator, try writing LL | if let Some(_) = (0..20).next() { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 12 previous errors +error: this loop never actually loops + --> $DIR/never_loop.rs:324:5 + | +LL | / loop { +LL | | 'label: { +LL | | let x = true; +LL | | // Lints because we cannot prove it's always `true` +... | +LL | | } +LL | | } + | |_____^ + +error: aborting due to 14 previous errors diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 1e42e1fbabfeb..6a726941be893 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -5,7 +5,8 @@ clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args, - clippy::unnecessary_struct_initialization + clippy::unnecessary_struct_initialization, + clippy::useless_vec )] struct Unit; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index f10f2bcf2a8a0..64edfc32504e5 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:98:5 | LL | 0; | ^^ @@ -7,151 +7,151 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:99:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:100:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:101:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:102:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:103:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:104:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:105:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:106:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:107:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:108:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:109:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:110:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:111:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:112:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:113:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:114:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:115:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:116:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:117:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:117:5 + --> $DIR/no_effect.rs:118:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:118:5 + --> $DIR/no_effect.rs:119:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:119:5 + --> $DIR/no_effect.rs:120:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:121:5 + --> $DIR/no_effect.rs:122:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:123:5 + --> $DIR/no_effect.rs:124:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:124:5 + --> $DIR/no_effect.rs:125:5 | LL | let _unused = 1; | ^^^^^^^^^^^^^^^^ @@ -159,19 +159,19 @@ LL | let _unused = 1; = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:125:5 + --> $DIR/no_effect.rs:126:5 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:126:5 + --> $DIR/no_effect.rs:127:5 | LL | let _duck = Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:127:5 + --> $DIR/no_effect.rs:128:5 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/no_effect_return.rs b/tests/ui/no_effect_return.rs new file mode 100644 index 0000000000000..231dd063ad893 --- /dev/null +++ b/tests/ui/no_effect_return.rs @@ -0,0 +1,81 @@ +#![allow(clippy::unused_unit, dead_code, unused)] +#![no_main] + +use std::ops::ControlFlow; + +fn a() -> u32 { + { + 0u32; + } + 0 +} + +async fn b() -> u32 { + { + 0u32; + } + 0 +} + +type C = i32; +async fn c() -> C { + { + 0i32 as C; + } + 0 +} + +fn d() -> u128 { + { + // not last stmt + 0u128; + println!("lol"); + } + 0 +} + +fn e() -> u32 { + { + // mismatched types + 0u16; + } + 0 +} + +fn f() -> [u16; 1] { + { + [1u16]; + } + [1] +} + +fn g() -> ControlFlow<()> { + { + ControlFlow::Break::<()>(()); + } + ControlFlow::Continue(()) +} + +fn h() -> Vec { + { + // function call, so this won't trigger `no_effect`. not an issue with this change, but the + // lint itself (but also not really.) + vec![0u16]; + } + vec![] +} + +fn i() -> () { + { + (); + } + () +} + +fn j() { + { + // does not suggest on function without explicit return type + (); + } + () +} diff --git a/tests/ui/no_effect_return.stderr b/tests/ui/no_effect_return.stderr new file mode 100644 index 0000000000000..779900e185908 --- /dev/null +++ b/tests/ui/no_effect_return.stderr @@ -0,0 +1,70 @@ +error: statement with no effect + --> $DIR/no_effect_return.rs:8:9 + | +LL | 0u32; + | -^^^^ + | | + | help: did you mean to return it?: `return` + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: statement with no effect + --> $DIR/no_effect_return.rs:15:9 + | +LL | 0u32; + | -^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:23:9 + | +LL | 0i32 as C; + | -^^^^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:31:9 + | +LL | 0u128; + | ^^^^^^ + +error: statement with no effect + --> $DIR/no_effect_return.rs:40:9 + | +LL | 0u16; + | ^^^^^ + +error: statement with no effect + --> $DIR/no_effect_return.rs:47:9 + | +LL | [1u16]; + | -^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:54:9 + | +LL | ControlFlow::Break::<()>(()); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:70:9 + | +LL | (); + | -^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:78:9 + | +LL | (); + | ^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 583096ac054a1..987a4775ef074 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -25,9 +25,9 @@ impl MaybeInst { } fn underscores_and_numbers() { - let _1 = 1; //~ERROR Consider a more descriptive name - let ____1 = 1; //~ERROR Consider a more descriptive name - let __1___2 = 12; //~ERROR Consider a more descriptive name + let _1 = 1; //~ERROR: consider choosing a more descriptive name + let ____1 = 1; //~ERROR: consider choosing a more descriptive name + let __1___2 = 12; //~ERROR: consider choosing a more descriptive name let _1_ok = 1; } @@ -48,9 +48,9 @@ struct Bar; impl Bar { fn bar() { - let _1 = 1; - let ____1 = 1; - let __1___2 = 12; + let _1 = 1; //~ERROR: consider choosing a more descriptive name + let ____1 = 1; //~ERROR: consider choosing a more descriptive name + let __1___2 = 12; //~ERROR: consider choosing a more descriptive name let _1_ok = 1; } } diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 116d5da8729c0..b62748d4989df 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,7 +1,7 @@ error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:28:9 | -LL | let _1 = 1; //~ERROR Consider a more descriptive name +LL | let _1 = 1; | ^^ | = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` @@ -9,13 +9,13 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:29:9 | -LL | let ____1 = 1; //~ERROR Consider a more descriptive name +LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:30:9 | -LL | let __1___2 = 12; //~ERROR Consider a more descriptive name +LL | let __1___2 = 12; | ^^^^^^^ error: consider choosing a more descriptive name diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed index 89d127528347c..5d0da8dce6702 100644 --- a/tests/ui/non_octal_unix_permissions.fixed +++ b/tests/ui/non_octal_unix_permissions.fixed @@ -1,4 +1,4 @@ -//@ignore-windows +//@ignore-target-windows //@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs index 1b3a322d72658..04a3643050e69 100644 --- a/tests/ui/non_octal_unix_permissions.rs +++ b/tests/ui/non_octal_unix_permissions.rs @@ -1,4 +1,4 @@ -//@ignore-windows +//@ignore-target-windows //@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index fec6b7713eef8..e4aa0937b9779 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -1,6 +1,7 @@ #![feature(lint_reasons)] -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] +#![allow(clippy::useless_vec)] fn main() { let a: bool = unimplemented!(); diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr index 91b5805aa97ab..e2e4d6477c9f1 100644 --- a/tests/ui/nonminimal_bool.stderr +++ b/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:11:13 + --> $DIR/nonminimal_bool.rs:12:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -7,43 +7,43 @@ LL | let _ = !true; = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:12:13 + --> $DIR/nonminimal_bool.rs:13:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:13:13 + --> $DIR/nonminimal_bool.rs:14:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:14:13 + --> $DIR/nonminimal_bool.rs:15:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:18:13 + --> $DIR/nonminimal_bool.rs:19:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:19:13 + --> $DIR/nonminimal_bool.rs:20:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:20:13 + --> $DIR/nonminimal_bool.rs:21:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:28:13 + --> $DIR/nonminimal_bool.rs:29:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:29:13 + --> $DIR/nonminimal_bool.rs:30:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:30:13 + --> $DIR/nonminimal_bool.rs:31:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:31:13 + --> $DIR/nonminimal_bool.rs:32:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:32:13 + --> $DIR/nonminimal_bool.rs:33:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let _ = a != b && c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:62:8 + --> $DIR/nonminimal_bool.rs:63:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed index 05802a2c865fb..294f2aa48f1c8 100644 --- a/tests/ui/nonminimal_bool_methods.fixed +++ b/tests/ui/nonminimal_bool_methods.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] fn methods_with_negation() { diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs index cd5b576fa07e1..a165368ab17dd 100644 --- a/tests/ui/nonminimal_bool_methods.rs +++ b/tests/ui/nonminimal_bool_methods.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] fn methods_with_negation() { diff --git a/tests/ui/octal_escapes.stderr b/tests/ui/octal_escapes.stderr index aa362e96321bd..63fdfe486e812 100644 --- a/tests/ui/octal_escapes.stderr +++ b/tests/ui/octal_escapes.stderr @@ -34,17 +34,17 @@ LL | let _bad2 = b"/x0033[0m"; error: octal-looking escape in string literal --> $DIR/octal_escapes.rs:6:17 | -LL | let _bad3 = "//033[0m"; +LL | let _bad3 = "///033[0m"; | ^^^^^^^^^^^ | = help: octal escapes are not supported, `/0` is always a null character help: if an octal escape was intended, use the hexadecimal representation instead | -LL | let _bad3 = "//x1b[0m"; +LL | let _bad3 = "///x1b[0m"; | ~~~~~~~~~~~ help: if the null character is intended, disambiguate using | -LL | let _bad3 = "//x0033[0m"; +LL | let _bad3 = "///x0033[0m"; | ~~~~~~~~~~~~~ error: octal-looking escape in string literal diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index ff68d38c73bf5..2047ee689d95c 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_literal_unwrap)] + use std::io; struct MyError(()); // doesn't implement Debug diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 6c40adbb53dc2..ab9df26ebc37e 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,5 +1,5 @@ error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:14:5 + --> $DIR/ok_expect.rs:16:5 | LL | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | res.ok().expect("disaster!"); = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:20:5 + --> $DIR/ok_expect.rs:22:5 | LL | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | res3.ok().expect("whoof"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:22:5 + --> $DIR/ok_expect.rs:24:5 | LL | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | res4.ok().expect("argh"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:24:5 + --> $DIR/ok_expect.rs:26:5 | LL | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | res5.ok().expect("oops"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:26:5 + --> $DIR/ok_expect.rs:28:5 | LL | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index e1c0fa3f7fd39..4d1a6a1ab98d1 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone)] +#![allow(unused, clippy::redundant_clone, clippy::useless_vec)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 6f4917fd149c9..66d5a1250360d 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone)] +#![allow(unused, clippy::redundant_clone, clippy::useless_vec)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index ee1fe3f1fc0fc..65a1b467f8114 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::option_env_unwrap)] #![allow(clippy::map_flatten)] diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 2b8ce5477cc6d..8e59e4375d2e8 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -208,3 +208,19 @@ fn issue9742() -> Option<&'static str> { _ => None, } } + +mod issue10729 { + #![allow(clippy::unit_arg, dead_code)] + + pub fn reproduce(initial: &Option) { + // 👇 needs `.as_ref()` because initial is an `&Option<_>` + initial.as_ref().map_or({}, |value| do_something(value)) + } + + pub fn reproduce2(initial: &mut Option) { + initial.as_mut().map_or({}, |value| do_something2(value)) + } + + fn do_something(_value: &str) {} + fn do_something2(_value: &mut str) {} +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index cfbec8cb27da1..e72edf2a8e318 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -249,3 +249,25 @@ fn issue9742() -> Option<&'static str> { _ => None, } } + +mod issue10729 { + #![allow(clippy::unit_arg, dead_code)] + + pub fn reproduce(initial: &Option) { + // 👇 needs `.as_ref()` because initial is an `&Option<_>` + match initial { + Some(value) => do_something(value), + None => {}, + } + } + + pub fn reproduce2(initial: &mut Option) { + match initial { + Some(value) => do_something2(value), + None => {}, + } + } + + fn do_something(_value: &str) {} + fn do_something2(_value: &mut str) {} +} diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 91d52fc79b810..aa2da21740032 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -271,5 +271,23 @@ error: use Option::map_or instead of an if let/else LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` -error: aborting due to 21 previous errors +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:258:9 + | +LL | / match initial { +LL | | Some(value) => do_something(value), +LL | | None => {}, +LL | | } + | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:265:9 + | +LL | / match initial { +LL | | Some(value) => do_something2(value), +LL | | None => {}, +LL | | } + | |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))` + +error: aborting due to 23 previous errors diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index f723a55f77f81..703debb7a26ae 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -1,7 +1,13 @@ //@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] -#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] +#![allow( + clippy::borrow_as_ptr, + clippy::uninlined_format_args, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::useless_vec +)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 61ef6e27f3228..bb86fe0d45fa0 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -1,7 +1,13 @@ //@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] -#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] +#![allow( + clippy::borrow_as_ptr, + clippy::uninlined_format_args, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::useless_vec +)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index ba3001db7a5f4..0b5c686bec0d9 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:48:22 + --> $DIR/or_fun_call.rs:54:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -7,163 +7,163 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:51:14 + --> $DIR/or_fun_call.rs:57:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:54:21 + --> $DIR/or_fun_call.rs:60:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:57:14 + --> $DIR/or_fun_call.rs:63:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:60:19 + --> $DIR/or_fun_call.rs:66:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:63:24 + --> $DIR/or_fun_call.rs:69:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:66:23 + --> $DIR/or_fun_call.rs:72:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:69:18 + --> $DIR/or_fun_call.rs:75:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(::default)` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:72:18 + --> $DIR/or_fun_call.rs:78:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:75:14 + --> $DIR/or_fun_call.rs:81:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:78:21 + --> $DIR/or_fun_call.rs:84:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:81:19 + --> $DIR/or_fun_call.rs:87:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:84:23 + --> $DIR/or_fun_call.rs:90:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:87:21 + --> $DIR/or_fun_call.rs:93:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:90:25 + --> $DIR/or_fun_call.rs:96:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:93:21 + --> $DIR/or_fun_call.rs:99:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:101:21 + --> $DIR/or_fun_call.rs:107:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:103:21 + --> $DIR/or_fun_call.rs:109:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:127:35 + --> $DIR/or_fun_call.rs:133:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:166:14 + --> $DIR/or_fun_call.rs:172:14 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:172:14 + --> $DIR/or_fun_call.rs:178:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:174:14 + --> $DIR/or_fun_call.rs:180:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:188:14 + --> $DIR/or_fun_call.rs:194:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:201:14 + --> $DIR/or_fun_call.rs:207:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:213:14 + --> $DIR/or_fun_call.rs:219:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:224:10 + --> $DIR/or_fun_call.rs:230:10 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:249:25 + --> $DIR/or_fun_call.rs:255:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:250:25 + --> $DIR/or_fun_call.rs:256:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)` diff --git a/tests/ui/or_then_unwrap.fixed b/tests/ui/or_then_unwrap.fixed index 40badac4424ac..773dfc3c5d148 100644 --- a/tests/ui/or_then_unwrap.fixed +++ b/tests/ui/or_then_unwrap.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::or_then_unwrap)] -#![allow(clippy::map_identity, clippy::let_unit_value)] +#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)] struct SomeStruct; impl SomeStruct { diff --git a/tests/ui/or_then_unwrap.rs b/tests/ui/or_then_unwrap.rs index 76c9942fe6c1d..5867e014878e2 100644 --- a/tests/ui/or_then_unwrap.rs +++ b/tests/ui/or_then_unwrap.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::or_then_unwrap)] -#![allow(clippy::map_identity, clippy::let_unit_value)] +#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)] struct SomeStruct; impl SomeStruct { diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index e1e30114081ef..14a6b98d07d14 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,4 +1,5 @@ #![warn(clippy::overflow_check_conditional)] +#![allow(clippy::needless_if)] fn test(a: u32, b: u32, c: u32) { if a + b < a {} diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 92d1d8ef911ef..3ec2298f828ae 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,5 +1,5 @@ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:4:8 + --> $DIR/overflow_check_conditional.rs:5:8 | LL | if a + b < a {} | ^^^^^^^^^ @@ -7,43 +7,43 @@ LL | if a + b < a {} = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:5:8 + --> $DIR/overflow_check_conditional.rs:6:8 | LL | if a > a + b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:6:8 + --> $DIR/overflow_check_conditional.rs:7:8 | LL | if a + b < b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:7:8 + --> $DIR/overflow_check_conditional.rs:8:8 | LL | if b > a + b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:8:8 + --> $DIR/overflow_check_conditional.rs:9:8 | LL | if a - b > b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:9:8 + --> $DIR/overflow_check_conditional.rs:10:8 | LL | if b < a - b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:10:8 + --> $DIR/overflow_check_conditional.rs:11:8 | LL | if a - b > a {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:11:8 + --> $DIR/overflow_check_conditional.rs:12:8 | LL | if a < a - b {} | ^^^^^^^^^ diff --git a/tests/ui/partialeq_to_none.fixed b/tests/ui/partialeq_to_none.fixed index 2df87a26d6d15..95e184b1de6cb 100644 --- a/tests/ui/partialeq_to_none.fixed +++ b/tests/ui/partialeq_to_none.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::partialeq_to_none)] -#![allow(clippy::eq_op)] +#![allow(clippy::eq_op, clippy::needless_if)] struct Foobar; diff --git a/tests/ui/partialeq_to_none.rs b/tests/ui/partialeq_to_none.rs index df6233b9afd63..4fa50dcc11b6e 100644 --- a/tests/ui/partialeq_to_none.rs +++ b/tests/ui/partialeq_to_none.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::partialeq_to_none)] -#![allow(clippy::eq_op)] +#![allow(clippy::eq_op, clippy::needless_if)] struct Foobar; diff --git a/tests/ui/patterns.fixed b/tests/ui/patterns.fixed index a1da47d84fd5c..714143e758694 100644 --- a/tests/ui/patterns.fixed +++ b/tests/ui/patterns.fixed @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] +#[macro_use] +extern crate proc_macros; + fn main() { let v = Some(true); let s = [0, 1, 2, 3, 4]; @@ -34,4 +38,11 @@ fn main() { ref x => println!("vec: {:?}", x), ref y if y == &vec![0] => (), } + external! { + let v = Some(true); + match v { + Some(x) => (), + y @ _ => (), + } + } } diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 399066b813e3e..153e264070173 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] +#[macro_use] +extern crate proc_macros; + fn main() { let v = Some(true); let s = [0, 1, 2, 3, 4]; @@ -34,4 +38,11 @@ fn main() { ref x @ _ => println!("vec: {:?}", x), ref y if y == &vec![0] => (), } + external! { + let v = Some(true); + match v { + Some(x) => (), + y @ _ => (), + } + } } diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 2c46b4eb593e3..276330d21c424 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,5 +1,5 @@ error: the `y @ _` pattern can be written as just `y` - --> $DIR/patterns.rs:11:9 + --> $DIR/patterns.rs:15:9 | LL | y @ _ => (), | ^^^^^ help: try: `y` @@ -7,13 +7,13 @@ LL | y @ _ => (), = note: `-D clippy::redundant-pattern` implied by `-D warnings` error: the `x @ _` pattern can be written as just `x` - --> $DIR/patterns.rs:26:9 + --> $DIR/patterns.rs:30:9 | LL | ref mut x @ _ => { | ^^^^^^^^^^^^^ help: try: `ref mut x` error: the `x @ _` pattern can be written as just `x` - --> $DIR/patterns.rs:34:9 + --> $DIR/patterns.rs:38:9 | LL | ref x @ _ => println!("vec: {:?}", x), | ^^^^^^^^^ help: try: `ref x` diff --git a/tests/ui/print_with_newline.fixed b/tests/ui/print_with_newline.fixed new file mode 100644 index 0000000000000..6098dea39911b --- /dev/null +++ b/tests/ui/print_with_newline.fixed @@ -0,0 +1,58 @@ +// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 +//@run-rustfix + +#![allow(clippy::print_literal)] +#![warn(clippy::print_with_newline)] + +fn main() { + println!("Hello"); + println!("Hello {}", "world"); + println!("Hello {} {}", "world", "#2"); + println!("{}", 1265); + println!(); + + // these are all fine + print!(""); + print!("Hello"); + println!("Hello"); + println!("Hello\n"); + println!("Hello {}\n", "world"); + print!("Issue\n{}", 1265); + print!("{}", 1265); + print!("\n{}", 1275); + print!("\n\n"); + print!("like eof\n\n"); + print!("Hello {} {}\n\n", "world", "#2"); + println!("\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + println!("\nbla\n\n"); // #3126 + + // Escaping + print!("\\n"); // #3514 + println!("\\"); // should fail + print!("\\\\n"); + + // Raw strings + print!(r"\n"); // #3778 + + // Literal newlines should also fail + println!( + + ); + println!( + + ); + + // Don't warn on CRLF (#4208) + print!("\r\n"); + print!("foo\r\n"); + println!("\\r"); // should fail + print!("foo\rbar\n"); + + // Ignore expanded format strings + macro_rules! newline { + () => { + "\n" + }; + } + print!(newline!()); +} diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index ff79ca75ffaab..d9c7acc274802 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -47,7 +47,7 @@ fn main() { // Don't warn on CRLF (#4208) print!("\r\n"); print!("foo\r\n"); - print!("\\r\n"); //~ ERROR + print!("\\r\n"); // should fail print!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index b9f5675faec73..b97711e777dd7 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -62,13 +62,13 @@ LL + println!(); error: using `print!()` with a format string that ends in a single newline --> $DIR/print_with_newline.rs:31:5 | -LL | print!("//n"); // should fail +LL | print!("///n"); // should fail | ^^^^^^^^^^^^^^ | help: use `println!` instead | -LL - print!("//n"); // should fail -LL + println!("/"); // should fail +LL - print!("///n"); // should fail +LL + println!("//"); // should fail | error: using `print!()` with a format string that ends in a single newline @@ -104,13 +104,13 @@ LL ~ error: using `print!()` with a format string that ends in a single newline --> $DIR/print_with_newline.rs:50:5 | -LL | print!("/r/n"); //~ ERROR +LL | print!("//r/n"); // should fail | ^^^^^^^^^^^^^^^ | help: use `println!` instead | -LL - print!("/r/n"); //~ ERROR -LL + println!("/r"); //~ ERROR +LL - print!("//r/n"); // should fail +LL + println!("//r"); // should fail | error: aborting due to 9 previous errors diff --git a/tests/ui/proc_macro.rs b/tests/ui/proc_macro.rs index 59914b8b8f627..b77874034d0ba 100644 --- a/tests/ui/proc_macro.rs +++ b/tests/ui/proc_macro.rs @@ -1,5 +1,4 @@ //! Check that we correctly lint procedural macros. -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc_macro.stderr b/tests/ui/proc_macro.stderr index c795f6ad0d25f..d912b50275512 100644 --- a/tests/ui/proc_macro.stderr +++ b/tests/ui/proc_macro.stderr @@ -1,5 +1,5 @@ error: approximate value of `f{32, 64}::consts::PI` found - --> $DIR/proc_macro.rs:10:14 + --> $DIR/proc_macro.rs:9:14 | LL | let _x = 3.14; | ^^^^ diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 5f54101ca15ad..709f74ee6aa2a 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,5 +1,10 @@ #![feature(lint_reasons)] -#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] +#![allow( + unused, + clippy::many_single_char_names, + clippy::needless_lifetimes, + clippy::redundant_clone +)] #![warn(clippy::ptr_arg)] use std::borrow::Cow; @@ -235,3 +240,29 @@ fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { takes_dyn(b); takes_dyn(c); } + +mod issue_9218 { + use std::borrow::Cow; + + fn cow_non_elided_lifetime<'a>(input: &Cow<'a, str>) -> &'a str { + todo!() + } + + // This one has an anonymous lifetime so it's not okay + fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { + todo!() + } + + // These two's return types don't use use 'a so it's not okay + fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { + todo!() + } + fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { + todo!() + } + + // Inferred to be `&'a str`, afaik. + fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + todo!() + } +} diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 6b4de98ce88c6..d663b070b9cfd 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:8:14 + --> $DIR/ptr_arg.rs:13:14 | LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec) { = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:12:18 + --> $DIR/ptr_arg.rs:17:18 | LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:16:14 + --> $DIR/ptr_arg.rs:21:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:20:18 + --> $DIR/ptr_arg.rs:25:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:24:15 + --> $DIR/ptr_arg.rs:29:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:28:19 + --> $DIR/ptr_arg.rs:33:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:36:18 + --> $DIR/ptr_arg.rs:41:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:49:14 + --> $DIR/ptr_arg.rs:54:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -60,7 +60,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:58:18 + --> $DIR/ptr_arg.rs:63:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -76,7 +76,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:66:19 + --> $DIR/ptr_arg.rs:71:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:74:44 + --> $DIR/ptr_arg.rs:79:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -106,19 +106,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:88:25 + --> $DIR/ptr_arg.rs:93:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:117:66 + --> $DIR/ptr_arg.rs:122:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:146:21 + --> $DIR/ptr_arg.rs:151:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -131,7 +131,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:151:23 + --> $DIR/ptr_arg.rs:156:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -144,7 +144,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:156:21 + --> $DIR/ptr_arg.rs:161:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -157,28 +157,46 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:162:29 + --> $DIR/ptr_arg.rs:167:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:17 + --> $DIR/ptr_arg.rs:229:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:35 + --> $DIR/ptr_arg.rs:229:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:51 + --> $DIR/ptr_arg.rs:229:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` -error: aborting due to 20 previous errors +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:252:39 + | +LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { + | ^^^^^^^^^^^^ help: change this to: `&str` + +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:257:36 + | +LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { + | ^^^^^^^^^^^^^^^^ help: change this to: `&str` + +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:260:40 + | +LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { + | ^^^^^^^^^^^^^^^^ help: change this to: `&str` + +error: aborting due to 23 previous errors diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index 2c2567d67cd9c..26a64c861cf4d 100644 --- a/tests/ui/ptr_as_ptr.fixed +++ b/tests/ui/ptr_as_ptr.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index 6000e5c08acbc..ea40d4947331b 100644 --- a/tests/ui/ptr_as_ptr.rs +++ b/tests/ui/ptr_as_ptr.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 24de573d0838e..1ef1809d15305 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -1,18 +1,25 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_cast_constness)] +#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; +unsafe fn ptr_to_ref(p: *const T, om: *mut U) { + let _: &mut T = std::mem::transmute(p.cast_mut()); + let _ = &mut *p.cast_mut(); + let _: &T = &*(om as *const T); +} + #[inline_macros] fn main() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *const i32; - let _ = mut_ptr as *mut i32; + let _ = ptr as *const u32; + let _ = mut_ptr as *mut u32; // Make sure the lint can handle the difference in their operator precedences. unsafe { @@ -29,10 +36,10 @@ fn main() { let _ = ptr_of_array as *const dyn std::fmt::Debug; // Make sure the lint is triggered inside a macro - let _ = inline!($ptr as *const i32); + let _ = inline!($ptr as *const u32); // Do not lint inside macros from external crates - let _ = external!($ptr as *const i32); + let _ = external!($ptr as *const u32); } #[clippy::msrv = "1.64"] @@ -41,8 +48,8 @@ fn _msrv_1_64() { let mut_ptr: *mut u32 = &mut 42_u32; // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } #[clippy::msrv = "1.65"] diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 63d973a9fca87..2c15cd429daf6 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -1,27 +1,34 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_cast_constness)] +#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; +unsafe fn ptr_to_ref(p: *const T, om: *mut U) { + let _: &mut T = std::mem::transmute(p as *mut T); + let _ = &mut *(p as *mut T); + let _: &T = &*(om as *const T); +} + #[inline_macros] fn main() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *const i32; - let _ = mut_ptr as *mut i32; + let _ = ptr as *const u32; + let _ = mut_ptr as *mut u32; // Make sure the lint can handle the difference in their operator precedences. unsafe { let ptr_ptr: *const *const u32 = &ptr; - let _ = *ptr_ptr as *mut i32; + let _ = *ptr_ptr as *mut u32; } - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; @@ -29,10 +36,10 @@ fn main() { let _ = ptr_of_array as *const dyn std::fmt::Debug; // Make sure the lint is triggered inside a macro - let _ = inline!($ptr as *const i32); + let _ = inline!($ptr as *const u32); // Do not lint inside macros from external crates - let _ = external!($ptr as *const i32); + let _ = external!($ptr as *const u32); } #[clippy::msrv = "1.64"] @@ -41,8 +48,8 @@ fn _msrv_1_64() { let mut_ptr: *mut u32 = &mut 42_u32; // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } #[clippy::msrv = "1.65"] @@ -50,6 +57,6 @@ fn _msrv_1_65() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 43816c87c1907..0c3ff863685ba 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -1,34 +1,46 @@ -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:20:17 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:11:41 | -LL | let _ = *ptr_ptr as *mut i32; - | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` +LL | let _: &mut T = std::mem::transmute(p as *mut T); + | ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` | = note: `-D clippy::ptr-cast-constness` implied by `-D warnings` -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:23:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:12: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 + --> $DIR/ptr_cast_constness.rs:27: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 + --> $DIR/ptr_cast_constness.rs:30:13 | -LL | let _ = ptr as *mut i32; +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 its constness - --> $DIR/ptr_cast_constness.rs:24:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:31:13 | -LL | let _ = mut_ptr as *const i32; +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 its constness - --> $DIR/ptr_cast_constness.rs:53:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:60:13 | -LL | let _ = ptr as *mut i32; +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 its constness - --> $DIR/ptr_cast_constness.rs:54:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:61:13 | -LL | let _ = mut_ptr as *const i32; +LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index f69bc131898f7..6ffa401d76172 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::unnecessary_cast)] +#![allow(clippy::unnecessary_cast, clippy::useless_vec)] fn main() { let vec = vec![b'a', b'b', b'c']; diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index eae36c27729e8..de1f86cb855c6 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::unnecessary_cast)] +#![allow(clippy::unnecessary_cast, clippy::useless_vec)] fn main() { let vec = vec![b'a', b'b', b'c']; diff --git a/tests/ui/pub_with_shorthand.fixed b/tests/ui/pub_with_shorthand.fixed new file mode 100644 index 0000000000000..a774faa0a673b --- /dev/null +++ b/tests/ui/pub_with_shorthand.fixed @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_with_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(in self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(in super) fn e() {} + pub(in self) fn f() {} + pub(in crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_with_shorthand.rs b/tests/ui/pub_with_shorthand.rs new file mode 100644 index 0000000000000..4a4bbc18728e9 --- /dev/null +++ b/tests/ui/pub_with_shorthand.rs @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_with_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_with_shorthand.stderr b/tests/ui/pub_with_shorthand.stderr new file mode 100644 index 0000000000000..323b5a23b247b --- /dev/null +++ b/tests/ui/pub_with_shorthand.stderr @@ -0,0 +1,28 @@ +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:13:1 + | +LL | pub(self) fn a() {} + | ^^^^^^^^^ help: add it: `pub(in self)` + | + = note: `-D clippy::pub-with-shorthand` implied by `-D warnings` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:19:5 + | +LL | pub(super) fn e() {} + | ^^^^^^^^^^ help: add it: `pub(in super)` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:20:5 + | +LL | pub(self) fn f() {} + | ^^^^^^^^^ help: add it: `pub(in self)` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:21:5 + | +LL | pub(crate) fn k() {} + | ^^^^^^^^^^ help: add it: `pub(in crate)` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pub_without_shorthand.fixed b/tests/ui/pub_without_shorthand.fixed new file mode 100644 index 0000000000000..fdb49ac4d9065 --- /dev/null +++ b/tests/ui/pub_without_shorthand.fixed @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_without_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(self) fn b() {} + +pub fn c() {} +mod a { + pub(super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_without_shorthand.rs b/tests/ui/pub_without_shorthand.rs new file mode 100644 index 0000000000000..1f2ef7ece391e --- /dev/null +++ b/tests/ui/pub_without_shorthand.rs @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_without_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_without_shorthand.stderr b/tests/ui/pub_without_shorthand.stderr new file mode 100644 index 0000000000000..a18c9bf893449 --- /dev/null +++ b/tests/ui/pub_without_shorthand.stderr @@ -0,0 +1,22 @@ +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:14:1 + | +LL | pub(in self) fn b() {} + | ^^^^^^^^^^^^ help: remove it: `pub(self)` + | + = note: `-D clippy::pub-without-shorthand` implied by `-D warnings` + +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:18:5 + | +LL | pub(in super) fn d() {} + | ^^^^^^^^^^^^^ help: remove it: `pub(super)` + +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:22:5 + | +LL | pub(in crate) fn m() {} + | ^^^^^^^^^^^^^ help: remove it: `pub(crate)` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 7f1660f31fa5b..2d8920ccc42f9 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -1,4 +1,5 @@ //@run-rustfix +#![feature(try_blocks)] #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] @@ -227,6 +228,27 @@ fn pattern() -> Result<(), PatternedError> { fn main() {} +// `?` is not the same as `return None;` if inside of a try block +fn issue8628(a: Option) -> Option { + let b: Option = try { + if a.is_none() { + return None; + } + 32 + }; + b.or(Some(128)) +} + +fn issue6828_nested_body() -> Option { + try { + fn f2(a: Option) -> Option { + a?; + Some(32) + } + 123 + } +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index a90eae50ed457..69451c17ee7a6 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,4 +1,5 @@ //@run-rustfix +#![feature(try_blocks)] #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] @@ -263,6 +264,31 @@ fn pattern() -> Result<(), PatternedError> { fn main() {} +// `?` is not the same as `return None;` if inside of a try block +fn issue8628(a: Option) -> Option { + let b: Option = try { + if a.is_none() { + return None; + } + 32 + }; + b.or(Some(128)) +} + +fn issue6828_nested_body() -> Option { + try { + fn f2(a: Option) -> Option { + if a.is_none() { + return None; + // do lint here, the outer `try` is not relevant here + // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 + } + Some(32) + } + 123 + } +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 23172d7e535dd..2cfd75863081b 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,5 +1,5 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:7:5 + --> $DIR/question_mark.rs:8:5 | LL | / if a.is_none() { LL | | return None; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:52:9 + --> $DIR/question_mark.rs:53:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:56:9 + --> $DIR/question_mark.rs:57:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:60:17 + --> $DIR/question_mark.rs:61:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:66:17 + --> $DIR/question_mark.rs:67:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ @@ -47,7 +47,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:83:9 + --> $DIR/question_mark.rs:84:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -55,7 +55,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:91:9 + --> $DIR/question_mark.rs:92:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -63,7 +63,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:99:9 + --> $DIR/question_mark.rs:100:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -71,7 +71,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:106:26 + --> $DIR/question_mark.rs:107:26 | LL | let v: &Vec<_> = if let Some(ref v) = self.opt { | __________________________^ @@ -82,7 +82,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:116:17 + --> $DIR/question_mark.rs:117:17 | LL | let v = if let Some(v) = self.opt { | _________________^ @@ -93,7 +93,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:131:5 + --> $DIR/question_mark.rs:132:5 | LL | / if f().is_none() { LL | | return None; @@ -101,13 +101,13 @@ LL | | } | |_____^ help: replace it with: `f()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:143:13 + --> $DIR/question_mark.rs:144:13 | LL | let _ = if let Ok(x) = x { x } else { return x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:145:5 + --> $DIR/question_mark.rs:146:5 | LL | / if x.is_err() { LL | | return x; @@ -115,7 +115,7 @@ LL | | } | |_____^ help: replace it with: `x?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:196:5 + --> $DIR/question_mark.rs:197:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); @@ -123,12 +123,22 @@ LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:203:5 + --> $DIR/question_mark.rs:204:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); LL | | } | |_____^ help: replace it with: `func_returning_result()?;` -error: aborting due to 15 previous errors +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:281:13 + | +LL | / if a.is_none() { +LL | | return None; +LL | | // do lint here, the outer `try` is not relevant here +LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 +LL | | } + | |_____________^ help: replace it with: `a?;` + +error: aborting due to 16 previous errors diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 628282509c1a5..46edf0921bf2c 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,3 +1,4 @@ +#![allow(clippy::useless_vec)] #[warn(clippy::range_zip_with_len)] fn main() { let v1 = vec![1, 2, 3]; diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index dcb5061371f80..ac83b67fde3aa 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,5 +1,5 @@ error: it is more idiomatic to use `v1.iter().enumerate()` - --> $DIR/range.rs:5:14 + --> $DIR/range.rs:6:14 | LL | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rc_clone_in_vec_init/arc.rs b/tests/ui/rc_clone_in_vec_init/arc.rs index 384060e6eae50..53fcbf3c49b46 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.rs +++ b/tests/ui/rc_clone_in_vec_init/arc.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::sync::{Arc, Mutex}; fn main() {} diff --git a/tests/ui/rc_clone_in_vec_init/arc.stderr b/tests/ui/rc_clone_in_vec_init/arc.stderr index 7814f5b54036b..a8fd28b84b3a6 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.stderr +++ b/tests/ui/rc_clone_in_vec_init/arc.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:7:13 + --> $DIR/arc.rs:8:13 | LL | let v = vec![Arc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:15:21 + --> $DIR/arc.rs:16:21 | LL | let v = vec![Arc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:21:13 + --> $DIR/arc.rs:22:13 | LL | let v = vec![ | _____________^ @@ -76,7 +76,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:30:14 + --> $DIR/arc.rs:31:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/rc_clone_in_vec_init/rc.rs b/tests/ui/rc_clone_in_vec_init/rc.rs index 0394457fe1708..88ea39bf9083f 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.rs +++ b/tests/ui/rc_clone_in_vec_init/rc.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::rc::Rc; use std::sync::Mutex; diff --git a/tests/ui/rc_clone_in_vec_init/rc.stderr b/tests/ui/rc_clone_in_vec_init/rc.stderr index 80deb7cb9f24d..eab464800ca97 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.stderr +++ b/tests/ui/rc_clone_in_vec_init/rc.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:8:13 + --> $DIR/rc.rs:9:13 | LL | let v = vec![Rc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:16:21 + --> $DIR/rc.rs:17:21 | LL | let v = vec![Rc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:22:13 + --> $DIR/rc.rs:23:13 | LL | let v = vec![ | _____________^ @@ -76,7 +76,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:31:14 + --> $DIR/rc.rs:32:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/rc_clone_in_vec_init/weak.rs b/tests/ui/rc_clone_in_vec_init/weak.rs index 693c9b553c562..03142165057d2 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.rs +++ b/tests/ui/rc_clone_in_vec_init/weak.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::rc::{Rc, Weak as UnSyncWeak}; use std::sync::{Arc, Mutex, Weak as SyncWeak}; diff --git a/tests/ui/rc_clone_in_vec_init/weak.stderr b/tests/ui/rc_clone_in_vec_init/weak.stderr index 789e14a302f6f..1f7a849b18083 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.stderr +++ b/tests/ui/rc_clone_in_vec_init/weak.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:8:13 + --> $DIR/weak.rs:9:13 | LL | let v = vec![SyncWeak::::new(); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:9:14 + --> $DIR/weak.rs:10:14 | LL | let v2 = vec![UnSyncWeak::::new(); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:11:13 + --> $DIR/weak.rs:12:13 | LL | let v = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:12:13 + --> $DIR/weak.rs:13:13 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:20:21 + --> $DIR/weak.rs:21:21 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:21:22 + --> $DIR/weak.rs:22:22 | LL | let v2 = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:27:13 + --> $DIR/weak.rs:28:13 | LL | let v = vec![ | _____________^ @@ -168,7 +168,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:36:14 + --> $DIR/weak.rs:37:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/redundant_at_rest_pattern.fixed b/tests/ui/redundant_at_rest_pattern.fixed new file mode 100644 index 0000000000000..080cf13b5dac2 --- /dev/null +++ b/tests/ui/redundant_at_rest_pattern.fixed @@ -0,0 +1,27 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![allow(irrefutable_let_patterns, unused)] +#![warn(clippy::redundant_at_rest_pattern)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + if let a = [()] {} + if let ref a = [()] {} + if let mut a = [()] {} + if let ref mut a = [()] {} + let v = vec![()]; + if let a = &*v {} + let s = &[()]; + if let a = s {} + // Don't lint + if let [..] = &*v {} + if let [a] = &*v {} + if let [()] = &*v {} + if let [first, rest @ ..] = &*v {} + if let a = [()] {} + external! { + if let [a @ ..] = [()] {} + } +} diff --git a/tests/ui/redundant_at_rest_pattern.rs b/tests/ui/redundant_at_rest_pattern.rs new file mode 100644 index 0000000000000..a8a8028295640 --- /dev/null +++ b/tests/ui/redundant_at_rest_pattern.rs @@ -0,0 +1,27 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![allow(irrefutable_let_patterns, unused)] +#![warn(clippy::redundant_at_rest_pattern)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + if let [a @ ..] = [()] {} + if let [ref a @ ..] = [()] {} + if let [mut a @ ..] = [()] {} + if let [ref mut a @ ..] = [()] {} + let v = vec![()]; + if let [a @ ..] = &*v {} + let s = &[()]; + if let [a @ ..] = s {} + // Don't lint + if let [..] = &*v {} + if let [a] = &*v {} + if let [()] = &*v {} + if let [first, rest @ ..] = &*v {} + if let a = [()] {} + external! { + if let [a @ ..] = [()] {} + } +} diff --git a/tests/ui/redundant_at_rest_pattern.stderr b/tests/ui/redundant_at_rest_pattern.stderr new file mode 100644 index 0000000000000..e2a4d9ffd57cb --- /dev/null +++ b/tests/ui/redundant_at_rest_pattern.stderr @@ -0,0 +1,40 @@ +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:10:12 + | +LL | if let [a @ ..] = [()] {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + | + = note: `-D clippy::redundant-at-rest-pattern` implied by `-D warnings` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:11:12 + | +LL | if let [ref a @ ..] = [()] {} + | ^^^^^^^^^^^^ help: this is better represented with just the binding: `ref a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:12:12 + | +LL | if let [mut a @ ..] = [()] {} + | ^^^^^^^^^^^^ help: this is better represented with just the binding: `mut a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:13:12 + | +LL | if let [ref mut a @ ..] = [()] {} + | ^^^^^^^^^^^^^^^^ help: this is better represented with just the binding: `ref mut a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:15:12 + | +LL | if let [a @ ..] = &*v {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_at_rest_pattern.rs:17:12 + | +LL | if let [a @ ..] = s {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 8bebb5183bc1a..5037c08ebd5f1 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -1,7 +1,13 @@ //@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] -#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] +#![warn(clippy::redundant_clone)] +#![allow( + clippy::drop_non_drop, + clippy::implicit_clone, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] use std::ffi::OsString; use std::path::Path; diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index b4bd5d16b1a68..501898bf113c8 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -1,7 +1,13 @@ //@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] -#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] +#![warn(clippy::redundant_clone)] +#![allow( + clippy::drop_non_drop, + clippy::implicit_clone, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] use std::ffi::OsString; use std::path::Path; diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 782590034d051..8660c0e1f6a04 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,180 +1,180 @@ error: redundant clone - --> $DIR/redundant_clone.rs:10:42 + --> $DIR/redundant_clone.rs:16:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:10:14 + --> $DIR/redundant_clone.rs:16:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::redundant-clone` implied by `-D warnings` error: redundant clone - --> $DIR/redundant_clone.rs:13:15 + --> $DIR/redundant_clone.rs:19:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:13:14 + --> $DIR/redundant_clone.rs:19:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:16:15 + --> $DIR/redundant_clone.rs:22:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:16:14 + --> $DIR/redundant_clone.rs:22:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:19:15 + --> $DIR/redundant_clone.rs:25:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:19:14 + --> $DIR/redundant_clone.rs:25:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:21:42 + --> $DIR/redundant_clone.rs:27:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:21:14 + --> $DIR/redundant_clone.rs:27:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:23:42 + --> $DIR/redundant_clone.rs:29:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:23:14 + --> $DIR/redundant_clone.rs:29:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:25:29 + --> $DIR/redundant_clone.rs:31:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:25:14 + --> $DIR/redundant_clone.rs:31:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:27:29 + --> $DIR/redundant_clone.rs:33:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:27:14 + --> $DIR/redundant_clone.rs:33:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:38:19 + --> $DIR/redundant_clone.rs:44:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:38:14 + --> $DIR/redundant_clone.rs:44:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:70:25 + --> $DIR/redundant_clone.rs:76:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:70:24 + --> $DIR/redundant_clone.rs:76:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> $DIR/redundant_clone.rs:127:15 + --> $DIR/redundant_clone.rs:133:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:127:14 + --> $DIR/redundant_clone.rs:133:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:128:15 + --> $DIR/redundant_clone.rs:134:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:128:14 + --> $DIR/redundant_clone.rs:134:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:138:19 + --> $DIR/redundant_clone.rs:144:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:138:18 + --> $DIR/redundant_clone.rs:144:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:150:14 + --> $DIR/redundant_clone.rs:156:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:150:13 + --> $DIR/redundant_clone.rs:156:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:204:11 + --> $DIR/redundant_clone.rs:210:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:204:10 + --> $DIR/redundant_clone.rs:210:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 61aed2733fef6..f3669a669ea1a 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -3,6 +3,7 @@ #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(clippy::redundant_async_block)] +#![allow(clippy::type_complexity)] #![allow(unused)] async fn something() -> u32 { @@ -38,4 +39,50 @@ fn main() { }; } m2!(); + issue9956(); +} + +fn issue9956() { + assert_eq!(43, 42); + + // ... and some more interesting cases I've found while implementing the fix + + // not actually immediately calling the closure: + let a = (|| 42); + dbg!(a()); + + // immediately calling it inside of a macro + dbg!(42); + + // immediately calling only one closure, so we can't remove the other ones + let a = (|| || 123); + dbg!(a()()); + + // nested async closures + let a = async { 1 }; + let h = async { a.await }; + + // macro expansion tests + macro_rules! echo { + ($e:expr) => { + $e + }; + } + let a = 1; + assert_eq!(a, 1); + let a = 123; + assert_eq!(a, 123); + + // chaining calls, but not closures + fn x() -> fn() -> fn() -> fn() -> i32 { + || || || 42 + } + let _ = x()()()(); + + fn bar() -> fn(i32, i32) { + foo + } + fn foo(_: i32, _: i32) {} + bar()(42, 5); + foo(42, 5); } diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index 56b2866353918..db8c7f80df48c 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -3,6 +3,7 @@ #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(clippy::redundant_async_block)] +#![allow(clippy::type_complexity)] #![allow(unused)] async fn something() -> u32 { @@ -38,4 +39,50 @@ fn main() { }; } m2!(); + issue9956(); +} + +fn issue9956() { + assert_eq!((|| || 43)()(), 42); + + // ... and some more interesting cases I've found while implementing the fix + + // not actually immediately calling the closure: + let a = (|| 42); + dbg!(a()); + + // immediately calling it inside of a macro + dbg!((|| 42)()); + + // immediately calling only one closure, so we can't remove the other ones + let a = (|| || || 123)(); + dbg!(a()()); + + // nested async closures + let a = (|| || || || async || 1)()()()()(); + let h = async { a.await }; + + // macro expansion tests + macro_rules! echo { + ($e:expr) => { + $e + }; + } + let a = (|| echo!(|| echo!(|| 1)))()()(); + assert_eq!(a, 1); + let a = (|| echo!((|| 123)))()(); + assert_eq!(a, 123); + + // chaining calls, but not closures + fn x() -> fn() -> fn() -> fn() -> i32 { + || || || 42 + } + let _ = x()()()(); + + fn bar() -> fn(i32, i32) { + foo + } + fn foo(_: i32, _: i32) {} + bar()((|| || 42)()(), 5); + foo((|| || 42)()(), 5); } diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 8a1f0771659b1..618f5e071d6b2 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -1,5 +1,5 @@ error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:17:13 + --> $DIR/redundant_closure_call_fixable.rs:18:13 | LL | let a = (|| 42)(); | ^^^^^^^^^ help: try doing something like: `42` @@ -7,7 +7,7 @@ LL | let a = (|| 42)(); = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:18:13 + --> $DIR/redundant_closure_call_fixable.rs:19:13 | LL | let b = (async || { | _____________^ @@ -27,7 +27,7 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:23:13 + --> $DIR/redundant_closure_call_fixable.rs:24:13 | LL | let c = (|| { | _____________^ @@ -47,13 +47,13 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:28:13 + --> $DIR/redundant_closure_call_fixable.rs:29:13 | LL | let d = (async || something().await)(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }` error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:37:13 + --> $DIR/redundant_closure_call_fixable.rs:38:13 | LL | (|| m!())() | ^^^^^^^^^^^ help: try doing something like: `m!()` @@ -64,7 +64,7 @@ LL | m2!(); = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:32:13 + --> $DIR/redundant_closure_call_fixable.rs:33:13 | LL | (|| 0)() | ^^^^^^^^ help: try doing something like: `0` @@ -74,5 +74,53 @@ LL | m2!(); | = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:46:16 + | +LL | assert_eq!((|| || 43)()(), 42); + | ^^^^^^^^^^^^^^ help: try doing something like: `43` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:55:10 + | +LL | dbg!((|| 42)()); + | ^^^^^^^^^ help: try doing something like: `42` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:58:13 + | +LL | let a = (|| || || 123)(); + | ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:62:13 + | +LL | let a = (|| || || || async || 1)()()()()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:71:13 + | +LL | let a = (|| echo!(|| echo!(|| 1)))()()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:73:13 + | +LL | let a = (|| echo!((|| 123)))()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:86:11 + | +LL | bar()((|| || 42)()(), 5); + | ^^^^^^^^^^^^^^ help: try doing something like: `42` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:87:9 + | +LL | foo((|| || 42)()(), 5); + | ^^^^^^^^^^^^^^ help: try doing something like: `42` + +error: aborting due to 14 previous errors diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index 481c9b263fbb8..d1134de5ab475 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -2,7 +2,12 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::equatable_if_let, + clippy::needless_if, + clippy::needless_else +)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index 86e46d41e65a1..d144086e791a3 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -2,7 +2,12 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::equatable_if_let, + clippy::needless_if, + clippy::needless_else +)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_drop_order.stderr b/tests/ui/redundant_pattern_matching_drop_order.stderr index 23f08103f358f..e9ea3f2e6886c 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.stderr +++ b/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:12:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:17:12 | LL | if let Ok(_) = m.lock() {} | -------^^^^^----------- help: try this: `if m.lock().is_ok()` @@ -9,7 +9,7 @@ LL | if let Ok(_) = m.lock() {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:13:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 | LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()` @@ -18,7 +18,7 @@ LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:16:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:21:16 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -27,7 +27,7 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:23:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -36,31 +36,31 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:21:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:26:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:22:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:27:12 | LL | if let Err(_) = Err::, _>(()) {} | -------^^^^^^------------------------------------------ help: try this: `if Err::, _>(()).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:24:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 | LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} | -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:25:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:30:12 | LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:28:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:33:12 | LL | if let Some(_) = Some(m.lock()) {} | -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()` @@ -69,7 +69,7 @@ LL | if let Some(_) = Some(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 | LL | if let Some(_) = Some(m.lock().unwrap().0) {} | -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()` @@ -78,7 +78,7 @@ LL | if let Some(_) = Some(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:32:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:37:16 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` @@ -87,7 +87,7 @@ LL | if let None = None::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:39:12 | LL | if let None = None::> { | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` @@ -96,25 +96,25 @@ LL | if let None = None::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:38:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:43:12 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:40:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 | LL | if let Some(_) = Some(String::new()) {} | -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:41:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:46:12 | LL | if let Some(_) = Some((String::new(), ())) {} | -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:44:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:49:12 | LL | if let Ready(_) = Ready(m.lock()) {} | -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()` @@ -123,7 +123,7 @@ LL | if let Ready(_) = Ready(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 | LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} | -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()` @@ -132,7 +132,7 @@ LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:48:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:53:16 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` @@ -141,7 +141,7 @@ LL | if let Pending = Pending::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:55:12 | LL | if let Pending = Pending::> { | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` @@ -150,19 +150,19 @@ LL | if let Pending = Pending::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:54:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:59:12 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:56:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:61:12 | LL | if let Ready(_) = Ready(String::new()) {} | -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:57:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:62:12 | LL | if let Ready(_) = Ready((String::new(), ())) {} | -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()` diff --git a/tests/ui/redundant_pattern_matching_ipaddr.fixed b/tests/ui/redundant_pattern_matching_ipaddr.fixed index a9faf12cd5a11..75ed143446c9f 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -4,6 +4,7 @@ #![allow( clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args )] diff --git a/tests/ui/redundant_pattern_matching_ipaddr.rs b/tests/ui/redundant_pattern_matching_ipaddr.rs index 574671d03d1c4..9ac77409f7919 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -4,6 +4,7 @@ #![allow( clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args )] diff --git a/tests/ui/redundant_pattern_matching_ipaddr.stderr b/tests/ui/redundant_pattern_matching_ipaddr.stderr index 536b589de54c0..6d1fb29646329 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:17:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 | LL | if let V4(_) = &ipaddr {} | -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()` @@ -7,31 +7,31 @@ LL | if let V4(_) = &ipaddr {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:19:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:21:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:22:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:23:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:25:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:26:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:35:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:36:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:40:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:41:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:45:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:46:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:50:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:51:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => true, @@ -67,49 +67,49 @@ LL | | }; | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:55:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:56:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:63:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:64:20 | LL | let _ = if let V4(_) = gen_ipaddr() { | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:65:19 + --> $DIR/redundant_pattern_matching_ipaddr.rs:66:19 | LL | } else if let V6(_) = gen_ipaddr() { | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:77:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:79:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:80:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:81:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:83:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:84:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:85:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:86:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -118,7 +118,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:90:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:91:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index dae931541d454..a63ba5809e4bb 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index 3f2fa3f53ce99..631f9091672d7 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 93760ce97a8f6..717b603c496e3 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:14:12 + --> $DIR/redundant_pattern_matching_option.rs:15:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` @@ -7,43 +7,43 @@ LL | if let None = None::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:16:12 + --> $DIR/redundant_pattern_matching_option.rs:17:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:18:12 + --> $DIR/redundant_pattern_matching_option.rs:19:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:24:15 + --> $DIR/redundant_pattern_matching_option.rs:25:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:26:15 + --> $DIR/redundant_pattern_matching_option.rs:27:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:28:15 + --> $DIR/redundant_pattern_matching_option.rs:29:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:31:15 + --> $DIR/redundant_pattern_matching_option.rs:32:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:39:5 + --> $DIR/redundant_pattern_matching_option.rs:40:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:44:5 + --> $DIR/redundant_pattern_matching_option.rs:45:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:49:13 + --> $DIR/redundant_pattern_matching_option.rs:50:13 | LL | let _ = match None::<()> { | _____________^ @@ -71,55 +71,55 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:55:20 + --> $DIR/redundant_pattern_matching_option.rs:56:20 | LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:61:20 + --> $DIR/redundant_pattern_matching_option.rs:62:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:63:19 + --> $DIR/redundant_pattern_matching_option.rs:64:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:69:12 + --> $DIR/redundant_pattern_matching_option.rs:70:12 | LL | if let Some(..) = gen_opt() {} | -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:84:12 + --> $DIR/redundant_pattern_matching_option.rs:85:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:86:12 + --> $DIR/redundant_pattern_matching_option.rs:87:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:88:15 + --> $DIR/redundant_pattern_matching_option.rs:89:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:90:15 + --> $DIR/redundant_pattern_matching_option.rs:91:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:92:5 + --> $DIR/redundant_pattern_matching_option.rs:93:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -128,7 +128,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:97:5 + --> $DIR/redundant_pattern_matching_option.rs:98:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -137,19 +137,19 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:105:12 + --> $DIR/redundant_pattern_matching_option.rs:106:12 | LL | if let None = *(&None::<()>) {} | -------^^^^----------------- help: try this: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:106:12 + --> $DIR/redundant_pattern_matching_option.rs:107:12 | LL | if let None = *&None::<()> {} | -------^^^^--------------- help: try this: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:112:5 + --> $DIR/redundant_pattern_matching_option.rs:113:5 | LL | / match x { LL | | Some(_) => true, @@ -158,7 +158,7 @@ LL | | }; | |_____^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:117:5 + --> $DIR/redundant_pattern_matching_option.rs:118:5 | LL | / match x { LL | | None => true, @@ -167,7 +167,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:122:5 + --> $DIR/redundant_pattern_matching_option.rs:123:5 | LL | / match x { LL | | Some(_) => false, @@ -176,7 +176,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:127:5 + --> $DIR/redundant_pattern_matching_option.rs:128:5 | LL | / match x { LL | | None => false, @@ -185,13 +185,13 @@ LL | | }; | |_____^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:142:13 + --> $DIR/redundant_pattern_matching_option.rs:143:13 | LL | let _ = matches!(x, Some(_)); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:144:13 + --> $DIR/redundant_pattern_matching_option.rs:145:13 | LL | let _ = matches!(x, None); | ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()` diff --git a/tests/ui/redundant_pattern_matching_poll.fixed b/tests/ui/redundant_pattern_matching_poll.fixed index bf3e692202c36..f739deaf58ea0 100644 --- a/tests/ui/redundant_pattern_matching_poll.fixed +++ b/tests/ui/redundant_pattern_matching_poll.fixed @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_poll.rs b/tests/ui/redundant_pattern_matching_poll.rs index 892a21d9d298e..88dde02b38b72 100644 --- a/tests/ui/redundant_pattern_matching_poll.rs +++ b/tests/ui/redundant_pattern_matching_poll.rs @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_poll.stderr b/tests/ui/redundant_pattern_matching_poll.stderr index 1b480f3157f70..b89fde35fcfa6 100644 --- a/tests/ui/redundant_pattern_matching_poll.stderr +++ b/tests/ui/redundant_pattern_matching_poll.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:16:12 + --> $DIR/redundant_pattern_matching_poll.rs:17:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` @@ -7,37 +7,37 @@ LL | if let Pending = Pending::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:18:12 + --> $DIR/redundant_pattern_matching_poll.rs:19:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:20:12 + --> $DIR/redundant_pattern_matching_poll.rs:21:12 | LL | if let Ready(_) = Ready(42) { | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:26:15 + --> $DIR/redundant_pattern_matching_poll.rs:27:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:28:15 + --> $DIR/redundant_pattern_matching_poll.rs:29:15 | LL | while let Pending = Ready(42) {} | ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:30:15 + --> $DIR/redundant_pattern_matching_poll.rs:31:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:36:5 + --> $DIR/redundant_pattern_matching_poll.rs:37:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -46,7 +46,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:41:5 + --> $DIR/redundant_pattern_matching_poll.rs:42:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, @@ -55,7 +55,7 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:46:13 + --> $DIR/redundant_pattern_matching_poll.rs:47:13 | LL | let _ = match Pending::<()> { | _____________^ @@ -65,49 +65,49 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:52:20 + --> $DIR/redundant_pattern_matching_poll.rs:53:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; | -------^^^^^^^^------- help: try this: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:56:20 + --> $DIR/redundant_pattern_matching_poll.rs:57:20 | LL | let _ = if let Ready(_) = gen_poll() { | -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:58:19 + --> $DIR/redundant_pattern_matching_poll.rs:59:19 | LL | } else if let Pending = gen_poll() { | -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:74:12 + --> $DIR/redundant_pattern_matching_poll.rs:75:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:76:12 + --> $DIR/redundant_pattern_matching_poll.rs:77:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:78:15 + --> $DIR/redundant_pattern_matching_poll.rs:79:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:80:15 + --> $DIR/redundant_pattern_matching_poll.rs:81:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:82:5 + --> $DIR/redundant_pattern_matching_poll.rs:83:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -116,7 +116,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:87:5 + --> $DIR/redundant_pattern_matching_poll.rs:88:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, diff --git a/tests/ui/redundant_pattern_matching_result.fixed b/tests/ui/redundant_pattern_matching_result.fixed index d77a2af761642..343e0d04340de 100644 --- a/tests/ui/redundant_pattern_matching_result.fixed +++ b/tests/ui/redundant_pattern_matching_result.fixed @@ -6,6 +6,7 @@ clippy::if_same_then_else, clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args, clippy::unnecessary_wraps )] diff --git a/tests/ui/redundant_pattern_matching_result.rs b/tests/ui/redundant_pattern_matching_result.rs index aa884ac6bb1ee..4d64eafe590c2 100644 --- a/tests/ui/redundant_pattern_matching_result.rs +++ b/tests/ui/redundant_pattern_matching_result.rs @@ -6,6 +6,7 @@ clippy::if_same_then_else, clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args, clippy::unnecessary_wraps )] diff --git a/tests/ui/redundant_pattern_matching_result.stderr b/tests/ui/redundant_pattern_matching_result.stderr index b462f7f41b9cc..f6ce666bb4ffc 100644 --- a/tests/ui/redundant_pattern_matching_result.stderr +++ b/tests/ui/redundant_pattern_matching_result.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:15:12 + --> $DIR/redundant_pattern_matching_result.rs:16:12 | LL | if let Ok(_) = &result {} | -------^^^^^---------- help: try this: `if result.is_ok()` @@ -7,31 +7,31 @@ LL | if let Ok(_) = &result {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:17:12 + --> $DIR/redundant_pattern_matching_result.rs:18:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:19:12 + --> $DIR/redundant_pattern_matching_result.rs:20:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:21:15 + --> $DIR/redundant_pattern_matching_result.rs:22:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:23:15 + --> $DIR/redundant_pattern_matching_result.rs:24:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:33:5 + --> $DIR/redundant_pattern_matching_result.rs:34:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:38:5 + --> $DIR/redundant_pattern_matching_result.rs:39:5 | LL | / match Ok::(42) { LL | | Ok(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:43:5 + --> $DIR/redundant_pattern_matching_result.rs:44:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:48:5 + --> $DIR/redundant_pattern_matching_result.rs:49:5 | LL | / match Err::(42) { LL | | Ok(_) => true, @@ -67,73 +67,73 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:53:20 + --> $DIR/redundant_pattern_matching_result.rs:54:20 | LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:61:20 + --> $DIR/redundant_pattern_matching_result.rs:62:20 | LL | let _ = if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:63:19 + --> $DIR/redundant_pattern_matching_result.rs:64:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:86:19 + --> $DIR/redundant_pattern_matching_result.rs:87:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:87:16 + --> $DIR/redundant_pattern_matching_result.rs:88:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:93:12 + --> $DIR/redundant_pattern_matching_result.rs:94:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:94:15 + --> $DIR/redundant_pattern_matching_result.rs:95:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:112:12 + --> $DIR/redundant_pattern_matching_result.rs:113:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:114:12 + --> $DIR/redundant_pattern_matching_result.rs:115:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:116:15 + --> $DIR/redundant_pattern_matching_result.rs:117:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:118:15 + --> $DIR/redundant_pattern_matching_result.rs:119:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:120:5 + --> $DIR/redundant_pattern_matching_result.rs:121:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -142,7 +142,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:125:5 + --> $DIR/redundant_pattern_matching_result.rs:126:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -151,7 +151,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:135:5 + --> $DIR/redundant_pattern_matching_result.rs:136:5 | LL | / match x { LL | | Ok(_) => true, @@ -160,7 +160,7 @@ LL | | }; | |_____^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:140:5 + --> $DIR/redundant_pattern_matching_result.rs:141:5 | LL | / match x { LL | | Ok(_) => false, @@ -169,7 +169,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:145:5 + --> $DIR/redundant_pattern_matching_result.rs:146:5 | LL | / match x { LL | | Err(_) => true, @@ -178,7 +178,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:150:5 + --> $DIR/redundant_pattern_matching_result.rs:151:5 | LL | / match x { LL | | Err(_) => false, @@ -187,13 +187,13 @@ LL | | }; | |_____^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:171:13 + --> $DIR/redundant_pattern_matching_result.rs:172:13 | LL | let _ = matches!(x, Ok(_)); | ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:173:13 + --> $DIR/redundant_pattern_matching_result.rs:174:13 | LL | let _ = matches!(x, Err(_)); | ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()` diff --git a/tests/ui/redundant_pub_crate.fixed b/tests/ui/redundant_pub_crate.fixed index f65c0fdd35da1..a1ed491bbc6e4 100644 --- a/tests/ui/redundant_pub_crate.fixed +++ b/tests/ui/redundant_pub_crate.fixed @@ -14,7 +14,7 @@ mod m1 { } pub mod m1_2 { - // ^ private due to m1 + //:^ private due to m1 fn f() {} pub fn g() {} // private due to m1_2 and m1 pub fn h() {} @@ -39,7 +39,7 @@ pub(crate) mod m2 { } pub mod m2_2 { - // ^ already crate visible due to m2 + //:^ already crate visible due to m2 fn f() {} pub fn g() {} // already crate visible due to m2_2 and m2 pub fn h() {} @@ -64,7 +64,7 @@ pub mod m3 { } pub(crate) mod m3_2 { - // ^ ok + //:^ ok fn f() {} pub fn g() {} // already crate visible due to m3_2 pub fn h() {} @@ -89,7 +89,7 @@ mod m4 { } pub mod m4_2 { - // ^ private: not re-exported by `pub use m4::*` + //:^ private: not re-exported by `pub use m4::*` fn f() {} pub fn g() {} // private due to m4_2 pub fn h() {} diff --git a/tests/ui/redundant_pub_crate.rs b/tests/ui/redundant_pub_crate.rs index fb07fed98befb..9accd297fc936 100644 --- a/tests/ui/redundant_pub_crate.rs +++ b/tests/ui/redundant_pub_crate.rs @@ -14,7 +14,7 @@ mod m1 { } pub(crate) mod m1_2 { - // ^ private due to m1 + //:^ private due to m1 fn f() {} pub(crate) fn g() {} // private due to m1_2 and m1 pub fn h() {} @@ -39,7 +39,7 @@ pub(crate) mod m2 { } pub(crate) mod m2_2 { - // ^ already crate visible due to m2 + //:^ already crate visible due to m2 fn f() {} pub(crate) fn g() {} // already crate visible due to m2_2 and m2 pub fn h() {} @@ -64,7 +64,7 @@ pub mod m3 { } pub(crate) mod m3_2 { - // ^ ok + //:^ ok fn f() {} pub(crate) fn g() {} // already crate visible due to m3_2 pub fn h() {} @@ -89,7 +89,7 @@ mod m4 { } pub(crate) mod m4_2 { - // ^ private: not re-exported by `pub use m4::*` + //:^ private: not re-exported by `pub use m4::*` fn f() {} pub(crate) fn g() {} // private due to m4_2 pub fn h() {} diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index 2651735d10364..a83699ec68da7 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -5,39 +5,39 @@ #[derive(Debug)] struct Foo; -const VAR_ONE: &str = "Test constant #1"; // ERROR Consider removing 'static. +const VAR_ONE: &str = "Test constant #1"; // ERROR: Consider removing 'static. const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. -const VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static +const VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static -const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static const VAR_SIX: &u8 = &5; const VAR_HEIGHT: &Foo = &Foo {}; -const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR Consider removing 'static. +const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR: Consider removing 'static. -const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static. +const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static. +const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. -static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR Consider removing 'static. +static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR: Consider removing 'static. static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. -static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static +static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static static STATIC_VAR_SIX: &u8 = &5; static STATIC_VAR_HEIGHT: &Foo = &Foo {}; -static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR Consider removing 'static. +static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR: Consider removing 'static. -static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static. +static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static. +static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0]; diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index 7286652899d6b..b165cbaa3aa16 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -5,39 +5,39 @@ #[derive(Debug)] struct Foo; -const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. -const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static -const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static const VAR_SIX: &'static u8 = &5; const VAR_HEIGHT: &'static Foo = &Foo {}; -const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. -const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. -static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. +static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. -static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static static STATIC_VAR_SIX: &'static u8 = &5; static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; -static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. +static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. -static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0]; diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index b2cbd2d9d01b0..a13e5eadf15dd 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -1,7 +1,7 @@ error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:8:17 | -LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` @@ -9,19 +9,19 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:12:21 | -LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:32 | -LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:47 | -LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime @@ -39,31 +39,31 @@ LL | const VAR_HEIGHT: &'static Foo = &Foo {}; error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:20:19 | -LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:22:19 | -LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:24:19 | -LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:26:25 | -LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:30:29 | -LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime @@ -81,19 +81,19 @@ LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:36:27 | -LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:38:27 | -LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:40:27 | -LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime diff --git a/tests/ui/redundant_static_lifetimes_multiple.rs b/tests/ui/redundant_static_lifetimes_multiple.rs index f57dd58e230a3..b3f263a7d66d8 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.rs +++ b/tests/ui/redundant_static_lifetimes_multiple.rs @@ -1,12 +1,12 @@ // these are rustfixable, but run-rustfix tests cannot handle them -const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; -static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static -static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; diff --git a/tests/ui/redundant_static_lifetimes_multiple.stderr b/tests/ui/redundant_static_lifetimes_multiple.stderr index cc7e55a757a32..4e7500903f811 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.stderr +++ b/tests/ui/redundant_static_lifetimes_multiple.stderr @@ -1,7 +1,7 @@ error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:18 | -LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` @@ -9,7 +9,7 @@ LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:30 | -LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime @@ -27,25 +27,25 @@ LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:40 | -LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:55 | -LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:26 | -LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:38 | -LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime diff --git a/tests/ui/redundant_type_annotations.rs b/tests/ui/redundant_type_annotations.rs new file mode 100644 index 0000000000000..cc507b8d658ce --- /dev/null +++ b/tests/ui/redundant_type_annotations.rs @@ -0,0 +1,176 @@ +#![allow(unused)] +#![warn(clippy::redundant_type_annotations)] + +#[derive(Debug, Default)] +struct Cake { + _data: T, +} + +fn make_something() -> T { + T::default() +} + +fn make_cake() -> Cake { + Cake::::default() +} + +fn plus_one>(val: T) -> T { + val + 1 +} + +#[derive(Default)] +struct Slice { + inner: u32, +} + +#[derive(Default)] +struct Pie { + inner: u32, + inner_struct: Slice, +} + +enum Pizza { + One, + Two, +} + +fn return_a_string() -> String { + String::new() +} + +fn return_a_struct() -> Pie { + Pie::default() +} + +fn return_an_enum() -> Pizza { + Pizza::One +} + +fn return_an_int() -> u32 { + 5 +} + +impl Pie { + fn return_an_int(&self) -> u32 { + self.inner + } + + fn return_a_ref(&self) -> &u32 { + &self.inner + } + + fn return_a_ref_to_struct(&self) -> &Slice { + &self.inner_struct + } + + fn associated_return_an_int() -> u32 { + 5 + } + + fn new() -> Self { + Self::default() + } + + fn associated_return_a_string() -> String { + String::from("") + } + + fn test_method_call(&self) { + // Everything here should be lint + + let v: u32 = self.return_an_int(); + let v: &u32 = self.return_a_ref(); + let v: &Slice = self.return_a_ref_to_struct(); + } +} + +fn test_generics() { + // The type annotation is needed to determine T + let _c: Cake = make_something(); + + // The type annotation is needed to determine the topic + let _c: Cake = make_cake(); + + // This could be lint, but currently doesn't + let _c: Cake = make_cake::(); + + // This could be lint, but currently doesn't + let _c: u8 = make_something::(); + + // This could be lint, but currently doesn't + let _c: u8 = plus_one(5_u8); + + // Annotation needed otherwise T is i32 + let _c: u8 = plus_one(5); + + // This could be lint, but currently doesn't + let _return: String = String::from("test"); +} + +fn test_non_locals() { + // This shouldn't be lint + fn _arg(x: u32) -> u32 { + x + } + + // This could lint, but probably shouldn't + let _closure_arg = |x: u32| x; +} + +fn test_complex_types() { + // Shouldn't be lint, since the literal will be i32 otherwise + let _u8: u8 = 128; + + // This could be lint, but currently doesn't + let _tuple_i32: (i32, i32) = (12, 13); + + // Shouldn't be lint, since the tuple will be i32 otherwise + let _tuple_u32: (u32, u32) = (1, 2); + + // Should be lint, since the type is determined by the init value, but currently doesn't + let _tuple_u32: (u32, u32) = (3_u32, 4_u32); + + // This could be lint, but currently doesn't + let _array: [i32; 3] = [5, 6, 7]; + + // Shouldn't be lint + let _array: [u32; 2] = [8, 9]; +} + +fn test_functions() { + // Everything here should be lint + + let _return: String = return_a_string(); + + let _return: Pie = return_a_struct(); + + let _return: Pizza = return_an_enum(); + + let _return: u32 = return_an_int(); + + let _return: String = String::new(); + + let new_pie: Pie = Pie::new(); + + let _return: u32 = new_pie.return_an_int(); + + let _return: u32 = Pie::associated_return_an_int(); + + let _return: String = Pie::associated_return_a_string(); +} + +fn test_simple_types() { + // Everything here should be lint + + let _var: u32 = u32::MAX; + + let _var: u32 = 5_u32; + + let _var: &str = "test"; + + let _var: &[u8] = b"test"; + + let _var: bool = false; +} + +fn main() {} diff --git a/tests/ui/redundant_type_annotations.stderr b/tests/ui/redundant_type_annotations.stderr new file mode 100644 index 0000000000000..e8b2fe5c3847a --- /dev/null +++ b/tests/ui/redundant_type_annotations.stderr @@ -0,0 +1,106 @@ +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:81:9 + | +LL | let v: u32 = self.return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::redundant-type-annotations` implied by `-D warnings` + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:82:9 + | +LL | let v: &u32 = self.return_a_ref(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:83:9 + | +LL | let v: &Slice = self.return_a_ref_to_struct(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:143:5 + | +LL | let _return: String = return_a_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:145:5 + | +LL | let _return: Pie = return_a_struct(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:147:5 + | +LL | let _return: Pizza = return_an_enum(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:149:5 + | +LL | let _return: u32 = return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:151:5 + | +LL | let _return: String = String::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:153:5 + | +LL | let new_pie: Pie = Pie::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:155:5 + | +LL | let _return: u32 = new_pie.return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:157:5 + | +LL | let _return: u32 = Pie::associated_return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:159:5 + | +LL | let _return: String = Pie::associated_return_a_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:165:5 + | +LL | let _var: u32 = u32::MAX; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:167:5 + | +LL | let _var: u32 = 5_u32; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:169:5 + | +LL | let _var: &str = "test"; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:171:5 + | +LL | let _var: &[u8] = b"test"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:173:5 + | +LL | let _var: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 1c8e47ab59494..89d1d94945454 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,4 +1,9 @@ -#![allow(unused, clippy::needless_borrow)] +#![allow( + unused, + clippy::needless_raw_strings, + clippy::needless_raw_string_hashes, + clippy::needless_borrow +)] #![warn(clippy::invalid_regex, clippy::trivial_regex)] extern crate regex; diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1e8a21283cd95..21f1cb44460ef 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,5 +1,5 @@ error: trivial regex - --> $DIR/regex.rs:13:45 + --> $DIR/regex.rs:18:45 | LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ @@ -8,7 +8,7 @@ LL | let pipe_in_wrong_position = Regex::new("|"); = note: `-D clippy::trivial-regex` implied by `-D warnings` error: trivial regex - --> $DIR/regex.rs:14:60 + --> $DIR/regex.rs:19:60 | LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ @@ -16,7 +16,7 @@ LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:15:42 + --> $DIR/regex.rs:20:42 | LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ @@ -24,7 +24,7 @@ LL | let wrong_char_ranice = Regex::new("[z-a]"); = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:16:37 + --> $DIR/regex.rs:21:37 | LL | let some_unicode = Regex::new("[é-è]"); | ^^^ @@ -33,13 +33,13 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:18:33 + --> $DIR/regex.rs:23:33 | LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:20:53 + --> $DIR/regex.rs:25:53 | LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ @@ -50,7 +50,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:21:41 + --> $DIR/regex.rs:26:41 | LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:22:56 + --> $DIR/regex.rs:27:56 | LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:34:37 + --> $DIR/regex.rs:39:37 | LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:35:39 + --> $DIR/regex.rs:40:39 | LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -86,27 +86,27 @@ error: regex parse error: /b/c ^^ error: unrecognized escape sequence - --> $DIR/regex.rs:42:42 + --> $DIR/regex.rs:47:42 | -LL | let escaped_string_span = Regex::new("/b/c"); +LL | let escaped_string_span = Regex::new("//b//c"); | ^^^^^^^^ | = help: consider using a raw string literal: `r".."` error: regex syntax error: duplicate flag - --> $DIR/regex.rs:44:34 + --> $DIR/regex.rs:49:34 | LL | let aux_span = Regex::new("(?ixi)"); | ^ ^ error: regex syntax error: pattern can match invalid UTF-8 - --> $DIR/regex.rs:49:53 + --> $DIR/regex.rs:54:53 | LL | let invalid_utf8_should_lint = Regex::new("(?-u)."); | ^ error: trivial regex - --> $DIR/regex.rs:53:33 + --> $DIR/regex.rs:58:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -114,7 +114,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:55:48 + --> $DIR/regex.rs:60:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:57:42 + --> $DIR/regex.rs:62:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -130,7 +130,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:59:40 + --> $DIR/regex.rs:64:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -138,7 +138,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:61:39 + --> $DIR/regex.rs:66:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -146,7 +146,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:63:39 + --> $DIR/regex.rs:68:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -154,15 +154,15 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:65:40 + --> $DIR/regex.rs:70:40 | -LL | let trivial_backslash = Regex::new("a/.b"); +LL | let trivial_backslash = Regex::new("a//.b"); | ^^^^^^^ | = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:68:36 + --> $DIR/regex.rs:73:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -170,7 +170,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:70:36 + --> $DIR/regex.rs:75:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -178,7 +178,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:72:36 + --> $DIR/regex.rs:77:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -186,7 +186,7 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:74:44 + --> $DIR/regex.rs:79:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index f1b25dc094ef6..b24c83d9a0da2 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -30,7 +30,7 @@ #![allow(clippy::invisible_characters)] #![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] -#![allow(cast_ref_to_mut)] +#![allow(invalid_nan_comparisons)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] @@ -41,12 +41,10 @@ #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] #![allow(invalid_from_utf8_unchecked)] -#![allow(invalid_nan_comparisons)] #![allow(let_underscore_drop)] #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] -#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(undropped_manually_drops)] #![allow(unknown_lints)] @@ -56,7 +54,6 @@ #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::box_collection)] -#![warn(invalid_nan_comparisons)] #![warn(clippy::redundant_static_lifetimes)] #![warn(clippy::cognitive_complexity)] #![warn(clippy::derived_hash_with_manual_eq)] @@ -83,6 +80,7 @@ #![warn(clippy::invisible_characters)] #![warn(cast_ref_to_mut)] #![warn(suspicious_double_ref_op)] +#![warn(invalid_nan_comparisons)] #![warn(drop_bounds)] #![warn(dropping_copy_types)] #![warn(dropping_references)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 4af511c344c4d..baa6345a64f83 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -30,7 +30,7 @@ #![allow(clippy::invisible_characters)] #![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] -#![allow(cast_ref_to_mut)] +#![allow(invalid_nan_comparisons)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] @@ -41,12 +41,10 @@ #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] #![allow(invalid_from_utf8_unchecked)] -#![allow(invalid_nan_comparisons)] #![allow(let_underscore_drop)] #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] -#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(undropped_manually_drops)] #![allow(unknown_lints)] @@ -56,7 +54,6 @@ #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![warn(clippy::box_vec)] -#![warn(clippy::cmp_nan)] #![warn(clippy::const_static_lifetime)] #![warn(clippy::cyclomatic_complexity)] #![warn(clippy::derive_hash_xor_eq)] @@ -83,6 +80,7 @@ #![warn(clippy::zero_width_space)] #![warn(clippy::cast_ref_to_mut)] #![warn(clippy::clone_double_ref)] +#![warn(clippy::cmp_nan)] #![warn(clippy::drop_bounds)] #![warn(clippy::drop_copy)] #![warn(clippy::drop_ref)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 156a8f96b5026..ae25c3b46bd24 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` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:52:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,307 +7,307 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:53: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_if_conditions` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` -error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> $DIR/rename.rs:59:9 - | -LL | #![warn(clippy::cmp_nan)] - | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` - error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:57: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` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:58: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` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:59: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` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:60: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` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:61: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` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:62: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` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:63: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` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:65: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` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:66: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` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:67: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` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:68: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` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:69: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` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:70: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` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:71: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` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:72: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` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:73: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` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:74: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` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:75: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` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:76: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` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:77: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` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:78: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` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:80: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 `cast_ref_to_mut` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:82: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` + --> $DIR/rename.rs:83: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` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:84: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` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:85: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` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:87: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` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:88: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` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:89: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` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:90: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` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:91: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` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:92: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` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:93: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` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:94: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` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:95: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` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:96: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` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:97: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` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:98: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` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:99: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` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:100: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` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:101: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` - --> $DIR/rename.rs:104:9 + --> $DIR/rename.rs:102: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` - --> $DIR/rename.rs:105:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index 08916398cbb28..a207e42213558 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -37,33 +37,33 @@ fn ifs_same_cond_fn() { if function() { } else if function() { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if fn_arg(a) { } else if fn_arg(a) { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if obj.method() { } else if obj.method() { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if obj.method_arg(a) { } else if obj.method_arg(a) { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } let mut v = vec![1]; if v.pop().is_none() { - //~ ERROR ifs same condition } else if v.pop().is_none() { + //~^ ERROR: `if` has the same function call as a previous `if` } if v.len() == 42 { - //~ ERROR ifs same condition } else if v.len() == 42 { + //~^ ERROR: `if` has the same function call as a previous `if` } if v.len() == 1 { diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index 6aacc73b90dc1..199e6769ff767 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -52,7 +52,7 @@ LL | if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:61:15 + --> $DIR/same_functions_in_if_condition.rs:60:15 | LL | } else if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:66:15 + --> $DIR/same_functions_in_if_condition.rs:65:15 | LL | } else if v.len() == 42 { | ^^^^^^^^^^^^^ diff --git a/tests/ui/search_is_some.rs b/tests/ui/search_is_some.rs index 670599b0dcf59..3cdbfaa162614 100644 --- a/tests/ui/search_is_some.rs +++ b/tests/ui/search_is_some.rs @@ -1,5 +1,6 @@ //@aux-build:option_helpers.rs #![warn(clippy::search_is_some)] +#![allow(clippy::useless_vec)] #![allow(dead_code)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; diff --git a/tests/ui/search_is_some.stderr b/tests/ui/search_is_some.stderr index 6bea8c6747797..7eff614d17c69 100644 --- a/tests/ui/search_is_some.stderr +++ b/tests/ui/search_is_some.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:14:13 + --> $DIR/search_is_some.rs:15:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -12,7 +12,7 @@ LL | | ).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with `position` - --> $DIR/search_is_some.rs:20:13 + --> $DIR/search_is_some.rs:21:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -24,7 +24,7 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `rposition` - --> $DIR/search_is_some.rs:26:13 + --> $DIR/search_is_some.rs:27:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -36,13 +36,13 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:41:20 + --> $DIR/search_is_some.rs:42:20 | LL | let _ = (0..1).find(some_closure).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(some_closure)` error: called `is_none()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:51:13 + --> $DIR/search_is_some.rs:52:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -54,7 +54,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `position` - --> $DIR/search_is_some.rs:57:13 + --> $DIR/search_is_some.rs:58:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -66,7 +66,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `rposition` - --> $DIR/search_is_some.rs:63:13 + --> $DIR/search_is_some.rs:64:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -78,7 +78,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:78:13 + --> $DIR/search_is_some.rs:79:13 | LL | let _ = (0..1).find(some_closure).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(some_closure)` diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed index 9386618c123ef..08fb87cb306e0 100644 --- a/tests/ui/search_is_some_fixable_none.fixed +++ b/tests/ui/search_is_some_fixable_none.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs index 6b2537a96c2af..ec3386933a61b 100644 --- a/tests/ui/search_is_some_fixable_none.rs +++ b/tests/ui/search_is_some_fixable_none.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index e9116fc59f10e..aa16f9da037d1 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index b152839945765..aeb6f118bedeb 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/self_assignment.rs b/tests/ui/self_assignment.rs index ef64762291024..ec3ae12094254 100644 --- a/tests/ui/self_assignment.rs +++ b/tests/ui/self_assignment.rs @@ -1,4 +1,5 @@ #![warn(clippy::self_assignment)] +#![allow(clippy::useless_vec)] pub struct S<'a> { a: i32, diff --git a/tests/ui/self_assignment.stderr b/tests/ui/self_assignment.stderr index 826e0d0ba888d..bed88244eea70 100644 --- a/tests/ui/self_assignment.stderr +++ b/tests/ui/self_assignment.stderr @@ -1,5 +1,5 @@ error: self-assignment of `a` to `a` - --> $DIR/self_assignment.rs:12:5 + --> $DIR/self_assignment.rs:13:5 | LL | a = a; | ^^^^^ @@ -7,61 +7,61 @@ LL | a = a; = note: `-D clippy::self-assignment` implied by `-D warnings` error: self-assignment of `*b` to `*b` - --> $DIR/self_assignment.rs:13:5 + --> $DIR/self_assignment.rs:14:5 | LL | *b = *b; | ^^^^^^^ error: self-assignment of `s` to `s` - --> $DIR/self_assignment.rs:14:5 + --> $DIR/self_assignment.rs:15:5 | LL | s = s; | ^^^^^ error: self-assignment of `s.a` to `s.a` - --> $DIR/self_assignment.rs:15:5 + --> $DIR/self_assignment.rs:16:5 | LL | s.a = s.a; | ^^^^^^^^^ error: self-assignment of `s.b[5 + 5]` to `s.b[10]` - --> $DIR/self_assignment.rs:16:5 + --> $DIR/self_assignment.rs:17:5 | LL | s.b[10] = s.b[5 + 5]; | ^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.c[0][1]` to `s.c[0][1]` - --> $DIR/self_assignment.rs:17:5 + --> $DIR/self_assignment.rs:18:5 | LL | s.c[0][1] = s.c[0][1]; | ^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.b[a]` to `s.b[a]` - --> $DIR/self_assignment.rs:18:5 + --> $DIR/self_assignment.rs:19:5 | LL | s.b[a] = s.b[a]; | ^^^^^^^^^^^^^^^ error: self-assignment of `*s.e` to `*s.e` - --> $DIR/self_assignment.rs:19:5 + --> $DIR/self_assignment.rs:20:5 | LL | *s.e = *s.e; | ^^^^^^^^^^^ error: self-assignment of `s.b[10 + a]` to `s.b[a + 10]` - --> $DIR/self_assignment.rs:20:5 + --> $DIR/self_assignment.rs:21:5 | LL | s.b[a + 10] = s.b[10 + a]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `t.1` to `t.1` - --> $DIR/self_assignment.rs:23:5 + --> $DIR/self_assignment.rs:24:5 | LL | t.1 = t.1; | ^^^^^^^^^ error: self-assignment of `(t.0)` to `t.0` - --> $DIR/self_assignment.rs:24:5 + --> $DIR/self_assignment.rs:25:5 | LL | t.0 = (t.0); | ^^^^^^^^^^^ diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 2c0fc3e3fd83f..9be8c5e59d014 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,7 +1,7 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_if)] extern crate proc_macro_derive; diff --git a/tests/ui/significant_drop_in_scrutinee.fixed b/tests/ui/significant_drop_in_scrutinee.fixed new file mode 100644 index 0000000000000..acc78d6bb0439 --- /dev/null +++ b/tests/ui/significant_drop_in_scrutinee.fixed @@ -0,0 +1,627 @@ +// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 +// //@run-rustfix +#![warn(clippy::significant_drop_in_scrutinee)] +#![allow(dead_code, unused_assignments)] +#![allow(clippy::match_single_binding, clippy::single_match, clippy::uninlined_format_args)] + +use std::num::ParseIntError; +use std::ops::Deref; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::RwLock; +use std::sync::{Mutex, MutexGuard}; + +struct State {} + +impl State { + fn foo(&self) -> bool { + true + } + + fn bar(&self) {} +} + +fn should_not_trigger_lint_with_mutex_guard_outside_match() { + let mutex = Mutex::new(State {}); + + // Should not trigger lint because the temporary should drop at the `;` on line before the match + let is_foo = mutex.lock().unwrap().foo(); + match is_foo { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_with_mutex_guard_when_taking_ownership_in_match() { + let mutex = Mutex::new(State {}); + + // Should not trigger lint because the scrutinee is explicitly returning the MutexGuard, + // so its lifetime should not be surprising. + match mutex.lock() { + Ok(guard) => { + guard.foo(); + mutex.lock().unwrap().bar(); + }, + _ => {}, + }; +} + +fn should_trigger_lint_with_mutex_guard_in_match_scrutinee() { + let mutex = Mutex::new(State {}); + + // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it + // is preserved until the end of the match, but there is no clear indication that this is the + // case. + match mutex.lock().unwrap().foo() { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_with_mutex_guard_in_match_scrutinee_when_lint_allowed() { + let mutex = Mutex::new(State {}); + + // Lint should not be triggered because it is "allowed" below. + #[allow(clippy::significant_drop_in_scrutinee)] + match mutex.lock().unwrap().foo() { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_insignificant_drop() { + // Should not trigger lint because there are no temporaries whose drops have a significant + // side effect. + match 1u64.to_string().is_empty() { + true => { + println!("It was empty") + }, + false => { + println!("It was not empty") + }, + } +} + +struct StateWithMutex { + m: Mutex, +} + +struct MutexGuardWrapper<'a> { + mg: MutexGuard<'a, u64>, +} + +impl<'a> MutexGuardWrapper<'a> { + fn get_the_value(&self) -> u64 { + *self.mg.deref() + } +} + +struct MutexGuardWrapperWrapper<'a> { + mg: MutexGuardWrapper<'a>, +} + +impl<'a> MutexGuardWrapperWrapper<'a> { + fn get_the_value(&self) -> u64 { + *self.mg.mg.deref() + } +} + +impl StateWithMutex { + fn lock_m(&self) -> MutexGuardWrapper<'_> { + MutexGuardWrapper { + mg: self.m.lock().unwrap(), + } + } + + fn lock_m_m(&self) -> MutexGuardWrapperWrapper<'_> { + MutexGuardWrapperWrapper { + mg: MutexGuardWrapper { + mg: self.m.lock().unwrap(), + }, + } + } + + fn foo(&self) -> bool { + true + } + + fn bar(&self) {} +} + +fn should_trigger_lint_with_wrapped_mutex() { + let s = StateWithMutex { m: Mutex::new(1) }; + + // Should trigger lint because a temporary contains a type with a significant drop and its + // lifetime is not obvious. Additionally, it is not obvious from looking at the scrutinee that + // the temporary contains such a type, making it potentially even more surprising. + match s.lock_m().get_the_value() { + 1 => { + println!("Got 1. Is it still 1?"); + println!("{}", s.lock_m().get_the_value()); + }, + 2 => { + println!("Got 2. Is it still 2?"); + println!("{}", s.lock_m().get_the_value()); + }, + _ => {}, + } + println!("All done!"); +} + +fn should_trigger_lint_with_double_wrapped_mutex() { + let s = StateWithMutex { m: Mutex::new(1) }; + + // Should trigger lint because a temporary contains a type which further contains a type with a + // significant drop and its lifetime is not obvious. Additionally, it is not obvious from + // looking at the scrutinee that the temporary contains such a type, making it potentially even + // more surprising. + match s.lock_m_m().get_the_value() { + 1 => { + println!("Got 1. Is it still 1?"); + println!("{}", s.lock_m().get_the_value()); + }, + 2 => { + println!("Got 2. Is it still 2?"); + println!("{}", s.lock_m().get_the_value()); + }, + _ => {}, + } + println!("All done!"); +} + +struct Counter { + i: AtomicU64, +} + +#[clippy::has_significant_drop] +struct CounterWrapper<'a> { + counter: &'a Counter, +} + +impl<'a> CounterWrapper<'a> { + fn new(counter: &Counter) -> CounterWrapper { + counter.i.fetch_add(1, Ordering::Relaxed); + CounterWrapper { counter } + } +} + +impl<'a> Drop for CounterWrapper<'a> { + fn drop(&mut self) { + self.counter.i.fetch_sub(1, Ordering::Relaxed); + } +} + +impl Counter { + fn temp_increment(&self) -> Vec { + vec![CounterWrapper::new(self), CounterWrapper::new(self)] + } +} + +fn should_trigger_lint_for_vec() { + let counter = Counter { i: AtomicU64::new(0) }; + + // Should trigger lint because the temporary in the scrutinee returns a collection of types + // which have significant drops. The types with significant drops are also non-obvious when + // reading the expression in the scrutinee. + match counter.temp_increment().len() { + 2 => { + let current_count = counter.i.load(Ordering::Relaxed); + println!("Current count {}", current_count); + assert_eq!(current_count, 0); + }, + 1 => {}, + 3 => {}, + _ => {}, + }; +} + +struct StateWithField { + s: String, +} + +// Should trigger lint only on the type in the tuple which is created using a temporary +// with a significant drop. Additionally, this test ensures that the format of the tuple +// is preserved correctly in the suggestion. +fn should_trigger_lint_for_tuple_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + { + match (mutex1.lock().unwrap().s.len(), true) { + (3, _) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + println!("done"); + }, + (_, _) => {}, + }; + + match (true, mutex1.lock().unwrap().s.len(), true) { + (_, 3, _) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + println!("done"); + }, + (_, _, _) => {}, + }; + + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { + (3, _, 3) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + (_, _, _) => {}, + }; + + let mutex3 = Mutex::new(StateWithField { s: "three".to_owned() }); + match mutex3.lock().unwrap().s.as_str() { + "three" => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + _ => {}, + }; + + match (true, mutex3.lock().unwrap().s.as_str()) { + (_, "three") => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + (_, _) => {}, + }; + } +} + +// Should trigger lint when either side of a binary operation creates a temporary with a +// significant drop. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_for_accessing_field_in_mutex_in_one_side_of_binary_op() { + let mutex = Mutex::new(StateWithField { s: "state".to_owned() }); + + match mutex.lock().unwrap().s.len() > 1 { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; + + match 1 < mutex.lock().unwrap().s.len() { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +// Should trigger lint when both sides of a binary operation creates a temporary with a +// significant drop. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_for_accessing_fields_in_mutex_in_both_sides_of_binary_op() { + let mutex1 = Mutex::new(StateWithField { s: "state".to_owned() }); + let mutex2 = Mutex::new(StateWithField { + s: "statewithfield".to_owned(), + }); + + match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { + true => { + println!( + "{} < {}", + mutex1.lock().unwrap().s.len(), + mutex2.lock().unwrap().s.len() + ); + }, + false => {}, + }; + + match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { + true => { + println!( + "{} >= {}", + mutex1.lock().unwrap().s.len(), + mutex2.lock().unwrap().s.len() + ); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_closure_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + let get_mutex_guard = || mutex1.lock().unwrap().s.len(); + + // Should not trigger lint because the temporary with a significant drop will be dropped + // at the end of the closure, so the MutexGuard will be unlocked and not have a potentially + // surprising lifetime. + match get_mutex_guard() > 1 { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_trigger_lint_for_return_from_closure_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + let get_mutex_guard = || mutex1.lock().unwrap(); + + // Should trigger lint because the temporary with a significant drop is returned from the + // closure but not used directly in any match arms, so it has a potentially surprising lifetime. + match get_mutex_guard().s.len() > 1 { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_trigger_lint_for_return_from_match_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + + let i = 100; + + // Should trigger lint because the nested match within the scrutinee returns a temporary with a + // significant drop is but not used directly in any match arms, so it has a potentially + // surprising lifetime. + match match i { + 100 => mutex1.lock().unwrap(), + _ => mutex2.lock().unwrap(), + } + .s + .len() + > 1 + { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => { + println!("nothing to do here"); + }, + }; +} + +fn should_trigger_lint_for_return_from_if_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + + let i = 100; + + // Should trigger lint because the nested if-expression within the scrutinee returns a temporary + // with a significant drop is but not used directly in any match arms, so it has a potentially + // surprising lifetime. + match if i > 1 { + mutex1.lock().unwrap() + } else { + mutex2.lock().unwrap() + } + .s + .len() + > 1 + { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_if_in_scrutinee() { + let mutex = Mutex::new(StateWithField { s: "state".to_owned() }); + + let i = 100; + + // Should not trigger the lint because the temporary with a significant drop *is* dropped within + // the body of the if-expression nested within the match scrutinee, and therefore does not have + // a potentially surprising lifetime. + match if i > 1 { + mutex.lock().unwrap().s.len() > 1 + } else { + false + } { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +struct StateWithBoxedMutexGuard { + u: Mutex, +} + +impl StateWithBoxedMutexGuard { + fn new() -> StateWithBoxedMutexGuard { + StateWithBoxedMutexGuard { u: Mutex::new(42) } + } + fn lock(&self) -> Box> { + Box::new(self.u.lock().unwrap()) + } +} + +fn should_trigger_lint_for_boxed_mutex_guard() { + let s = StateWithBoxedMutexGuard::new(); + + // Should trigger lint because a temporary Box holding a type with a significant drop in a match + // scrutinee may have a potentially surprising lifetime. + match s.lock().deref().deref() { + 0 | 1 => println!("Value was less than 2"), + _ => println!("Value is {}", s.lock().deref()), + }; +} + +struct StateStringWithBoxedMutexGuard { + s: Mutex, +} + +impl StateStringWithBoxedMutexGuard { + fn new() -> StateStringWithBoxedMutexGuard { + StateStringWithBoxedMutexGuard { + s: Mutex::new("A String".to_owned()), + } + } + fn lock(&self) -> Box> { + Box::new(self.s.lock().unwrap()) + } +} + +fn should_trigger_lint_for_boxed_mutex_guard_holding_string() { + let s = StateStringWithBoxedMutexGuard::new(); + + let matcher = String::from("A String"); + + // Should trigger lint because a temporary Box holding a type with a significant drop in a match + // scrutinee may have a potentially surprising lifetime. + match s.lock().deref().deref() { + matcher => println!("Value is {}", s.lock().deref()), + _ => println!("Value was not a match"), + }; +} + +struct StateWithIntField { + i: u64, +} + +// Should trigger lint when either side of an assign expression contains a temporary with a +// significant drop, because the temporary's lifetime will be extended to the end of the match. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_in_assign_expr() { + let mutex = Mutex::new(StateWithIntField { i: 10 }); + + let mut i = 100; + + match mutex.lock().unwrap().i = i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match i = mutex.lock().unwrap().i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match mutex.lock().unwrap().i += 1 { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match i += mutex.lock().unwrap().i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; +} + +#[derive(Debug)] +enum RecursiveEnum { + Foo(Option>), +} + +#[derive(Debug)] +enum GenericRecursiveEnum { + Foo(T, Option>>), +} + +fn should_not_cause_stack_overflow() { + // Test that when a type recursively contains itself, a stack overflow does not occur when + // checking sub-types for significant drops. + let f = RecursiveEnum::Foo(Some(Box::new(RecursiveEnum::Foo(None)))); + match f { + RecursiveEnum::Foo(Some(f)) => { + println!("{:?}", f) + }, + RecursiveEnum::Foo(f) => { + println!("{:?}", f) + }, + } + + let f = GenericRecursiveEnum::Foo(1u64, Some(Box::new(GenericRecursiveEnum::Foo(2u64, None)))); + match f { + GenericRecursiveEnum::Foo(i, Some(f)) => { + println!("{} {:?}", i, f) + }, + GenericRecursiveEnum::Foo(i, f) => { + println!("{} {:?}", i, f) + }, + } +} + +fn should_not_produce_lint_for_try_desugar() -> Result { + // TryDesugar (i.e. using `?` for a Result type) will turn into a match but is out of scope + // for this lint + let rwlock = RwLock::new("1".to_string()); + let result = rwlock.read().unwrap().parse::()?; + println!("{}", result); + rwlock.write().unwrap().push('2'); + Ok(result) +} + +struct ResultReturner { + s: String, +} + +impl ResultReturner { + fn to_number(&self) -> Result { + self.s.parse::() + } +} + +fn should_trigger_lint_for_non_ref_move_and_clone_suggestion() { + let rwlock = RwLock::::new(ResultReturner { s: "1".to_string() }); + match rwlock.read().unwrap().to_number() { + Ok(n) => println!("Converted to number: {}", n), + Err(e) => println!("Could not convert {} to number", e), + }; +} + +fn should_trigger_lint_for_read_write_lock_for_loop() { + // For-in loops desugar to match expressions and are prone to the type of deadlock this lint is + // designed to look for. + let rwlock = RwLock::>::new(vec!["1".to_string()]); + for s in rwlock.read().unwrap().iter() { + println!("{}", s); + } +} + +fn do_bar(mutex: &Mutex) { + mutex.lock().unwrap().bar(); +} + +fn should_trigger_lint_without_significant_drop_in_arm() { + let mutex = Mutex::new(State {}); + + // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it + // is preserved until the end of the match, but there is no clear indication that this is the + // case. + match mutex.lock().unwrap().foo() { + true => do_bar(&mutex), + false => {}, + }; +} + +fn should_not_trigger_on_significant_iterator_drop() { + let lines = std::io::stdin().lines(); + for line in lines { + println!("foo: {}", line.unwrap()); + } +} + +fn main() {} diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index ee7f2b0631ad6..7b848ead78467 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -16,6 +16,18 @@ pub fn complex_return_triggers_the_lint() -> i32 { foo() } +pub fn issue_10413() { + let mutex = Mutex::new(Some(1)); + let opt = Some(1); + if opt.is_some() { + let lock = mutex.lock().unwrap(); + let _ = *lock; + if opt.is_some() { + let _ = *lock; + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index 9c139deb95f2d..36f77cf1bdb6e 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -15,6 +15,18 @@ pub fn complex_return_triggers_the_lint() -> i32 { foo() } +pub fn issue_10413() { + let mutex = Mutex::new(Some(1)); + let opt = Some(1); + if opt.is_some() { + let lock = mutex.lock().unwrap(); + let _ = *lock; + if opt.is_some() { + let _ = *lock; + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index ab8ce356ec7b5..3bdac0b0a6b7b 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -23,7 +23,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:44:13 + --> $DIR/significant_drop_tightening.rs:56:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -43,7 +43,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:65:13 + --> $DIR/significant_drop_tightening.rs:77:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -67,7 +67,7 @@ LL + | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:71:17 + --> $DIR/significant_drop_tightening.rs:83:17 | LL | / { LL | | let mutex = Mutex::new(vec![1i32]); diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs new file mode 100644 index 0000000000000..76e175014b877 --- /dev/null +++ b/tests/ui/single_call_fn.rs @@ -0,0 +1,74 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::redundant_closure_call, unused)] +#![warn(clippy::single_call_fn)] +#![no_main] + +#[macro_use] +extern crate proc_macros; + +// Do not lint since it's public +pub fn f() {} + +fn i() {} +fn j() {} + +fn h() { + // Linted + let a = i; + // Do not lint closures + let a = (|| { + // Not linted + a(); + // Imo, it's reasonable to lint this as the function is still only being used once. Just in + // a closure. + j(); + }); + a(); +} + +fn g() { + f(); +} + +fn c() { + println!("really"); + println!("long"); + println!("function..."); +} + +fn d() { + c(); +} + +fn a() {} + +fn b() { + a(); + + external! { + fn lol() { + lol_inner(); + } + fn lol_inner() {} + } + with_span! { + span + fn lol2() { + lol2_inner(); + } + fn lol2_inner() {} + } +} + +fn e() { + b(); + b(); +} + +#[test] +fn k() {} + +#[test] +fn l() { + k(); +} diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr new file mode 100644 index 0000000000000..9ef8c487844fb --- /dev/null +++ b/tests/ui/single_call_fn.stderr @@ -0,0 +1,55 @@ +error: this function is only used once + --> $DIR/single_call_fn.rs:33:1 + | +LL | / fn c() { +LL | | println!("really"); +LL | | println!("long"); +LL | | println!("function..."); +LL | | } + | |_^ + | +help: used here + --> $DIR/single_call_fn.rs:40:5 + | +LL | c(); + | ^ + = note: `-D clippy::single-call-fn` implied by `-D warnings` + +error: this function is only used once + --> $DIR/single_call_fn.rs:12:1 + | +LL | fn i() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:17:13 + | +LL | let a = i; + | ^ + +error: this function is only used once + --> $DIR/single_call_fn.rs:43:1 + | +LL | fn a() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:46:5 + | +LL | a(); + | ^ + +error: this function is only used once + --> $DIR/single_call_fn.rs:13:1 + | +LL | fn j() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:24:9 + | +LL | j(); + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index cbcf1ab21c9bd..cb301c8bc1529 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index a1f005cc833b1..99baf35ac2979 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.stderr b/tests/ui/single_char_add_str.stderr index 55d91583ad04d..3f93c18470eac 100644 --- a/tests/ui/single_char_add_str.stderr +++ b/tests/ui/single_char_add_str.stderr @@ -1,5 +1,5 @@ error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:14:5 + --> $DIR/single_char_add_str.rs:15:5 | LL | string.push_str("R"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('R')` @@ -7,85 +7,85 @@ LL | string.push_str("R"); = note: `-D clippy::single-char-add-str` implied by `-D warnings` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:15:5 + --> $DIR/single_char_add_str.rs:16:5 | LL | string.push_str("'"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/'')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:20:5 + --> $DIR/single_char_add_str.rs:21:5 | LL | string.push_str("/x52"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/x52')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:21:5 + --> $DIR/single_char_add_str.rs:22:5 | LL | string.push_str("/u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/u{0052}')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:22:5 + --> $DIR/single_char_add_str.rs:23:5 | LL | string.push_str(r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:24:5 + --> $DIR/single_char_add_str.rs:25:5 | LL | get_string!().push_str("ö"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `get_string!().push('ö')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:29:5 + --> $DIR/single_char_add_str.rs:30:5 | LL | string.insert_str(0, "R"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, 'R')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:30:5 + --> $DIR/single_char_add_str.rs:31:5 | LL | string.insert_str(1, "'"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(1, '/'')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:35:5 + --> $DIR/single_char_add_str.rs:36:5 | LL | string.insert_str(0, "/x52"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/x52')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:36:5 + --> $DIR/single_char_add_str.rs:37:5 | LL | string.insert_str(0, "/u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/u{0052}')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:38:5 + --> $DIR/single_char_add_str.rs:39:5 | LL | string.insert_str(x, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(x, 'a')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:40:5 + --> $DIR/single_char_add_str.rs:41:5 | LL | string.insert_str(Y, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, 'a')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:41:5 + --> $DIR/single_char_add_str.rs:42:5 | LL | string.insert_str(Y, r##"""##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '"')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:42:5 + --> $DIR/single_char_add_str.rs:43:5 | LL | string.insert_str(Y, r##"'"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '/'')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:44:5 + --> $DIR/single_char_add_str.rs:45:5 | LL | get_string!().insert_str(1, "?"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `get_string!().insert(1, '?')` diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index dba89872070e8..7ae62231acc0f 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused_must_use)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 6a145a14bfdc7..0604624e767be 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused_must_use)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 5564aac674d97..5ae2450c22681 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -226,13 +226,13 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:65:13 | LL | x.split(r#"/"#); - | ^^^^^^ help: try using a `char` instead: `'/'` + | ^^^^^^ help: try using a `char` instead: `'//'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:66:13 | LL | x.split(r"/"); - | ^^^^ help: try using a `char` instead: `'/'` + | ^^^^ help: try using a `char` instead: `'//'` error: aborting due to 39 previous errors diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index 1697a0cf29b8e..598f259415da5 100644 --- a/tests/ui/single_element_loop.fixed +++ b/tests/ui/single_element_loop.fixed @@ -1,6 +1,8 @@ //@run-rustfix // Tests from for_loop.rs that don't have suggestions +#![allow(clippy::single_range_in_vec_init)] + #[warn(clippy::single_element_loop)] fn main() { let item1 = 2; diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs index 860424f42ddf0..3fc461735a499 100644 --- a/tests/ui/single_element_loop.rs +++ b/tests/ui/single_element_loop.rs @@ -1,6 +1,8 @@ //@run-rustfix // Tests from for_loop.rs that don't have suggestions +#![allow(clippy::single_range_in_vec_init)] + #[warn(clippy::single_element_loop)] fn main() { let item1 = 2; diff --git a/tests/ui/single_element_loop.stderr b/tests/ui/single_element_loop.stderr index 14437a59745e0..c40c6198945a0 100644 --- a/tests/ui/single_element_loop.stderr +++ b/tests/ui/single_element_loop.stderr @@ -1,5 +1,5 @@ error: for loop over a single element - --> $DIR/single_element_loop.rs:7:5 + --> $DIR/single_element_loop.rs:9:5 | LL | / for item in &[item1] { LL | | dbg!(item); @@ -16,7 +16,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:11:5 + --> $DIR/single_element_loop.rs:13:5 | LL | / for item in [item1].iter() { LL | | dbg!(item); @@ -32,7 +32,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:15:5 + --> $DIR/single_element_loop.rs:17:5 | LL | / for item in &[0..5] { LL | | dbg!(item); @@ -48,7 +48,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:19:5 + --> $DIR/single_element_loop.rs:21:5 | LL | / for item in [0..5].iter_mut() { LL | | dbg!(item); @@ -64,7 +64,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:23:5 + --> $DIR/single_element_loop.rs:25:5 | LL | / for item in [0..5] { LL | | dbg!(item); @@ -80,7 +80,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:27:5 + --> $DIR/single_element_loop.rs:29:5 | LL | / for item in [0..5].into_iter() { LL | | dbg!(item); @@ -96,7 +96,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:46:5 + --> $DIR/single_element_loop.rs:48:5 | LL | / for _ in [42] { LL | | let _f = |n: u32| { diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 77a2cf3b991f6..e7b1fd6a85f22 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -1,6 +1,11 @@ //@run-rustfix #![warn(clippy::single_match)] -#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] +#![allow( + unused, + clippy::uninlined_format_args, + clippy::needless_if, + clippy::redundant_pattern_matching +)] fn dummy() {} fn single_match() { @@ -207,3 +212,43 @@ fn issue_10808(bar: Option) { } } } + +mod issue8634 { + struct SomeError(i32, i32); + + fn foo(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(()) => { + // Ignore this error because blah blah blah. + }, + } + } + + fn bar(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + // TODO: Process the error properly. + }, + } + } + + fn block_comment(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + /* + let's make sure that this also + does not lint block comments. + */ + }, + } + } +} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 8d0ab5b99ad51..1515a7053e5dd 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,6 +1,11 @@ //@run-rustfix #![warn(clippy::single_match)] -#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] +#![allow( + unused, + clippy::uninlined_format_args, + clippy::needless_if, + clippy::redundant_pattern_matching +)] fn dummy() {} fn single_match() { @@ -265,3 +270,43 @@ fn issue_10808(bar: Option) { _ => {}, } } + +mod issue8634 { + struct SomeError(i32, i32); + + fn foo(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(()) => { + // Ignore this error because blah blah blah. + }, + } + } + + fn bar(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + // TODO: Process the error properly. + }, + } + } + + fn block_comment(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + /* + let's make sure that this also + does not lint block comments. + */ + }, + } + } +} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index dad66e2ab2ec3..ef90151324043 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` - --> $DIR/single_match.rs:9:5 + --> $DIR/single_match.rs:14:5 | LL | / match x { LL | | Some(y) => { @@ -18,7 +18,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:17:5 + --> $DIR/single_match.rs:22:5 | LL | / match x { LL | | // Note the missing block braces. @@ -30,7 +30,7 @@ LL | | } | |_____^ help: try this: `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` - --> $DIR/single_match.rs:26:5 + --> $DIR/single_match.rs:31:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -39,7 +39,7 @@ LL | | }; | |_____^ help: try this: `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` - --> $DIR/single_match.rs:55:5 + --> $DIR/single_match.rs:60:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -48,7 +48,7 @@ LL | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:60:5 + --> $DIR/single_match.rs:65:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -57,7 +57,7 @@ LL | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:67:5 + --> $DIR/single_match.rs:72:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -66,7 +66,7 @@ LL | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:88:5 + --> $DIR/single_match.rs:93:5 | LL | / match x { LL | | "test" => println!(), @@ -75,7 +75,7 @@ LL | | } | |_____^ help: try this: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:101:5 + --> $DIR/single_match.rs:106:5 | LL | / match x { LL | | Foo::A => println!(), @@ -84,7 +84,7 @@ LL | | } | |_____^ help: try this: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:107:5 + --> $DIR/single_match.rs:112:5 | LL | / match x { LL | | FOO_C => println!(), @@ -93,7 +93,7 @@ LL | | } | |_____^ help: try this: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:112:5 + --> $DIR/single_match.rs:117:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -102,7 +102,7 @@ LL | | } | |_____^ help: try this: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:118:5 + --> $DIR/single_match.rs:123:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -111,7 +111,7 @@ LL | | } | |_____^ help: try this: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:135:5 + --> $DIR/single_match.rs:140:5 | LL | / match x { LL | | Bar::A => println!(), @@ -120,7 +120,7 @@ LL | | } | |_____^ help: try this: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:143:5 + --> $DIR/single_match.rs:148:5 | LL | / match x { LL | | None => println!(), @@ -129,7 +129,7 @@ LL | | }; | |_____^ help: try this: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:165:5 + --> $DIR/single_match.rs:170:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -138,7 +138,7 @@ LL | | } | |_____^ help: try this: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:171:5 + --> $DIR/single_match.rs:176:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -147,7 +147,7 @@ LL | | } | |_____^ help: try this: `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` - --> $DIR/single_match.rs:177:5 + --> $DIR/single_match.rs:182:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -156,7 +156,7 @@ LL | | } | |_____^ help: try this: `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` - --> $DIR/single_match.rs:249:5 + --> $DIR/single_match.rs:254:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -176,7 +176,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:257:5 + --> $DIR/single_match.rs:262:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed index f88498655a418..fcc8f14803d31 100644 --- a/tests/ui/single_match_else.fixed +++ b/tests/ui/single_match_else.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index b34b95539190c..77afd58a08dc7 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs new file mode 100644 index 0000000000000..833e1c43bfc0b --- /dev/null +++ b/tests/ui/single_range_in_vec_init.rs @@ -0,0 +1,58 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::no_effect, clippy::useless_vec, unused)] +#![warn(clippy::single_range_in_vec_init)] +#![feature(generic_arg_infer)] + +#[macro_use] +extern crate proc_macros; + +macro_rules! a { + () => { + vec![0..200]; + }; +} + +fn awa(start: T, end: T) { + [start..end]; +} + +fn awa_vec(start: T, end: T) { + vec![start..end]; +} + +fn main() { + // Lint + [0..200]; + vec![0..200]; + [0u8..200]; + [0usize..200]; + [0..200usize]; + vec![0u8..200]; + vec![0usize..200]; + vec![0..200usize]; + // Only suggest collect + [0..200isize]; + vec![0..200isize]; + // Do not lint + [0..200, 0..100]; + vec![0..200, 0..100]; + [0.0..200.0]; + vec![0.0..200.0]; + // `Copy` is not implemented for `Range`, so this doesn't matter + // FIXME: [0..200; 2]; + // FIXME: [vec!0..200; 2]; + + // Unfortunately skips any macros + a!(); + + // Skip external macros and procedural macros + external! { + [0..200]; + vec![0..200]; + } + with_span! { + span + [0..200]; + vec![0..200]; + } +} diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr new file mode 100644 index 0000000000000..3e3d521f4a50e --- /dev/null +++ b/tests/ui/single_range_in_vec_init.stderr @@ -0,0 +1,145 @@ +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:25:5 + | +LL | [0..200]; + | ^^^^^^^^ + | + = note: `-D clippy::single-range-in-vec-init` implied by `-D warnings` +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0; 200]; + | ~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:26:5 + | +LL | vec![0..200]; + | ^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0; 200]; + | ~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:27:5 + | +LL | [0u8..200]; + | ^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0u8..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0u8; 200]; + | ~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:28:5 + | +LL | [0usize..200]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0usize..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0usize; 200]; + | ~~~~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:29:5 + | +LL | [0..200usize]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200usize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200usize, try + | +LL | [0; 200usize]; + | ~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:30:5 + | +LL | vec![0u8..200]; + | ^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0u8..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0u8; 200]; + | ~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:31:5 + | +LL | vec![0usize..200]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0usize..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0usize; 200]; + | ~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:32:5 + | +LL | vec![0..200usize]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200usize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200usize, try + | +LL | vec![0; 200usize]; + | ~~~~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:34:5 + | +LL | [0..200isize]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200isize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:35:5 + | +LL | vec![0..200isize]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains the entire range, try + | +LL | (0..200isize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index 62574e2c8ceaa..8e4cd82cec306 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -1,7 +1,7 @@ //@aux-build:option_helpers.rs #![warn(clippy::skip_while_next)] -#![allow(clippy::disallowed_names)] +#![allow(clippy::disallowed_names, clippy::useless_vec)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed index 1370dd2df4dae..50c1fc71a3f9e 100644 --- a/tests/ui/stable_sort_primitive.fixed +++ b/tests/ui/stable_sort_primitive.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::stable_sort_primitive)] +#![allow(clippy::useless_vec)] fn main() { // positive examples diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs index cd344dd123897..bd1bb428f2bbe 100644 --- a/tests/ui/stable_sort_primitive.rs +++ b/tests/ui/stable_sort_primitive.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::stable_sort_primitive)] +#![allow(clippy::useless_vec)] fn main() { // positive examples diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr index 1432fdcff77ad..aa5d7b7e49146 100644 --- a/tests/ui/stable_sort_primitive.stderr +++ b/tests/ui/stable_sort_primitive.stderr @@ -1,5 +1,5 @@ error: used `sort` on primitive type `i32` - --> $DIR/stable_sort_primitive.rs:7:5 + --> $DIR/stable_sort_primitive.rs:8:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -8,7 +8,7 @@ LL | vec.sort(); = note: `-D clippy::stable-sort-primitive` implied by `-D warnings` error: used `sort` on primitive type `bool` - --> $DIR/stable_sort_primitive.rs:9:5 + --> $DIR/stable_sort_primitive.rs:10:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -16,7 +16,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `char` - --> $DIR/stable_sort_primitive.rs:11:5 + --> $DIR/stable_sort_primitive.rs:12:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -24,7 +24,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `str` - --> $DIR/stable_sort_primitive.rs:13:5 + --> $DIR/stable_sort_primitive.rs:14:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -32,7 +32,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `tuple` - --> $DIR/stable_sort_primitive.rs:15:5 + --> $DIR/stable_sort_primitive.rs:16:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -40,7 +40,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `array` - --> $DIR/stable_sort_primitive.rs:17:5 + --> $DIR/stable_sort_primitive.rs:18:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -48,7 +48,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `i32` - --> $DIR/stable_sort_primitive.rs:19:5 + --> $DIR/stable_sort_primitive.rs:20:5 | LL | arr.sort(); | ^^^^^^^^^^ help: try: `arr.sort_unstable()` diff --git a/tests/ui/starts_ends_with.fixed b/tests/ui/starts_ends_with.fixed index 29d56f852edde..b7237069dc5ce 100644 --- a/tests/ui/starts_ends_with.fixed +++ b/tests/ui/starts_ends_with.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, unused_must_use)] +#![allow(clippy::needless_if, dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 56bbe2574d426..658312e87e47f 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, unused_must_use)] +#![allow(clippy::needless_if, dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs index de78dfe4d6990..6980242ae727b 100644 --- a/tests/ui/string_add.rs +++ b/tests/ui/string_add.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro extern crate proc_macros; use proc_macros::external; diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 3fc11b8b0885e..0edd81acc7afb 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:macro_rules.rs -#![allow(dead_code, unused_variables)] +#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] #[macro_use] diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 7d54acf630e6c..2647f02f0e92c 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:macro_rules.rs -#![allow(dead_code, unused_variables)] +#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] #[macro_use] diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index 4823d9092089b..0473ccdc3f636 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -1,7 +1,12 @@ -//@aux-build:proc_macro_suspicious_else_formatting.rs +//@aux-build:proc_macro_suspicious_else_formatting.rs:proc-macro #![warn(clippy::suspicious_else_formatting)] -#![allow(clippy::if_same_then_else, clippy::let_unit_value, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::let_unit_value, + clippy::needless_if, + clippy::needless_else +)] extern crate proc_macro_suspicious_else_formatting; use proc_macro_suspicious_else_formatting::DeriveBadSpan; @@ -108,6 +113,13 @@ fn main() { else { } + + //#10273 This is fine. Don't warn + if foo() { + } else + /* whelp */ + { + } } // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions. diff --git a/tests/ui/suspicious_else_formatting.stderr b/tests/ui/suspicious_else_formatting.stderr index 2e512b47f1236..723fdd7e93e3b 100644 --- a/tests/ui/suspicious_else_formatting.stderr +++ b/tests/ui/suspicious_else_formatting.stderr @@ -1,5 +1,5 @@ error: this looks like an `else {..}` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:17:6 + --> $DIR/suspicious_else_formatting.rs:22:6 | LL | } { | ^ @@ -8,7 +8,7 @@ LL | } { = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:21:6 + --> $DIR/suspicious_else_formatting.rs:26:6 | LL | } if foo() { | ^ @@ -16,7 +16,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:28:10 + --> $DIR/suspicious_else_formatting.rs:33:10 | LL | } if foo() { | ^ @@ -24,7 +24,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:36:10 + --> $DIR/suspicious_else_formatting.rs:41:10 | LL | } if foo() { | ^ @@ -32,7 +32,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:45:6 + --> $DIR/suspicious_else_formatting.rs:50:6 | LL | } else | ______^ @@ -42,7 +42,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:57:6 + --> $DIR/suspicious_else_formatting.rs:62:6 | LL | } else | ______^ @@ -52,7 +52,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:62:6 + --> $DIR/suspicious_else_formatting.rs:67:6 | LL | } | ______^ @@ -63,7 +63,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:89:6 + --> $DIR/suspicious_else_formatting.rs:94:6 | LL | } | ______^ @@ -75,7 +75,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:97:6 + --> $DIR/suspicious_else_formatting.rs:102:6 | LL | } | ______^ diff --git a/tests/ui/suspicious_unary_op_formatting.rs b/tests/ui/suspicious_unary_op_formatting.rs index 9564e373c246d..3c5ca1762fe49 100644 --- a/tests/ui/suspicious_unary_op_formatting.rs +++ b/tests/ui/suspicious_unary_op_formatting.rs @@ -1,4 +1,5 @@ #![warn(clippy::suspicious_unary_op_formatting)] +#![allow(clippy::needless_if)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/suspicious_unary_op_formatting.stderr b/tests/ui/suspicious_unary_op_formatting.stderr index 9f1289ccba0c0..52b0e99a1d3e8 100644 --- a/tests/ui/suspicious_unary_op_formatting.stderr +++ b/tests/ui/suspicious_unary_op_formatting.stderr @@ -1,5 +1,5 @@ error: by not having a space between `>` and `-` it looks like `>-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:8:9 + --> $DIR/suspicious_unary_op_formatting.rs:9:9 | LL | if a >- 30 {} | ^^^^ @@ -8,7 +8,7 @@ LL | if a >- 30 {} = note: `-D clippy::suspicious-unary-op-formatting` implied by `-D warnings` error: by not having a space between `>=` and `-` it looks like `>=-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:9:9 + --> $DIR/suspicious_unary_op_formatting.rs:10:9 | LL | if a >=- 30 {} | ^^^^^ @@ -16,7 +16,7 @@ LL | if a >=- 30 {} = help: put a space between `>=` and `-` and remove the space after `-` error: by not having a space between `&&` and `!` it looks like `&&!` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:14:9 + --> $DIR/suspicious_unary_op_formatting.rs:15:9 | LL | if b &&! c {} | ^^^^^ @@ -24,7 +24,7 @@ LL | if b &&! c {} = help: put a space between `&&` and `!` and remove the space after `!` error: by not having a space between `>` and `-` it looks like `>-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:16:9 + --> $DIR/suspicious_unary_op_formatting.rs:17:9 | LL | if a >- 30 {} | ^^^^^^ diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index fd3569cf36254..22f904e3fd9e6 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -10,7 +10,8 @@ dead_code, unused_assignments, unused_variables, - clippy::let_and_return + clippy::let_and_return, + clippy::useless_vec )] struct Foo(u32); diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 34fbce0524b21..ada64f89e6d27 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -10,7 +10,8 @@ dead_code, unused_assignments, unused_variables, - clippy::let_and_return + clippy::let_and_return, + clippy::useless_vec )] struct Foo(u32); diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 0c246268499d9..a3b9c2b744c98 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,5 +1,5 @@ error: this looks like you are swapping `bar.a` and `bar.b` manually - --> $DIR/swap.rs:27:5 + --> $DIR/swap.rs:28:5 | LL | / let temp = bar.a; LL | | bar.a = bar.b; @@ -10,7 +10,7 @@ LL | | bar.b = temp; = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:39:5 + --> $DIR/swap.rs:40:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -18,7 +18,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:48:5 + --> $DIR/swap.rs:49:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -26,7 +26,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:67:5 + --> $DIR/swap.rs:68:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -34,7 +34,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:78:5 + --> $DIR/swap.rs:79:5 | LL | / a ^= b; LL | | b ^= a; @@ -42,7 +42,7 @@ LL | | a ^= b; | |___________^ help: try: `std::mem::swap(&mut a, &mut b);` error: this looks like you are swapping `bar.a` and `bar.b` manually - --> $DIR/swap.rs:86:5 + --> $DIR/swap.rs:87:5 | LL | / bar.a ^= bar.b; LL | | bar.b ^= bar.a; @@ -50,7 +50,7 @@ LL | | bar.a ^= bar.b; | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:94:5 + --> $DIR/swap.rs:95:5 | LL | / foo[0] ^= foo[1]; LL | | foo[1] ^= foo[0]; @@ -58,7 +58,7 @@ LL | | foo[0] ^= foo[1]; | |_____________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually - --> $DIR/swap.rs:123:5 + --> $DIR/swap.rs:124:5 | LL | / let temp = foo[0][1]; LL | | foo[0][1] = bar[1][0]; @@ -68,7 +68,7 @@ LL | | bar[1][0] = temp; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:137:7 + --> $DIR/swap.rs:138:7 | LL | ; let t = a; | _______^ @@ -79,7 +79,7 @@ LL | | b = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:146:7 + --> $DIR/swap.rs:147:7 | LL | ; let t = c.0; | _______^ @@ -90,7 +90,7 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `b` and `a` manually - --> $DIR/swap.rs:172:5 + --> $DIR/swap.rs:173:5 | LL | / let t = b; LL | | b = a; @@ -100,7 +100,7 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:134:5 + --> $DIR/swap.rs:135:5 | LL | / a = b; LL | | b = a; @@ -110,7 +110,7 @@ LL | | b = a; = note: `-D clippy::almost-swapped` implied by `-D warnings` error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:143:5 + --> $DIR/swap.rs:144:5 | LL | / c.0 = a; LL | | a = c.0; @@ -119,7 +119,7 @@ LL | | a = c.0; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:150:5 + --> $DIR/swap.rs:151:5 | LL | / let a = b; LL | | let b = a; @@ -128,7 +128,7 @@ LL | | let b = a; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `d` and `c` - --> $DIR/swap.rs:155:5 + --> $DIR/swap.rs:156:5 | LL | / d = c; LL | | c = d; @@ -137,7 +137,7 @@ LL | | c = d; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:159:5 + --> $DIR/swap.rs:160:5 | LL | / let a = b; LL | | b = a; @@ -146,7 +146,7 @@ LL | | b = a; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `s.0.x` and `s.0.y` manually - --> $DIR/swap.rs:207:5 + --> $DIR/swap.rs:208:5 | LL | / let t = s.0.x; LL | | s.0.x = s.0.y; diff --git a/tests/ui/tests_outside_test_module.rs b/tests/ui/tests_outside_test_module.rs index 21fdfdf900516..d53c692b78e13 100644 --- a/tests/ui/tests_outside_test_module.rs +++ b/tests/ui/tests_outside_test_module.rs @@ -1,4 +1,3 @@ -//@compile-flags: --test #![allow(unused)] #![warn(clippy::tests_outside_test_module)] diff --git a/tests/ui/tests_outside_test_module.stderr b/tests/ui/tests_outside_test_module.stderr index 125a79d6edfed..71c649c5d2706 100644 --- a/tests/ui/tests_outside_test_module.stderr +++ b/tests/ui/tests_outside_test_module.stderr @@ -1,5 +1,5 @@ error: this function marked with #[test] is outside a #[cfg(test)] module - --> $DIR/tests_outside_test_module.rs:11:1 + --> $DIR/tests_outside_test_module.rs:10:1 | LL | fn my_test() {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/to_string_in_format_args_incremental.fixed b/tests/ui/to_string_in_format_args_incremental.fixed new file mode 100644 index 0000000000000..9f75ad895cda8 --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.fixed @@ -0,0 +1,9 @@ +//@run-rustfix +//@compile-flags: -C incremental=target/debug/test/incr + +// see https://github.com/rust-lang/rust-clippy/issues/10969 + +fn main() { + let s = "Hello, world!"; + println!("{}", s); +} diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs new file mode 100644 index 0000000000000..67115f7c5a7b7 --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.rs @@ -0,0 +1,9 @@ +//@run-rustfix +//@compile-flags: -C incremental=target/debug/test/incr + +// see https://github.com/rust-lang/rust-clippy/issues/10969 + +fn main() { + let s = "Hello, world!"; + println!("{}", s.to_string()); +} diff --git a/tests/ui/to_string_in_format_args_incremental.stderr b/tests/ui/to_string_in_format_args_incremental.stderr new file mode 100644 index 0000000000000..a992c54291495 --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.stderr @@ -0,0 +1,10 @@ +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/to_string_in_format_args_incremental.rs:8:21 + | +LL | println!("{}", s.to_string()); + | ^^^^^^^^^^^^ help: remove this + | + = note: `-D clippy::to-string-in-format-args` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index ea30c1fda6fce..9ad45c7a817b4 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::uninlined_format_args, unused)] +#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 7a3d33e5be5a2..45ccc024cbdec 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::uninlined_format_args, unused)] +#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs index 8aaf47b1bd0c5..464762af82536 100644 --- a/tests/ui/toplevel_ref_arg_non_rustfix.rs +++ b/tests/ui/toplevel_ref_arg_non_rustfix.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::toplevel_ref_arg)] #![allow(unused)] diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index f06ffab5d9be9..61a6c98ed5ac7 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -32,7 +32,7 @@ fn transmute_ptr_to_ptr() { // ref-ref transmutes; bad let _: &f32 = std::mem::transmute(&1u32); let _: &f64 = std::mem::transmute(&1f32); - // ^ this test is here because both f32 and f64 are the same TypeVariant, but they are not + //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type let _: &mut f32 = std::mem::transmute(&mut 1u32); let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index ac55ab5a8e2d1..215f0ac184225 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -1,8 +1,7 @@ //@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding)] -#![allow(unused_must_use)] +#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; @@ -39,7 +38,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; let raw = 42 as *const i32; - let _ = unsafe { &*(raw as *const u8) }; + unsafe { &*(raw as *const u8) }; } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 901a3e90dbecc..3528e13790393 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -1,8 +1,7 @@ //@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding)] -#![allow(unused_must_use)] +#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); @@ -39,7 +38,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; let raw = 42 as *const i32; - let _ = unsafe { std::mem::transmute::<_, Bar>(raw) }; + unsafe { std::mem::transmute::<_, Bar>(raw) }; } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 68007edc41028..b3e6c09d2d7a1 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -1,5 +1,5 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:8:17 + --> $DIR/transmute_ptr_to_ref.rs:7:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -7,127 +7,127 @@ LL | let _: &T = std::mem::transmute(p); = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:11:21 + --> $DIR/transmute_ptr_to_ref.rs:10:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:14:17 + --> $DIR/transmute_ptr_to_ref.rs:13:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:17:21 + --> $DIR/transmute_ptr_to_ref.rs:16:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:20:17 + --> $DIR/transmute_ptr_to_ref.rs:19:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:23:21 + --> $DIR/transmute_ptr_to_ref.rs:22:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:26:17 + --> $DIR/transmute_ptr_to_ref.rs:25:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) - --> $DIR/transmute_ptr_to_ref.rs:36:32 + --> $DIR/transmute_ptr_to_ref.rs:35:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) - --> $DIR/transmute_ptr_to_ref.rs:38:33 + --> $DIR/transmute_ptr_to_ref.rs:37:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute_ptr_to_ref.rs:42:22 + --> $DIR/transmute_ptr_to_ref.rs:41:14 | -LL | let _ = unsafe { std::mem::transmute::<_, Bar>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` +LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:47:14 + --> $DIR/transmute_ptr_to_ref.rs:46:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:48:14 + --> $DIR/transmute_ptr_to_ref.rs:47:14 | LL | 1 => std::mem::transmute(y), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:49:14 + --> $DIR/transmute_ptr_to_ref.rs:48:14 | LL | 2 => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:50:14 + --> $DIR/transmute_ptr_to_ref.rs:49:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(y), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:58:19 + --> $DIR/transmute_ptr_to_ref.rs:57:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:59:19 + --> $DIR/transmute_ptr_to_ref.rs:58:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:61:14 + --> $DIR/transmute_ptr_to_ref.rs:60:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:62:14 + --> $DIR/transmute_ptr_to_ref.rs:61:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:70:19 + --> $DIR/transmute_ptr_to_ref.rs:69:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:71:19 + --> $DIR/transmute_ptr_to_ref.rs:70:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:73:14 + --> $DIR/transmute_ptr_to_ref.rs:72:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:74:14 + --> $DIR/transmute_ptr_to_ref.rs:73:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index dc773ad4bad95..1816740870ad6 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![deny(clippy::try_err)] #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)] diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 7a7433a7ec29a..0e47c4d023ef7 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![deny(clippy::try_err)] #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)] diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs new file mode 100644 index 0000000000000..f96a7c97f1aa6 --- /dev/null +++ b/tests/ui/tuple_array_conversions.rs @@ -0,0 +1,73 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::no_effect, clippy::useless_vec, unused)] +#![warn(clippy::tuple_array_conversions)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); + + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + t1.iter().for_each(|&(a, b)| _ = [a, b]); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + t1.iter().for_each(|&(a, b)| _ = [a, b]); + // Do not lint + let v2: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); + let t3: Vec<(u32, u32)> = v2.iter().map(|&v| v.into()).collect(); + let x = [1; 13]; + let x = ( + x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], + ); + let x = [x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7, x.8, x.9, x.10, x.11, x.12]; + let x = (1, 2); + let x = (x.0, x.1); + let x = [1, 2]; + let x = [x[0], x[1]]; + let x = vec![1, 2]; + let x = (x[0], x[1]); + let x = [1; 3]; + let x = (x[0],); + let x = (1, 2, 3); + let x = [x.0]; + let x = (1, 2); + let y = (1, 2); + [x.0, y.0]; + [x.0, y.1]; + let x = [x.0, x.0]; + let x = (x[0], x[0]); + external! { + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + } + with_span! { + span + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + } +} + +#[clippy::msrv = "1.70.0"] +fn msrv_too_low() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); +} + +#[clippy::msrv = "1.71.0"] +fn msrv_juust_right() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); +} diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr new file mode 100644 index 0000000000000..be653e8efb799 --- /dev/null +++ b/tests/ui/tuple_array_conversions.stderr @@ -0,0 +1,83 @@ +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:10:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + = note: `-D clippy::tuple-array-conversions` implied by `-D warnings` + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:11:13 + | +LL | let x = [x.0, x.1]; + | ^^^^^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:13:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:16:53 + | +LL | let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + | ^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:17:38 + | +LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); + | ^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:18:55 + | +LL | let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + | ^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:19:38 + | +LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); + | ^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:69:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:70:13 + | +LL | let x = [x.0, x.1]; + | ^^^^^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:72:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: aborting due to 10 previous errors + diff --git a/tests/ui/type_complexity.rs b/tests/ui/type_complexity.rs index 86a7bd7b62735..816950110b201 100644 --- a/tests/ui/type_complexity.rs +++ b/tests/ui/type_complexity.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)] +#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)] #![feature(associated_type_defaults)] type Alias = Vec>>; // no warning here diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 8b4613b3f6ec7..874d97f7a46c7 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -1,6 +1,7 @@ #![deny(clippy::type_repetition_in_bounds)] #![allow(clippy::extra_unused_type_parameters)] +use serde::Deserialize; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; pub fn foo(_t: T) @@ -70,6 +71,20 @@ mod issue4326 { } } +// Extern macros shouldn't lint, again (see #10504) +mod issue10504 { + use serde::{Deserialize, Serialize}; + use std::fmt::Debug; + use std::hash::Hash; + + #[derive(Debug, Serialize, Deserialize)] + #[serde(bound( + serialize = "T: Serialize + Hash + Eq", + deserialize = "Box: serde::de::DeserializeOwned + Hash + Eq" + ))] + struct OpaqueParams(std::marker::PhantomData); +} + // Issue #7360 struct Foo where @@ -95,4 +110,28 @@ where // This should not lint fn impl_trait(_: impl AsRef, _: impl AsRef) {} +#[clippy::msrv = "1.14.0"] +mod issue8772_fail { + pub trait Trait {} + + pub fn f(arg: usize) + where + T: Trait, Box<[String]>, bool> + 'static, + U: Clone + Sync + 'static, + { + } +} + +#[clippy::msrv = "1.15.0"] +mod issue8772_pass { + pub trait Trait {} + + pub fn f(arg: usize) + where + T: Trait, Box<[String]>, bool> + 'static, + U: Clone + Sync + 'static, + { + } +} + fn main() {} diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index a90df03c04ffc..54973c5bda572 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -1,5 +1,5 @@ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:9:5 + --> $DIR/type_repetition_in_bounds.rs:10:5 | LL | T: Clone, | ^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:26:5 + --> $DIR/type_repetition_in_bounds.rs:27:5 | LL | Self: Copy + Default + Ord, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | Self: Copy + Default + Ord, = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord` error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:86:5 + --> $DIR/type_repetition_in_bounds.rs:101:5 | LL | T: Clone, | ^^^^^^^^ @@ -28,12 +28,20 @@ LL | T: Clone, = help: consider combining the bounds: `T: ?Sized + Clone` error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:91:5 + --> $DIR/type_repetition_in_bounds.rs:106:5 | LL | T: ?Sized, | ^^^^^^^^^ | = help: consider combining the bounds: `T: Clone + ?Sized` -error: aborting due to 4 previous errors +error: this type has already been used as a bound predicate + --> $DIR/type_repetition_in_bounds.rs:131:9 + | +LL | T: Trait, Box<[String]>, bool> + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider combining the bounds: `T: ?Sized + Trait, Box<[String]>, bool>` + +error: aborting due to 5 previous errors diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index 229d150851a43..a9cc429543563 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_unsafe.rs +//@aux-build:proc_macro_unsafe.rs:proc-macro #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] #![allow(clippy::let_unit_value, clippy::missing_safety_doc)] @@ -509,4 +509,26 @@ fn issue_9142() { }; } +pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { + 1 +} + +pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { + 2 +} + +fn issue_10832() { + // Safety: A safety comment. But it will warn anyways + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment. But it will warn anyways + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment. But it will warn anyways + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; +} + fn main() {} diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr index d1c1bb5ffeac8..ee1d3aa285a28 100644 --- a/tests/ui/undocumented_unsafe_blocks.stderr +++ b/tests/ui/undocumented_unsafe_blocks.stderr @@ -318,5 +318,29 @@ LL | let bar = unsafe {}; | = help: consider adding a safety comment on the preceding line -error: aborting due to 36 previous errors +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:523:9 + | +LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:527:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:531:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 39 previous errors diff --git a/tests/ui/unicode.fixed b/tests/ui/unicode.fixed index 910968afa7f44..032040c4805c8 100644 --- a/tests/ui/unicode.fixed +++ b/tests/ui/unicode.fixed @@ -1,5 +1,4 @@ //@run-rustfix -//@compile-flags: --test #![allow(dead_code)] #[warn(clippy::invisible_characters)] diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index bc4b84d34354a..dd215bc604870 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,5 +1,4 @@ //@run-rustfix -//@compile-flags: --test #![allow(dead_code)] #[warn(clippy::invisible_characters)] diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index ea74a81451e3a..21cc22a778bc5 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,5 +1,5 @@ error: invisible character detected - --> $DIR/unicode.rs:7:12 + --> $DIR/unicode.rs:6:12 | LL | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{200B}< is a ZWS, and /u{200B}another"` @@ -7,19 +7,19 @@ LL | print!("Here >​< is a ZWS, and ​another"); = note: `-D clippy::invisible-characters` implied by `-D warnings` error: invisible character detected - --> $DIR/unicode.rs:9:12 + --> $DIR/unicode.rs:8:12 | LL | print!("Here >­< is a SHY, and ­another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{AD}< is a SHY, and /u{AD}another"` error: invisible character detected - --> $DIR/unicode.rs:11:12 + --> $DIR/unicode.rs:10:12 | LL | print!("Here >⁠< is a WJ, and ⁠another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{2060}< is a WJ, and /u{2060}another"` error: non-NFC Unicode sequence detected - --> $DIR/unicode.rs:17:12 + --> $DIR/unicode.rs:16:12 | LL | print!("̀àh?"); | ^^^^^ help: consider replacing the string with: `"̀àh?"` @@ -27,37 +27,37 @@ LL | print!("̀àh?"); = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` error: literal non-ASCII character detected - --> $DIR/unicode.rs:25:16 + --> $DIR/unicode.rs:24:16 | LL | print!("Üben!"); | ^^^^^^^ help: consider replacing the string with: `"/u{dc}ben!"` | note: the lint level is defined here - --> $DIR/unicode.rs:22:13 + --> $DIR/unicode.rs:21:13 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: literal non-ASCII character detected - --> $DIR/unicode.rs:31:36 + --> $DIR/unicode.rs:30:36 | LL | const _EMPTY_BLOCK: char = '▱'; | ^^^ help: consider replacing the string with: `'/u{25b1}'` error: literal non-ASCII character detected - --> $DIR/unicode.rs:32:35 + --> $DIR/unicode.rs:31:35 | LL | const _FULL_BLOCK: char = '▰'; | ^^^ help: consider replacing the string with: `'/u{25b0}'` error: literal non-ASCII character detected - --> $DIR/unicode.rs:52:21 + --> $DIR/unicode.rs:51:21 | LL | let _ = "悲しいかな、ここに日本語を書くことはできない。"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"/u{60b2}/u{3057}/u{3044}/u{304b}/u{306a}/u{3001}/u{3053}/u{3053}/u{306b}/u{65e5}/u{672c}/u{8a9e}/u{3092}/u{66f8}/u{304f}/u{3053}/u{3068}/u{306f}/u{3067}/u{304d}/u{306a}/u{3044}/u{3002}"` | note: the lint level is defined here - --> $DIR/unicode.rs:41:17 + --> $DIR/unicode.rs:40:17 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index e25d123dd51f1..a042731a9bf5f 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -1,8 +1,13 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro //@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] -#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] +#![allow( + clippy::eq_op, + clippy::format_in_format_args, + clippy::print_literal, + clippy::unnecessary_literal_unwrap +)] extern crate proc_macros; use proc_macros::with_span; diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 6793ec24441ce..d830b74d6072d 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -1,8 +1,13 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro //@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] -#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] +#![allow( + clippy::eq_op, + clippy::format_in_format_args, + clippy::print_literal, + clippy::unnecessary_literal_unwrap +)] extern crate proc_macros; use proc_macros::with_span; diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index dc4af6ef42ecd..44ca61f008c5f 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:40:5 + --> $DIR/uninlined_format_args.rs:45:5 | LL | println!("val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:41:5 + --> $DIR/uninlined_format_args.rs:46:5 | LL | println!("val='{ }'", local_i32); // 3 spaces | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + println!("val='{local_i32}'"); // 3 spaces | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:42:5 + --> $DIR/uninlined_format_args.rs:47:5 | LL | println!("val='{ }'", local_i32); // tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + println!("val='{local_i32}'"); // tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:43:5 + --> $DIR/uninlined_format_args.rs:48:5 | LL | println!("val='{ }'", local_i32); // space+tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + println!("val='{local_i32}'"); // space+tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:44:5 + --> $DIR/uninlined_format_args.rs:49:5 | LL | println!("val='{ }'", local_i32); // tab+space | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + println!("val='{local_i32}'"); // tab+space | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:45:5 + --> $DIR/uninlined_format_args.rs:50:5 | LL | / println!( LL | | "val='{ @@ -70,7 +70,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:50:5 + --> $DIR/uninlined_format_args.rs:55:5 | LL | println!("{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:51:5 + --> $DIR/uninlined_format_args.rs:56:5 | LL | println!("{}", fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL + println!("{fn_arg}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:52:5 + --> $DIR/uninlined_format_args.rs:57:5 | LL | println!("{:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:53:5 + --> $DIR/uninlined_format_args.rs:58:5 | LL | println!("{:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:54:5 + --> $DIR/uninlined_format_args.rs:59:5 | LL | println!("{:4}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL + println!("{local_i32:4}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:55:5 + --> $DIR/uninlined_format_args.rs:60:5 | LL | println!("{:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:56:5 + --> $DIR/uninlined_format_args.rs:61:5 | LL | println!("{:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:57:5 + --> $DIR/uninlined_format_args.rs:62:5 | LL | println!("{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:58:5 + --> $DIR/uninlined_format_args.rs:63:5 | LL | println!("{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:62:5 + --> $DIR/uninlined_format_args.rs:67:5 | LL | println!("{} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:64:5 + --> $DIR/uninlined_format_args.rs:69:5 | LL | println!("{}", val); | ^^^^^^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:65:5 + --> $DIR/uninlined_format_args.rs:70:5 | LL | println!("{}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +214,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:67:5 + --> $DIR/uninlined_format_args.rs:72:5 | LL | println!("val='{/t }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:68:5 + --> $DIR/uninlined_format_args.rs:73:5 | LL | println!("val='{/n }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:69:5 + --> $DIR/uninlined_format_args.rs:74:5 | LL | println!("val='{local_i32}'", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:70:5 + --> $DIR/uninlined_format_args.rs:75:5 | LL | println!("val='{local_i32}'", local_i32 = fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +262,7 @@ LL + println!("val='{fn_arg}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:71:5 + --> $DIR/uninlined_format_args.rs:76:5 | LL | println!("{0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +274,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:72:5 + --> $DIR/uninlined_format_args.rs:77:5 | LL | println!("{0:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -286,7 +286,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:73:5 + --> $DIR/uninlined_format_args.rs:78:5 | LL | println!("{0:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -298,7 +298,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:74:5 + --> $DIR/uninlined_format_args.rs:79:5 | LL | println!("{0:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,7 +310,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:75:5 + --> $DIR/uninlined_format_args.rs:80:5 | LL | println!("{0:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -322,7 +322,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:76:5 + --> $DIR/uninlined_format_args.rs:81:5 | LL | println!("{0:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:77:5 + --> $DIR/uninlined_format_args.rs:82:5 | LL | println!("{0:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -346,7 +346,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:78:5 + --> $DIR/uninlined_format_args.rs:83:5 | LL | println!("{0} {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL + println!("{local_i32} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:79:5 + --> $DIR/uninlined_format_args.rs:84:5 | LL | println!("{1} {} {0} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -370,7 +370,7 @@ LL + println!("{local_f64} {local_i32} {local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:80:5 + --> $DIR/uninlined_format_args.rs:85:5 | LL | println!("{0} {1}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -382,7 +382,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:81:5 + --> $DIR/uninlined_format_args.rs:86:5 | LL | println!("{1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -394,7 +394,7 @@ LL + println!("{local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:82:5 + --> $DIR/uninlined_format_args.rs:87:5 | LL | println!("{1} {0} {1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -406,7 +406,7 @@ LL + println!("{local_f64} {local_i32} {local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:84:5 + --> $DIR/uninlined_format_args.rs:89:5 | LL | println!("{v}", v = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:85:5 + --> $DIR/uninlined_format_args.rs:90:5 | LL | println!("{local_i32:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -430,7 +430,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:86:5 + --> $DIR/uninlined_format_args.rs:91:5 | LL | println!("{local_i32:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -442,7 +442,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:87:5 + --> $DIR/uninlined_format_args.rs:92:5 | LL | println!("{local_i32:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -454,7 +454,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:88:5 + --> $DIR/uninlined_format_args.rs:93:5 | LL | println!("{local_i32:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:89:5 + --> $DIR/uninlined_format_args.rs:94:5 | LL | println!("{:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +478,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:90:5 + --> $DIR/uninlined_format_args.rs:95:5 | LL | println!("{0:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:91:5 + --> $DIR/uninlined_format_args.rs:96:5 | LL | println!("{:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +502,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:92:5 + --> $DIR/uninlined_format_args.rs:97:5 | LL | println!("{0:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +514,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:93:5 + --> $DIR/uninlined_format_args.rs:98:5 | LL | println!("{0:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -526,7 +526,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:94:5 + --> $DIR/uninlined_format_args.rs:99:5 | LL | println!("{0:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -538,7 +538,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:95:5 + --> $DIR/uninlined_format_args.rs:100:5 | LL | println!("{v:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -550,7 +550,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:96:5 + --> $DIR/uninlined_format_args.rs:101:5 | LL | println!("{v:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -562,7 +562,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:97:5 + --> $DIR/uninlined_format_args.rs:102:5 | LL | println!("{v:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -574,7 +574,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:98:5 + --> $DIR/uninlined_format_args.rs:103:5 | LL | println!("{v:v$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -586,7 +586,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:99:5 + --> $DIR/uninlined_format_args.rs:104:5 | LL | println!("{:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -598,7 +598,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:100:5 + --> $DIR/uninlined_format_args.rs:105:5 | LL | println!("{:1$}", local_i32, width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -610,7 +610,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:101:5 + --> $DIR/uninlined_format_args.rs:106:5 | LL | println!("{:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -622,7 +622,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:102:5 + --> $DIR/uninlined_format_args.rs:107:5 | LL | println!("{:w$}", local_i32, w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -634,7 +634,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:103:5 + --> $DIR/uninlined_format_args.rs:108:5 | LL | println!("{:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -646,7 +646,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:104:5 + --> $DIR/uninlined_format_args.rs:109:5 | LL | println!("{:.1$}", local_i32, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -658,7 +658,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:105:5 + --> $DIR/uninlined_format_args.rs:110:5 | LL | println!("{:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -670,7 +670,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:106:5 + --> $DIR/uninlined_format_args.rs:111:5 | LL | println!("{:.p$}", local_i32, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -682,7 +682,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:107:5 + --> $DIR/uninlined_format_args.rs:112:5 | LL | println!("{:0$.1$}", width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -694,7 +694,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:108:5 + --> $DIR/uninlined_format_args.rs:113:5 | LL | println!("{:0$.w$}", width, w = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -706,7 +706,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:109:5 + --> $DIR/uninlined_format_args.rs:114:5 | LL | println!("{:1$.2$}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -718,7 +718,7 @@ LL + println!("{local_f64:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:110:5 + --> $DIR/uninlined_format_args.rs:115:5 | LL | println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -730,7 +730,7 @@ LL + println!("{local_f64:width$.prec$} {local_f64} {width} {prec}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:111:5 + --> $DIR/uninlined_format_args.rs:116:5 | LL | / println!( LL | | "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}", @@ -739,7 +739,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:122:5 + --> $DIR/uninlined_format_args.rs:127:5 | LL | println!("Width = {}, value with width = {:0$}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -751,7 +751,7 @@ LL + println!("Width = {local_i32}, value with width = {local_f64:local_i32$ | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:123:5 + --> $DIR/uninlined_format_args.rs:128:5 | LL | println!("{:w$.p$}", local_i32, w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -763,7 +763,7 @@ LL + println!("{local_i32:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:124:5 + --> $DIR/uninlined_format_args.rs:129:5 | LL | println!("{:w$.p$}", w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -775,7 +775,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:143:5 + --> $DIR/uninlined_format_args.rs:148:5 | LL | / println!( LL | | "{}", @@ -785,7 +785,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:148:5 + --> $DIR/uninlined_format_args.rs:153:5 | LL | println!("{}", /* comment with a comma , in it */ val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -797,7 +797,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:154:9 + --> $DIR/uninlined_format_args.rs:159:9 | LL | panic!("p1 {}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -809,7 +809,7 @@ LL + panic!("p1 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:157:9 + --> $DIR/uninlined_format_args.rs:162:9 | LL | panic!("p2 {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -821,7 +821,7 @@ LL + panic!("p2 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:160:9 + --> $DIR/uninlined_format_args.rs:165:9 | LL | panic!("p3 {local_i32}", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -833,7 +833,7 @@ LL + panic!("p3 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:180:5 + --> $DIR/uninlined_format_args.rs:185:5 | LL | println!("expand='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index d082063c8e820..fded8db5daf93 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,4 +1,4 @@ -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::unit_arg)] #![allow(unused_must_use, unused_variables)] #![allow( diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index 3d271104361b6..fc75f548a1bcc 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -2,7 +2,8 @@ #![allow( clippy::no_effect, clippy::unnecessary_operation, - clippy::derive_partial_eq_without_eq + clippy::derive_partial_eq_without_eq, + clippy::needless_if )] #[derive(PartialEq)] diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 41cf19ae685ed..79c890d644cd4 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,5 +1,5 @@ error: ==-comparison of unit values detected. This will always be true - --> $DIR/unit_cmp.rs:16:8 + --> $DIR/unit_cmp.rs:17:8 | LL | if { | ________^ @@ -12,7 +12,7 @@ LL | | } {} = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false - --> $DIR/unit_cmp.rs:22:8 + --> $DIR/unit_cmp.rs:23:8 | LL | if { | ________^ @@ -23,7 +23,7 @@ LL | | } {} | |_____^ error: `assert_eq` of unit values detected. This will always succeed - --> $DIR/unit_cmp.rs:28:5 + --> $DIR/unit_cmp.rs:29:5 | LL | / assert_eq!( LL | | { @@ -35,7 +35,7 @@ LL | | ); | |_____^ error: `debug_assert_eq` of unit values detected. This will always succeed - --> $DIR/unit_cmp.rs:36:5 + --> $DIR/unit_cmp.rs:37:5 | LL | / debug_assert_eq!( LL | | { @@ -47,7 +47,7 @@ LL | | ); | |_____^ error: `assert_ne` of unit values detected. This will always fail - --> $DIR/unit_cmp.rs:45:5 + --> $DIR/unit_cmp.rs:46:5 | LL | / assert_ne!( LL | | { @@ -59,7 +59,7 @@ LL | | ); | |_____^ error: `debug_assert_ne` of unit values detected. This will always fail - --> $DIR/unit_cmp.rs:53:5 + --> $DIR/unit_cmp.rs:54:5 | LL | / debug_assert_ne!( LL | | { diff --git a/tests/ui/unit_return_expecting_ord.rs b/tests/ui/unit_return_expecting_ord.rs index bdb4710cc6972..f2a9694f99e5b 100644 --- a/tests/ui/unit_return_expecting_ord.rs +++ b/tests/ui/unit_return_expecting_ord.rs @@ -1,6 +1,7 @@ #![warn(clippy::unit_return_expecting_ord)] #![allow(clippy::needless_return)] #![allow(clippy::unused_unit)] +#![allow(clippy::useless_vec)] #![feature(is_sorted)] struct Struct { diff --git a/tests/ui/unit_return_expecting_ord.stderr b/tests/ui/unit_return_expecting_ord.stderr index 1d9564ce225e1..3a295af55eac9 100644 --- a/tests/ui/unit_return_expecting_ord.stderr +++ b/tests/ui/unit_return_expecting_ord.stderr @@ -1,36 +1,36 @@ error: this closure returns the unit type which also implements Ord - --> $DIR/unit_return_expecting_ord.rs:18:25 + --> $DIR/unit_return_expecting_ord.rs:19:25 | LL | structs.sort_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> $DIR/unit_return_expecting_ord.rs:19:24 + --> $DIR/unit_return_expecting_ord.rs:20:24 | LL | double(s.field); | ^ = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings` error: this closure returns the unit type which also implements PartialOrd - --> $DIR/unit_return_expecting_ord.rs:22:30 + --> $DIR/unit_return_expecting_ord.rs:23:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> $DIR/unit_return_expecting_ord.rs:23:24 + --> $DIR/unit_return_expecting_ord.rs:24:24 | LL | double(s.field); | ^ error: this closure returns the unit type which also implements PartialOrd - --> $DIR/unit_return_expecting_ord.rs:25:30 + --> $DIR/unit_return_expecting_ord.rs:26:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ error: this closure returns the unit type which also implements Ord - --> $DIR/unit_return_expecting_ord.rs:35:25 + --> $DIR/unit_return_expecting_ord.rs:36:25 | LL | structs.sort_by_key(|s| unit(s.field)); | ^^^ diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index bcc231ea7bce5..8efd44baf59fe 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -1,13 +1,43 @@ //@run-rustfix +//@aux-build:extern_fake_libc.rs #![warn(clippy::unnecessary_cast)] #![allow( - unused_must_use, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, - clippy::unnecessary_operation + clippy::unnecessary_operation, + nonstandard_style, + unused )] +extern crate extern_fake_libc; + +type PtrConstU8 = *const u8; +type PtrMutU8 = *mut u8; + +fn owo(ptr: *const T) -> *const T { + ptr +} + +fn uwu(ptr: *const T) -> *const U { + ptr as *const U +} + +mod fake_libc { + type pid_t = i32; + pub unsafe fn getpid() -> pid_t { + pid_t::from(0) + } + // Make sure a where clause does not break it + pub fn getpid_SAFE_TRUTH(t: &T) -> pid_t + where + T: Clone, + { + t; + unsafe { getpid() } + } +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -22,6 +52,26 @@ fn main() { 1_i32; 1_f32; + let _: *mut u8 = [1u8, 2].as_ptr() as *mut u8; + + [1u8, 2].as_ptr(); + [1u8, 2].as_ptr() as *mut u8; + [1u8, 2].as_mut_ptr(); + [1u8, 2].as_mut_ptr() as *const u8; + [1u8, 2].as_ptr() as PtrConstU8; + [1u8, 2].as_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrConstU8; + let _: *const u8 = [1u8, 2].as_ptr() as _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + let _: *const u8 = [1u8, 2].as_ptr() as *const _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; + + owo::([1u32].as_ptr()); + uwu::([1u32].as_ptr()); + // this will not lint in the function body even though they have the same type, instead here + uwu::([1u32].as_ptr()); + // macro version macro_rules! foo { ($a:ident, $b:ident) => { @@ -35,12 +85,37 @@ fn main() { foo!(b, f32); foo!(c, f64); + // do not lint cast from cfg-dependant type + let x = 0 as std::ffi::c_ulong; + let y = x as u64; + let x: std::ffi::c_ulong = 0; + let y = x as u64; + // do not lint cast to cfg-dependant type - 1 as std::os::raw::c_char; + let x = 1 as std::os::raw::c_char; + let y = x as u64; // do not lint cast to alias type 1 as I32Alias; &1 as &I32Alias; + // or from + let x: I32Alias = 1; + let y = x as u64; + fake_libc::getpid_SAFE_TRUTH(&0u32) as i32; + extern_fake_libc::getpid_SAFE_TRUTH() as i32; + let pid = unsafe { fake_libc::getpid() }; + pid as i32; + + let i8_ptr: *const i8 = &1; + let u8_ptr: *const u8 = &1; + + // cfg dependant pointees + i8_ptr as *const std::os::raw::c_char; + u8_ptr as *const std::os::raw::c_char; + + // type aliased pointees + i8_ptr as *const std::ffi::c_char; + u8_ptr as *const std::ffi::c_char; // issue #9960 macro_rules! bind_var { diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 282b2f1283ee9..c7723ef51f990 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -1,13 +1,43 @@ //@run-rustfix +//@aux-build:extern_fake_libc.rs #![warn(clippy::unnecessary_cast)] #![allow( - unused_must_use, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, - clippy::unnecessary_operation + clippy::unnecessary_operation, + nonstandard_style, + unused )] +extern crate extern_fake_libc; + +type PtrConstU8 = *const u8; +type PtrMutU8 = *mut u8; + +fn owo(ptr: *const T) -> *const T { + ptr as *const T +} + +fn uwu(ptr: *const T) -> *const U { + ptr as *const U +} + +mod fake_libc { + type pid_t = i32; + pub unsafe fn getpid() -> pid_t { + pid_t::from(0) + } + // Make sure a where clause does not break it + pub fn getpid_SAFE_TRUTH(t: &T) -> pid_t + where + T: Clone, + { + t; + unsafe { getpid() } + } +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -22,6 +52,26 @@ fn main() { 1_i32 as i32; 1_f32 as f32; + let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; + + [1u8, 2].as_ptr() as *const u8; + [1u8, 2].as_ptr() as *mut u8; + [1u8, 2].as_mut_ptr() as *mut u8; + [1u8, 2].as_mut_ptr() as *const u8; + [1u8, 2].as_ptr() as PtrConstU8; + [1u8, 2].as_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrConstU8; + let _: *const u8 = [1u8, 2].as_ptr() as _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + let _: *const u8 = [1u8, 2].as_ptr() as *const _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; + + owo::([1u32].as_ptr()) as *const u32; + uwu::([1u32].as_ptr()) as *const u8; + // this will not lint in the function body even though they have the same type, instead here + uwu::([1u32].as_ptr()) as *const u32; + // macro version macro_rules! foo { ($a:ident, $b:ident) => { @@ -35,12 +85,37 @@ fn main() { foo!(b, f32); foo!(c, f64); + // do not lint cast from cfg-dependant type + let x = 0 as std::ffi::c_ulong; + let y = x as u64; + let x: std::ffi::c_ulong = 0; + let y = x as u64; + // do not lint cast to cfg-dependant type - 1 as std::os::raw::c_char; + let x = 1 as std::os::raw::c_char; + let y = x as u64; // do not lint cast to alias type 1 as I32Alias; &1 as &I32Alias; + // or from + let x: I32Alias = 1; + let y = x as u64; + fake_libc::getpid_SAFE_TRUTH(&0u32) as i32; + extern_fake_libc::getpid_SAFE_TRUTH() as i32; + let pid = unsafe { fake_libc::getpid() }; + pid as i32; + + let i8_ptr: *const i8 = &1; + let u8_ptr: *const u8 = &1; + + // cfg dependant pointees + i8_ptr as *const std::os::raw::c_char; + u8_ptr as *const std::os::raw::c_char; + + // type aliased pointees + i8_ptr as *const std::ffi::c_char; + u8_ptr as *const std::ffi::c_char; // issue #9960 macro_rules! bind_var { diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index fcee4ee2a65cc..f0443556fb4d5 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,190 +1,232 @@ +error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`) + --> $DIR/unnecessary_cast.rs:19:5 + | +LL | ptr as *const T + | ^^^^^^^^^^^^^^^ help: try: `ptr` + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:14:5 + --> $DIR/unnecessary_cast.rs:44:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` - | - = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:15:5 + --> $DIR/unnecessary_cast.rs:45:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/unnecessary_cast.rs:16:5 + --> $DIR/unnecessary_cast.rs:46:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:19:5 + --> $DIR/unnecessary_cast.rs:49:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:20:5 + --> $DIR/unnecessary_cast.rs:50:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:21:5 + --> $DIR/unnecessary_cast.rs:51:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:22:5 + --> $DIR/unnecessary_cast.rs:52:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:23:5 + --> $DIR/unnecessary_cast.rs:53:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:55:22 + | +LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:57:5 + | +LL | [1u8, 2].as_ptr() as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` + +error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) + --> $DIR/unnecessary_cast.rs:59:5 + | +LL | [1u8, 2].as_mut_ptr() as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) + --> $DIR/unnecessary_cast.rs:70:5 + | +LL | owo::([1u32].as_ptr()) as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:71:5 + | +LL | uwu::([1u32].as_ptr()) as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) + --> $DIR/unnecessary_cast.rs:73:5 + | +LL | uwu::([1u32].as_ptr()) as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` + error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:64:9 + --> $DIR/unnecessary_cast.rs:139:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:65:9 + --> $DIR/unnecessary_cast.rs:140:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:66:9 + --> $DIR/unnecessary_cast.rs:141:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:67:17 + --> $DIR/unnecessary_cast.rs:142:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:68:17 + --> $DIR/unnecessary_cast.rs:143:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:69:17 + --> $DIR/unnecessary_cast.rs:144:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:70:9 + --> $DIR/unnecessary_cast.rs:145:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:71:9 + --> $DIR/unnecessary_cast.rs:146:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:83:9 + --> $DIR/unnecessary_cast.rs:158:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:84:9 + --> $DIR/unnecessary_cast.rs:159:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:85:9 + --> $DIR/unnecessary_cast.rs:160:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:86:9 + --> $DIR/unnecessary_cast.rs:161:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:87:9 + --> $DIR/unnecessary_cast.rs:162:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:89:9 + --> $DIR/unnecessary_cast.rs:164:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:90:9 + --> $DIR/unnecessary_cast.rs:165:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:94:17 + --> $DIR/unnecessary_cast.rs:169:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:95:17 + --> $DIR/unnecessary_cast.rs:170:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:101:18 + --> $DIR/unnecessary_cast.rs:176:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:107:22 + --> $DIR/unnecessary_cast.rs:182:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:109:22 + --> $DIR/unnecessary_cast.rs:184:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:116:22 + --> $DIR/unnecessary_cast.rs:191:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:118:23 + --> $DIR/unnecessary_cast.rs:193:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:126:20 + --> $DIR/unnecessary_cast.rs:201:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 31 previous errors +error: aborting due to 38 previous errors diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed index 2bed14973caa7..bd1d4a152aebc 100644 --- a/tests/ui/unnecessary_fold.fixed +++ b/tests/ui/unnecessary_fold.fixed @@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() { .any(|x| x > 2); } +fn issue10000() { + use std::collections::HashMap; + use std::hash::BuildHasher; + + fn anything(_: T) {} + fn num(_: i32) {} + fn smoketest_map(mut map: HashMap) { + map.insert(0, 0); + assert_eq!(map.values().sum::(), 0); + + // more cases: + let _ = map.values().sum::(); + let _ = map.values().product::(); + let _: i32 = map.values().sum(); + let _: i32 = map.values().product(); + anything(map.values().sum::()); + anything(map.values().product::()); + num(map.values().sum()); + num(map.values().product()); + } + + smoketest_map(HashMap::new()); +} + fn main() {} diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index a3cec8ea3d554..d27cc460c44af 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() { .fold(false, |acc, x| acc || x > 2); } +fn issue10000() { + use std::collections::HashMap; + use std::hash::BuildHasher; + + fn anything(_: T) {} + fn num(_: i32) {} + fn smoketest_map(mut map: HashMap) { + map.insert(0, 0); + assert_eq!(map.values().fold(0, |x, y| x + y), 0); + + // more cases: + let _ = map.values().fold(0, |x, y| x + y); + let _ = map.values().fold(1, |x, y| x * y); + let _: i32 = map.values().fold(0, |x, y| x + y); + let _: i32 = map.values().fold(1, |x, y| x * y); + anything(map.values().fold(0, |x, y| x + y)); + anything(map.values().fold(1, |x, y| x * y)); + num(map.values().fold(0, |x, y| x + y)); + num(map.values().fold(1, |x, y| x * y)); + } + + smoketest_map(HashMap::new()); +} + fn main() {} diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 22c44588ab7af..98979f7477fbb 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -36,5 +36,59 @@ error: this `.fold` can be written more succinctly using another method LL | .fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` -error: aborting due to 6 previous errors +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:60:33 + | +LL | assert_eq!(map.values().fold(0, |x, y| x + y), 0); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:63:30 + | +LL | let _ = map.values().fold(0, |x, y| x + y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:64:30 + | +LL | let _ = map.values().fold(1, |x, y| x * y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:65:35 + | +LL | let _: i32 = map.values().fold(0, |x, y| x + y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:66:35 + | +LL | let _: i32 = map.values().fold(1, |x, y| x * y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:67:31 + | +LL | anything(map.values().fold(0, |x, y| x + y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:68:31 + | +LL | anything(map.values().fold(1, |x, y| x * y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:69:26 + | +LL | num(map.values().fold(0, |x, y| x + y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:70:26 + | +LL | num(map.values().fold(1, |x, y| x * y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` + +error: aborting due to 15 previous errors diff --git a/tests/ui/unnecessary_join.fixed b/tests/ui/unnecessary_join.fixed index e102df6259989..f13a5275e31b5 100644 --- a/tests/ui/unnecessary_join.fixed +++ b/tests/ui/unnecessary_join.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::unnecessary_join)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { // should be linted diff --git a/tests/ui/unnecessary_join.rs b/tests/ui/unnecessary_join.rs index b87c15bc12635..6014d723a2f40 100644 --- a/tests/ui/unnecessary_join.rs +++ b/tests/ui/unnecessary_join.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::unnecessary_join)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { // should be linted diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index c3728886ec9c6..dca38034177b2 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -1,9 +1,13 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +#![allow(clippy::needless_borrow)] +#![allow(clippy::unnecessary_literal_unwrap)] + +use std::ops::Deref; extern crate proc_macros; use proc_macros::with_span; @@ -41,6 +45,15 @@ impl Drop for Issue9427FollowUp { } } +struct Issue10437; +impl Deref for Issue10437 { + type Target = u32; + fn deref(&self) -> &Self::Target { + println!("side effect deref"); + &0 + } +} + fn main() { let astronomers_pi = 10; let ext_arr: [usize; 1] = [2]; @@ -65,6 +78,15 @@ fn main() { let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); let _ = cond.then_some(astronomers_pi); + // Should lint - Builtin deref + let r = &1; + let _ = Some(1).unwrap_or(*r); + let b = Box::new(1); + let _ = Some(1).unwrap_or(*b); + // Should lint - Builtin deref through autoderef + let _ = Some(1).as_ref().unwrap_or(&r); + let _ = Some(1).as_ref().unwrap_or(&b); + // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); let _ = Some(10).and(ext_opt); @@ -93,6 +115,12 @@ fn main() { let _ = deep.0.or_else(|| some_call()); let _ = opt.ok_or_else(|| ext_arr[0]); + let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl + let _ = Some(1).unwrap_or(*Issue10437); + + let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437); + let _ = Some(1).as_ref().unwrap_or(&Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 76e50fa5b0304..7fda719edc1b7 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -1,9 +1,13 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +#![allow(clippy::needless_borrow)] +#![allow(clippy::unnecessary_literal_unwrap)] + +use std::ops::Deref; extern crate proc_macros; use proc_macros::with_span; @@ -41,6 +45,15 @@ impl Drop for Issue9427FollowUp { } } +struct Issue10437; +impl Deref for Issue10437 { + type Target = u32; + fn deref(&self) -> &Self::Target { + println!("side effect deref"); + &0 + } +} + fn main() { let astronomers_pi = 10; let ext_arr: [usize; 1] = [2]; @@ -65,6 +78,15 @@ fn main() { let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); let _ = cond.then(|| astronomers_pi); + // Should lint - Builtin deref + let r = &1; + let _ = Some(1).unwrap_or_else(|| *r); + let b = Box::new(1); + let _ = Some(1).unwrap_or_else(|| *b); + // Should lint - Builtin deref through autoderef + let _ = Some(1).as_ref().unwrap_or_else(|| &r); + let _ = Some(1).as_ref().unwrap_or_else(|| &b); + // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); let _ = Some(10).and_then(|_| ext_opt); @@ -93,6 +115,12 @@ fn main() { let _ = deep.0.or_else(|| some_call()); let _ = opt.ok_or_else(|| ext_arr[0]); + let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl + let _ = Some(1).unwrap_or(*Issue10437); + + let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437); + let _ = Some(1).as_ref().unwrap_or(&Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 0339755442c5a..458eed1f359ad 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:56:13 + --> $DIR/unnecessary_lazy_eval.rs:69:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:57:13 + --> $DIR/unnecessary_lazy_eval.rs:70:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:58:13 + --> $DIR/unnecessary_lazy_eval.rs:71:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:60:13 + --> $DIR/unnecessary_lazy_eval.rs:73:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:61:13 + --> $DIR/unnecessary_lazy_eval.rs:74:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:62:13 + --> $DIR/unnecessary_lazy_eval.rs:75:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:63:13 + --> $DIR/unnecessary_lazy_eval.rs:76:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:64:13 + --> $DIR/unnecessary_lazy_eval.rs:77:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -65,7 +65,7 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:65:13 + --> $DIR/unnecessary_lazy_eval.rs:78:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- @@ -73,7 +73,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:66:13 + --> $DIR/unnecessary_lazy_eval.rs:79:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^----------------------- @@ -81,7 +81,39 @@ LL | let _ = cond.then(|| astronomers_pi); | help: use `then_some(..)` instead: `then_some(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:69:13 + --> $DIR/unnecessary_lazy_eval.rs:83:13 + | +LL | let _ = Some(1).unwrap_or_else(|| *r); + | ^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:85:13 + | +LL | let _ = Some(1).unwrap_or_else(|| *b); + | ^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:87:13 + | +LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); + | ^^^^^^^^^^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:88:13 + | +LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); + | ^^^^^^^^^^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:91:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- @@ -89,7 +121,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:70:13 + --> $DIR/unnecessary_lazy_eval.rs:92:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -97,7 +129,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:71:28 + --> $DIR/unnecessary_lazy_eval.rs:93:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -105,7 +137,7 @@ LL | let _: Option = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:72:13 + --> $DIR/unnecessary_lazy_eval.rs:94:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -113,7 +145,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:73:35 + --> $DIR/unnecessary_lazy_eval.rs:95:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -121,7 +153,7 @@ LL | let _: Result = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:74:28 + --> $DIR/unnecessary_lazy_eval.rs:96:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^---------------- @@ -129,7 +161,7 @@ LL | let _: Option = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:77:13 + --> $DIR/unnecessary_lazy_eval.rs:99:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -137,7 +169,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:78:13 + --> $DIR/unnecessary_lazy_eval.rs:100:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -145,7 +177,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:79:13 + --> $DIR/unnecessary_lazy_eval.rs:101:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -153,7 +185,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:80:13 + --> $DIR/unnecessary_lazy_eval.rs:102:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -161,7 +193,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:81:13 + --> $DIR/unnecessary_lazy_eval.rs:103:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -169,7 +201,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:105:28 + --> $DIR/unnecessary_lazy_eval.rs:133:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -177,7 +209,7 @@ LL | let _: Option = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:106:13 + --> $DIR/unnecessary_lazy_eval.rs:134:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -185,7 +217,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:107:13 + --> $DIR/unnecessary_lazy_eval.rs:135:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -193,7 +225,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:113:13 + --> $DIR/unnecessary_lazy_eval.rs:141:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -201,7 +233,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:114:13 + --> $DIR/unnecessary_lazy_eval.rs:142:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -209,7 +241,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:115:13 + --> $DIR/unnecessary_lazy_eval.rs:143:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -217,7 +249,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:137:35 + --> $DIR/unnecessary_lazy_eval.rs:165:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -225,7 +257,7 @@ LL | let _: Result = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:138:35 + --> $DIR/unnecessary_lazy_eval.rs:166:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -233,7 +265,7 @@ LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:139:35 + --> $DIR/unnecessary_lazy_eval.rs:167:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -241,7 +273,7 @@ LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:141:35 + --> $DIR/unnecessary_lazy_eval.rs:169:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -249,7 +281,7 @@ LL | let _: Result = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:142:35 + --> $DIR/unnecessary_lazy_eval.rs:170:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -257,7 +289,7 @@ LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:143:35 + --> $DIR/unnecessary_lazy_eval.rs:171:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -265,7 +297,7 @@ LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:144:35 + --> $DIR/unnecessary_lazy_eval.rs:172:35 | LL | let _: Result = res. | ___________________________________^ @@ -279,5 +311,5 @@ LL | | or_else(|_| Ok(ext_str.some_field)); | | | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` -error: aborting due to 34 previous errors +error: aborting due to 38 previous errors diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.rs b/tests/ui/unnecessary_lazy_eval_unfixable.rs index b05dd143bfd74..b4a1f81679ad9 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.rs +++ b/tests/ui/unnecessary_lazy_eval_unfixable.rs @@ -1,4 +1,5 @@ #![warn(clippy::unnecessary_lazy_evaluations)] +#![allow(clippy::unnecessary_literal_unwrap)] struct Deep(Option); diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/tests/ui/unnecessary_lazy_eval_unfixable.stderr index 20acab6e844f8..7f353ba06982a 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.stderr +++ b/tests/ui/unnecessary_lazy_eval_unfixable.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:12:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:13:13 | LL | let _ = Ok(1).unwrap_or_else(|()| 2); | ^^^^^^---------------------- @@ -9,7 +9,7 @@ LL | let _ = Ok(1).unwrap_or_else(|()| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:16:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13 | LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); | ^^^^^^------------------------ @@ -17,7 +17,7 @@ LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:18:13 | LL | let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); | ^^^^^^------------------------------------- diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed new file mode 100644 index 0000000000000..630a1bea3c879 --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -0,0 +1,78 @@ +//@run-rustfix +#![warn(clippy::unnecessary_literal_unwrap)] +#![allow(unreachable_code)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect +)] + +fn unwrap_option_some() { + let _val = 1; + let _val = 1; + + 1; + 1; +} + +fn unwrap_option_none() { + let _val = panic!(); + let _val = panic!("this always happens"); + + panic!(); + panic!("this always happens"); +} + +fn unwrap_result_ok() { + let _val = 1; + let _val = 1; + let _val = panic!("{:?}", 1); + let _val = panic!("{1}: {:?}", 1, "this always happens"); + + 1; + 1; + panic!("{:?}", 1); + panic!("{1}: {:?}", 1, "this always happens"); +} + +fn unwrap_result_err() { + let _val = 1; + let _val = 1; + let _val = panic!("{:?}", 1); + let _val = panic!("{1}: {:?}", 1, "this always happens"); + + 1; + 1; + panic!("{:?}", 1); + panic!("{1}: {:?}", 1, "this always happens"); +} + +fn unwrap_methods_option() { + let _val = 1; + let _val = 1; + let _val = 1; + + 1; + 1; + 1; +} + +fn unwrap_methods_result() { + let _val = 1; + let _val = 1; + let _val = 1; + + 1; + 1; + 1; +} + +fn main() { + unwrap_option_some(); + unwrap_option_none(); + unwrap_result_ok(); + unwrap_result_err(); + unwrap_methods_option(); + unwrap_methods_result(); +} diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs new file mode 100644 index 0000000000000..14f92cb370f6a --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -0,0 +1,78 @@ +//@run-rustfix +#![warn(clippy::unnecessary_literal_unwrap)] +#![allow(unreachable_code)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect +)] + +fn unwrap_option_some() { + let _val = Some(1).unwrap(); + let _val = Some(1).expect("this never happens"); + + Some(1).unwrap(); + Some(1).expect("this never happens"); +} + +fn unwrap_option_none() { + let _val = None::<()>.unwrap(); + let _val = None::<()>.expect("this always happens"); + + None::<()>.unwrap(); + None::<()>.expect("this always happens"); +} + +fn unwrap_result_ok() { + let _val = Ok::<_, ()>(1).unwrap(); + let _val = Ok::<_, ()>(1).expect("this never happens"); + let _val = Ok::<_, ()>(1).unwrap_err(); + let _val = Ok::<_, ()>(1).expect_err("this always happens"); + + Ok::<_, ()>(1).unwrap(); + Ok::<_, ()>(1).expect("this never happens"); + Ok::<_, ()>(1).unwrap_err(); + Ok::<_, ()>(1).expect_err("this always happens"); +} + +fn unwrap_result_err() { + let _val = Err::<(), _>(1).unwrap_err(); + let _val = Err::<(), _>(1).expect_err("this never happens"); + let _val = Err::<(), _>(1).unwrap(); + let _val = Err::<(), _>(1).expect("this always happens"); + + Err::<(), _>(1).unwrap_err(); + Err::<(), _>(1).expect_err("this never happens"); + Err::<(), _>(1).unwrap(); + Err::<(), _>(1).expect("this always happens"); +} + +fn unwrap_methods_option() { + let _val = Some(1).unwrap_or(2); + let _val = Some(1).unwrap_or_default(); + let _val = Some(1).unwrap_or_else(|| 2); + + Some(1).unwrap_or(2); + Some(1).unwrap_or_default(); + Some(1).unwrap_or_else(|| 2); +} + +fn unwrap_methods_result() { + let _val = Ok::<_, ()>(1).unwrap_or(2); + let _val = Ok::<_, ()>(1).unwrap_or_default(); + let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); + + Ok::<_, ()>(1).unwrap_or(2); + Ok::<_, ()>(1).unwrap_or_default(); + Ok::<_, ()>(1).unwrap_or_else(|_| 2); +} + +fn main() { + unwrap_option_some(); + unwrap_option_none(); + unwrap_result_ok(); + unwrap_result_err(); + unwrap_methods_option(); + unwrap_methods_result(); +} diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr new file mode 100644 index 0000000000000..0c71ee053231c --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -0,0 +1,413 @@ +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:12:16 + | +LL | let _val = Some(1).unwrap(); + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` +help: remove the `Some` and `unwrap()` + | +LL - let _val = Some(1).unwrap(); +LL + let _val = 1; + | + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:13:16 + | +LL | let _val = Some(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + | +LL - let _val = Some(1).expect("this never happens"); +LL + let _val = 1; + | + +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:15:5 + | +LL | Some(1).unwrap(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + | +LL - Some(1).unwrap(); +LL + 1; + | + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:16:5 + | +LL | Some(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + | +LL - Some(1).expect("this never happens"); +LL + 1; + | + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:20:16 + | +LL | let _val = None::<()>.unwrap(); + | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:21:16 + | +LL | let _val = None::<()>.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + | +LL | let _val = panic!("this always happens"); + | ~~~~~~~ ~ + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:23:5 + | +LL | None::<()>.unwrap(); + | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:24:5 + | +LL | None::<()>.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + | +LL | panic!("this always happens"); + | ~~~~~~~ ~ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:28:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + | +LL - let _val = Ok::<_, ()>(1).unwrap(); +LL + let _val = 1; + | + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:29:16 + | +LL | let _val = Ok::<_, ()>(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + | +LL - let _val = Ok::<_, ()>(1).expect("this never happens"); +LL + let _val = 1; + | + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:30:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + | +LL | let _val = panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:31:16 + | +LL | let _val = Ok::<_, ()>(1).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + | +LL | let _val = panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:33:5 + | +LL | Ok::<_, ()>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + | +LL - Ok::<_, ()>(1).unwrap(); +LL + 1; + | + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:34:5 + | +LL | Ok::<_, ()>(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + | +LL - Ok::<_, ()>(1).expect("this never happens"); +LL + 1; + | + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:35:5 + | +LL | Ok::<_, ()>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + | +LL | panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:36:5 + | +LL | Ok::<_, ()>(1).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + | +LL | panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:40:16 + | +LL | let _val = Err::<(), _>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + | +LL - let _val = Err::<(), _>(1).unwrap_err(); +LL + let _val = 1; + | + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:41:16 + | +LL | let _val = Err::<(), _>(1).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + | +LL - let _val = Err::<(), _>(1).expect_err("this never happens"); +LL + let _val = 1; + | + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:42:16 + | +LL | let _val = Err::<(), _>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + | +LL | let _val = panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:43:16 + | +LL | let _val = Err::<(), _>(1).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + | +LL | let _val = panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:45:5 + | +LL | Err::<(), _>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + | +LL - Err::<(), _>(1).unwrap_err(); +LL + 1; + | + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:46:5 + | +LL | Err::<(), _>(1).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + | +LL - Err::<(), _>(1).expect_err("this never happens"); +LL + 1; + | + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:47:5 + | +LL | Err::<(), _>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + | +LL | panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:48:5 + | +LL | Err::<(), _>(1).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + | +LL | panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:52:16 + | +LL | let _val = Some(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + | +LL - let _val = Some(1).unwrap_or(2); +LL + let _val = 1; + | + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:53:16 + | +LL | let _val = Some(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + | +LL - let _val = Some(1).unwrap_or_default(); +LL + let _val = 1; + | + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:54:16 + | +LL | let _val = Some(1).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + | +LL - let _val = Some(1).unwrap_or_else(|| 2); +LL + let _val = 1; + | + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:56:5 + | +LL | Some(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + | +LL - Some(1).unwrap_or(2); +LL + 1; + | + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:57:5 + | +LL | Some(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + | +LL - Some(1).unwrap_or_default(); +LL + 1; + | + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:58:5 + | +LL | Some(1).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + | +LL - Some(1).unwrap_or_else(|| 2); +LL + 1; + | + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:62:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + | +LL - let _val = Ok::<_, ()>(1).unwrap_or(2); +LL + let _val = 1; + | + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:63:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + | +LL - let _val = Ok::<_, ()>(1).unwrap_or_default(); +LL + let _val = 1; + | + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:64:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + | +LL - let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); +LL + let _val = 1; + | + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:66:5 + | +LL | Ok::<_, ()>(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + | +LL - Ok::<_, ()>(1).unwrap_or(2); +LL + 1; + | + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:67:5 + | +LL | Ok::<_, ()>(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + | +LL - Ok::<_, ()>(1).unwrap_or_default(); +LL + 1; + | + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:68:5 + | +LL | Ok::<_, ()>(1).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + | +LL - Ok::<_, ()>(1).unwrap_or_else(|_| 2); +LL + 1; + | + +error: aborting due to 36 previous errors + diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs new file mode 100644 index 0000000000000..711fdce39624e --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -0,0 +1,116 @@ +#![warn(clippy::unnecessary_literal_unwrap)] +#![allow(unreachable_code)] +#![allow(clippy::unnecessary_lazy_evaluations, clippy::let_unit_value)] + +fn unwrap_option_some() { + let val = Some(1); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); +} + +fn unwrap_option_some_context() { + let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + + let val = Some::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); +} + +fn unwrap_option_none() { + let val = None::<()>; + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); +} + +fn unwrap_result_ok() { + let val = Ok::<_, ()>(1); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this always happens"); +} + +fn unwrap_result_ok_context() { + let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + + let val = Ok::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this always happens"); +} + +fn unwrap_result_err() { + let val = Err::<(), _>(1); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this never happens"); + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); +} + +fn unwrap_result_err_context() { + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + + let val = Err::<(), usize>([1, 2, 3].iter().sum()); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this never happens"); + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); +} + +fn unwrap_methods_option() { + let val = Some(1); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|| 2); +} + +fn unwrap_methods_option_context() { + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + + let val = Some::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|| 2); +} + +fn unwrap_methods_result() { + let val = Ok::<_, ()>(1); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|_| 2); +} + +fn unwrap_methods_result_context() { + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + + let val = Ok::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|_| 2); +} + +fn main() { + unwrap_option_some(); + unwrap_option_some_context(); + unwrap_option_none(); + unwrap_result_ok(); + unwrap_result_ok_context(); + unwrap_result_err(); + unwrap_result_err_context(); + unwrap_methods_option(); + unwrap_methods_option_context(); + unwrap_methods_result(); + unwrap_methods_result_context(); +} diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr new file mode 100644 index 0000000000000..feb9325b77a67 --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -0,0 +1,603 @@ +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:7:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15 + | +LL | let val = Some(1); + | ^^^^^^^ + = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:8:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:16:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:17:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15 + | +LL | let val = None::<()>; + | ^^^^^^^^^^ + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:23:17 + | +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15 + | +LL | let val = None::<()>; + | ^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:28:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:31:17 + | +LL | let _val2 = val.expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:42:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:43:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:44:17 + | +LL | let _val2 = val.expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:49:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:50:17 + | +LL | let _val2 = val.expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:51:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:52:17 + | +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:62:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:63:17 + | +LL | let _val2 = val.expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:64:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:65:17 + | +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:70:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:71:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:72:17 + | +LL | let _val2 = val.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:81:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:82:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:83:17 + | +LL | let _val2 = val.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:88:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:89:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:90:17 + | +LL | let _val2 = val.unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:99:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:100:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:101:17 + | +LL | let _val2 = val.unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 50 previous errors + diff --git a/tests/ui/unnecessary_safety_comment.rs b/tests/ui/unnecessary_safety_comment.rs index 89fedb145f88b..d858701ae8ac5 100644 --- a/tests/ui/unnecessary_safety_comment.rs +++ b/tests/ui/unnecessary_safety_comment.rs @@ -1,5 +1,5 @@ #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(clippy::let_unit_value, clippy::missing_safety_doc)] +#![allow(clippy::let_unit_value, clippy::missing_safety_doc, clippy::needless_if)] mod unsafe_items_invalid_comment { // SAFETY: diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 165cabd829890..19380ad00dcd9 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::stable_sort_primitive)] +#![allow(clippy::stable_sort_primitive, clippy::useless_vec)] use std::cell::Ref; diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 8a2158d5a8416..cea1b65b52031 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::stable_sort_primitive)] +#![allow(clippy::stable_sort_primitive, clippy::useless_vec)] use std::cell::Ref; diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed index bdf746cf2c425..eae1271d1aa72 100644 --- a/tests/ui/unnecessary_struct_initialization.fixed +++ b/tests/ui/unnecessary_struct_initialization.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs index 7271e2f957a87..4abd560f84bec 100644 --- a/tests/ui/unnecessary_struct_initialization.rs +++ b/tests/ui/unnecessary_struct_initialization.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index c879fdc3b6aec..592a53f3a8198 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] -#![warn(clippy::unnecessary_to_owned)] +#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; @@ -474,3 +474,36 @@ mod issue_10021 { Ok(()) } } + +mod issue_10033 { + #![allow(dead_code)] + use std::{fmt::Display, ops::Deref}; + + fn _main() { + let f = Foo; + + // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does + // deref to `str`) + foo(&f.to_string()); + } + + fn foo(s: &str) { + println!("{}", s); + } + + struct Foo; + + impl Deref for Foo { + type Target = str; + + fn deref(&self) -> &Self::Target { + "str" + } + } + + impl Display for Foo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Foo") + } + } +} diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 10588beb263b6..f2e48b1c4a6a7 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -1,7 +1,7 @@ //@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] -#![warn(clippy::unnecessary_to_owned)] +#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; @@ -474,3 +474,36 @@ mod issue_10021 { Ok(()) } } + +mod issue_10033 { + #![allow(dead_code)] + use std::{fmt::Display, ops::Deref}; + + fn _main() { + let f = Foo; + + // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does + // deref to `str`) + foo(&f.to_string()); + } + + fn foo(s: &str) { + println!("{}", s); + } + + struct Foo; + + impl Deref for Foo { + type Target = str; + + fn deref(&self) -> &Self::Target { + "str" + } + } + + impl Display for Foo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Foo") + } + } +} diff --git a/tests/ui/unnecessary_unsafety_doc.rs b/tests/ui/unnecessary_unsafety_doc.rs index 373b18470f695..2d55dc664a32d 100644 --- a/tests/ui/unnecessary_unsafety_doc.rs +++ b/tests/ui/unnecessary_unsafety_doc.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::let_unit_value)] #![warn(clippy::unnecessary_safety_doc)] diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index fa639aa70d61d..48ae1cf66405e 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,5 +1,9 @@ +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::unneeded_field_pattern)] -#[allow(dead_code, unused)] +#![allow(dead_code, unused)] + +#[macro_use] +extern crate proc_macros; struct Foo { a: i32, @@ -19,4 +23,12 @@ fn main() { Foo { b: 0, .. } => {}, // should be OK Foo { .. } => {}, // and the Force might be with this one } + external! { + let f = Foo { a: 0, b: 0, c: 0 }; + match f { + Foo { a: _, b: 0, .. } => {}, + + Foo { a: _, b: _, c: _ } => {}, + } + } } diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 6f7c315456969..3f15684986fe0 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: you matched a field with a wildcard pattern, consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:14:15 + --> $DIR/unneeded_field_pattern.rs:18:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` error: all the struct fields are matched to a wildcard pattern, consider using `..` - --> $DIR/unneeded_field_pattern.rs:16:9 + --> $DIR/unneeded_field_pattern.rs:20:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index 16c2de760e55f..2eeba509e8338 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,6 +1,11 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::needless_if)] + +#[macro_use] +extern crate proc_macros; fn main() { let t = (0, 1, 2, 3); @@ -42,4 +47,8 @@ fn main() { { if let S(0, ..,) = s {}; } + external! { + let t = (0, 1, 2, 3); + if let (0, _, ..) = t {}; + } } diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index 9d9eae1d90330..5416cfaa5425f 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,6 +1,11 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::needless_if)] + +#[macro_use] +extern crate proc_macros; fn main() { let t = (0, 1, 2, 3); @@ -42,4 +47,8 @@ fn main() { { if let S(0, .., _, _,) = s {}; } + external! { + let t = (0, 1, 2, 3); + if let (0, _, ..) = t {}; + } } diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index 716d9ecff89af..ffbdc049506e0 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -1,89 +1,89 @@ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:8:18 + --> $DIR/unneeded_wildcard_pattern.rs:13:18 | LL | if let (0, .., _) = t {}; | ^^^ help: remove it | note: the lint level is defined here - --> $DIR/unneeded_wildcard_pattern.rs:3:9 + --> $DIR/unneeded_wildcard_pattern.rs:4:9 | LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:9:16 + --> $DIR/unneeded_wildcard_pattern.rs:14:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:10:13 + --> $DIR/unneeded_wildcard_pattern.rs:15:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:11:15 + --> $DIR/unneeded_wildcard_pattern.rs:16:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:12:16 + --> $DIR/unneeded_wildcard_pattern.rs:17:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:13:18 + --> $DIR/unneeded_wildcard_pattern.rs:18:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:22:22 + --> $DIR/unneeded_wildcard_pattern.rs:27:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:29:19 + --> $DIR/unneeded_wildcard_pattern.rs:34:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:30:17 + --> $DIR/unneeded_wildcard_pattern.rs:35:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:31:14 + --> $DIR/unneeded_wildcard_pattern.rs:36:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:32:16 + --> $DIR/unneeded_wildcard_pattern.rs:37:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:33:17 + --> $DIR/unneeded_wildcard_pattern.rs:38:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:34:19 + --> $DIR/unneeded_wildcard_pattern.rs:39:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:43:23 + --> $DIR/unneeded_wildcard_pattern.rs:48:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 8ec35ba4eea7e..738045595c0bc 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -2,7 +2,13 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::needless_if, + clippy::manual_range_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index efdb91b2402b7..9e0e7b5def980 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -2,7 +2,13 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::needless_if, + clippy::manual_range_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index a1f193db555ad..b997e4ce85fb9 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:12:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:13:12 + --> $DIR/unnested_or_patterns.rs:19:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:15:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let Some(1) | C0 | Some(2) = None {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(1 | 2) | C0 = None {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:16:12 + --> $DIR/unnested_or_patterns.rs:22:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:19:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:26:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:27:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:22:12 + --> $DIR/unnested_or_patterns.rs:28:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:23:12 + --> $DIR/unnested_or_patterns.rs:29:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:30:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:26:12 + --> $DIR/unnested_or_patterns.rs:32:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:27:12 + --> $DIR/unnested_or_patterns.rs:33:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:28:12 + --> $DIR/unnested_or_patterns.rs:34:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:33:12 + --> $DIR/unnested_or_patterns.rs:39:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:44:12 + --> $DIR/unnested_or_patterns.rs:50:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index de40e93674713..11dc34378758f 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::needless_if, + clippy::manual_range_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 87f66d26c4678..b255608274130 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::needless_if, + clippy::manual_range_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.stderr b/tests/ui/unnested_or_patterns2.stderr index 41e8d3fc70924..76e890b3a2e3e 100644 --- a/tests/ui/unnested_or_patterns2.stderr +++ b/tests/ui/unnested_or_patterns2.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:9:12 + --> $DIR/unnested_or_patterns2.rs:14:12 | LL | if let Some(Some(0)) | Some(Some(1)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(Some(0 | 1)) = None {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:10:12 + --> $DIR/unnested_or_patterns2.rs:15:12 | LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:11:12 + --> $DIR/unnested_or_patterns2.rs:16:12 | LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:12:12 + --> $DIR/unnested_or_patterns2.rs:17:12 | LL | if let Some(Some(0) | Some(1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:13:12 + --> $DIR/unnested_or_patterns2.rs:18:12 | LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let ((0 | 1 | 2,),) = ((0,),) {} | ~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:14:12 + --> $DIR/unnested_or_patterns2.rs:19:12 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let 0 | 1 | 2 = 0 {} | ~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:15:12 + --> $DIR/unnested_or_patterns2.rs:20:12 | LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:16:12 + --> $DIR/unnested_or_patterns2.rs:21:12 | LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unseparated_prefix_literals.fixed b/tests/ui/unseparated_prefix_literals.fixed index b6241612d9da9..1251208726703 100644 --- a/tests/ui/unseparated_prefix_literals.fixed +++ b/tests/ui/unseparated_prefix_literals.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] diff --git a/tests/ui/unseparated_prefix_literals.rs b/tests/ui/unseparated_prefix_literals.rs index ae583f4bde379..0a3ffc4784b2d 100644 --- a/tests/ui/unseparated_prefix_literals.rs +++ b/tests/ui/unseparated_prefix_literals.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index bfaa5dadfa59e..69e46ab473622 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -1,4 +1,6 @@ #![warn(clippy::unused_async)] +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] use std::future::Future; use std::pin::Pin; @@ -23,6 +25,18 @@ mod issue10800 { } } +mod issue10459 { + trait HasAsyncMethod { + async fn do_something() -> u32; + } + + impl HasAsyncMethod for () { + async fn do_something() -> u32 { + 1 + } + } +} + async fn foo() -> i32 { 4 } diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index 8ac2066a6b24d..ffae8366b88c3 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -1,5 +1,5 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:11:5 + --> $DIR/unused_async.rs:13:5 | LL | / async fn async_block_await() { LL | | async { @@ -10,14 +10,14 @@ LL | | } | = help: consider removing the `async` from this function note: `await` used in an async block, which does not require the enclosing function to be `async` - --> $DIR/unused_async.rs:13:23 + --> $DIR/unused_async.rs:15:23 | LL | ready(()).await; | ^^^^^ = note: `-D clippy::unused-async` implied by `-D warnings` error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:26:1 + --> $DIR/unused_async.rs:40:1 | LL | / async fn foo() -> i32 { LL | | 4 @@ -27,7 +27,7 @@ LL | | } = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:37:5 + --> $DIR/unused_async.rs:51:5 | LL | / async fn unused(&self) -> i32 { LL | | 1 diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs index d9fd402e7cfb9..64d6437834e6b 100644 --- a/tests/ui/unwrap.rs +++ b/tests/ui/unwrap.rs @@ -1,4 +1,5 @@ #![warn(clippy::unwrap_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn unwrap_option() { let opt = Some(0); diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr index d49bf2b322837..3796d942ff9fc 100644 --- a/tests/ui/unwrap.stderr +++ b/tests/ui/unwrap.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on an `Option` value - --> $DIR/unwrap.rs:5:13 + --> $DIR/unwrap.rs:6:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: used `unwrap()` on a `Result` value - --> $DIR/unwrap.rs:10:13 + --> $DIR/unwrap.rs:11:13 | LL | let _ = res.unwrap(); | ^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = res.unwrap(); = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message error: used `unwrap_err()` on a `Result` value - --> $DIR/unwrap.rs:11:13 + --> $DIR/unwrap.rs:12:13 | LL | let _ = res.unwrap_err(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs index 9f27fef82494b..7f57efc53c9c8 100644 --- a/tests/ui/unwrap_expect_used.rs +++ b/tests/ui/unwrap_expect_used.rs @@ -1,4 +1,5 @@ #![warn(clippy::unwrap_used, clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] trait OptionExt { type Item; diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr index fe4ecef114535..1a551ab5ab8ea 100644 --- a/tests/ui/unwrap_expect_used.stderr +++ b/tests/ui/unwrap_expect_used.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_expect_used.rs:23:5 + --> $DIR/unwrap_expect_used.rs:24:5 | LL | Some(3).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | Some(3).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: used `expect()` on an `Option` value - --> $DIR/unwrap_expect_used.rs:24:5 + --> $DIR/unwrap_expect_used.rs:25:5 | LL | Some(3).expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | Some(3).expect("Hello world!"); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `unwrap()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:31:5 + --> $DIR/unwrap_expect_used.rs:32:5 | LL | a.unwrap(); | ^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | a.unwrap(); = help: if this value is an `Err`, it will panic error: used `expect()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:32:5 + --> $DIR/unwrap_expect_used.rs:33:5 | LL | a.expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | a.expect("Hello world!"); = help: if this value is an `Err`, it will panic error: used `unwrap_err()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:33:5 + --> $DIR/unwrap_expect_used.rs:34:5 | LL | a.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | a.unwrap_err(); = help: if this value is an `Ok`, it will panic error: used `expect_err()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:34:5 + --> $DIR/unwrap_expect_used.rs:35:5 | LL | a.expect_err("Hello error!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index a0c003f5b1eac..5bea85e669249 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -1,4 +1,5 @@ #![warn(clippy::all, clippy::or_fun_call)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index c3a7464fd470e..cf720eaaf052e 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:4:47 + --> $DIR/unwrap_or.rs:5:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` @@ -7,7 +7,7 @@ LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()) = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:8:47 + --> $DIR/unwrap_or.rs:9:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` diff --git a/tests/ui/unwrap_or_else_default.fixed b/tests/ui/unwrap_or_else_default.fixed index 59a0ca3f192fc..08b89a18bbbd4 100644 --- a/tests/ui/unwrap_or_else_default.fixed +++ b/tests/ui/unwrap_or_else_default.fixed @@ -2,7 +2,7 @@ #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. fn unwrap_or_else_default() { diff --git a/tests/ui/unwrap_or_else_default.rs b/tests/ui/unwrap_or_else_default.rs index 97cafa336eda6..ad2a744908fcb 100644 --- a/tests/ui/unwrap_or_else_default.rs +++ b/tests/ui/unwrap_or_else_default.rs @@ -2,7 +2,7 @@ #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. fn unwrap_or_else_default() { diff --git a/tests/ui/update-all-references.sh b/tests/ui/update-all-references.sh index 4391499a1e1f8..d42043070261e 100755 --- a/tests/ui/update-all-references.sh +++ b/tests/ui/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 89ea14759b7db..4179f21c51002 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 49e5bcb7ed961..01a36def9e97f 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index c672eff1c2710..879e2e24ab341 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![feature(rustc_private)] #![warn(clippy::all)] #![warn(clippy::used_underscore_binding)] diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index de6660c95e6e9..8e77ec444b52e 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 8de4331e8a690..27498d9bc132c 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index c16caa38fe93e..5d2c5b11658e2 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![deny(clippy::useless_conversion)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::needless_if, clippy::unnecessary_wraps)] fn test_generic(val: T) -> T { let _ = val; @@ -155,6 +155,35 @@ fn main() { let _ = vec![s4, s4, s4].into_iter(); } +#[allow(dead_code)] +fn explicit_into_iter_fn_arg() { + fn a(_: T) {} + fn b>(_: T) {} + fn c(_: impl IntoIterator) {} + fn d(_: T) + where + T: IntoIterator, + { + } + fn f(_: std::vec::IntoIter) {} + + a(vec![1, 2].into_iter()); + b(vec![1, 2]); + c(vec![1, 2]); + d(vec![1, 2]); + b([&1, &2, &3].into_iter().cloned()); + + b(vec![1, 2]); + b(vec![1, 2]); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); +} + #[derive(Copy, Clone)] struct Foo; diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index c75a2bce4ca23..03a3e3f95ba42 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -1,7 +1,7 @@ //@run-rustfix #![deny(clippy::useless_conversion)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::needless_if, clippy::unnecessary_wraps)] fn test_generic(val: T) -> T { let _ = T::from(val); @@ -155,6 +155,35 @@ fn main() { let _ = vec![s4, s4, s4].into_iter().into_iter(); } +#[allow(dead_code)] +fn explicit_into_iter_fn_arg() { + fn a(_: T) {} + fn b>(_: T) {} + fn c(_: impl IntoIterator) {} + fn d(_: T) + where + T: IntoIterator, + { + } + fn f(_: std::vec::IntoIter) {} + + a(vec![1, 2].into_iter()); + b(vec![1, 2].into_iter()); + c(vec![1, 2].into_iter()); + d(vec![1, 2].into_iter()); + b([&1, &2, &3].into_iter().cloned()); + + b(vec![1, 2].into_iter().into_iter()); + b(vec![1, 2].into_iter().into_iter().into_iter()); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); +} + #[derive(Copy, Clone)] struct Foo; diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 4dca3aac53361..4957f73a469a6 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -118,5 +118,65 @@ error: useless conversion to the same type: `std::vec::IntoIter>` LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` -error: aborting due to 19 previous errors +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:171:7 + | +LL | b(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:172:7 + | +LL | c(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:162:18 + | +LL | fn c(_: impl IntoIterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:173:7 + | +LL | d(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:165:12 + | +LL | T: IntoIterator, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:176:7 + | +LL | b(vec![1, 2].into_iter().into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:177:7 + | +LL | b(vec![1, 2].into_iter().into_iter().into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs index 4acf5b5fa2d1b..ec0512ce210b6 100644 --- a/tests/ui/useless_conversion_try.rs +++ b/tests/ui/useless_conversion_try.rs @@ -1,4 +1,5 @@ #![deny(clippy::useless_conversion)] +#![allow(clippy::needless_if)] fn test_generic(val: T) -> T { let _ = T::try_from(val).unwrap(); diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr index 9aef9dda6f685..54189f8d28606 100644 --- a/tests/ui/useless_conversion_try.stderr +++ b/tests/ui/useless_conversion_try.stderr @@ -1,5 +1,5 @@ error: useless conversion to the same type: `T` - --> $DIR/useless_conversion_try.rs:4:13 + --> $DIR/useless_conversion_try.rs:5:13 | LL | let _ = T::try_from(val).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> $DIR/useless_conversion_try.rs:5:5 + --> $DIR/useless_conversion_try.rs:6:5 | LL | val.try_into().unwrap() | ^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | val.try_into().unwrap() = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:27:21 + --> $DIR/useless_conversion_try.rs:28:21 | LL | let _: String = "foo".to_string().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _: String = "foo".to_string().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:28:21 + --> $DIR/useless_conversion_try.rs:29:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); = help: consider removing `TryFrom::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:29:13 + --> $DIR/useless_conversion_try.rs:30:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:30:13 + --> $DIR/useless_conversion_try.rs:31:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:31:21 + --> $DIR/useless_conversion_try.rs:32:21 | LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:32:21 + --> $DIR/useless_conversion_try.rs:33:21 | LL | let _: String = String::new().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | let _: String = String::new().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:33:27 + --> $DIR/useless_conversion_try.rs:34:27 | LL | let _: String = match String::from("_").try_into() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index d77a4dd8e0b00..fcdc917c1b139 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -1,9 +1,12 @@ //@run-rustfix #![warn(clippy::useless_vec)] -#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)] -#[derive(Debug)] -struct NonCopy; +use std::rc::Rc; + +struct StructWithVec { + _x: Vec, +} fn on_slice(_: &[u8]) {} @@ -60,14 +63,6 @@ fn main() { on_mut_slice(&mut vec![2; line.length]); on_mut_slice(&mut vec![2; line.length()]); - for a in &[1, 2, 3] { - println!("{:?}", a); - } - - for a in vec![NonCopy, NonCopy] { - println!("{:?}", a); - } - on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` @@ -75,4 +70,69 @@ fn main() { for a in vec![1; 201] { println!("{:?}", a); } + + // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 + let _x: i32 = [1, 2, 3].iter().sum(); + + // Do lint + let mut x = [1, 2, 3]; + x.fill(123); + dbg!(x[0]); + dbg!(x.len()); + dbg!(x.iter().sum::()); + + let _x: &[i32] = &[1, 2, 3]; + + for _ in [1, 2, 3] {} + + // Don't lint + let x = vec![1, 2, 3]; + let _v: Vec = x; + + let x = vec![1, 2, 3]; + let _s = StructWithVec { _x: x }; + + // Explicit type annotation would make the change to [1, 2, 3] + // a compile error. + let _x: Vec = vec![1, 2, 3]; + + // Calling a Vec method through a mutable reference + let mut x = vec![1, 2, 3]; + let re = &mut x; + re.push(4); + + // Comparing arrays whose length is not equal is a compile error + let x = vec![1, 2, 3]; + let y = vec![1, 2, 3, 4]; + dbg!(x == y); + + // Non-copy types + let _x = vec![String::new(); 10]; + #[allow(clippy::rc_clone_in_vec_init)] + let _x = vec![Rc::new(1); 10]; + + // Too large + let _x = vec![1; 201]; +} + +#[clippy::msrv = "1.53"] +fn above() { + for a in [1, 2, 3] { + let _: usize = a; + } + + for a in [String::new(), String::new()] { + let _: String = a; + } +} + +#[clippy::msrv = "1.52"] +fn below() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } } diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index dfed3a29a03e1..0404d8cdb8421 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,9 +1,12 @@ //@run-rustfix #![warn(clippy::useless_vec)] -#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)] -#[derive(Debug)] -struct NonCopy; +use std::rc::Rc; + +struct StructWithVec { + _x: Vec, +} fn on_slice(_: &[u8]) {} @@ -60,14 +63,6 @@ fn main() { on_mut_slice(&mut vec![2; line.length]); on_mut_slice(&mut vec![2; line.length()]); - for a in vec![1, 2, 3] { - println!("{:?}", a); - } - - for a in vec![NonCopy, NonCopy] { - println!("{:?}", a); - } - on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` @@ -75,4 +70,69 @@ fn main() { for a in vec![1; 201] { println!("{:?}", a); } + + // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 + let _x: i32 = vec![1, 2, 3].iter().sum(); + + // Do lint + let mut x = vec![1, 2, 3]; + x.fill(123); + dbg!(x[0]); + dbg!(x.len()); + dbg!(x.iter().sum::()); + + let _x: &[i32] = &vec![1, 2, 3]; + + for _ in vec![1, 2, 3] {} + + // Don't lint + let x = vec![1, 2, 3]; + let _v: Vec = x; + + let x = vec![1, 2, 3]; + let _s = StructWithVec { _x: x }; + + // Explicit type annotation would make the change to [1, 2, 3] + // a compile error. + let _x: Vec = vec![1, 2, 3]; + + // Calling a Vec method through a mutable reference + let mut x = vec![1, 2, 3]; + let re = &mut x; + re.push(4); + + // Comparing arrays whose length is not equal is a compile error + let x = vec![1, 2, 3]; + let y = vec![1, 2, 3, 4]; + dbg!(x == y); + + // Non-copy types + let _x = vec![String::new(); 10]; + #[allow(clippy::rc_clone_in_vec_init)] + let _x = vec![Rc::new(1); 10]; + + // Too large + let _x = vec![1; 201]; +} + +#[clippy::msrv = "1.53"] +fn above() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } +} + +#[clippy::msrv = "1.52"] +fn below() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } } diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 7d1de05a5c836..33d565b2d5250 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:28:14 + --> $DIR/vec.rs:31:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,64 +7,94 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:30:18 + --> $DIR/vec.rs:33:18 | LL | on_mut_slice(&mut vec![]); | ^^^^^^^^^^^ help: you can use a slice directly: `&mut []` error: useless use of `vec!` - --> $DIR/vec.rs:32:14 + --> $DIR/vec.rs:35:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:34:18 + --> $DIR/vec.rs:37:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:36:14 + --> $DIR/vec.rs:39:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:38:18 + --> $DIR/vec.rs:41:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:40:14 + --> $DIR/vec.rs:43:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:42:18 + --> $DIR/vec.rs:45:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:44:14 + --> $DIR/vec.rs:47:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:46:18 + --> $DIR/vec.rs:49:18 | LL | on_mut_slice(&mut vec![1; 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:63:14 + --> $DIR/vec.rs:75:19 + | +LL | let _x: i32 = vec![1, 2, 3].iter().sum(); + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:78:17 + | +LL | let mut x = vec![1, 2, 3]; + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:84:22 + | +LL | let _x: &[i32] = &vec![1, 2, 3]; + | ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:86:14 + | +LL | for _ in vec![1, 2, 3] {} + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:120:14 | LL | for a in vec![1, 2, 3] { - | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:124:14 + | +LL | for a in vec![String::new(), String::new()] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` -error: aborting due to 11 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index c2f216a8911c4..41a380ab8f6a4 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -6,7 +6,9 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::single_range_in_vec_init, + clippy::uninlined_format_args, + clippy::useless_vec )] fn base() { diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 971bd5f0c4a86..4c6433880b63e 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -6,7 +6,9 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::single_range_in_vec_init, + clippy::uninlined_format_args, + clippy::useless_vec )] fn base() { diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 4d98666190d67..3236765e1db0f 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:14:5 + --> $DIR/while_let_on_iterator.rs:16:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,151 +7,151 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:19:5 + --> $DIR/while_let_on_iterator.rs:21:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:24:5 + --> $DIR/while_let_on_iterator.rs:26:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:100:9 + --> $DIR/while_let_on_iterator.rs:102:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:107:9 + --> $DIR/while_let_on_iterator.rs:109:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:120:9 + --> $DIR/while_let_on_iterator.rs:122:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:140:9 + --> $DIR/while_let_on_iterator.rs:142:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:197:9 + --> $DIR/while_let_on_iterator.rs:199:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:208:5 + --> $DIR/while_let_on_iterator.rs:210:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:210:9 + --> $DIR/while_let_on_iterator.rs:212:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:219:9 + --> $DIR/while_let_on_iterator.rs:221:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:228:9 + --> $DIR/while_let_on_iterator.rs:230:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:245:9 + --> $DIR/while_let_on_iterator.rs:247:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:260:13 + --> $DIR/while_let_on_iterator.rs:262:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:292:13 + --> $DIR/while_let_on_iterator.rs:294:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:321:5 + --> $DIR/while_let_on_iterator.rs:323:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:333:9 + --> $DIR/while_let_on_iterator.rs:335:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:347:5 + --> $DIR/while_let_on_iterator.rs:349:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:358:5 + --> $DIR/while_let_on_iterator.rs:360:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:393:5 + --> $DIR/while_let_on_iterator.rs:395:5 | LL | while let Some(x) = s.x.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:400:5 + --> $DIR/while_let_on_iterator.rs:402:5 | LL | while let Some(x) = x[0].next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:408:9 + --> $DIR/while_let_on_iterator.rs:410:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:418:9 + --> $DIR/while_let_on_iterator.rs:420:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:428:9 + --> $DIR/while_let_on_iterator.rs:430:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:438:9 + --> $DIR/while_let_on_iterator.rs:440:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:448:5 + --> $DIR/while_let_on_iterator.rs:450:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 733bbcfbcefab..2961b062ec37c 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -211,7 +211,7 @@ mod super_imports { } mod use_explicit_should_be_replaced { - use super_imports::foofoo; + use crate::super_imports::foofoo; fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 4acdd374bdeca..28508a2538b28 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -212,7 +212,7 @@ mod super_imports { } mod use_explicit_should_be_replaced { - use super_imports::*; + use crate::super_imports::*; fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 235be2d57081b..c96b3041a005f 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -107,8 +107,8 @@ LL | use super::*; error: usage of wildcard import --> $DIR/wildcard_imports.rs:215:13 | -LL | use super_imports::*; - | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import --> $DIR/wildcard_imports.rs:224:17 diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs index 55a11daa1d344..805127e275005 100644 --- a/tests/ui/write_literal_2.rs +++ b/tests/ui/write_literal_2.rs @@ -1,5 +1,5 @@ #![allow(unused_must_use)] -#![warn(clippy::write_literal)] +#![warn(clippy::needless_raw_strings, clippy::write_literal)] use std::io::Write; diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index d5956db9ff0b4..18591250aad9e 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -1,3 +1,11 @@ +error: unnecessary raw string literal + --> $DIR/write_literal_2.rs:10:24 + | +LL | writeln!(v, r"{}", r"{hello}"); + | ^^^^^^^^^^ help: try: `"{hello}"` + | + = note: `-D clippy::needless-raw-strings` implied by `-D warnings` + error: literal with an empty format string --> $DIR/write_literal_2.rs:9:23 | @@ -87,7 +95,7 @@ LL | "1", "2", "3", help: try this | LL ~ "some 1/ -LL ~ {} / {}", "2", "3", +LL ~ {} // {}", "2", "3", | error: literal with an empty format string @@ -98,7 +106,7 @@ LL | "1", "2", "3", | help: try this | -LL ~ 2 / {}", +LL ~ 2 // {}", LL ~ "1", "3", | @@ -110,43 +118,43 @@ LL | "1", "2", "3", | help: try this | -LL ~ {} / 3", +LL ~ {} // 3", LL ~ "1", "2", | error: literal with an empty format string --> $DIR/write_literal_2.rs:27:23 | -LL | writeln!(v, "{}", "/"); +LL | writeln!(v, "{}", "//"); | ^^^^ | help: try this | -LL - writeln!(v, "{}", "/"); -LL + writeln!(v, "/"); +LL - writeln!(v, "{}", "//"); +LL + writeln!(v, "//"); | error: literal with an empty format string --> $DIR/write_literal_2.rs:28:24 | -LL | writeln!(v, r"{}", "/"); +LL | writeln!(v, r"{}", "//"); | ^^^^ | help: try this | -LL - writeln!(v, r"{}", "/"); +LL - writeln!(v, r"{}", "//"); LL + writeln!(v, r"/"); | error: literal with an empty format string --> $DIR/write_literal_2.rs:29:26 | -LL | writeln!(v, r#"{}"#, "/"); +LL | writeln!(v, r#"{}"#, "//"); | ^^^^ | help: try this | -LL - writeln!(v, r#"{}"#, "/"); +LL - writeln!(v, r#"{}"#, "//"); LL + writeln!(v, r#"/"#); | @@ -159,7 +167,7 @@ LL | writeln!(v, "{}", r"/"); help: try this | LL - writeln!(v, "{}", r"/"); -LL + writeln!(v, "/"); +LL + writeln!(v, "//"); | error: literal with an empty format string @@ -186,5 +194,5 @@ error: literal with an empty format string LL | writeln!(v, r#"{}{}"#, '#', '"'); // hard mode | ^^^ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/write_with_newline.fixed b/tests/ui/write_with_newline.fixed new file mode 100644 index 0000000000000..0a10e526a2f56 --- /dev/null +++ b/tests/ui/write_with_newline.fixed @@ -0,0 +1,63 @@ +// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 +// //@run-rustfix + +#![allow(clippy::write_literal)] +#![warn(clippy::write_with_newline)] + +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should fail + writeln!(v, "Hello"); + writeln!(v, "Hello {}", "world"); + writeln!(v, "Hello {} {}", "world", "#2"); + writeln!(v, "{}", 1265); + writeln!(v); + + // These should be fine + write!(v, ""); + write!(v, "Hello"); + writeln!(v, "Hello"); + writeln!(v, "Hello\n"); + writeln!(v, "Hello {}\n", "world"); + write!(v, "Issue\n{}", 1265); + write!(v, "{}", 1265); + write!(v, "\n{}", 1275); + write!(v, "\n\n"); + write!(v, "like eof\n\n"); + write!(v, "Hello {} {}\n\n", "world", "#2"); + writeln!(v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + writeln!(v, "\nbla\n\n"); // #3126 + + // Escaping + write!(v, "\\n"); // #3514 + writeln!(v, "\\"); // should fail + write!(v, "\\\\n"); + + // Raw strings + write!(v, r"\n"); // #3778 + + // Literal newlines should also fail + writeln!( + v + ); + writeln!( + v + ); + + // Don't warn on CRLF (#4208) + write!(v, "\r\n"); + write!(v, "foo\r\n"); + writeln!(v, "\\r"); // warns + write!(v, "foo\rbar\n"); + + // Ignore expanded format strings + macro_rules! newline { + () => { + "\n" + }; + } + write!(v, newline!()); +} diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 9035275b29db4..03a18a4dc3f37 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -62,13 +62,13 @@ LL + writeln!(v); error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:36:5 | -LL | write!(v, "//n"); // should fail +LL | write!(v, "///n"); // should fail | ^^^^^^^^^^^^^^^^^ | help: use `writeln!` instead | -LL - write!(v, "//n"); // should fail -LL + writeln!(v, "/"); // should fail +LL - write!(v, "///n"); // should fail +LL + writeln!(v, "//"); // should fail | error: using `write!()` with a format string that ends in a single newline @@ -106,13 +106,13 @@ LL ~ v error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:57:5 | -LL | write!(v, "/r/n"); +LL | write!(v, "//r/n"); | ^^^^^^^^^^^^^^^^^^ | help: use `writeln!` instead | -LL - write!(v, "/r/n"); -LL + writeln!(v, "/r"); +LL - write!(v, "//r/n"); +LL + writeln!(v, "//r"); | error: aborting due to 9 previous errors diff --git a/tests/workspace.rs b/tests/workspace.rs index c9cbc50546cf3..699ab2be199a8 100644 --- a/tests/workspace.rs +++ b/tests/workspace.rs @@ -6,6 +6,46 @@ use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE}; mod test_utils; +#[test] +fn test_module_style_with_dep_in_subdir() { + if IS_RUSTC_TEST_SUITE { + return; + } + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let target_dir = root.join("target").join("workspace_test"); + let cwd = root.join("tests/workspace_test"); + + // Make sure we start with a clean state + Command::new("cargo") + .current_dir(&cwd) + .env("CARGO_TARGET_DIR", &target_dir) + .arg("clean") + .args(["-p", "pass-no-mod-with-dep-in-subdir"]) + .args(["-p", "pass-mod-with-dep-in-subdir"]) + .output() + .unwrap(); + + // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) + // `mod.rs` checks should not be applied to crate dependencies + // located in the subdirectory of workspace + let output = Command::new(&*CARGO_CLIPPY_PATH) + .current_dir(&cwd) + .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TARGET_DIR", &target_dir) + .arg("clippy") + .args(["-p", "pass-no-mod-with-dep-in-subdir"]) + .args(["-p", "pass-mod-with-dep-in-subdir"]) + .arg("--") + .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir + .output() + .unwrap(); + + println!("status: {}", output.status); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + assert!(output.status.success()); +} + #[test] fn test_no_deps_ignores_path_deps_in_workspaces() { if IS_RUSTC_TEST_SUITE { diff --git a/tests/workspace_test/Cargo.toml b/tests/workspace_test/Cargo.toml index bf5b4ca5288a4..d24b278ccc282 100644 --- a/tests/workspace_test/Cargo.toml +++ b/tests/workspace_test/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2018" [workspace] -members = ["subcrate"] +members = ["subcrate", "module_style/pass_no_mod_with_dep_in_subdir", "module_style/pass_mod_with_dep_in_subdir"] diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml new file mode 100644 index 0000000000000..15dcde4e30a1f --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pass-mod-with-dep-in-subdir" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dep-no-mod = { path = "dep_no_mod"} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml new file mode 100644 index 0000000000000..55569bc25ed75 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dep-no-mod" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs new file mode 100644 index 0000000000000..7b0966a458673 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs @@ -0,0 +1,2 @@ +pub mod hello; +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs new file mode 100644 index 0000000000000..99940dce528a6 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs @@ -0,0 +1 @@ +pub struct Hello; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs new file mode 100644 index 0000000000000..c62f9acbf2cbf --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs @@ -0,0 +1,5 @@ +pub mod foo; + +pub fn foo() { + let _ = foo::Thing; +} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs new file mode 100644 index 0000000000000..f19ab10d5fb06 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs @@ -0,0 +1 @@ +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs new file mode 100644 index 0000000000000..5cb4795e94518 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs @@ -0,0 +1,13 @@ +#![deny(clippy::self_named_module_files)] + +mod bad; +mod more; +extern crate dep_no_mod; + +fn main() { + let _ = bad::Thing; + let _ = more::foo::Foo; + let _ = more::inner::Inner; + let _ = dep_no_mod::foo::Thing; + let _ = dep_no_mod::foo::hello::Hello; +} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs new file mode 100644 index 0000000000000..4a835673a596b --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs new file mode 100644 index 0000000000000..aa84f78cc2ca1 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs @@ -0,0 +1 @@ +pub struct Inner; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs new file mode 100644 index 0000000000000..d79569f78ffbe --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs @@ -0,0 +1,2 @@ +pub mod foo; +pub mod inner; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml new file mode 100644 index 0000000000000..060cb18dc9f97 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pass-no-mod-with-dep-in-subdir" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dep-with-mod = { path = "dep_with_mod"} diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml new file mode 100644 index 0000000000000..b25725cd5610e --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dep-with-mod" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs new file mode 100644 index 0000000000000..4647424f2c2fd --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs @@ -0,0 +1,7 @@ +pub mod with_mod; + +pub fn foo() { + let _ = with_mod::Thing; + let _ = with_mod::inner::stuff::Inner; + let _ = with_mod::inner::stuff::most::Snarks; +} diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs new file mode 100644 index 0000000000000..91cd540a28fdd --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs @@ -0,0 +1 @@ +pub mod stuff; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs new file mode 100644 index 0000000000000..7713fa9d35c4a --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs @@ -0,0 +1,3 @@ +pub mod most; + +pub struct Inner; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs new file mode 100644 index 0000000000000..5a5eaf9670f90 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs @@ -0,0 +1 @@ +pub struct Snarks; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs new file mode 100644 index 0000000000000..a12734db7cb5f --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs @@ -0,0 +1,3 @@ +pub mod inner; + +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs new file mode 100644 index 0000000000000..f19ab10d5fb06 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs @@ -0,0 +1 @@ +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs new file mode 100644 index 0000000000000..42eb99cd7a3e1 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs @@ -0,0 +1,9 @@ +#![deny(clippy::mod_module_files)] + +mod good; +pub use dep_with_mod::with_mod::Thing; + +fn main() { + let _ = good::Thing; + let _ = dep_with_mod::with_mod::Thing; +} diff --git a/util/etc/vscode-tasks.json b/util/etc/vscode-tasks.json index ab98f9b4154ac..38e31b337a06b 100644 --- a/util/etc/vscode-tasks.json +++ b/util/etc/vscode-tasks.json @@ -47,9 +47,9 @@ "group": "test" }, { - "label": "cargo dev bless", + "label": "bless ui tests", "type": "shell", - "command": "cargo dev bless", + "command": "cargo bless", "problemMatcher": [], "group": "none" } diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 8791debad7231..99e211654d19c 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -501,9 +501,11 @@

Clippy Lints

- + - @@ -517,7 +519,8 @@

Clippy Lints

{{lint.id}} - + 📋 diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 1c16ecd6b0b1f..f59245e556cd2 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -24,9 +24,9 @@ target.scrollIntoView(); } - function scrollToLintByURL($scope) { - var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) { - scrollToLint(window.location.hash.slice(1)); + function scrollToLintByURL($scope, $location) { + var removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) { + scrollToLint($location.path().substring(1)); removeListener(); }); } @@ -106,10 +106,10 @@ } }; }) - .controller("lintList", function ($scope, $http, $timeout) { + .controller("lintList", function ($scope, $http, $location, $timeout) { // Level filter var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; - $scope.levels = LEVEL_FILTERS_DEFAULT; + $scope.levels = { ...LEVEL_FILTERS_DEFAULT }; $scope.byLevels = function (lint) { return $scope.levels[lint.level]; }; @@ -146,6 +146,165 @@ "=": {enabled: false, minorVersion: null }, }; + // Map the versionFilters to the query parameters in a way that is easier to work with in a URL + const versionFilterKeyMap = { + "≥": "gte", + "≤": "lte", + "=": "eq" + }; + const reverseVersionFilterKeyMap = Object.fromEntries( + Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key]) + ); + + // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them + // to corresponding $scope variables. + function loadFromURLParameters() { + // Extract parameters from URL + const urlParameters = $location.search(); + + // Define a helper function that assigns URL parameters to a provided scope variable + const handleParameter = (parameter, scopeVariable, defaultValues) => { + if (urlParameters[parameter]) { + const items = urlParameters[parameter].split(','); + for (const key in scopeVariable) { + if (scopeVariable.hasOwnProperty(key)) { + scopeVariable[key] = items.includes(key); + } + } + } else if (defaultValues) { + for (const key in defaultValues) { + if (scopeVariable.hasOwnProperty(key)) { + scopeVariable[key] = defaultValues[key]; + } + } + } + }; + + handleParameter('levels', $scope.levels, LEVEL_FILTERS_DEFAULT); + handleParameter('groups', $scope.groups, GROUPS_FILTER_DEFAULT); + + // Handle 'versions' parameter separately because it needs additional processing + if (urlParameters.versions) { + const versionFilters = urlParameters.versions.split(','); + for (const versionFilter of versionFilters) { + const [key, minorVersion] = versionFilter.split(':'); + const parsedMinorVersion = parseInt(minorVersion); + + // Map the key from the URL parameter to its original form + const originalKey = reverseVersionFilterKeyMap[key]; + + if (originalKey in $scope.versionFilters && !isNaN(parsedMinorVersion)) { + $scope.versionFilters[originalKey].enabled = true; + $scope.versionFilters[originalKey].minorVersion = parsedMinorVersion; + } + } + } + + // Load the search parameter from the URL path + const searchParameter = $location.path().substring(1); // Remove the leading slash + if (searchParameter) { + $scope.search = searchParameter; + $scope.open[searchParameter] = true; + scrollToLintByURL($scope, $location); + } + } + + // updateURLParameter updates the URL parameter with the given key to the given value + function updateURLParameter(filterObj, urlKey, defaultValue = {}, processFilter = filter => filter) { + const parameter = Object.keys(filterObj) + .filter(filter => filterObj[filter]) + .sort() + .map(processFilter) + .filter(Boolean) // Filters out any falsy values, including null + .join(','); + + const defaultParameter = Object.keys(defaultValue) + .filter(filter => defaultValue[filter]) + .sort() + .map(processFilter) + .filter(Boolean) // Filters out any falsy values, including null + .join(','); + + // if we ended up back at the defaults, just remove it from the URL + if (parameter === defaultParameter) { + $location.search(urlKey, null); + } else { + $location.search(urlKey, parameter || null); + } + } + + // updateVersionURLParameter updates the version URL parameter with the given version filters + function updateVersionURLParameter(versionFilters) { + updateURLParameter( + versionFilters, + 'versions', {}, + versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null + ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}` + : null + ); + } + + // updateAllURLParameters updates all the URL parameters with the current filter settings + function updateAllURLParameters() { + updateURLParameter($scope.levels, 'levels', LEVEL_FILTERS_DEFAULT); + updateURLParameter($scope.groups, 'groups', GROUPS_FILTER_DEFAULT); + updateVersionURLParameter($scope.versionFilters); + } + + // Add $watches to automatically update URL parameters when the data changes + $scope.$watch('levels', function (newVal, oldVal) { + if (newVal !== oldVal) { + updateURLParameter(newVal, 'levels', LEVEL_FILTERS_DEFAULT); + } + }, true); + + $scope.$watch('groups', function (newVal, oldVal) { + if (newVal !== oldVal) { + updateURLParameter(newVal, 'groups', GROUPS_FILTER_DEFAULT); + } + }, true); + + $scope.$watch('versionFilters', function (newVal, oldVal) { + if (newVal !== oldVal) { + updateVersionURLParameter(newVal); + } + }, true); + + // Watch for changes in the URL path and update the search and lint display + $scope.$watch(function () { return $location.path(); }, function (newPath) { + const searchParameter = newPath.substring(1); + if ($scope.search !== searchParameter) { + $scope.search = searchParameter; + $scope.open[searchParameter] = true; + scrollToLintByURL($scope, $location); + } + }); + + let debounceTimeout; + $scope.$watch('search', function (newVal, oldVal) { + if (newVal !== oldVal) { + if (debounceTimeout) { + $timeout.cancel(debounceTimeout); + } + + debounceTimeout = $timeout(function () { + $location.path(newVal); + }, 1000); + } + }); + + $scope.$watch(function () { return $location.search(); }, function (newParameters) { + loadFromURLParameters(); + }, true); + + $scope.updatePath = function () { + if (debounceTimeout) { + $timeout.cancel(debounceTimeout); + } + + $location.path($scope.search); + } + $scope.selectTheme = function (theme) { setTheme(theme, true); } @@ -169,10 +328,9 @@ }; $scope.resetGroupsToDefault = function () { - const groups = $scope.groups; - for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) { - groups[key] = value; - } + $scope.groups = { + ...GROUPS_FILTER_DEFAULT + }; }; $scope.selectedValuesCount = function (obj) { @@ -272,6 +430,12 @@ return true; } + // Show details for one lint + $scope.openLint = function (lint) { + $scope.open[lint.id] = true; + $location.path(lint.id); + }; + $scope.copyToClipboard = function (lint) { const clipboard = document.getElementById("clipboard-" + lint.id); if (clipboard) { @@ -296,14 +460,12 @@ // Get data $scope.open = {}; $scope.loading = true; + // This will be used to jump into the source code of the version that this documentation is for. $scope.docVersion = window.location.pathname.split('/')[2] || "master"; - if (window.location.hash.length > 1) { - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - scrollToLintByURL($scope); - } + // Set up the filters from the URL parameters before we start loading the data + loadFromURLParameters(); $http.get('./lints.json') .success(function (data) { @@ -315,7 +477,7 @@ selectGroup($scope, selectedGroup.toLowerCase()); } - scrollToLintByURL($scope); + scrollToLintByURL($scope, $location); setTimeout(function () { var el = document.getElementById('filter-input'); @@ -326,18 +488,6 @@ $scope.error = data; $scope.loading = false; }); - - window.addEventListener('hashchange', function () { - // trigger re-render - $timeout(function () { - $scope.levels = LEVEL_FILTERS_DEFAULT; - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - - scrollToLintByURL($scope); - }); - return true; - }, false); }); })(); diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index 6e810a349bfcc..31ce881932952 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -36,7 +36,7 @@

@@ -54,18 +54,15 @@

.controller('docVersions', function ($scope, $http) { $scope.loading = true; - $scope.normalizeVersionDisplay = function(v) { - return v.replace(/^v/, ''); - }; - $scope.normalizeVersion = function(v) { - return v.replace(/^v/, '').replace(/^rust-/, ''); + return v.replace(/^rust-/, ''); }; $scope.versionOrder = function(v) { if (v === 'master') { return Infinity; } if (v === 'stable') { return Number.MAX_VALUE; } if (v === 'beta') { return Number.MAX_VALUE - 1; } + if (v === 'pre-1.29.0') { return Number.MIN_VALUE; } return $scope.normalizeVersion(v) .split('.') diff --git a/util/versions.py b/util/versions.py index 0cfa007d1b271..c041fc606a8f3 100755 --- a/util/versions.py +++ b/util/versions.py @@ -1,24 +1,27 @@ #!/usr/bin/env python import json +import logging as log import os import sys -import logging as log -log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s') + +log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s") def key(v): - if v == 'master': - return float('inf') - if v == 'stable': + if v == "master": + return float("inf") + if v == "stable": return sys.maxsize - if v == 'beta': + if v == "beta": return sys.maxsize - 1 + if v == "pre-1.29.0": + return -1 - v = v.replace('v', '').replace('rust-', '') + v = v.replace("rust-", "") s = 0 - for i, val in enumerate(v.split('.')[::-1]): + for i, val in enumerate(v.split(".")[::-1]): s += int(val) * 100**i return s @@ -31,7 +34,11 @@ def main(): outdir = sys.argv[1] versions = [ - dir for dir in os.listdir(outdir) if not dir.startswith(".") and os.path.isdir(os.path.join(outdir, dir)) + dir + for dir in os.listdir(outdir) + if not dir.startswith(".") + and not dir.startswith("v") + and os.path.isdir(os.path.join(outdir, dir)) ] versions.sort(key=key) From ba1ffec5b5284bca28c58f18b875b3a8e50a277a Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 14:59:44 +0200 Subject: [PATCH 18/80] Fix valtree changes --- clippy_utils/src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 068820801dfe0..dd3cda8ec5277 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -725,8 +725,8 @@ fn field_of_struct<'tcx>( result: mir::ConstantKind<'tcx>, field: &Ident, ) -> Option> { - let dc = lcx.tcx.destructure_mir_constant(lcx.param_env, result); - if let Some(dc_variant) = dc.variant + if let Some(dc) = lcx.tcx.try_destructure_mir_constant(lcx.param_env.and(result)) + && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) && let Some(dc_field) = dc.fields.get(field_idx) From 4aa4fecf897869b656d91791b8dcb03db189733d Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 15:07:39 +0200 Subject: [PATCH 19/80] Fix compile-test tests to work with the new ui_test crate --- tests/compile-test.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index dce6f2fc27269..0fd37c640aef8 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -31,7 +31,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { }, dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()), target: None, - out_dir: "target/ui_test".into(), + out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap_or("target".into())).join("ui_test"), ..compiletest::Config::rustc(Path::new("tests").join(test_dir)) }; @@ -116,10 +116,7 @@ fn run_ui_toml() { config.stderr_filter( ®ex::escape( - &std::path::Path::new(file!()) - .parent() - .unwrap() - .canonicalize() + &fs::canonicalize("tests") .unwrap() .parent() .unwrap() @@ -175,10 +172,7 @@ fn run_ui_cargo() { config.stderr_filter( ®ex::escape( - &std::path::Path::new(file!()) - .parent() - .unwrap() - .canonicalize() + &fs::canonicalize("tests") .unwrap() .parent() .unwrap() From e29a5acf6f177e35ad00d7120fc3422ac94c3ac9 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 2 Jul 2023 14:17:34 +0000 Subject: [PATCH 20/80] let_and_return: lint 'static lifetimes, don't lint borrows in closures --- clippy_lints/src/returns.rs | 6 ++-- tests/ui/let_and_return.rs | 61 ++++++++++++++++++---------------- tests/ui/let_and_return.stderr | 22 +++++++++--- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 958351ad81bb7..ad0167a3d3271 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::source::{snippet_opt, snippet_with_context}; -use clippy_utils::visitors::{for_each_expr, Descend}; +use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; use clippy_utils::{fn_def_id, path_to_local_id, span_find_starting_semi}; use core::ops::ControlFlow; use if_chain::if_chain; @@ -328,7 +328,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec, } fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - for_each_expr(expr, |e| { + for_each_expr_with_closures(cx, expr, |e| { if let Some(def_id) = fn_def_id(cx, e) && cx .tcx @@ -337,7 +337,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) .skip_binder() .output() .walk() - .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))) + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static())) { ControlFlow::Break(()) } else { diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index bb162adc9adb2..7e4d783a026c3 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -1,6 +1,8 @@ #![allow(unused)] #![warn(clippy::let_and_return)] +use std::cell::RefCell; + fn test() -> i32 { let _y = 0; // no warning let x = 5; @@ -65,45 +67,46 @@ macro_rules! tuple_encode { ); } +fn issue_3792() -> String { + use std::io::{self, BufRead, Stdin}; + + let stdin = io::stdin(); + // `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin` + // https://github.com/rust-lang/rust/pull/93965 + let line = stdin.lock().lines().next().unwrap().unwrap(); + line +} + tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); mod no_lint_if_stmt_borrows { - mod issue_3792 { - use std::io::{self, BufRead, Stdin}; + use std::cell::RefCell; + use std::rc::{Rc, Weak}; + struct Bar; - fn read_line() -> String { - let stdin = io::stdin(); - let line = stdin.lock().lines().next().unwrap().unwrap(); - line + impl Bar { + fn new() -> Self { + Bar {} } - } - - mod issue_3324 { - use std::cell::RefCell; - use std::rc::{Rc, Weak}; - - fn test(value: Weak>) -> u32 { - let value = value.upgrade().unwrap(); - let ret = value.borrow().baz(); - ret + fn baz(&self) -> u32 { + 0 } + } - struct Bar; + fn issue_3324(value: Weak>) -> u32 { + let value = value.upgrade().unwrap(); + let ret = value.borrow().baz(); + ret + } - impl Bar { - fn new() -> Self { - Bar {} - } - fn baz(&self) -> u32 { - 0 - } + fn borrows_in_closure(value: Weak>) -> u32 { + fn f(mut x: impl FnMut() -> u32) -> impl FnMut() -> u32 { + x } - fn main() { - let a = Rc::new(RefCell::new(Bar::new())); - let b = Rc::downgrade(&a); - test(b); - } + let value = value.upgrade().unwrap(); + let ret = f(|| value.borrow().baz())(); + ret } mod free_function { diff --git a/tests/ui/let_and_return.stderr b/tests/ui/let_and_return.stderr index 17fd694bf7ac9..4ca0a05c858fb 100644 --- a/tests/ui/let_and_return.stderr +++ b/tests/ui/let_and_return.stderr @@ -1,5 +1,5 @@ error: returning the result of a `let` binding from a block - --> $DIR/let_and_return.rs:7:5 + --> $DIR/let_and_return.rs:9:5 | LL | let x = 5; | ---------- unnecessary `let` binding @@ -14,7 +14,7 @@ LL ~ 5 | error: returning the result of a `let` binding from a block - --> $DIR/let_and_return.rs:13:9 + --> $DIR/let_and_return.rs:15:9 | LL | let x = 5; | ---------- unnecessary `let` binding @@ -28,7 +28,21 @@ LL ~ 5 | error: returning the result of a `let` binding from a block - --> $DIR/let_and_return.rs:164:13 + --> $DIR/let_and_return.rs:77:5 + | +LL | let line = stdin.lock().lines().next().unwrap().unwrap(); + | --------------------------------------------------------- unnecessary `let` binding +LL | line + | ^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ stdin.lock().lines().next().unwrap().unwrap() + | + +error: returning the result of a `let` binding from a block + --> $DIR/let_and_return.rs:167:13 | LL | let clone = Arc::clone(&self.foo); | ---------------------------------- unnecessary `let` binding @@ -41,5 +55,5 @@ LL ~ LL ~ Arc::clone(&self.foo) as _ | -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 555ceb83fefc937e03bade598b608b76700234cb Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 2 Jul 2023 21:42:39 +0200 Subject: [PATCH 21/80] [`missing_fields_in_debug`]: make sure `self` is an adt --- clippy_lints/src/missing_fields_in_debug.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index 1138d1163a4a9..497514fbcd606 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -207,11 +207,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { 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 && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind - // don't trigger if self is a generic parameter, e.g. `impl Debug for T` - // this can only happen in core itself, where the trait is defined, - // but it caused ICEs in the past: - // https://github.com/rust-lang/rust-clippy/issues/10887 - && !matches!(self_path.res, Res::Def(DefKind::TyParam, _)) + // make sure that the self type is either a struct, an enum or a union + // this prevents ICEs such as when self is a type parameter or a primitive type + // (see #10887, #11063) + && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, self_path_did) = self_path.res && cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug]) // don't trigger if this impl was derived && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) @@ -222,7 +221,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { && let body = cx.tcx.hir().body(*body_id) && let ExprKind::Block(block, _) = body.value.kind // inspect `self` - && let self_ty = cx.tcx.type_of(self_path.res.def_id()).skip_binder().peel_refs() + && let self_ty = cx.tcx.type_of(self_path_did).skip_binder().peel_refs() && let Some(self_adt) = self_ty.ty_adt_def() && let Some(self_def_id) = self_adt.did().as_local() && let Some(Node::Item(self_item)) = cx.tcx.hir().find_by_def_id(self_def_id) From 6990eaa9720e45b3b09eb00d9476b89839935c10 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 2 Jul 2023 04:03:20 +0200 Subject: [PATCH 22/80] Don't suppress manual_let_else if question_mark is allowed If question_mark is allowed, there is no overlap any more, so we can just not suppress it. --- clippy_lints/src/manual_let_else.rs | 20 +++++++++---------- tests/ui/manual_let_else_question_mark.fixed | 7 +++++++ tests/ui/manual_let_else_question_mark.rs | 7 +++++++ tests/ui/manual_let_else_question_mark.stderr | 8 +++++++- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 363018f138195..18739e9d8e20b 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,12 +1,10 @@ -use crate::question_mark::{pat_and_expr_can_be_question_mark, QuestionMark}; +use crate::question_mark::{pat_and_expr_can_be_question_mark, QuestionMark, QUESTION_MARK}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; -use clippy_utils::msrvs; -use clippy_utils::peel_blocks; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; -use if_chain::if_chain; +use clippy_utils::{is_lint_allowed, msrvs, peel_blocks}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; @@ -65,12 +63,14 @@ impl<'tcx> QuestionMark { let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) { match if_let_or_match { - IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! { - if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then); - if let Some(if_else) = if_else; - if expr_diverges(cx, if_else); - if pat_and_expr_can_be_question_mark(cx, let_pat, if_else).is_none(); - then { + IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => { + if + let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then) && + let Some(if_else) = if_else && + expr_diverges(cx, if_else) && + let qm_allowed = is_lint_allowed(cx, QUESTION_MARK, stmt.hir_id) && + (qm_allowed || pat_and_expr_can_be_question_mark(cx, let_pat, if_else).is_none()) + { emit_manual_let_else(cx, stmt.span, if_let_expr, &ident_map, let_pat, if_else); } }, diff --git a/tests/ui/manual_let_else_question_mark.fixed b/tests/ui/manual_let_else_question_mark.fixed index 617f127b9a868..02308bc7c4c13 100644 --- a/tests/ui/manual_let_else_question_mark.fixed +++ b/tests/ui/manual_let_else_question_mark.fixed @@ -52,5 +52,12 @@ fn foo() -> Option<()> { let Some(v) = g() else { return None }; } + // This is a copy of the case above where we'd fire the question_mark lint, but here we have allowed + // it. Make sure that manual_let_else is fired as the fallback. + #[allow(clippy::question_mark)] + { + let Some(v) = g() else { return None }; + } + Some(()) } diff --git a/tests/ui/manual_let_else_question_mark.rs b/tests/ui/manual_let_else_question_mark.rs index 3cf1eca867349..9c7ad386dc99f 100644 --- a/tests/ui/manual_let_else_question_mark.rs +++ b/tests/ui/manual_let_else_question_mark.rs @@ -57,5 +57,12 @@ fn foo() -> Option<()> { }; } + // This is a copy of the case above where we'd fire the question_mark lint, but here we have allowed + // it. Make sure that manual_let_else is fired as the fallback. + #[allow(clippy::question_mark)] + { + let v = if let Some(v_some) = g() { v_some } else { return None }; + } + Some(()) } diff --git a/tests/ui/manual_let_else_question_mark.stderr b/tests/ui/manual_let_else_question_mark.stderr index 31052acf75cd7..d7d2e127ea3f3 100644 --- a/tests/ui/manual_let_else_question_mark.stderr +++ b/tests/ui/manual_let_else_question_mark.stderr @@ -45,5 +45,11 @@ LL | | _ => return None, LL | | }; | |__________^ help: consider writing: `let Some(v) = g() else { return None };` -error: aborting due to 5 previous errors +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_question_mark.rs:64:9 + | +LL | let v = if let Some(v_some) = g() { v_some } else { return None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return None };` + +error: aborting due to 6 previous errors From d80581c7d2db05a899e3363c8fc937012311de69 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 3 Jul 2023 09:42:43 +0200 Subject: [PATCH 23/80] Move pat_and_expr_can_be_question_mark into clippy_utils --- clippy_lints/src/manual_let_else.rs | 4 +-- clippy_lints/src/question_mark.rs | 50 ++--------------------------- clippy_utils/src/lib.rs | 45 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 18739e9d8e20b..ade85e23bd3a3 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,10 +1,10 @@ -use crate::question_mark::{pat_and_expr_can_be_question_mark, QuestionMark, QUESTION_MARK}; +use crate::question_mark::{QuestionMark, QUESTION_MARK}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; -use clippy_utils::{is_lint_allowed, msrvs, peel_blocks}; +use clippy_utils::{is_lint_allowed, msrvs, pat_and_expr_can_be_question_mark, peel_blocks}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index d473b6fd5c435..9840d464b75fd 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -4,8 +4,8 @@ use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ - eq_expr_value, get_parent_node, in_constant, is_else_clause, is_refutable, is_res_lang_ctor, path_to_local, - path_to_local_id, peel_blocks, peel_blocks_with_stmt, + eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, pat_and_expr_can_be_question_mark, + path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, }; use clippy_utils::{higher, is_path_lang_item}; use if_chain::if_chain; @@ -13,7 +13,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, Pat, PatKind, PathSegment, QPath, Stmt, StmtKind, + BindingAnnotation, Block, ByRef, Expr, ExprKind, Local, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -95,50 +95,6 @@ enum IfBlockType<'hir> { ), } -/// Returns whether the given let pattern and else body can be turned into a question mark -/// -/// For this example: -/// ```ignore -/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None }; -/// ``` -/// We get as parameters: -/// ```ignore -/// pat: Some(a) -/// else_body: return None -/// ``` - -/// And for this example: -/// ```ignore -/// let Some(FooBar { a, b }) = ex else { return None }; -/// ``` -/// We get as parameters: -/// ```ignore -/// pat: Some(FooBar { a, b }) -/// else_body: return None -/// ``` - -/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because -/// the question mark operator is applicable here. Callers have to check whether we are in a -/// constant or not. -pub(crate) fn pat_and_expr_can_be_question_mark<'a, 'hir>( - cx: &LateContext<'_>, - pat: &'a Pat<'hir>, - else_body: &Expr<'_>, -) -> Option<&'a Pat<'hir>> { - if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind && - is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) && - !is_refutable(cx, inner_pat) && - let else_body = peel_blocks(else_body) && - let ExprKind::Ret(Some(ret_val)) = else_body.kind && - let ExprKind::Path(ret_path) = ret_val.kind && - is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone) - { - Some(inner_pat) - } else { - None - } -} - fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { if let StmtKind::Local(Local { pat, init: Some(init_expr), els: Some(els), .. }) = stmt.kind && let Block { stmts: &[], expr: Some(els), .. } = els && diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 727b59f1f432a..02ab1b31e72a0 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -87,6 +87,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; +use rustc_hir::LangItem::OptionSome; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, @@ -2542,6 +2543,50 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span { sm.span_take_while(span, |&ch| ch == ' ' || ch == ';') } +/// Returns whether the given let pattern and else body can be turned into a question mark +/// +/// For this example: +/// ```ignore +/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(a) +/// else_body: return None +/// ``` + +/// And for this example: +/// ```ignore +/// let Some(FooBar { a, b }) = ex else { return None }; +/// ``` +/// We get as parameters: +/// ```ignore +/// pat: Some(FooBar { a, b }) +/// else_body: return None +/// ``` + +/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because +/// the question mark operator is applicable here. Callers have to check whether we are in a +/// constant or not. +pub fn pat_and_expr_can_be_question_mark<'a, 'hir>( + cx: &LateContext<'_>, + pat: &'a Pat<'hir>, + else_body: &Expr<'_>, +) -> Option<&'a Pat<'hir>> { + if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind && + is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome) && + !is_refutable(cx, inner_pat) && + let else_body = peel_blocks(else_body) && + let ExprKind::Ret(Some(ret_val)) = else_body.kind && + let ExprKind::Path(ret_path) = ret_val.kind && + is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone) + { + Some(inner_pat) + } else { + None + } +} + macro_rules! op_utils { ($($name:ident $assign:ident)*) => { /// Binary operation traits like `LangItem::Add` From 75c339cd0ad7c38f8d258a369570400eae933973 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 3 Jul 2023 11:34:02 +0200 Subject: [PATCH 24/80] [`arc_with_non_send_sync`]: look for nested type parameters --- clippy_lints/src/arc_with_non_send_sync.rs | 6 +++++- tests/ui/arc_with_non_send_sync.rs | 3 +++ tests/ui/arc_with_non_send_sync.stderr | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index a1e44668e1adc..62313df9f90ec 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -7,6 +7,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_lint::LateLintPass; use rustc_middle::ty; +use rustc_middle::ty::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; @@ -47,7 +48,10 @@ impl LateLintPass<'_> for ArcWithNonSendSync { if let ExprKind::Path(func_path) = func.kind; if last_path_segment(&func_path).ident.name == sym::new; if let arg_ty = cx.typeck_results().expr_ty(arg); - if !matches!(arg_ty.kind(), ty::Param(_)); + // make sure that the type is not and does not contain any type parameters + if arg_ty.walk().all(|arg| { + !matches!(arg.unpack(), GenericArgKind::Type(ty) if matches!(ty.kind(), ty::Param(_))) + }); if !cx.tcx .lang_items() .sync_trait() diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index ac786f68c123d..9d5849277c204 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -7,6 +7,9 @@ fn foo(x: T) { // Should not lint - purposefully ignoring generic args. let a = Arc::new(x); } +fn issue11076() { + let a: Arc> = Arc::new(Vec::new()); +} fn main() { // This is safe, as `i32` implements `Send` and `Sync`. diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index fc2fc5f93b13b..520c21b565ba5 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -1,5 +1,5 @@ error: usage of `Arc` where `T` is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:16:13 + --> $DIR/arc_with_non_send_sync.rs:19:13 | LL | let b = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From 9a581077d41dcc9a751a30cdfeca17464d5a7be2 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Mon, 3 Jul 2023 06:35:04 -0500 Subject: [PATCH 25/80] Fix FP [`needless_raw_string_hashes`] --- clippy_lints/src/raw_strings.rs | 2 +- tests/ui/needless_raw_string_hashes.fixed | 4 ++++ tests/ui/needless_raw_string_hashes.rs | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index f45bb1ef3e1f8..0e964ec4724d9 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -95,7 +95,7 @@ impl EarlyLintPass for RawStrings { // `once` so a raw string ending in hashes is still checked let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| { match b { - b'"' => (following_quote, req) = (true, 1), + b'"' if !following_quote => (following_quote, req) = (true, 1), // I'm a bit surprised the compiler didn't optimize this out, there's no // branch but it still ends up doing an unnecessary comparison, it's: // - cmp r9b,1h diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index e4d7d8fb017a9..a9a6282628e92 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -16,4 +16,8 @@ fn main() { cr#"Hello "world"!"#; cr####" "### "## "# "####; cr###" "aa" "# "## "###; + // Issue #11068, do not lint + r##"a"#"a"##; + br##"a"#"a"##; + cr##"a"#"a"##; } diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs index e2d85c52e78cc..baa97d8647031 100644 --- a/tests/ui/needless_raw_string_hashes.rs +++ b/tests/ui/needless_raw_string_hashes.rs @@ -16,4 +16,8 @@ fn main() { cr##"Hello "world"!"##; cr######" "### "## "# "######; cr######" "aa" "# "## "######; + // Issue #11068, do not lint + r##"a"#"a"##; + br##"a"#"a"##; + cr##"a"#"a"##; } From 1f77f8cc3cca968d47d15c9e621d48f0193f8ab1 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 3 Jul 2023 13:40:33 +0200 Subject: [PATCH 26/80] [`useless_vec`]: use the source span --- clippy_lints/src/vec.rs | 2 +- tests/ui/vec.fixed | 11 +++++++++++ tests/ui/vec.rs | 11 +++++++++++ tests/ui/vec.stderr | 12 +++++++++--- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 2a594e750b9b2..ca0daa9eceecd 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -181,7 +181,7 @@ impl UselessVec { if args.len() as u64 * size_of(cx, last) > self.too_large_for_stack { return; } - let span = args[0].span.to(last.span); + let span = args[0].span.source_callsite().to(last.span.source_callsite()); let args = snippet_with_applicability(cx, span, "..", &mut applicability); match suggest_slice { diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index fcdc917c1b139..14ab8bd8897e1 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -115,6 +115,17 @@ fn main() { let _x = vec![1; 201]; } +fn issue11075() { + macro_rules! repro { + ($e:expr) => { + stringify!($e) + }; + } + for _string in [repro!(true), repro!(null)] { + unimplemented!(); + } +} + #[clippy::msrv = "1.53"] fn above() { for a in [1, 2, 3] { diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 0404d8cdb8421..e57cb4374e38f 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -115,6 +115,17 @@ fn main() { let _x = vec![1; 201]; } +fn issue11075() { + macro_rules! repro { + ($e:expr) => { + stringify!($e) + }; + } + for _string in vec![repro!(true), repro!(null)] { + unimplemented!(); + } +} + #[clippy::msrv = "1.53"] fn above() { for a in vec![1, 2, 3] { diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 33d565b2d5250..1b82d5cbea885 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -85,16 +85,22 @@ LL | for _ in vec![1, 2, 3] {} | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:120:14 + --> $DIR/vec.rs:124:20 + | +LL | for _string in vec![repro!(true), repro!(null)] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[repro!(true), repro!(null)]` + +error: useless use of `vec!` + --> $DIR/vec.rs:131:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:124:14 + --> $DIR/vec.rs:135:14 | LL | for a in vec![String::new(), String::new()] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors From b4549c50b599929ec47ff4e9d880c27654342bb9 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 3 Jul 2023 18:13:01 +0200 Subject: [PATCH 27/80] [`useless_vec`]: add more tests for macro combinations --- clippy_lints/src/vec.rs | 4 ++++ tests/ui/vec.fixed | 29 +++++++++++++++++++++++++++++ tests/ui/vec.rs | 29 +++++++++++++++++++++++++++++ tests/ui/vec.stderr | 18 +++++++++++++++--- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index ca0daa9eceecd..6a96114ae769f 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -154,6 +154,10 @@ impl UselessVec { span: Span, suggest_slice: SuggestedType, ) { + if span.from_expansion() { + return; + } + let mut applicability = Applicability::MachineApplicable; let snippet = match *vec_args { diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 14ab8bd8897e1..7a7d0026f797b 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -124,6 +124,35 @@ fn issue11075() { for _string in [repro!(true), repro!(null)] { unimplemented!(); } + + macro_rules! in_macro { + ($e:expr, $vec:expr, $vec2:expr) => {{ + vec![1; 2].fill(3); + vec![1, 2].fill(3); + for _ in vec![1, 2] {} + for _ in vec![1; 2] {} + for _ in vec![$e, $e] {} + for _ in vec![$e; 2] {} + for _ in $vec {} + for _ in $vec2 {} + }}; + } + + in_macro!(1, [1, 2], [1; 2]); + + macro_rules! from_macro { + () => { + vec![1, 2, 3] + }; + } + macro_rules! from_macro_repeat { + () => { + vec![1; 3] + }; + } + + for _ in from_macro!() {} + for _ in from_macro_repeat!() {} } #[clippy::msrv = "1.53"] diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index e57cb4374e38f..cbe7685b45339 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -124,6 +124,35 @@ fn issue11075() { for _string in vec![repro!(true), repro!(null)] { unimplemented!(); } + + macro_rules! in_macro { + ($e:expr, $vec:expr, $vec2:expr) => {{ + vec![1; 2].fill(3); + vec![1, 2].fill(3); + for _ in vec![1, 2] {} + for _ in vec![1; 2] {} + for _ in vec![$e, $e] {} + for _ in vec![$e; 2] {} + for _ in $vec {} + for _ in $vec2 {} + }}; + } + + in_macro!(1, vec![1, 2], vec![1; 2]); + + macro_rules! from_macro { + () => { + vec![1, 2, 3] + }; + } + macro_rules! from_macro_repeat { + () => { + vec![1; 3] + }; + } + + for _ in from_macro!() {} + for _ in from_macro_repeat!() {} } #[clippy::msrv = "1.53"] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 1b82d5cbea885..8f6d2a1df8037 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -91,16 +91,28 @@ LL | for _string in vec![repro!(true), repro!(null)] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[repro!(true), repro!(null)]` error: useless use of `vec!` - --> $DIR/vec.rs:131:14 + --> $DIR/vec.rs:141:18 + | +LL | in_macro!(1, vec![1, 2], vec![1; 2]); + | ^^^^^^^^^^ help: you can use an array directly: `[1, 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:141:30 + | +LL | in_macro!(1, vec![1, 2], vec![1; 2]); + | ^^^^^^^^^^ help: you can use an array directly: `[1; 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:160:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:135:14 + --> $DIR/vec.rs:164:14 | LL | for a in vec![String::new(), String::new()] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` -error: aborting due to 17 previous errors +error: aborting due to 19 previous errors From b41fc6784fc723ea52da0e0668fc5205b740f81a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 6 Jun 2023 19:27:12 +0200 Subject: [PATCH 28/80] Add needless_pass_by_ref lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/needless_pass_by_ref_mut.rs | 238 +++++++++++++++++++ clippy_lints/src/needless_pass_by_value.rs | 2 +- 5 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/needless_pass_by_ref_mut.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f9310b4ab31fa..762efed5c1206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5047,6 +5047,7 @@ Released 2018-09-13 [`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals +[`needless_pass_by_ref_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index e1dbe5003965f..4f945ebc6101a 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -470,6 +470,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_if::NEEDLESS_IF_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, + crate::needless_pass_by_ref_mut::NEEDLESS_PASS_BY_REF_MUT_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO, crate::needless_update::NEEDLESS_UPDATE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c43e0b753dc8d..e1e4a83b031bc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -229,6 +229,7 @@ mod needless_for_each; mod needless_if; mod needless_late_init; mod needless_parens_on_range_literals; +mod needless_pass_by_ref_mut; mod needless_pass_by_value; mod needless_question_mark; mod needless_update; @@ -1057,6 +1058,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); + store.register_late_pass(|_| Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut)); store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls)); store.register_late_pass(move |_| { Box::new(single_call_fn::SingleCallFn { diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs new file mode 100644 index 0000000000000..c5dc87cdfa888 --- /dev/null +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -0,0 +1,238 @@ +use super::needless_pass_by_value::requires_exact_signature; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::{is_from_proc_macro, is_self}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, FnDecl, HirId, Impl, ItemKind, Mutability, Node, PatKind}; +use rustc_hir::{HirIdMap, HirIdSet}; +use rustc_hir_typeck::expr_use_visitor as euv; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::mir::FakeReadCause; +use rustc_middle::ty::{self, Ty}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::def_id::LocalDefId; +use rustc_span::symbol::kw; +use rustc_span::Span; +use rustc_target::spec::abi::Abi; + +declare_clippy_lint! { + /// ### What it does + /// Check if a `&mut` function argument is actually used mutably. + /// + /// ### Why is this bad? + /// Less `mut` means less fights with the borrow checker. It can also lead to more + /// opportunities for parallelization. + /// + /// ### Example + /// ```rust + /// fn foo(y: &mut i32) -> i32 { + /// 12 + *y + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn foo(y: &i32) -> i32 { + /// 12 + *y + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_PASS_BY_REF_MUT, + suspicious, + "using a `&mut` argument when it's not mutated" +} +declare_lint_pass!(NeedlessPassByRefMut => [NEEDLESS_PASS_BY_REF_MUT]); + +fn should_skip<'tcx>( + cx: &LateContext<'tcx>, + input: rustc_hir::Ty<'tcx>, + ty: Ty<'_>, + arg: &rustc_hir::Param<'_>, +) -> bool { + // We check if this a `&mut`. `ref_mutability` returns `None` if it's not a reference. + if !matches!(ty.ref_mutability(), Some(Mutability::Mut)) { + return true; + } + + if is_self(arg) { + return true; + } + + if let PatKind::Binding(.., name, _) = arg.pat.kind { + // If it's a potentially unused variable, we don't check it. + if name.name == kw::Underscore || name.as_str().starts_with('_') { + return true; + } + } + + // All spans generated from a proc-macro invocation are the same... + is_from_proc_macro(cx, &input) +} + +impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + span: Span, + fn_def_id: LocalDefId, + ) { + if span.from_expansion() { + return; + } + + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id); + + match kind { + FnKind::ItemFn(.., header) => { + let attrs = cx.tcx.hir().attrs(hir_id); + if header.abi != Abi::Rust || requires_exact_signature(attrs) { + return; + } + }, + FnKind::Method(..) => (), + FnKind::Closure => return, + } + + // Exclude non-inherent impls + if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { + if matches!( + item.kind, + ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) + ) { + return; + } + } + + let fn_sig = cx.tcx.fn_sig(fn_def_id).subst_identity(); + let fn_sig = cx.tcx.liberate_late_bound_regions(fn_def_id.to_def_id(), fn_sig); + + // If there are no `&mut` argument, no need to go any further. + if !decl + .inputs + .iter() + .zip(fn_sig.inputs()) + .zip(body.params) + .any(|((&input, &ty), arg)| !should_skip(cx, input, ty, arg)) + { + return; + } + + // Collect variables mutably used and spans which will need dereferencings from the + // function body. + let MutablyUsedVariablesCtxt { mutably_used_vars, .. } = { + let mut ctx = MutablyUsedVariablesCtxt::default(); + let infcx = cx.tcx.infer_ctxt().build(); + euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body); + ctx + }; + + for ((&input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(body.params) { + if should_skip(cx, input, ty, arg) { + continue; + } + + // Only take `&mut` arguments. + if_chain! { + if let PatKind::Binding(_, canonical_id, ..) = arg.pat.kind; + if !mutably_used_vars.contains(&canonical_id); + if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind; + then { + // If the argument is never used mutably, we emit the error. + span_lint_and_sugg( + cx, + NEEDLESS_PASS_BY_REF_MUT, + input.span, + "this argument is a mutable reference, but not used mutably", + "consider changing to", + format!("&{}", snippet(cx, cx.tcx.hir().span(inner_ty.ty.hir_id), "_")), + Applicability::Unspecified, + ); + } + } + } + } +} + +#[derive(Default)] +struct MutablyUsedVariablesCtxt { + mutably_used_vars: HirIdSet, + prev_bind: Option, + aliases: HirIdMap, +} + +impl MutablyUsedVariablesCtxt { + fn add_mutably_used_var(&mut self, mut used_id: HirId) { + while let Some(id) = self.aliases.get(&used_id) { + self.mutably_used_vars.insert(used_id); + used_id = *id; + } + self.mutably_used_vars.insert(used_id); + } +} + +impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt { + fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) { + if let euv::Place { + base: euv::PlaceBase::Local(vid), + base_ty, + .. + } = &cmt.place + { + if let Some(bind_id) = self.prev_bind.take() { + self.aliases.insert(bind_id, *vid); + } else if matches!(base_ty.ref_mutability(), Some(Mutability::Mut)) { + self.add_mutably_used_var(*vid); + } + } + } + + fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId, borrow: ty::BorrowKind) { + self.prev_bind = None; + if let euv::Place { + base: euv::PlaceBase::Local(vid), + base_ty, + .. + } = &cmt.place + { + // If this is a mutable borrow, it was obviously used mutably so we add it. However + // for `UniqueImmBorrow`, it's interesting because if you do: `array[0] = value` inside + // a closure, it'll return this variant whereas if you have just an index access, it'll + // return `ImmBorrow`. So if there is "Unique" and it's a mutable reference, we add it + // to the mutably used variables set. + if borrow == ty::BorrowKind::MutBorrow + || (borrow == ty::BorrowKind::UniqueImmBorrow && base_ty.ref_mutability() == Some(Mutability::Mut)) + { + self.add_mutably_used_var(*vid); + } + } + } + + fn mutate(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) { + self.prev_bind = None; + if let euv::Place { + projections, + base: euv::PlaceBase::Local(vid), + .. + } = &cmt.place + { + if !projections.is_empty() { + self.add_mutably_used_var(*vid); + } + } + } + + fn copy(&mut self, _cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) { + self.prev_bind = None; + } + + fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} + + fn bind(&mut self, _cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) { + self.prev_bind = Some(id); + } +} diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ece10474715f2..5d299f9355d56 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } /// Functions marked with these attributes must have the exact signature. -fn requires_exact_signature(attrs: &[Attribute]) -> bool { +pub(crate) fn requires_exact_signature(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] .iter() From a43bea101621d6ecbf2b33f5fcf122819115171d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 6 Jun 2023 21:06:49 +0200 Subject: [PATCH 29/80] Add UI test for `needless_pass_by_ref_mut` --- tests/ui/needless_pass_by_ref_mut.rs | 105 +++++++++++++++++++++++ tests/ui/needless_pass_by_ref_mut.stderr | 28 ++++++ 2 files changed, 133 insertions(+) create mode 100644 tests/ui/needless_pass_by_ref_mut.rs create mode 100644 tests/ui/needless_pass_by_ref_mut.stderr diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs new file mode 100644 index 0000000000000..5e7280995c60f --- /dev/null +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -0,0 +1,105 @@ +#![allow(unused)] + +use std::ptr::NonNull; + +// Should only warn for `s`. +fn foo(s: &mut Vec, b: &u32, x: &mut u32) { + *x += *b + s.len() as u32; +} + +// Should not warn. +fn foo2(s: &mut Vec) { + s.push(8); +} + +// Should not warn because we return it. +fn foo3(s: &mut Vec) -> &mut Vec { + s +} + +// Should not warn because `s` is used as mutable. +fn foo4(s: &mut Vec) { + Vec::push(s, 4); +} + +// Should not warn. +fn foo5(s: &mut Vec) { + foo2(s); +} + +// Should warn. +fn foo6(s: &mut Vec) { + non_mut_ref(s); +} + +fn non_mut_ref(_: &Vec) {} + +struct Bar; + +impl Bar { + // Should not warn on `&mut self`. + fn bar(&mut self) {} + + // Should warn about `vec` + fn mushroom(&self, vec: &mut Vec) -> usize { + vec.len() + } + + // Should warn about `vec` (and not `self`). + fn badger(&mut self, vec: &mut Vec) -> usize { + vec.len() + } +} + +trait Babar { + // Should not warn here since it's a trait method. + fn method(arg: &mut u32); +} + +impl Babar for Bar { + // Should not warn here since it's a trait method. + fn method(a: &mut u32) {} +} + +// Should not warn (checking variable aliasing). +fn alias_check(s: &mut Vec) { + let mut alias = s; + let mut alias2 = alias; + let mut alias3 = alias2; + alias3.push(0); +} + +// Should not warn (checking variable aliasing). +fn alias_check2(mut s: &mut Vec) { + let mut alias = &mut s; + alias.push(0); +} + +struct Mut { + ptr: NonNull, +} + +impl Mut { + // Should not warn because `NonNull::from` also accepts `&mut`. + fn new(ptr: &mut T) -> Self { + Mut { + ptr: NonNull::from(ptr), + } + } +} + +// Should not warn. +fn unused(_: &mut u32, _b: &mut u8) {} + +fn main() { + let mut u = 0; + let mut v = vec![0]; + foo(&mut v, &0, &mut u); + foo2(&mut v); + foo3(&mut v); + foo4(&mut v); + foo5(&mut v); + alias_check(&mut v); + alias_check2(&mut v); + println!("{u}"); +} diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr new file mode 100644 index 0000000000000..5e9d80bb6c488 --- /dev/null +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -0,0 +1,28 @@ +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:6:11 + | +LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { + | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:31:12 + | +LL | fn foo6(s: &mut Vec) { + | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:44:29 + | +LL | fn mushroom(&self, vec: &mut Vec) -> usize { + | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:49:31 + | +LL | fn badger(&mut self, vec: &mut Vec) -> usize { + | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + +error: aborting due to 4 previous errors + From c62c7fadac19354ca24c79fc9b9fb0e747a11505 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 15 Jun 2023 17:24:39 +0200 Subject: [PATCH 30/80] Update UI tests with new `needless_pass_by_ref_mut` lint --- tests/ui-toml/toml_trivially_copy/test.rs | 1 + tests/ui-toml/toml_trivially_copy/test.stderr | 4 +- tests/ui/borrow_box.rs | 6 ++- tests/ui/borrow_box.stderr | 20 ++++---- tests/ui/infinite_loop.stderr | 10 +++- tests/ui/let_underscore_future.stderr | 10 +++- tests/ui/must_use_candidates.fixed | 7 ++- tests/ui/must_use_candidates.rs | 7 ++- tests/ui/must_use_candidates.stderr | 10 ++-- tests/ui/mut_from_ref.rs | 2 +- tests/ui/mut_key.stderr | 10 +++- tests/ui/mut_mut.rs | 7 ++- tests/ui/mut_mut.stderr | 18 ++++---- tests/ui/mut_reference.stderr | 16 ++++++- tests/ui/ptr_arg.rs | 3 +- tests/ui/ptr_arg.stderr | 46 +++++++++---------- tests/ui/read_zero_byte_vec.rs | 2 +- tests/ui/self_assignment.rs | 2 +- .../ui/should_impl_trait/method_list_2.stderr | 10 +++- tests/ui/slow_vector_initialization.stderr | 10 +++- tests/ui/trivially_copy_pass_by_ref.rs | 3 +- tests/ui/trivially_copy_pass_by_ref.stderr | 36 +++++++-------- tests/ui/unused_io_amount.rs | 2 +- tests/ui/useless_asref.fixed | 6 ++- tests/ui/useless_asref.rs | 6 ++- tests/ui/useless_asref.stderr | 22 ++++----- 26 files changed, 180 insertions(+), 96 deletions(-) diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index f267a67f40ee5..78784bfff0fd0 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -2,6 +2,7 @@ //@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" #![warn(clippy::trivially_copy_pass_by_ref)] +#![allow(clippy::needless_pass_by_ref_mut)] #[derive(Copy, Clone)] struct Foo(u8); diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index d2b55eff16dbf..db5d6805362de 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,5 +1,5 @@ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/test.rs:14:11 + --> $DIR/test.rs:15:11 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` @@ -7,7 +7,7 @@ LL | fn bad(x: &u16, y: &Foo) {} = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/test.rs:14:20 + --> $DIR/test.rs:15:20 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `Foo` diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index 3b5b6bf4c9502..95b6b0f50383a 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,6 +1,10 @@ #![deny(clippy::borrowed_box)] #![allow(dead_code, unused_variables)] -#![allow(clippy::uninlined_format_args, clippy::disallowed_names)] +#![allow( + clippy::uninlined_format_args, + clippy::disallowed_names, + clippy::needless_pass_by_ref_mut +)] use std::fmt::Display; diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 99cb60a1ead9b..90e752211ff05 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:20:14 + --> $DIR/borrow_box.rs:24:14 | LL | let foo: &Box; | ^^^^^^^^^^ help: try: `&bool` @@ -11,55 +11,55 @@ LL | #![deny(clippy::borrowed_box)] | ^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:24:10 + --> $DIR/borrow_box.rs:28:10 | LL | foo: &'a Box, | ^^^^^^^^^^^^^ help: try: `&'a bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:28:17 + --> $DIR/borrow_box.rs:32:17 | LL | fn test4(a: &Box); | ^^^^^^^^^^ help: try: `&bool` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:94:25 + --> $DIR/borrow_box.rs:98:25 | LL | pub fn test14(_display: &Box) {} | ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:95:25 + --> $DIR/borrow_box.rs:99:25 | LL | pub fn test15(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:96:29 + --> $DIR/borrow_box.rs:100:29 | LL | pub fn test16<'a>(_display: &'a Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:98:25 + --> $DIR/borrow_box.rs:102:25 | LL | pub fn test17(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:99:25 + --> $DIR/borrow_box.rs:103:25 | LL | pub fn test18(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:100:29 + --> $DIR/borrow_box.rs:104:29 | LL | pub fn test19<'a>(_display: &'a Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> $DIR/borrow_box.rs:105:25 + --> $DIR/borrow_box.rs:109:25 | LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)` diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 85258b9d64f94..701b3cd190410 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,3 +1,11 @@ +error: this argument is a mutable reference, but not used mutably + --> $DIR/infinite_loop.rs:7:17 + | +LL | fn fn_mutref(i: &mut i32) { + | ^^^^^^^^ help: consider changing to: `&i32` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + error: variables in the condition are not mutated in the loop body --> $DIR/infinite_loop.rs:20:11 | @@ -91,5 +99,5 @@ LL | while y < 10 { = note: this loop contains `return`s or `break`s = help: rewrite it as `if cond { loop { } }` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/let_underscore_future.stderr b/tests/ui/let_underscore_future.stderr index 33a748736a880..9e69fb0413309 100644 --- a/tests/ui/let_underscore_future.stderr +++ b/tests/ui/let_underscore_future.stderr @@ -1,3 +1,11 @@ +error: this argument is a mutable reference, but not used mutably + --> $DIR/let_underscore_future.rs:11:35 + | +LL | fn do_something_to_future(future: &mut impl Future) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&impl Future` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + error: non-binding `let` on a future --> $DIR/let_underscore_future.rs:14:5 | @@ -23,5 +31,5 @@ LL | let _ = future; | = help: consider awaiting the future or dropping explicitly with `std::mem::drop` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 0c275504d36b3..3ca20c07d9baf 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -1,6 +1,11 @@ //@run-rustfix #![feature(never_type)] -#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)] +#![allow( + unused_mut, + unused_tuple_struct_fields, + clippy::redundant_allocation, + clippy::needless_pass_by_ref_mut +)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index d1c9267732fa0..dc4e0118ec720 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -1,6 +1,11 @@ //@run-rustfix #![feature(never_type)] -#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)] +#![allow( + unused_mut, + unused_tuple_struct_fields, + clippy::redundant_allocation, + clippy::needless_pass_by_ref_mut +)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 0fa3849d03bff..5fb302ccbf14e 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -1,5 +1,5 @@ error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:12:1 + --> $DIR/must_use_candidates.rs:17:1 | LL | pub fn pure(i: u8) -> u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8` @@ -7,25 +7,25 @@ LL | pub fn pure(i: u8) -> u8 { = note: `-D clippy::must-use-candidate` implied by `-D warnings` error: this method could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:17:5 + --> $DIR/must_use_candidates.rs:22:5 | LL | pub fn inherent_pure(&self) -> u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:48:1 + --> $DIR/must_use_candidates.rs:53:1 | LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:60:1 + --> $DIR/must_use_candidates.rs:65:1 | LL | pub fn rcd(_x: Rc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc) -> bool` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:68:1 + --> $DIR/must_use_candidates.rs:73:1 | LL | pub fn arcd(_x: Arc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc) -> bool` diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 7de1533059470..8c0c23b657065 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,4 +1,4 @@ -#![allow(unused, clippy::needless_lifetimes)] +#![allow(unused, clippy::needless_lifetimes, clippy::needless_pass_by_ref_mut)] #![warn(clippy::mut_from_ref)] struct Foo; diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index 25dd029b16eee..fe1eeb31d07a1 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -12,6 +12,14 @@ error: mutable key type LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^ +error: this argument is a mutable reference, but not used mutably + --> $DIR/mut_key.rs:30:32 + | +LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&HashMap` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + error: mutable key type --> $DIR/mut_key.rs:31:5 | @@ -102,5 +110,5 @@ error: mutable key type LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index b721342836771..fe7d53e8e9991 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,7 +1,12 @@ //@aux-build:proc_macros.rs:proc-macro #![warn(clippy::mut_mut)] #![allow(unused)] -#![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)] +#![allow( + clippy::no_effect, + clippy::uninlined_format_args, + clippy::unnecessary_operation, + clippy::needless_pass_by_ref_mut +)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 93b857eb20748..58a1c4e683c96 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 - --> $DIR/mut_mut.rs:9:11 + --> $DIR/mut_mut.rs:14:11 | LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:26:17 + --> $DIR/mut_mut.rs:31:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:41:25 + --> $DIR/mut_mut.rs:46:25 | LL | let mut z = inline!(&mut $(&mut 3u32)); | ^ @@ -21,37 +21,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 - --> $DIR/mut_mut.rs:28:21 + --> $DIR/mut_mut.rs:33:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:32:32 + --> $DIR/mut_mut.rs:37:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:32:16 + --> $DIR/mut_mut.rs:37:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:37:37 + --> $DIR/mut_mut.rs:42:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:37:16 + --> $DIR/mut_mut.rs:42:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:37:21 + --> $DIR/mut_mut.rs:42:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 062d30b262c1b..23c812475c2af 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,3 +1,17 @@ +error: this argument is a mutable reference, but not used mutably + --> $DIR/mut_reference.rs:4:33 + | +LL | fn takes_a_mutable_reference(a: &mut i32) {} + | ^^^^^^^^ help: consider changing to: `&i32` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + +error: this argument is a mutable reference, but not used mutably + --> $DIR/mut_reference.rs:11:44 + | +LL | fn takes_a_mutable_reference(&self, a: &mut i32) {} + | ^^^^^^^^ help: consider changing to: `&i32` + error: the function `takes_an_immutable_reference` doesn't need a mutable reference --> $DIR/mut_reference.rs:17:34 | @@ -18,5 +32,5 @@ error: the method `takes_an_immutable_reference` doesn't need a mutable referenc LL | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 709f74ee6aa2a..13e993d247b2c 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -3,7 +3,8 @@ unused, clippy::many_single_char_names, clippy::needless_lifetimes, - clippy::redundant_clone + clippy::redundant_clone, + clippy::needless_pass_by_ref_mut )] #![warn(clippy::ptr_arg)] diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index d663b070b9cfd..0e9dd760f453a 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:13:14 + --> $DIR/ptr_arg.rs:14:14 | LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec) { = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:17:18 + --> $DIR/ptr_arg.rs:18:18 | LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:21:14 + --> $DIR/ptr_arg.rs:22:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:25:18 + --> $DIR/ptr_arg.rs:26:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:29:15 + --> $DIR/ptr_arg.rs:30:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:33:19 + --> $DIR/ptr_arg.rs:34:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:41:18 + --> $DIR/ptr_arg.rs:42:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:54:14 + --> $DIR/ptr_arg.rs:55:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -60,7 +60,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:63:18 + --> $DIR/ptr_arg.rs:64:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -76,7 +76,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:71:19 + --> $DIR/ptr_arg.rs:72:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:79:44 + --> $DIR/ptr_arg.rs:80:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -106,19 +106,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:93:25 + --> $DIR/ptr_arg.rs:94:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:122:66 + --> $DIR/ptr_arg.rs:123:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:151:21 + --> $DIR/ptr_arg.rs:152:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -131,7 +131,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:156:23 + --> $DIR/ptr_arg.rs:157:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -144,7 +144,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:161:21 + --> $DIR/ptr_arg.rs:162:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -157,43 +157,43 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:167:29 + --> $DIR/ptr_arg.rs:168:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:229:17 + --> $DIR/ptr_arg.rs:230:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:229:35 + --> $DIR/ptr_arg.rs:230:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:229:51 + --> $DIR/ptr_arg.rs:230:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:252:39 + --> $DIR/ptr_arg.rs:253:39 | LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { | ^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:257:36 + --> $DIR/ptr_arg.rs:258:36 | LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:260:40 + --> $DIR/ptr_arg.rs:261:40 | LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` diff --git a/tests/ui/read_zero_byte_vec.rs b/tests/ui/read_zero_byte_vec.rs index 30807e0f8b92f..c6025ef1f4da1 100644 --- a/tests/ui/read_zero_byte_vec.rs +++ b/tests/ui/read_zero_byte_vec.rs @@ -1,5 +1,5 @@ #![warn(clippy::read_zero_byte_vec)] -#![allow(clippy::unused_io_amount)] +#![allow(clippy::unused_io_amount, clippy::needless_pass_by_ref_mut)] use std::fs::File; use std::io; use std::io::prelude::*; diff --git a/tests/ui/self_assignment.rs b/tests/ui/self_assignment.rs index ec3ae12094254..d6682cc63dcf9 100644 --- a/tests/ui/self_assignment.rs +++ b/tests/ui/self_assignment.rs @@ -1,5 +1,5 @@ #![warn(clippy::self_assignment)] -#![allow(clippy::useless_vec)] +#![allow(clippy::useless_vec, clippy::needless_pass_by_ref_mut)] pub struct S<'a> { a: i32, diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr index 10bfea68ff572..e47cb209b8394 100644 --- a/tests/ui/should_impl_trait/method_list_2.stderr +++ b/tests/ui/should_impl_trait/method_list_2.stderr @@ -39,6 +39,14 @@ LL | | } | = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name +error: this argument is a mutable reference, but not used mutably + --> $DIR/method_list_2.rs:38:31 + | +LL | pub fn hash(&self, state: &mut T) { + | ^^^^^^ help: consider changing to: `&T` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + error: method `index` can be confused for the standard trait method `std::ops::Index::index` --> $DIR/method_list_2.rs:42:5 | @@ -149,5 +157,5 @@ LL | | } | = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index cb3ce3e95a7af..22376680a8e6b 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -72,5 +72,13 @@ LL | vec1 = Vec::with_capacity(10); LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: this argument is a mutable reference, but not used mutably + --> $DIR/slow_vector_initialization.rs:62:18 + | +LL | fn do_stuff(vec: &mut [u8]) {} + | ^^^^^^^^^ help: consider changing to: `&[u8]` + | + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + +error: aborting due to 10 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 486155831561d..86f5cc937f445 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -5,7 +5,8 @@ clippy::disallowed_names, clippy::needless_lifetimes, clippy::redundant_field_names, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::needless_pass_by_ref_mut )] #[derive(Copy, Clone)] diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 8c5cfa8a0f17c..2af668537f5c3 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,5 +1,5 @@ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:51:11 + --> $DIR/trivially_copy_pass_by_ref.rs:52:11 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` @@ -11,103 +11,103 @@ LL | #![deny(clippy::trivially_copy_pass_by_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:51:20 + --> $DIR/trivially_copy_pass_by_ref.rs:52:20 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:51:29 + --> $DIR/trivially_copy_pass_by_ref.rs:52:29 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:58:12 + --> $DIR/trivially_copy_pass_by_ref.rs:59:12 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:58:22 + --> $DIR/trivially_copy_pass_by_ref.rs:59:22 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:58:31 + --> $DIR/trivially_copy_pass_by_ref.rs:59:31 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:58:40 + --> $DIR/trivially_copy_pass_by_ref.rs:59:40 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:60:16 + --> $DIR/trivially_copy_pass_by_ref.rs:61:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:60:25 + --> $DIR/trivially_copy_pass_by_ref.rs:61:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:60:34 + --> $DIR/trivially_copy_pass_by_ref.rs:61:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:62:35 + --> $DIR/trivially_copy_pass_by_ref.rs:63:35 | LL | fn bad_issue7518(self, other: &Self) {} | ^^^^^ help: consider passing by value instead: `Self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:74:16 + --> $DIR/trivially_copy_pass_by_ref.rs:75:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:74:25 + --> $DIR/trivially_copy_pass_by_ref.rs:75:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:74:34 + --> $DIR/trivially_copy_pass_by_ref.rs:75:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:78:34 + --> $DIR/trivially_copy_pass_by_ref.rs:79:34 | LL | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:110:21 + --> $DIR/trivially_copy_pass_by_ref.rs:111:21 | LL | fn foo_never(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:115:15 + --> $DIR/trivially_copy_pass_by_ref.rs:116:15 | LL | fn foo(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:142:37 + --> $DIR/trivially_copy_pass_by_ref.rs:143:37 | LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { | ^^^^^^^ help: consider passing by value instead: `u32` diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 8d3e094b75967..e9d1eeb31612c 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +#![allow(dead_code, clippy::needless_pass_by_ref_mut)] #![warn(clippy::unused_io_amount)] extern crate futures; diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index 490d36ae6d692..e42731f9bcf61 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -1,6 +1,10 @@ //@run-rustfix #![deny(clippy::useless_asref)] -#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)] +#![allow( + clippy::explicit_auto_deref, + clippy::uninlined_format_args, + clippy::needless_pass_by_ref_mut +)] use std::fmt::Debug; diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index f2681af924da4..50c9990bb045d 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,6 +1,10 @@ //@run-rustfix #![deny(clippy::useless_asref)] -#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)] +#![allow( + clippy::explicit_auto_deref, + clippy::uninlined_format_args, + clippy::needless_pass_by_ref_mut +)] use std::fmt::Debug; diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 67ce8b64e0e3d..b6515e4fe0eea 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 - --> $DIR/useless_asref.rs:43:18 + --> $DIR/useless_asref.rs:47:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` @@ -11,61 +11,61 @@ LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:45:20 + --> $DIR/useless_asref.rs:49:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:49:21 + --> $DIR/useless_asref.rs:53:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:51:20 + --> $DIR/useless_asref.rs:55:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:58:20 + --> $DIR/useless_asref.rs:62:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:60:18 + --> $DIR/useless_asref.rs:64:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:65:21 + --> $DIR/useless_asref.rs:69:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:67:20 + --> $DIR/useless_asref.rs:71:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:71:16 + --> $DIR/useless_asref.rs:75:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:121:13 + --> $DIR/useless_asref.rs:125:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:123:12 + --> $DIR/useless_asref.rs:127:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` From dd3e00f102aa9773c10a645db37c3a10967f31cb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 15 Jun 2023 20:53:08 +0200 Subject: [PATCH 31/80] Fix warnings of `needless_pass_by_ref_mut` in clippy --- clippy_lints/src/literal_representation.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index dadcd9c5135c2..09ca0317337cf 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -264,7 +264,7 @@ impl LiteralDigitGrouping { return; } - if Self::is_literal_uuid_formatted(&mut num_lit) { + if Self::is_literal_uuid_formatted(&num_lit) { return; } @@ -376,7 +376,7 @@ impl LiteralDigitGrouping { /// /// Returns `true` if the radix is hexadecimal, and the groups match the /// UUID format of 8-4-4-4-12. - fn is_literal_uuid_formatted(num_lit: &mut NumericLiteral<'_>) -> bool { + fn is_literal_uuid_formatted(num_lit: &NumericLiteral<'_>) -> bool { if num_lit.radix != Radix::Hexadecimal { return false; } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 9f6917c146f63..d562047cbf15b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -91,7 +91,7 @@ struct ExistingName { struct SimilarNamesLocalVisitor<'a, 'tcx> { names: Vec, cx: &'a EarlyContext<'tcx>, - lint: &'a NonExpressiveNames, + lint: NonExpressiveNames, /// A stack of scopes containing the single-character bindings in each scope. single_char_names: Vec>, @@ -365,7 +365,7 @@ impl EarlyLintPass for NonExpressiveNames { .. }) = item.kind { - do_check(self, cx, &item.attrs, &sig.decl, blk); + do_check(*self, cx, &item.attrs, &sig.decl, blk); } } @@ -380,12 +380,12 @@ impl EarlyLintPass for NonExpressiveNames { .. }) = item.kind { - do_check(self, cx, &item.attrs, &sig.decl, blk); + do_check(*self, cx, &item.attrs, &sig.decl, blk); } } } -fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { +fn do_check(lint: NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) { if !attrs.iter().any(|attr| attr.has_name(sym::test)) { let mut visitor = SimilarNamesLocalVisitor { names: Vec::new(), From 33adfcd327880f45fce08660c1bd70f83ce09f84 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Jul 2023 22:48:40 +0200 Subject: [PATCH 32/80] Add warning for `NEEDLESS_PASS_BY_REF_MUT` lint about the fact that it changes API --- clippy_lints/src/needless_pass_by_ref_mut.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index c5dc87cdfa888..d535963a1dc40 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -22,6 +22,9 @@ declare_clippy_lint! { /// ### What it does /// Check if a `&mut` function argument is actually used mutably. /// + /// Be careful if the function is publically reexported as it would break compatibility with + /// users of this function. + /// /// ### Why is this bad? /// Less `mut` means less fights with the borrow checker. It can also lead to more /// opportunities for parallelization. From 8fad54e8f942e545458c7f339f0444513c5fcb1e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 17 Jun 2023 01:41:11 +0200 Subject: [PATCH 33/80] new lint: `read_line_without_trim` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 34 +++++++++ .../src/methods/read_line_without_trim.rs | 74 +++++++++++++++++++ tests/ui/read_line_without_trim.fixed | 19 +++++ tests/ui/read_line_without_trim.rs | 19 +++++ tests/ui/read_line_without_trim.stderr | 31 ++++++++ 7 files changed, 179 insertions(+) create mode 100644 clippy_lints/src/methods/read_line_without_trim.rs create mode 100644 tests/ui/read_line_without_trim.fixed create mode 100644 tests/ui/read_line_without_trim.rs create mode 100644 tests/ui/read_line_without_trim.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index f9310b4ab31fa..e2004c2931d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5134,6 +5134,7 @@ Released 2018-09-13 [`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer [`rc_clone_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_clone_in_vec_init [`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex +[`read_line_without_trim`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_line_without_trim [`read_zero_byte_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_zero_byte_vec [`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index e1dbe5003965f..ca97db040792c 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -389,6 +389,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::OR_THEN_UNWRAP_INFO, crate::methods::PATH_BUF_PUSH_OVERWRITE_INFO, crate::methods::RANGE_ZIP_WITH_LEN_INFO, + crate::methods::READ_LINE_WITHOUT_TRIM_INFO, crate::methods::REPEAT_ONCE_INFO, crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO, crate::methods::SEARCH_IS_SOME_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ab97cf0e53dcd..c99f7c1fdd9fd 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -72,6 +72,7 @@ mod or_fun_call; mod or_then_unwrap; mod path_buf_push_overwrite; mod range_zip_with_len; +mod read_line_without_trim; mod repeat_once; mod search_is_some; mod seek_from_current; @@ -3348,6 +3349,35 @@ declare_clippy_lint! { "checks for usage of `Iterator::fold` with a type that implements `Try`" } +declare_clippy_lint! { + /// Looks for calls to [`Stdin::read_line`] to read a line from the standard input + /// into a string, then later attempting to parse this string into a type without first trimming it, which will + /// always fail because the string has a trailing newline in it. + /// + /// ### Why is this bad? + /// The `.parse()` call will always fail. + /// + /// ### Example + /// ```rust,ignore + /// let mut input = String::new(); + /// std::io::stdin().read_line(&mut input).expect("Failed to read a line"); + /// let num: i32 = input.parse().expect("Not a number!"); + /// assert_eq!(num, 42); // we never even get here! + /// ``` + /// Use instead: + /// ```rust,ignore + /// let mut input = String::new(); + /// std::io::stdin().read_line(&mut input).expect("Failed to read a line"); + /// let num: i32 = input.trim_end().parse().expect("Not a number!"); + /// // ^^^^^^^^^^^ remove the trailing newline + /// assert_eq!(num, 42); + /// ``` + #[clippy::version = "1.72.0"] + pub READ_LINE_WITHOUT_TRIM, + correctness, + "calling `Stdin::read_line`, then trying to parse it without first trimming" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3468,6 +3498,7 @@ impl_lint_pass!(Methods => [ REPEAT_ONCE, STABLE_SORT_PRIMITIVE, UNIT_HASH, + READ_LINE_WITHOUT_TRIM, UNNECESSARY_SORT_BY, VEC_RESIZE_TO_ZERO, VERBOSE_FILE_READS, @@ -3879,6 +3910,9 @@ impl Methods { ("read_to_string", [_]) => { verbose_file_reads::check(cx, expr, recv, verbose_file_reads::READ_TO_STRING_MSG); }, + ("read_line", [arg]) => { + read_line_without_trim::check(cx, expr, recv, arg); + } ("repeat", [arg]) => { repeat_once::check(cx, expr, recv, arg); }, diff --git a/clippy_lints/src/methods/read_line_without_trim.rs b/clippy_lints/src/methods/read_line_without_trim.rs new file mode 100644 index 0000000000000..49e4f1acaa6f6 --- /dev/null +++ b/clippy_lints/src/methods/read_line_without_trim.rs @@ -0,0 +1,74 @@ +use std::ops::ControlFlow; + +use clippy_utils::{ + diagnostics::span_lint_and_then, get_parent_expr, match_def_path, source::snippet, ty::is_type_diagnostic_item, + visitors::for_each_local_use_after_expr, +}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_hir::QPath; +use rustc_hir::{def::Res, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; +use rustc_span::sym; + +use super::READ_LINE_WITHOUT_TRIM; + +/// Will a `.parse::()` call fail if the input has a trailing newline? +fn parse_fails_on_trailing_newline(ty: Ty<'_>) -> bool { + // only allow a very limited set of types for now, for which we 100% know parsing will fail + matches!(ty.kind(), ty::Float(_) | ty::Bool | ty::Int(_) | ty::Uint(_)) +} + +pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { + if let Some(recv_adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() + && match_def_path(cx, recv_adt.did(), &["std", "io", "stdio", "Stdin"]) + && let ExprKind::Path(QPath::Resolved(_, path)) = arg.peel_borrows().kind + && let Res::Local(local_id) = path.res + { + // We've checked that `call` is a call to `Stdin::read_line()` with the right receiver, + // now let's check if the first use of the string passed to `::read_line()` is + // parsed into a type that will always fail if it has a trailing newline. + for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| { + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(segment, .., span) = parent.kind + && segment.ident.name == sym!(parse) + && let parse_result_ty = cx.typeck_results().expr_ty(parent) + && is_type_diagnostic_item(cx, parse_result_ty, sym::Result) + && let ty::Adt(_, substs) = parse_result_ty.kind() + && let Some(ok_ty) = substs[0].as_type() + && parse_fails_on_trailing_newline(ok_ty) + { + let local_snippet = snippet(cx, expr.span, ""); + span_lint_and_then( + cx, + READ_LINE_WITHOUT_TRIM, + span, + "calling `.parse()` without trimming the trailing newline character", + |diag| { + diag.span_note(call.span, "call to `.read_line()` here, \ + which leaves a trailing newline character in the buffer, \ + which in turn will cause `.parse()` to fail"); + + diag.span_suggestion( + expr.span, + "try", + format!("{local_snippet}.trim_end()"), + Applicability::MachineApplicable, + ); + } + ); + } + + // only consider the first use to prevent this scenario: + // ``` + // let mut s = String::new(); + // std::io::stdin().read_line(&mut s); + // s.pop(); + // let _x: i32 = s.parse().unwrap(); + // ``` + // this is actually fine, because the pop call removes the trailing newline. + ControlFlow::<(), ()>::Break(()) + }); + } +} diff --git a/tests/ui/read_line_without_trim.fixed b/tests/ui/read_line_without_trim.fixed new file mode 100644 index 0000000000000..5995c8f523e25 --- /dev/null +++ b/tests/ui/read_line_without_trim.fixed @@ -0,0 +1,19 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::read_line_without_trim)] + +fn main() { + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + input.pop(); + let _x: i32 = input.parse().unwrap(); // don't trigger here, newline character is popped + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x: i32 = input.trim_end().parse().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.trim_end().parse::().unwrap(); +} diff --git a/tests/ui/read_line_without_trim.rs b/tests/ui/read_line_without_trim.rs new file mode 100644 index 0000000000000..84527b624b683 --- /dev/null +++ b/tests/ui/read_line_without_trim.rs @@ -0,0 +1,19 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::read_line_without_trim)] + +fn main() { + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + input.pop(); + let _x: i32 = input.parse().unwrap(); // don't trigger here, newline character is popped + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x: i32 = input.parse().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.parse::().unwrap(); +} diff --git a/tests/ui/read_line_without_trim.stderr b/tests/ui/read_line_without_trim.stderr new file mode 100644 index 0000000000000..f0f7a61e9ffa0 --- /dev/null +++ b/tests/ui/read_line_without_trim.stderr @@ -0,0 +1,31 @@ +error: calling `.parse()` without trimming the trailing newline character + --> $DIR/read_line_without_trim.rs:14:25 + | +LL | let _x: i32 = input.parse().unwrap(); + | ----- ^^^^^^^ + | | + | help: try: `input.trim_end()` + | +note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause `.parse()` to fail + --> $DIR/read_line_without_trim.rs:13:5 + | +LL | std::io::stdin().read_line(&mut input).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::read-line-without-trim` implied by `-D warnings` + +error: calling `.parse()` without trimming the trailing newline character + --> $DIR/read_line_without_trim.rs:18:20 + | +LL | let _x = input.parse::().unwrap(); + | ----- ^^^^^^^^^^^^^^ + | | + | help: try: `input.trim_end()` + | +note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause `.parse()` to fail + --> $DIR/read_line_without_trim.rs:17:5 + | +LL | std::io::stdin().read_line(&mut input).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 85f535b25f58a58de561216aa4e8378ad0b56391 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:50:41 +0200 Subject: [PATCH 34/80] add test cases for u32, f32, bool, String --- tests/ui/read_line_without_trim.fixed | 17 ++++++++++ tests/ui/read_line_without_trim.rs | 17 ++++++++++ tests/ui/read_line_without_trim.stderr | 44 +++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/tests/ui/read_line_without_trim.fixed b/tests/ui/read_line_without_trim.fixed index 5995c8f523e25..cb6aab84e49a8 100644 --- a/tests/ui/read_line_without_trim.fixed +++ b/tests/ui/read_line_without_trim.fixed @@ -16,4 +16,21 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.trim_end().parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.trim_end().parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.trim_end().parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.trim_end().parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + // this is actually ok, so don't lint here + let _x = input.parse::().unwrap(); } diff --git a/tests/ui/read_line_without_trim.rs b/tests/ui/read_line_without_trim.rs index 84527b624b683..bdc409a701065 100644 --- a/tests/ui/read_line_without_trim.rs +++ b/tests/ui/read_line_without_trim.rs @@ -16,4 +16,21 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let _x = input.parse::().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + // this is actually ok, so don't lint here + let _x = input.parse::().unwrap(); } diff --git a/tests/ui/read_line_without_trim.stderr b/tests/ui/read_line_without_trim.stderr index f0f7a61e9ffa0..f3d7b60425fbb 100644 --- a/tests/ui/read_line_without_trim.stderr +++ b/tests/ui/read_line_without_trim.stderr @@ -27,5 +27,47 @@ note: call to `.read_line()` here, which leaves a trailing newline character in LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: calling `.parse()` without trimming the trailing newline character + --> $DIR/read_line_without_trim.rs:22:20 + | +LL | let _x = input.parse::().unwrap(); + | ----- ^^^^^^^^^^^^^^ + | | + | help: try: `input.trim_end()` + | +note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause `.parse()` to fail + --> $DIR/read_line_without_trim.rs:21:5 + | +LL | std::io::stdin().read_line(&mut input).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: calling `.parse()` without trimming the trailing newline character + --> $DIR/read_line_without_trim.rs:26:20 + | +LL | let _x = input.parse::().unwrap(); + | ----- ^^^^^^^^^^^^^^ + | | + | help: try: `input.trim_end()` + | +note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause `.parse()` to fail + --> $DIR/read_line_without_trim.rs:25:5 + | +LL | std::io::stdin().read_line(&mut input).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: calling `.parse()` without trimming the trailing newline character + --> $DIR/read_line_without_trim.rs:30:20 + | +LL | let _x = input.parse::().unwrap(); + | ----- ^^^^^^^^^^^^^^^ + | | + | help: try: `input.trim_end()` + | +note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause `.parse()` to fail + --> $DIR/read_line_without_trim.rs:29:5 + | +LL | std::io::stdin().read_line(&mut input).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors From f048f73251309075c558f078538682c2e52b01a3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 4 Jul 2023 20:35:23 +0200 Subject: [PATCH 35/80] Add warning about semver compatibility if it's a public function --- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 61 ++++++++++++++----- .../ui/should_impl_trait/method_list_2.stderr | 1 + 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1e4a83b031bc..040ed1a8619ae 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1058,7 +1058,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); - store.register_late_pass(|_| Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut)); + store.register_late_pass(move |_| { + Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut::new( + avoid_breaking_exported_api, + )) + }); store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls)); store.register_late_pass(move |_| { Box::new(single_call_fn::SingleCallFn { diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index d535963a1dc40..96cb09c071ace 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -1,5 +1,5 @@ use super::needless_pass_by_value::requires_exact_signature; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::{is_from_proc_macro, is_self}; use if_chain::if_chain; @@ -12,7 +12,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; use rustc_span::Span; @@ -46,7 +46,21 @@ declare_clippy_lint! { suspicious, "using a `&mut` argument when it's not mutated" } -declare_lint_pass!(NeedlessPassByRefMut => [NEEDLESS_PASS_BY_REF_MUT]); + +#[derive(Copy, Clone)] +pub struct NeedlessPassByRefMut { + avoid_breaking_exported_api: bool, +} + +impl NeedlessPassByRefMut { + pub fn new(avoid_breaking_exported_api: bool) -> Self { + Self { + avoid_breaking_exported_api, + } + } +} + +impl_lint_pass!(NeedlessPassByRefMut => [NEEDLESS_PASS_BY_REF_MUT]); fn should_skip<'tcx>( cx: &LateContext<'tcx>, @@ -134,26 +148,45 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut { ctx }; - for ((&input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(body.params) { - if should_skip(cx, input, ty, arg) { - continue; - } - + let mut it = decl + .inputs + .iter() + .zip(fn_sig.inputs()) + .zip(body.params) + .filter(|((&input, &ty), arg)| !should_skip(cx, input, ty, arg)) + .peekable(); + if it.peek().is_none() { + return; + } + let show_semver_warning = self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(fn_def_id); + for ((&input, &_), arg) in it { // Only take `&mut` arguments. if_chain! { if let PatKind::Binding(_, canonical_id, ..) = arg.pat.kind; if !mutably_used_vars.contains(&canonical_id); if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind; then { - // If the argument is never used mutably, we emit the error. - span_lint_and_sugg( + // If the argument is never used mutably, we emit the warning. + let sp = input.span; + span_lint_and_then( cx, NEEDLESS_PASS_BY_REF_MUT, - input.span, + sp, "this argument is a mutable reference, but not used mutably", - "consider changing to", - format!("&{}", snippet(cx, cx.tcx.hir().span(inner_ty.ty.hir_id), "_")), - Applicability::Unspecified, + |diag| { + diag.span_suggestion( + sp, + "consider changing to".to_string(), + format!( + "&{}", + snippet(cx, cx.tcx.hir().span(inner_ty.ty.hir_id), "_"), + ), + Applicability::Unspecified, + ); + if show_semver_warning { + diag.warn("changing this function will impact semver compatibility"); + } + }, ); } } diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr index e47cb209b8394..2ae9fa34d142b 100644 --- a/tests/ui/should_impl_trait/method_list_2.stderr +++ b/tests/ui/should_impl_trait/method_list_2.stderr @@ -45,6 +45,7 @@ error: this argument is a mutable reference, but not used mutably LL | pub fn hash(&self, state: &mut T) { | ^^^^^^ help: consider changing to: `&T` | + = warning: changing this function will impact semver compatibility = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` error: method `index` can be confused for the standard trait method `std::ops::Index::index` From 406241832efef6efbf553a8ba332a6da37e19365 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jul 2023 15:41:45 +0100 Subject: [PATCH 36/80] Deal with fallout --- clippy_utils/src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index dd3cda8ec5277..1e1bb2a1d962f 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -689,7 +689,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) @@ -700,7 +700,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) From 6868c0a74bb1edeff8c078bb8b09994075e826cb Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:30:39 +0200 Subject: [PATCH 37/80] [`unnecessary_literal_unwrap`]: don't lint if binding initializer is expn --- clippy_lints/src/methods/unnecessary_literal_unwrap.rs | 5 +++++ tests/ui/unnecessary_literal_unwrap.fixed | 10 ++++++++++ tests/ui/unnecessary_literal_unwrap.rs | 10 ++++++++++ 3 files changed, 25 insertions(+) diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 7877f6a386cb3..ce93d7c3eb339 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -29,6 +29,11 @@ pub(super) fn check( args: &[hir::Expr<'_>], ) { let init = clippy_utils::expr_or_init(cx, recv); + if init.span.from_expansion() { + // don't lint if the receiver or binding initializer comes from a macro + // (e.g. `let x = option_env!(..); x.unwrap()`) + return; + } let (constructor, call_args, ty) = if let hir::ExprKind::Call(call, call_args) = init.kind { let Some(qpath) = call.qpath_opt() else { return }; diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 630a1bea3c879..092bf78feabec 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -68,6 +68,16 @@ fn unwrap_methods_result() { 1; } +fn unwrap_from_binding() { + macro_rules! from_macro { + () => { + Some("") + }; + } + let val = from_macro!(); + let _ = val.unwrap_or(""); +} + fn main() { unwrap_option_some(); unwrap_option_none(); diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 14f92cb370f6a..b9df893d1d2b9 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -68,6 +68,16 @@ fn unwrap_methods_result() { Ok::<_, ()>(1).unwrap_or_else(|_| 2); } +fn unwrap_from_binding() { + macro_rules! from_macro { + () => { + Some("") + }; + } + let val = from_macro!(); + let _ = val.unwrap_or(""); +} + fn main() { unwrap_option_some(); unwrap_option_none(); From a4f99149fce5ce1ea03a85f73d06d29ee7bd6d5e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Jul 2023 16:16:03 +0000 Subject: [PATCH 38/80] Patch clippy --- clippy_utils/src/consts.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index dd3cda8ec5277..b7f62af75b815 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -725,13 +725,14 @@ fn field_of_struct<'tcx>( result: mir::ConstantKind<'tcx>, field: &Ident, ) -> Option> { - if let Some(dc) = lcx.tcx.try_destructure_mir_constant(lcx.param_env.and(result)) + if let mir::ConstantKind::Val(result, ty) = result + && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty)) && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) - && let Some(dc_field) = dc.fields.get(field_idx) + && let Some(&(val, ty)) = dc.fields.get(field_idx) { - Some(*dc_field) + Some(mir::ConstantKind::Val(val, ty)) } else { None From f9453511701192ac391a42b37c1794621ece0f77 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Wed, 5 Jul 2023 18:04:10 +0000 Subject: [PATCH 39/80] Fix regex lints for regex 1.9.0 --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/regex.rs | 66 +++++++++++++++++++++++++++------------ clippy_utils/src/paths.rs | 12 +++---- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c43e0b753dc8d..00d46025caa86 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -722,7 +722,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef)); store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum)); store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); - store.register_late_pass(|_| Box::new(regex::Regex)); + store.register_late_pass(|_| Box::::default()); let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone()))); store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator)); diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 674f8bf4c0f30..b795e4b15bace 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -3,12 +3,12 @@ use std::fmt::Display; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::snippet_opt; -use clippy_utils::{match_def_path, paths}; -use if_chain::if_chain; +use clippy_utils::{def_path_def_ids, path_def_id, paths}; use rustc_ast::ast::{LitKind, StrStyle}; +use rustc_hir::def_id::DefIdMap; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, Span}; declare_clippy_lint! { @@ -55,26 +55,52 @@ declare_clippy_lint! { "trivial regular expressions" } -declare_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); +#[derive(Copy, Clone)] +enum RegexKind { + Unicode, + UnicodeSet, + Bytes, + BytesSet, +} + +#[derive(Default)] +pub struct Regex { + definitions: DefIdMap, +} + +impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); impl<'tcx> LateLintPass<'tcx> for Regex { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { + // We don't use `match_def_path` here because that relies on matching the exact path, which changed + // between regex 1.8 and 1.9 + // + // `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform + // the operation once and store the results + let mut resolve = |path, kind| { + for id in def_path_def_ids(cx, path) { + self.definitions.insert(id, kind); + } + }; + + resolve(&paths::REGEX_NEW, RegexKind::Unicode); + resolve(&paths::REGEX_BUILDER_NEW, RegexKind::Unicode); + resolve(&paths::REGEX_SET_NEW, RegexKind::UnicodeSet); + resolve(&paths::REGEX_BYTES_NEW, RegexKind::Bytes); + resolve(&paths::REGEX_BYTES_BUILDER_NEW, RegexKind::Bytes); + resolve(&paths::REGEX_BYTES_SET_NEW, RegexKind::BytesSet); + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(fun, [arg]) = expr.kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - then { - if match_def_path(cx, def_id, &paths::REGEX_NEW) || - match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { - check_regex(cx, arg, true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) || - match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { - check_regex(cx, arg, false); - } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { - check_set(cx, arg, true); - } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { - check_set(cx, arg, false); - } + if let ExprKind::Call(fun, [arg]) = expr.kind + && let Some(def_id) = path_def_id(cx, fun) + && let Some(regex_kind) = self.definitions.get(&def_id) + { + match regex_kind { + RegexKind::Unicode => check_regex(cx, arg, true), + RegexKind::UnicodeSet => check_set(cx, arg, true), + RegexKind::Bytes => check_regex(cx, arg, false), + RegexKind::BytesSet => check_set(cx, arg, false), } } } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 0e6f01287b561..f3677e6f61417 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -94,12 +94,12 @@ pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"]; pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"]; -pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; -pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; -pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; -pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; -pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; +pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"]; +pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"]; +pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"]; +pub const REGEX_BYTES_SET_NEW: [&str; 4] = ["regex", "bytes", "RegexSet", "new"]; +pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"]; +pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; From cbe468222a068f59ba0dd9ac15d5f45eeda8b83e Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 5 Jul 2023 20:13:26 +0100 Subject: [PATCH 40/80] Move `TyCtxt::mk_x` to `Ty::new_x` where applicable --- clippy_lints/src/bool_assert_comparison.rs | 2 +- clippy_lints/src/loops/explicit_iter_loop.rs | 4 ++-- clippy_lints/src/methods/needless_collect.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 4 ++-- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/redundant_slicing.rs | 3 ++- clippy_lints/src/transmute/transmute_ptr_to_ptr.rs | 2 +- clippy_lints/src/transmute/transmute_ref_to_ref.rs | 4 ++-- clippy_lints/src/transmute/useless_transmute.rs | 2 +- clippy_utils/src/ty.rs | 4 ++-- 11 files changed, 18 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs index 8c3ad24eeed43..e8775b0814448 100644 --- a/clippy_lints/src/bool_assert_comparison.rs +++ b/clippy_lints/src/bool_assert_comparison.rs @@ -61,7 +61,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - ) }) .map_or(false, |assoc_item| { - let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, [])); + let proj = Ty::new_projection(cx.tcx,assoc_item.def_id, cx.tcx.mk_substs_trait(ty, [])); let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); nty.is_bool() diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index f3347e33077b7..5c5a4cfce8844 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -149,7 +149,7 @@ fn is_ref_iterable<'tcx>( let self_ty = if mutbl.is_mut() { self_ty } else { - cx.tcx.mk_ref(region, TypeAndMut { ty, mutbl }) + Ty::new_ref(cx.tcx,region, TypeAndMut { ty, mutbl }) }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = @@ -164,7 +164,7 @@ fn is_ref_iterable<'tcx>( && !self_ty.is_ref() { // Attempt to borrow - let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut { + let self_ty = Ty::new_ref(cx.tcx,cx.tcx.lifetimes.re_erased, TypeAndMut { ty: self_ty, mutbl, }); diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index ac209d014062e..8ca7af8107f67 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -215,7 +215,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( cx.param_env, - cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs) + Ty::new_projection(cx.tcx,into_iter_item_proj.def_id, into_iter_item_proj.substs) ) { iter_item_ty == into_iter_item_ty @@ -238,7 +238,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - .associated_items(iter_trait) .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait) && let substs = cx.tcx.mk_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) - && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs) + && let proj_ty = Ty::new_projection(cx.tcx,iter_item.def_id, substs) && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) { item_ty == EarlyBinder::bind(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id)) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 16ef24bd4e345..6bd5e9e88c846 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -270,7 +270,7 @@ fn check_other_call_arg<'tcx>( if 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, cx.tcx.mk_ref( + Some((1, Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, ty::TypeAndMut { ty: receiver_ty, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ece10474715f2..f11d5773d0413 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -17,7 +17,7 @@ use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, TypeVisitableExt}; +use rustc_middle::ty::{self, TypeVisitableExt, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; @@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| cx.tcx.is_diagnostic_item(sym::Borrow, t.def_id())), !preds.is_empty() && { - let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_erased, ty); + let ty_empty_region = Ty::new_imm_ref(cx.tcx,cx.tcx.lifetimes.re_erased, ty); preds.iter().all(|t| { let ty_params = t.trait_ref.substs.iter().skip(1).collect::>(); implements_trait(cx, ty_empty_region, t.def_id(), &ty_params) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 866a04466c909..32213718b270d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -389,11 +389,11 @@ impl<'tcx> DerefTy<'tcx> { fn ty(&self, cx: &LateContext<'tcx>) -> Ty<'tcx> { match *self { Self::Str => cx.tcx.types.str_, - Self::Path => cx.tcx.mk_adt( + Self::Path => Ty::new_adt(cx.tcx, cx.tcx.adt_def(cx.tcx.get_diagnostic_item(sym::Path).unwrap()), List::empty(), ), - Self::Slice(_, ty) => cx.tcx.mk_slice(ty), + Self::Slice(_, ty) => Ty::new_slice(cx.tcx,ty), } } diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index 2fdd775ad4893..c70ce83a9c45d 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -7,6 +7,7 @@ use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; +use rustc_middle::ty::Ty; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::subst::GenericArg; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -134,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( cx.param_env, - cx.tcx.mk_projection(target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])), + Ty::new_projection(cx.tcx,target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 31a9b69ca1583..857d2ad825888 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -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(cx.tcx.mk_ptr(*to_ty)); + let sugg = arg.as_ty(Ty::new_ptr(cx.tcx,*to_ty)); diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); } }, diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 426c7253806e3..ea9ad99618abc 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -64,8 +64,8 @@ pub(super) fn check<'tcx>( }; let ty_to_and_mut = ty::TypeAndMut { ty: *ty_to, mutbl: *to_mutbl }; let sugg_paren = arg - .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) - .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + .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 { sugg_paren.mut_addr_deref() } else { diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs index 56207fe767c57..b6615410e257f 100644 --- a/clippy_lints/src/transmute/useless_transmute.rs +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>( let sugg = if *ptr_ty == rty_and_mut { arg.as_ty(to_ty) } else { - arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) + arg.as_ty(Ty::new_ptr(cx.tcx,rty_and_mut)).as_ty(to_ty) }; diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 9c39d22c61b2a..d650cbe0b1329 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -1124,7 +1124,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) { + match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection(tcx,ty.def_id, ty.substs)) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1207,7 +1207,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( .infer_ctxt() .build() .at(&cause, param_env) - .query_normalize(tcx.mk_projection(ty.def_id, ty.substs)) + .query_normalize(Ty::new_projection(tcx,ty.def_id, ty.substs)) { Ok(ty) => Some(ty.value), Err(e) => { From f12edfdb53b13008dcff9eba2a3fd9a19370d2ee Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:31:08 -0500 Subject: [PATCH 41/80] `manual_float_methods` --- CHANGELOG.md | 2 + clippy_lints/src/declared_lints.rs | 2 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/manual_float_methods.rs | 106 +++++++++++++++++++++++ clippy_utils/src/consts.rs | 11 +++ tests/ui/manual_float_methods.fixed | 37 ++++++++ tests/ui/manual_float_methods.rs | 37 ++++++++ tests/ui/manual_float_methods.stderr | 42 +++++++++ 8 files changed, 239 insertions(+) create mode 100644 clippy_lints/src/manual_float_methods.rs create mode 100644 tests/ui/manual_float_methods.fixed create mode 100644 tests/ui/manual_float_methods.rs create mode 100644 tests/ui/manual_float_methods.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index e2004c2931d56..59719080e440d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4941,6 +4941,8 @@ Released 2018-09-13 [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten [`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check +[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite +[`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index ca97db040792c..f8b8b94dd29a6 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -273,6 +273,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_async_fn::MANUAL_ASYNC_FN_INFO, crate::manual_bits::MANUAL_BITS_INFO, crate::manual_clamp::MANUAL_CLAMP_INFO, + crate::manual_float_methods::MANUAL_IS_FINITE_INFO, + crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO, crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 00d46025caa86..9abcbe01176d7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -184,6 +184,7 @@ mod manual_assert; mod manual_async_fn; mod manual_bits; mod manual_clamp; +mod manual_float_methods; mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; @@ -1073,6 +1074,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: 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() })); + store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs new file mode 100644 index 0000000000000..abf1eb788dd0b --- /dev/null +++ b/clippy_lints/src/manual_float_methods.rs @@ -0,0 +1,106 @@ +use clippy_utils::{ + consts::constant, diagnostics::span_lint_and_sugg, is_from_proc_macro, path_to_local, source::snippet_opt, +}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `x == ::INFINITY || x == ::NEG_INFINITY`. + /// + /// ### Why is this bad? + /// This should use the dedicated method instead, `is_infinite`. + /// + /// ### Example + /// ```rust + /// # let x = 1.0f32; + /// if x == f32::INFINITY || x == f32::NEG_INFINITY {} + /// ``` + /// Use instead: + /// ```rust + /// # let x = 1.0f32; + /// if x.is_infinite() {} + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_IS_INFINITE, + style, + "use dedicated method to check if a float is infinite" +} +declare_clippy_lint! { + /// ### What it does + /// Checks for `x != ::INFINITY && x != ::NEG_INFINITY`. + /// + /// ### Why is this bad? + /// This should use the dedicated method instead, `is_finite`. + /// + /// ### Example + /// ```rust + /// # let x = 1.0f32; + /// if x != f32::INFINITY && x != f32::NEG_INFINITY {} + /// ``` + /// Use instead: + /// ```rust + /// # let x = 1.0f32; + /// if x.is_finite() {} + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_IS_FINITE, + style, + "use dedicated method to check if a float is finite" +} +declare_lint_pass!(ManualFloatMethods => [MANUAL_IS_INFINITE, MANUAL_IS_FINITE]); + +impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if !in_external_macro(cx.sess(), expr.span) + && let ExprKind::Binary(kind, lhs, rhs) = expr.kind + && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind + && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind + && let (operands, consts) = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs] + .into_iter() + .partition::>, _>(|i| path_to_local(i).is_some()) + && let [first, second] = &*operands + && let Some([const_1, const_2]) = consts + .into_iter() + .map(|i| constant(cx, cx.typeck_results(), i).and_then(|c| c.to_bits())) + .collect::>>() + .as_deref() + && path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s)) + && (is_infinity(*const_1) && is_neg_infinity(*const_2) + || is_neg_infinity(*const_1) && is_infinity(*const_2)) + && let Some(local_snippet) = snippet_opt(cx, first.span) + && !is_from_proc_macro(cx, expr) + { + let (msg, lint, sugg_fn) = match (kind.node, lhs_kind.node, rhs_kind.node) { + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => { + ("manually checking if a float is infinite", MANUAL_IS_INFINITE, "is_infinite") + }, + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => { + ("manually checking if a float is finite", MANUAL_IS_FINITE, "is_finite") + }, + _ => return, + }; + + span_lint_and_sugg( + cx, + lint, + expr.span, + msg, + "try", + format!("{local_snippet}.{sugg_fn}()"), + Applicability::MachineApplicable, + ); + } + } +} + +fn is_infinity(bits: u128) -> bool { + bits == 0x7f80_0000 || bits == 0x7ff0_0000_0000_0000 +} + +fn is_neg_infinity(bits: u128) -> bool { + bits == 0xff80_0000 || bits == 0xfff0_0000_0000_0000 +} diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 87d85d742ce41..b9f8eefeb8e7c 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -190,6 +190,17 @@ impl<'tcx> Constant<'tcx> { } } + /// Returns the bit representation if `self` is a bool, integer, or float. + pub fn to_bits(&self) -> Option { + match self { + Constant::Int(int) => Some(*int), + Constant::F32(float) => Some(u128::from(float.to_bits())), + Constant::F64(float) => Some(u128::from(float.to_bits())), + Constant::Bool(bool) => Some(u128::from(*bool)), + _ => None, + } + } + /// Returns the integer value or `None` if `self` or `val_type` is not integer type. pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option { if let Constant::Int(const_int) = *self { diff --git a/tests/ui/manual_float_methods.fixed b/tests/ui/manual_float_methods.fixed new file mode 100644 index 0000000000000..87a23b5a75b7f --- /dev/null +++ b/tests/ui/manual_float_methods.fixed @@ -0,0 +1,37 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::needless_if, unused)] +#![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] + +#[macro_use] +extern crate proc_macros; + +const INFINITE: f32 = f32::INFINITY; +const NEG_INFINITE: f32 = f32::NEG_INFINITY; + +fn main() { + let x = 1.0f32; + if x.is_infinite() {} + if x.is_finite() {} + if x.is_infinite() {} + if x.is_finite() {} + let x = 1.0f64; + if x.is_infinite() {} + if x.is_finite() {} + // Don't lint + if x.is_infinite() {} + if x.is_finite() {} + // If they're doing it this way, they probably know what they're doing + if x.abs() < f64::INFINITY {} + external! { + let x = 1.0; + if x == f32::INFINITY || x == f32::NEG_INFINITY {} + if x != f32::INFINITY && x != f32::NEG_INFINITY {} + } + with_span! { + span + let x = 1.0; + if x == f32::INFINITY || x == f32::NEG_INFINITY {} + if x != f32::INFINITY && x != f32::NEG_INFINITY {} + } +} diff --git a/tests/ui/manual_float_methods.rs b/tests/ui/manual_float_methods.rs new file mode 100644 index 0000000000000..9255bf9341879 --- /dev/null +++ b/tests/ui/manual_float_methods.rs @@ -0,0 +1,37 @@ +//@run-rustfix +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::needless_if, unused)] +#![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] + +#[macro_use] +extern crate proc_macros; + +const INFINITE: f32 = f32::INFINITY; +const NEG_INFINITE: f32 = f32::NEG_INFINITY; + +fn main() { + let x = 1.0f32; + if x == f32::INFINITY || x == f32::NEG_INFINITY {} + if x != f32::INFINITY && x != f32::NEG_INFINITY {} + if x == INFINITE || x == NEG_INFINITE {} + if x != INFINITE && x != NEG_INFINITE {} + let x = 1.0f64; + if x == f64::INFINITY || x == f64::NEG_INFINITY {} + if x != f64::INFINITY && x != f64::NEG_INFINITY {} + // Don't lint + if x.is_infinite() {} + if x.is_finite() {} + // If they're doing it this way, they probably know what they're doing + if x.abs() < f64::INFINITY {} + external! { + let x = 1.0; + if x == f32::INFINITY || x == f32::NEG_INFINITY {} + if x != f32::INFINITY && x != f32::NEG_INFINITY {} + } + with_span! { + span + let x = 1.0; + if x == f32::INFINITY || x == f32::NEG_INFINITY {} + if x != f32::INFINITY && x != f32::NEG_INFINITY {} + } +} diff --git a/tests/ui/manual_float_methods.stderr b/tests/ui/manual_float_methods.stderr new file mode 100644 index 0000000000000..00227593a9eab --- /dev/null +++ b/tests/ui/manual_float_methods.stderr @@ -0,0 +1,42 @@ +error: manually checking if a float is infinite + --> $DIR/manual_float_methods.rs:14:8 + | +LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + | + = note: `-D clippy::manual-is-infinite` implied by `-D warnings` + +error: manually checking if a float is finite + --> $DIR/manual_float_methods.rs:15:8 + | +LL | if x != f32::INFINITY && x != f32::NEG_INFINITY {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + | + = note: `-D clippy::manual-is-finite` implied by `-D warnings` + +error: manually checking if a float is infinite + --> $DIR/manual_float_methods.rs:16:8 + | +LL | if x == INFINITE || x == NEG_INFINITE {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + +error: manually checking if a float is finite + --> $DIR/manual_float_methods.rs:17:8 + | +LL | if x != INFINITE && x != NEG_INFINITE {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + +error: manually checking if a float is infinite + --> $DIR/manual_float_methods.rs:19:8 + | +LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + +error: manually checking if a float is finite + --> $DIR/manual_float_methods.rs:20:8 + | +LL | if x != f64::INFINITY && x != f64::NEG_INFINITY {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + +error: aborting due to 6 previous errors + From 5949f762bfa15e62657771e556c160abe4caee8b Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sun, 2 Jul 2023 11:43:05 -0500 Subject: [PATCH 42/80] Make suggestion give multiple alternatives --- clippy_lints/src/manual_float_methods.rs | 82 +++++++++++++++++++----- tests/ui/manual_float_methods.fixed | 37 ----------- tests/ui/manual_float_methods.rs | 1 - tests/ui/manual_float_methods.stderr | 62 ++++++++++++++---- 4 files changed, 117 insertions(+), 65 deletions(-) delete mode 100644 tests/ui/manual_float_methods.fixed diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index abf1eb788dd0b..0f488627b4e93 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -1,9 +1,9 @@ use clippy_utils::{ - consts::constant, diagnostics::span_lint_and_sugg, is_from_proc_macro, path_to_local, source::snippet_opt, + consts::constant, diagnostics::span_lint_and_then, is_from_proc_macro, path_to_local, source::snippet_opt, }; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -53,12 +53,37 @@ declare_clippy_lint! { } declare_lint_pass!(ManualFloatMethods => [MANUAL_IS_INFINITE, MANUAL_IS_FINITE]); +#[derive(Clone, Copy)] +enum Variant { + ManualIsInfinite, + ManualIsFinite, +} + +impl Variant { + pub fn lint(self) -> &'static Lint { + match self { + Self::ManualIsInfinite => MANUAL_IS_INFINITE, + Self::ManualIsFinite => MANUAL_IS_FINITE, + } + } + + pub fn msg(self) -> &'static str { + match self { + Self::ManualIsInfinite => "manually checking if a float is infinite", + Self::ManualIsFinite => "manually checking if a float is finite", + } + } +} + impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if !in_external_macro(cx.sess(), expr.span) + && (!cx.param_env.is_const() || cx.tcx.features().active(sym!(const_float_classify))) && let ExprKind::Binary(kind, lhs, rhs) = expr.kind && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind + // Checking all possible scenarios using a function would be a hopeless task, as we have + // 16 possible alignments of constants/operands. For now, let's use `partition`. && let (operands, consts) = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs] .into_iter() .partition::>, _>(|i| path_to_local(i).is_some()) @@ -74,24 +99,51 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { && let Some(local_snippet) = snippet_opt(cx, first.span) && !is_from_proc_macro(cx, expr) { - let (msg, lint, sugg_fn) = match (kind.node, lhs_kind.node, rhs_kind.node) { - (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => { - ("manually checking if a float is infinite", MANUAL_IS_INFINITE, "is_infinite") - }, - (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => { - ("manually checking if a float is finite", MANUAL_IS_FINITE, "is_finite") - }, + let variant = match (kind.node, lhs_kind.node, rhs_kind.node) { + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite, + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => Variant::ManualIsFinite, _ => return, }; - span_lint_and_sugg( + span_lint_and_then( cx, - lint, + variant.lint(), expr.span, - msg, - "try", - format!("{local_snippet}.{sugg_fn}()"), - Applicability::MachineApplicable, + variant.msg(), + |diag| { + match variant { + Variant::ManualIsInfinite => { + diag.span_suggestion( + expr.span, + "use the dedicated method instead", + format!("{local_snippet}.is_infinite()"), + Applicability::MachineApplicable, + ); + }, + Variant::ManualIsFinite => { + // TODO: There's probably some better way to do this, i.e., create + // multiple suggestions with notes between each of them + diag.span_suggestion_verbose( + expr.span, + "use the dedicated method instead", + format!("{local_snippet}.is_finite()"), + Applicability::MaybeIncorrect, + ); + diag.span_suggestion_verbose( + expr.span, + "this will alter how it handles NaN; if that is a problem, use instead", + format!("{local_snippet}.is_finite() || {local_snippet}.is_nan()"), + Applicability::MaybeIncorrect, + ); + diag.span_suggestion_verbose( + expr.span, + "or, for conciseness", + format!("!{local_snippet}.is_infinite()"), + Applicability::MaybeIncorrect, + ); + } + } + } ); } } diff --git a/tests/ui/manual_float_methods.fixed b/tests/ui/manual_float_methods.fixed deleted file mode 100644 index 87a23b5a75b7f..0000000000000 --- a/tests/ui/manual_float_methods.fixed +++ /dev/null @@ -1,37 +0,0 @@ -//@run-rustfix -//@aux-build:proc_macros.rs:proc-macro -#![allow(clippy::needless_if, unused)] -#![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] - -#[macro_use] -extern crate proc_macros; - -const INFINITE: f32 = f32::INFINITY; -const NEG_INFINITE: f32 = f32::NEG_INFINITY; - -fn main() { - let x = 1.0f32; - if x.is_infinite() {} - if x.is_finite() {} - if x.is_infinite() {} - if x.is_finite() {} - let x = 1.0f64; - if x.is_infinite() {} - if x.is_finite() {} - // Don't lint - if x.is_infinite() {} - if x.is_finite() {} - // If they're doing it this way, they probably know what they're doing - if x.abs() < f64::INFINITY {} - external! { - let x = 1.0; - if x == f32::INFINITY || x == f32::NEG_INFINITY {} - if x != f32::INFINITY && x != f32::NEG_INFINITY {} - } - with_span! { - span - let x = 1.0; - if x == f32::INFINITY || x == f32::NEG_INFINITY {} - if x != f32::INFINITY && x != f32::NEG_INFINITY {} - } -} diff --git a/tests/ui/manual_float_methods.rs b/tests/ui/manual_float_methods.rs index 9255bf9341879..b772202c003f5 100644 --- a/tests/ui/manual_float_methods.rs +++ b/tests/ui/manual_float_methods.rs @@ -1,4 +1,3 @@ -//@run-rustfix //@aux-build:proc_macros.rs:proc-macro #![allow(clippy::needless_if, unused)] #![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] diff --git a/tests/ui/manual_float_methods.stderr b/tests/ui/manual_float_methods.stderr index 00227593a9eab..7f4a4d2e95b39 100644 --- a/tests/ui/manual_float_methods.stderr +++ b/tests/ui/manual_float_methods.stderr @@ -1,42 +1,80 @@ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:14:8 + --> $DIR/manual_float_methods.rs:13:8 | LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` | = note: `-D clippy::manual-is-infinite` implied by `-D warnings` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:15:8 + --> $DIR/manual_float_methods.rs:14:8 | LL | if x != f32::INFINITY && x != f32::NEG_INFINITY {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-is-finite` implied by `-D warnings` +help: use the dedicated method instead + | +LL | if x.is_finite() {} + | ~~~~~~~~~~~~~ +help: this will alter how it handles NaN; if that is a problem, use instead + | +LL | if x.is_finite() || x.is_nan() {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: or, for conciseness + | +LL | if !x.is_infinite() {} + | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:16:8 + --> $DIR/manual_float_methods.rs:15:8 | LL | if x == INFINITE || x == NEG_INFINITE {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:17:8 + --> $DIR/manual_float_methods.rs:16:8 | LL | if x != INFINITE && x != NEG_INFINITE {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the dedicated method instead + | +LL | if x.is_finite() {} + | ~~~~~~~~~~~~~ +help: this will alter how it handles NaN; if that is a problem, use instead + | +LL | if x.is_finite() || x.is_nan() {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: or, for conciseness + | +LL | if !x.is_infinite() {} + | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:19:8 + --> $DIR/manual_float_methods.rs:18:8 | LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_infinite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:20:8 + --> $DIR/manual_float_methods.rs:19:8 | LL | if x != f64::INFINITY && x != f64::NEG_INFINITY {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_finite()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the dedicated method instead + | +LL | if x.is_finite() {} + | ~~~~~~~~~~~~~ +help: this will alter how it handles NaN; if that is a problem, use instead + | +LL | if x.is_finite() || x.is_nan() {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: or, for conciseness + | +LL | if !x.is_infinite() {} + | ~~~~~~~~~~~~~~~~ error: aborting due to 6 previous errors From 4939a716e80214edd19dab6b678fce3e769388f5 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 4 Jul 2023 16:58:02 +0000 Subject: [PATCH 43/80] arc_with_non_send_sync: reword and move to suspicious --- clippy_lints/src/arc_with_non_send_sync.rs | 71 +++++++++++----------- tests/ui/arc_with_non_send_sync.rs | 12 ++-- tests/ui/arc_with_non_send_sync.stderr | 33 ++++++++-- 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 62313df9f90ec..98ee8a9a8806c 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -1,12 +1,11 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::last_path_segment; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use if_chain::if_chain; - use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_lint::LateLintPass; use rustc_middle::ty; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; @@ -16,8 +15,8 @@ declare_clippy_lint! { /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. /// /// ### Why is this bad? - /// Wrapping a type in Arc doesn't add thread safety to the underlying data, so data races - /// could occur when touching the underlying data. + /// `Arc` is only `Send`/`Sync` when `T` is [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E), + /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` /// /// ### Example /// ```rust @@ -25,16 +24,17 @@ declare_clippy_lint! { /// # use std::sync::Arc; /// /// fn main() { - /// // This is safe, as `i32` implements `Send` and `Sync`. + /// // This is fine, as `i32` implements `Send` and `Sync`. /// let a = Arc::new(42); /// - /// // This is not safe, as `RefCell` does not implement `Sync`. + /// // `RefCell` is `!Sync`, so either the `Arc` should be replaced with an `Rc` + /// // or the `RefCell` replaced with something like a `RwLock` /// let b = Arc::new(RefCell::new(42)); /// } /// ``` #[clippy::version = "1.72.0"] pub ARC_WITH_NON_SEND_SYNC, - correctness, + suspicious, "using `Arc` with a type that does not implement `Send` or `Sync`" } declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); @@ -42,35 +42,38 @@ declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); impl LateLintPass<'_> for ArcWithNonSendSync { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let ty = cx.typeck_results().expr_ty(expr); - if_chain! { - if is_type_diagnostic_item(cx, ty, sym::Arc); - if let ExprKind::Call(func, [arg]) = expr.kind; - if let ExprKind::Path(func_path) = func.kind; - if last_path_segment(&func_path).ident.name == sym::new; - if let arg_ty = cx.typeck_results().expr_ty(arg); + if is_type_diagnostic_item(cx, ty, sym::Arc) + && let ExprKind::Call(func, [arg]) = expr.kind + && let ExprKind::Path(func_path) = func.kind + && last_path_segment(&func_path).ident.name == sym::new + && let arg_ty = cx.typeck_results().expr_ty(arg) // make sure that the type is not and does not contain any type parameters - if arg_ty.walk().all(|arg| { + && arg_ty.walk().all(|arg| { !matches!(arg.unpack(), GenericArgKind::Type(ty) if matches!(ty.kind(), ty::Param(_))) - }); - if !cx.tcx - .lang_items() - .sync_trait() - .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])) || - !cx.tcx - .get_diagnostic_item(sym::Send) - .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])); + }) + && let Some(send) = cx.tcx.get_diagnostic_item(sym::Send) + && let Some(sync) = cx.tcx.lang_items().sync_trait() + && let [is_send, is_sync] = [send, sync].map(|id| implements_trait(cx, arg_ty, id, &[])) + && !(is_send && is_sync) + { + span_lint_and_then( + cx, + ARC_WITH_NON_SEND_SYNC, + expr.span, + "usage of an `Arc` that is not `Send` or `Sync`", + |diag| with_forced_trimmed_paths!({ + if !is_send { + diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`")); + } + if !is_sync { + diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`")); + } + + diag.note(format!("required for `{ty}` to implement `Send` and `Sync`")); - then { - span_lint_and_help( - cx, - ARC_WITH_NON_SEND_SYNC, - expr.span, - "usage of `Arc` where `T` is not `Send` or `Sync`", - None, - "consider using `Rc` instead or wrapping `T` in a std::sync type like \ - `Mutex`", - ); - } + diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`"); + } + )); } } } diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index 9d5849277c204..b6fcca0a7919e 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -12,9 +12,13 @@ fn issue11076() { } fn main() { - // This is safe, as `i32` implements `Send` and `Sync`. - let a = Arc::new(42); + let _ = Arc::new(42); - // This is not safe, as `RefCell` does not implement `Sync`. - let b = Arc::new(RefCell::new(42)); + // !Sync + let _ = Arc::new(RefCell::new(42)); + let mutex = Mutex::new(1); + // !Send + let _ = Arc::new(mutex.lock().unwrap()); + // !Send + !Sync + let _ = Arc::new(&42 as *const i32); } diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index 520c21b565ba5..7633b38dfb597 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -1,11 +1,34 @@ -error: usage of `Arc` where `T` is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:19:13 +error: usage of an `Arc` that is not `Send` or `Sync` + --> $DIR/arc_with_non_send_sync.rs:18:13 | -LL | let b = Arc::new(RefCell::new(42)); +LL | let _ = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider using `Rc` instead or wrapping `T` in a std::sync type like `Mutex` + = note: the trait `Sync` is not implemented for `RefCell` + = note: required for `Arc>` to implement `Send` and `Sync` + = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` -error: aborting due to previous error +error: usage of an `Arc` that is not `Send` or `Sync` + --> $DIR/arc_with_non_send_sync.rs:21:13 + | +LL | let _ = Arc::new(mutex.lock().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = note: required for `Arc>` to implement `Send` and `Sync` + = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` + +error: usage of an `Arc` that is not `Send` or `Sync` + --> $DIR/arc_with_non_send_sync.rs:23:13 + | +LL | let _ = Arc::new(&42 as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Send` is not implemented for `*const i32` + = note: the trait `Sync` is not implemented for `*const i32` + = note: required for `Arc<*const i32>` to implement `Send` and `Sync` + = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` + +error: aborting due to 3 previous errors From 28655266b5797292a23dc10027d37b4a598662d8 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 6 Jul 2023 14:43:21 +0000 Subject: [PATCH 44/80] Fix changelog PR listings, create them automatically in `fetch_prs_between.sh` --- CHANGELOG.md | 109 +++++++----------- .../infrastructure/changelog_update.md | 22 ---- util/fetch_prs_between.sh | 22 +++- 3 files changed, 60 insertions(+), 93 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2004c2931d56..da070adb8086f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ document. Current stable, released 2023-06-01 -[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) +[View all 91 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-02-26T01%3A05%3A43Z..2023-04-11T13%3A27%3A30Z+base%3Amaster) ### New Lints @@ -137,7 +137,7 @@ Current stable, released 2023-06-01 Released 2023-04-20 -[**View 86 PRs merged since 1.68**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-03-09..2023-04-20+base%3Amaster+sort%3Amerged-desc+) +[View all 72 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-01-13T06%3A12%3A46Z..2023-02-25T23%3A48%3A10Z+base%3Amaster) ### New Lints @@ -252,7 +252,7 @@ Released 2023-04-20 Released 2023-03-09 -[**View 85 PRs merged since 1.67**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-01-26..2023-03-09+base%3Amaster+sort%3Amerged-desc+) +[View all 76 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-12-01T20%3A40%3A04Z..2023-01-12T18%3A58%3A59Z+base%3Amaster) ### New Lints @@ -399,7 +399,7 @@ Released 2023-03-09 Released 2023-01-26 -[**View 68 PRs merged since 1.66**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-12-15..2023-01-26+base%3Amaster+sort%3Amerged-desc+) +[View all 104 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-10-23T13%3A35%3A19Z..2022-12-01T13%3A34%3A39Z+base%3Amaster) ### New Lints @@ -590,8 +590,7 @@ Released 2023-01-26 Released 2022-12-15 -[**View 93 PRs merged since 1.65**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-11-03..2022-12-15+base%3Amaster+sort%3Amerged-desc+) - +[View all 116 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-09-09T17%3A32%3A39Z..2022-10-23T11%3A27%3A24Z+base%3Amaster) ### New Lints @@ -762,8 +761,7 @@ Released 2022-12-15 Released 2022-11-03 -[**View 129 PRs merged since 1.64**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-09-22..2022-11-03+base%3Amaster+sort%3Amerged-desc+) - +[View all 86 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-07-29T01%3A09%3A31Z..2022-09-09T00%3A01%3A54Z+base%3Amaster) ### Important Changes @@ -907,8 +905,7 @@ Released 2022-11-03 Released 2022-09-22 -[**View 92 PRs merged since 1.63**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-08-11..2022-09-22+base%3Amaster+sort%3Amerged-desc+) - +[View all 110 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-06-17T21%3A25%3A31Z..2022-07-28T17%3A11%3A18Z+base%3Amaster) ### New Lints @@ -1058,8 +1055,7 @@ Released 2022-09-22 Released 2022-08-11 -[**View 100 PRs merged since 1.62**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-06-30..2022-08-11+base%3Amaster+sort%3Amerged-desc+) - +[View all 91 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-05-05T17%3A24%3A22Z..2022-06-16T14%3A24%3A48Z+base%3Amaster) ### New Lints @@ -1205,8 +1201,7 @@ Released 2022-08-11 Released 2022-06-30 -[**View 104 PRs merged since 1.61**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-05-19..2022-06-30+base%3Amaster+sort%3Amerged-desc+) - +[View all 90 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-03-25T17%3A22%3A30Z..2022-05-05T13%3A29%3A44Z+base%3Amaster) ### New Lints @@ -1363,8 +1358,7 @@ Released 2022-06-30 Released 2022-05-19 -[**View 93 PRs merged since 1.60**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-04-07..2022-05-19+base%3Amaster+sort%3Amerged-desc+) - +[View all 60 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2022-02-11T16%3A54%3A41Z..2022-03-24T13%3A42%3A25Z+base%3Amaster) ### New Lints @@ -1465,8 +1459,7 @@ Released 2022-05-19 Released 2022-04-07 -[**View 75 PRs merged since 1.59**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-02-24..2022-04-07+base%3Amaster+sort%3Amerged-desc+) - +[View all 73 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-12-31T17%3A53%3A37Z..2022-02-10T17%3A31%3A37Z+base%3Amaster) ### New Lints @@ -1598,8 +1591,7 @@ Released 2022-04-07 Released 2022-02-24 -[**View 63 PRs merged since 1.58**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-01-13..2022-02-24+base%3Amaster+sort%3Amerged-desc+) - +[View all 94 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-11-04T12%3A40%3A18Z..2021-12-30T13%3A36%3A20Z+base%3Amaster) ### New Lints @@ -1763,8 +1755,7 @@ Released 2022-02-24 Released 2022-01-13 -[**View 73 PRs merged since 1.57**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-12-02..2022-01-13+base%3Amaster+sort%3Amerged-desc+) - +[View all 68 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-10-07T09%3A49%3A18Z..2021-11-04T12%3A20%3A12Z+base%3Amaster) ### Rust 1.58.1 @@ -1885,8 +1876,7 @@ Released 2022-01-13 Released 2021-12-02 -[**View 92 PRs merged since 1.56**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-10-21..2021-12-02+base%3Amaster+sort%3Amerged-desc+) - +[View all 148 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-08-12T20%3A36%3A04Z..2021-11-03T17%3A57%3A59Z+base%3Amaster) ### New Lints @@ -2037,7 +2027,7 @@ Released 2021-12-02 Released 2021-10-21 -[**View 92 PRs merged since 1.55**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-09-09..2021-10-21+base%3Amaster+sort%3Amerged-desc+) +[View all 38 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-07-19T14%3A33%3A33Z..2021-08-12T09%3A28%3A38Z+base%3Amaster) ### New Lints @@ -2103,7 +2093,7 @@ Released 2021-10-21 Released 2021-09-09 -[**View 61 PRs merged since 1.54**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-07-29..2021-09-09+base%3Amaster+sort%3Amerged-desc+) +[View all 83 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-06-03T07%3A23%3A59Z..2021-07-29T11%3A47%3A32Z+base%3Amaster) ### Important Changes @@ -2221,8 +2211,7 @@ Released 2021-09-09 Released 2021-07-29 -[**View 68 PRs merged since 1.53**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-06-17..2021-07-29+base%3Amaster+sort%3Amerged-desc+) - +[View all 74 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-04-27T23%3A51%3A18Z..2021-06-03T06%3A54%3A07Z+base%3Amaster) ### New Lints @@ -2350,7 +2339,7 @@ Released 2021-07-29 Released 2021-06-17 -[**View 80 PRs merged since 1.52**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-05-06..2021-06-17+base%3Amaster+sort%3Amerged-desc+) +[View all 126 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-03-12T22%3A49%3A20Z..2021-04-27T14%3A38%3A20Z+base%3Amaster) ### New Lints @@ -2534,8 +2523,7 @@ Released 2021-06-17 Released 2021-05-06 -[**View 113 PRs merged since 1.51**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-03-25..2021-05-06+base%3Amaster+sort%3Amerged-desc+) - +[View all 102 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2021-02-03T15%3A59%3A06Z..2021-03-11T20%3A06%3A43Z+base%3Amaster) ### New Lints @@ -2670,8 +2658,7 @@ Released 2021-05-06 Released 2021-03-25 -[**View 117 PRs merged since 1.50**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-02-11..2021-03-25+base%3Amaster+sort%3Amerged-desc+) - +[View all 78 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-12-21T15%3A43%3A04Z..2021-02-03T04%3A21%3A10Z+base%3Amaster) ### New Lints @@ -2786,8 +2773,7 @@ Released 2021-03-25 Released 2021-02-11 -[**View 90 PRs merged since 1.49**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-12-31..2021-02-11+base%3Amaster+sort%3Amerged-desc+) - +[View all 119 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-11-06T18%3A32%3A40Z..2021-01-03T14%3A51%3A18Z+base%3Amaster) ### New Lints @@ -2916,8 +2902,7 @@ Released 2021-02-11 Released 2020-12-31 -[**View 85 PRs merged since 1.48**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-11-19..2020-12-31+base%3Amaster+sort%3Amerged-desc+) - +[View all 107 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-09-24T14%3A05%3A12Z..2020-11-05T13%3A35%3A44Z+base%3Amaster) ### New Lints @@ -3023,7 +3008,7 @@ Released 2020-12-31 Released 2020-11-19 -[**View 112 PRs merged since 1.47**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-10-08..2020-11-19+base%3Amaster+sort%3Amerged-desc+) +[View all 99 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-08-11T13%3A14%3A38Z..2020-09-23T18%3A55%3A22Z+base%3Amaster) ### New lints @@ -3141,8 +3126,7 @@ Released 2020-11-19 Released 2020-10-08 -[**View 80 PRs merged since 1.46**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-08-27..2020-10-08+base%3Amaster+sort%3Amerged-desc+) - +[View all 76 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-06-23T16%3A27%3A11Z..2020-08-11T12%3A52%3A41Z+base%3Amaster) ### New lints @@ -3244,8 +3228,7 @@ Released 2020-10-08 Released 2020-08-27 -[**View 93 PRs merged since 1.45**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-07-16..2020-08-27+base%3Amaster+sort%3Amerged-desc+) - +[View all 48 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-05-31T12%3A50%3A53Z..2020-06-23T15%3A00%3A32Z+base%3Amaster) ### New lints @@ -3307,8 +3290,7 @@ Released 2020-08-27 Released 2020-07-16 -[**View 65 PRs merged since 1.44**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-06-04..2020-07-16+base%3Amaster+sort%3Amerged-desc+) - +[View all 81 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-04-18T20%3A18%3A04Z..2020-05-27T19%3A25%3A04Z+base%3Amaster) ### New lints @@ -3385,8 +3367,7 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565 Released 2020-06-04 -[**View 88 PRs merged since 1.43**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-04-23..2020-06-04+base%3Amaster+sort%3Amerged-desc+) - +[View all 124 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-03-05T17%3A30%3A53Z..2020-04-18T09%3A20%3A51Z+base%3Amaster) ### New lints @@ -3469,8 +3450,7 @@ Released 2020-06-04 Released 2020-04-23 -[**View 121 PRs merged since 1.42**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-03-12..2020-04-23+base%3Amaster+sort%3Amerged-desc+) - +[View all 91 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2020-01-26T16%3A01%3A11Z..2020-03-04T16%3A45%3A37Z+base%3Amaster) ### New lints @@ -3528,7 +3508,7 @@ Released 2020-04-23 Released 2020-03-12 -[**View 106 PRs merged since 1.41**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-01-30..2020-03-12+base%3Amaster+sort%3Amerged-desc+) +[View all 101 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-12-15T01%3A40%3A34Z..2020-01-26T11%3A22%3A13Z+base%3Amaster) ### New lints @@ -3595,7 +3575,7 @@ Released 2020-03-12 Released 2020-01-30 -[**View 107 PRs merged since 1.40**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-12-19..2020-01-30+base%3Amaster+sort%3Amerged-desc+) +[View all 74 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-10-28T20%3A50%3A24Z..2019-12-12T00%3A53%3A03Z+base%3Amaster) * New Lints: * [`exit`] [#4697](https://github.com/rust-lang/rust-clippy/pull/4697) @@ -3640,8 +3620,7 @@ Released 2020-01-30 Released 2019-12-19 -[**View 69 😺 PRs merged since 1.39**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-11-07..2019-12-19+base%3Amaster+sort%3Amerged-desc+) - +[View all 76 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-09-23T06%3A18%3A04Z..2019-10-28T17%3A34%3A55Z+base%3Amaster) * New Lints: * [`unneeded_wildcard_pattern`] [#4537](https://github.com/rust-lang/rust-clippy/pull/4537) @@ -3683,7 +3662,7 @@ Released 2019-12-19 Released 2019-11-07 -[**View 84 PRs merged since 1.38**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-09-26..2019-11-07+base%3Amaster+sort%3Amerged-desc+) +[View all 100 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-08-11T19%3A21%3A38Z..2019-09-22T12%3A07%3A39Z+base%3Amaster) * New Lints: * [`uninit_assumed_init`] [#4479](https://github.com/rust-lang/rust-clippy/pull/4479) @@ -3727,7 +3706,7 @@ Released 2019-11-07 Released 2019-09-26 -[**View 102 PRs merged since 1.37**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-08-15..2019-09-26+base%3Amaster+sort%3Amerged-desc+) +[View all 76 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-06-30T13%3A40%3A26Z..2019-08-11T09%3A47%3A27Z+base%3Amaster) * New Lints: * [`main_recursion`] [#4203](https://github.com/rust-lang/rust-clippy/pull/4203) @@ -3757,7 +3736,7 @@ Released 2019-09-26 Released 2019-08-15 -[**View 83 PRs merged since 1.36**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-07-04..2019-08-15+base%3Amaster+sort%3Amerged-desc+) +[View all 72 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-05-19T08%3A11%3A23Z..2019-06-25T23%3A22%3A22Z+base%3Amaster) * New Lints: * [`checked_conversions`] [#4088](https://github.com/rust-lang/rust-clippy/pull/4088) @@ -3781,8 +3760,7 @@ Released 2019-08-15 Released 2019-07-04 -[**View 75 PRs merged since 1.35**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-05-20..2019-07-04+base%3Amaster+sort%3Amerged-desc+) - +[View all 81 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-04-10T09%3A41%3A56Z..2019-05-18T00%3A29%3A40Z+base%3Amaster) * New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039) * New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954) @@ -3813,8 +3791,7 @@ Released 2019-07-04 Released 2019-05-20 -[**View 90 PRs merged since 1.34**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-04-10..2019-05-20+base%3Amaster+sort%3Amerged-desc+) - +[1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e) * New lint: `drop_bounds` to detect `T: Drop` bounds * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) @@ -3842,8 +3819,7 @@ Released 2019-05-20 Released 2019-04-10 -[**View 66 PRs merged since 1.33**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-02-26..2019-04-10+base%3Amaster+sort%3Amerged-desc+) - +[View all 61 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2019-01-17T17%3A45%3A39Z..2019-02-19T08%3A24%3A05Z+base%3Amaster) * New lint: [`assertions_on_constants`] to detect for example `assert!(true)` * New lint: [`dbg_macro`] to detect uses of the `dbg!` macro @@ -3873,7 +3849,7 @@ Released 2019-04-10 Released 2019-02-26 -[**View 83 PRs merged since 1.32**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-01-17..2019-02-26+base%3Amaster+sort%3Amerged-desc+) +[View all 120 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2018-11-28T06%3A19%3A50Z..2019-01-15T09%3A27%3A02Z+base%3Amaster) * New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`] * The `rust-clippy` repository is now part of the `rust-lang` org. @@ -3906,7 +3882,7 @@ Released 2019-02-26 Released 2019-01-17 -[**View 106 PRs merged since 1.31**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-12-06..2019-01-17+base%3Amaster+sort%3Amerged-desc+) +[View all 71 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2018-10-24T05%3A02%3A21Z..2018-11-27T17%3A29%3A34Z+base%3Amaster) * New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`, [`redundant_clone`], [`wildcard_dependencies`], @@ -3936,8 +3912,7 @@ Released 2019-01-17 Released 2018-12-06 -[**View 85 PRs merged since 1.30**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-10-25..2018-12-06+base%3Amaster+sort%3Amerged-desc+) - +[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2) * Clippy has been relicensed under a dual MIT / Apache license. See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more @@ -3977,9 +3952,7 @@ Released 2018-12-06 Released 2018-10-25 -[**View 106 PRs merged since 1.29**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-09-13..2018-10-25+base%3Amaster+sort%3Amerged-desc+) - - +[View all 88 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2018-08-02T16%3A54%3A12Z..2018-09-17T09%3A44%3A06Z+base%3Amaster) * Deprecate `assign_ops` lint * New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`], [`needless_collect`], [`copy_iterator`] diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index 52445494436c6..df9b1bbe18f32 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -56,28 +56,6 @@ and open that file in your editor of choice. When updating the changelog it's also a good idea to make sure that `commit1` is already correct in the current changelog. -#### PR ranges - -We developed the concept of PR ranges to help the user understand the size of a new update. To create a PR range, -get the current release date and the date that the last version was released (YYYY-MM-DD) and use the following link: - -``` -[**View PRs merged since 1.**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A..+base%3Amaster+sort%3Amerged-desc+) -``` - -> Note: Be sure to check click the link and check how many PRs got merged between - -Example: - -``` -[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) -``` - -Which renders to: -[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) - -Note that **commit ranges should not be included**, only PR ranges. - ### 3. Authoring the final changelog The above script should have dumped all the relevant PRs to the file you diff --git a/util/fetch_prs_between.sh b/util/fetch_prs_between.sh index 6865abf971b28..fa7560b6929dc 100755 --- a/util/fetch_prs_between.sh +++ b/util/fetch_prs_between.sh @@ -6,15 +6,20 @@ # If you want to use this to update the Clippy changelog, be sure to manually # exclude the non-user facing changes like 'rustup' PRs, typo fixes, etc. -first=$1 -last=$2 +set -e IFS=' ' -for pr in $(git log --oneline --grep "Merge #" --grep "Merge pull request" --grep "Auto merge of" --grep "Rollup merge of" "$first...$last" | sort -rn | uniq); do +for pr in $(git log --oneline --merges --first-parent "$1...$2"); do id=$(echo "$pr" | rg -o '#[0-9]{3,5}' | cut -c 2-) commit=$(echo "$pr" | cut -d' ' -f 1) message=$(git --no-pager show --pretty=medium "$commit") + + if [[ -z "$newest_pr" ]]; then + newest_pr="$id" + fi + oldest_pr="$id" + if [[ -n $(echo "$message" | rg "^[\s]{4}changelog: [nN]one\.*$") ]]; then continue fi @@ -25,3 +30,14 @@ for pr in $(git log --oneline --grep "Merge #" --grep "Merge pull request" --gre echo "---------------------------------------------------------" echo done + +newest_merged_at="$(gh pr view -R rust-lang/rust-clippy --json mergedAt $newest_pr -q .mergedAt)" +oldest_merged_at="$(gh pr view -R rust-lang/rust-clippy --json mergedAt $oldest_pr -q .mergedAt)" + +query="merged:$oldest_merged_at..$newest_merged_at base:master" +encoded_query="$(echo $query | sed 's/ /+/g; s/:/%3A/g')" + +pr_link="https://github.com/rust-lang/rust-clippy/pulls?q=$encoded_query" +count="$(gh api -X GET search/issues -f "q=$query repo:rust-lang/rust-clippy" -q .total_count)" + +echo "[View all $count merged pull requests]($pr_link)" From 5cc0c048264779509800a7b029e79454c48987a8 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 3 Jul 2023 20:24:14 +0200 Subject: [PATCH 45/80] [`manual_range_patterns`]: lint negative values --- clippy_lints/src/manual_range_patterns.rs | 19 +++++++++++-------- tests/ui/manual_range_patterns.fixed | 4 ++++ tests/ui/manual_range_patterns.rs | 4 ++++ tests/ui/manual_range_patterns.stderr | 16 ++++++++++++++-- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs index 65ff555209a69..eb9576992a324 100644 --- a/clippy_lints/src/manual_range_patterns.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -6,6 +6,7 @@ use rustc_hir::Expr; use rustc_hir::ExprKind; use rustc_hir::PatKind; use rustc_hir::RangeEnd; +use rustc_hir::UnOp; use rustc_lint::LintContext; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -36,11 +37,13 @@ declare_clippy_lint! { } declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); -fn expr_as_u128(expr: &Expr<'_>) -> Option { - if let ExprKind::Lit(lit) = expr.kind +fn expr_as_i128(expr: &Expr<'_>) -> Option { + if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind { + expr_as_i128(expr).map(|num| -num) + } else if let ExprKind::Lit(lit) = expr.kind && let LitKind::Int(num, _) = lit.node { - Some(num) + Some(num as i128) } else { None } @@ -56,22 +59,22 @@ impl LateLintPass<'_> for ManualRangePatterns { if let PatKind::Or(pats) = pat.kind && pats.len() >= 3 { - let mut min = u128::MAX; - let mut max = 0; + let mut min = i128::MAX; + let mut max = i128::MIN; let mut numbers_found = FxHashSet::default(); let mut ranges_found = Vec::new(); for pat in pats { if let PatKind::Lit(lit) = pat.kind - && let Some(num) = expr_as_u128(lit) + && let Some(num) = expr_as_i128(lit) { numbers_found.insert(num); min = min.min(num); max = max.max(num); } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind - && let Some(left) = expr_as_u128(left) - && let Some(right) = expr_as_u128(right) + && let Some(left) = expr_as_i128(left) + && let Some(right) = expr_as_i128(right) && right >= left { min = min.min(left); diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed index 9eee8f371874a..6bfcf263aa5e2 100644 --- a/tests/ui/manual_range_patterns.fixed +++ b/tests/ui/manual_range_patterns.fixed @@ -25,6 +25,10 @@ fn main() { 1..=10 => true, _ => false, }; + let _ = matches!(f, -5..=3); + let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing + let _ = matches!(f, -1000001..=1000001); + let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002); macro_rules! mac { ($e:expr) => { diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs index 10743a7d04c66..4a429bb2aed32 100644 --- a/tests/ui/manual_range_patterns.rs +++ b/tests/ui/manual_range_patterns.rs @@ -25,6 +25,10 @@ fn main() { 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, _ => false, }; + let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2); + let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing + let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001); + let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002); macro_rules! mac { ($e:expr) => { diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr index bc9e335016457..b1b55d483e723 100644 --- a/tests/ui/manual_range_patterns.stderr +++ b/tests/ui/manual_range_patterns.stderr @@ -37,7 +37,19 @@ LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_patterns.rs:31:26 + --> $DIR/manual_range_patterns.rs:28:25 + | +LL | let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-5..=3` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:30:25 + | +LL | let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1000001..=1000001` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_patterns.rs:35:26 | LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` @@ -47,5 +59,5 @@ LL | mac!(f); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors From c927912c5bc7aa511ca70e5c3786fa0ac8442774 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:05:26 +0200 Subject: [PATCH 46/80] [`manual_range_patterns`]: document what range we don't lint --- clippy_lints/src/manual_range_patterns.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs index eb9576992a324..64d4c8e456658 100644 --- a/clippy_lints/src/manual_range_patterns.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -20,6 +20,10 @@ declare_clippy_lint! { /// ### Why is this bad? /// Using an explicit range is more concise and easier to read. /// + /// ### Known issues + /// This lint intentionally does not handle numbers greater than `i128::MAX` for `u128` literals + /// in order to support negative numbers. + /// /// ### Example /// ```rust /// let x = 6; @@ -43,7 +47,8 @@ fn expr_as_i128(expr: &Expr<'_>) -> Option { } else if let ExprKind::Lit(lit) = expr.kind && let LitKind::Int(num, _) = lit.node { - Some(num as i128) + // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now. + num.try_into().ok() } else { None } From b5ac726ed348430ee25a04d7de6569cb4627e726 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:07:03 +0200 Subject: [PATCH 47/80] Rename `adjustment::PointerCast` and variants using it to `PointerCoercion` It makes it sound like the `ExprKind` and `Rvalue` are supposed to represent all pointer related casts, when in reality their just used to share a some enum variants. Make it clear there these are only coercion to make it clear why only some pointer related "casts" are in the enum. --- clippy_lints/src/derivable_impls.rs | 4 ++-- clippy_lints/src/pass_by_ref_or_value.rs | 4 ++-- clippy_utils/src/qualify_min_const_fn.rs | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index ec0ca50cfec70..020ffe7f8fa22 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -9,7 +9,7 @@ use rustc_hir::{ Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -116,7 +116,7 @@ fn check_struct<'tcx>( let is_default_without_adjusts = |expr| { is_default_equivalent(cx, expr) && typeck_results.expr_adjustments(expr).iter().all(|adj| { - !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) + !matches!(adj.kind, Adjust::Pointer(PointerCoercion::Unsize) if contains_trait_object(adj.target)) }) }; diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 0d78c3048ba12..eab725de17f68 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, RegionKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -195,7 +195,7 @@ impl<'tcx> PassByRefOrValue { .adjustments() .items() .flat_map(|(_, a)| a) - .any(|a| matches!(a.kind, Adjust::Pointer(PointerCast::UnsafeFnPointer))) + .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer))) { continue; } diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index c9938caefb067..fbf4ab2722e60 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::{ImplSource, ObligationCause}; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; use rustc_middle::ty::{BoundConstness, TraitRef}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; @@ -119,18 +119,18 @@ fn check_rvalue<'tcx>( | CastKind::FloatToFloat | CastKind::FnPtrToPtr | CastKind::PtrToPtr - | CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), + | CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer), operand, _, ) => check_operand(tcx, operand, span, body), Rvalue::Cast( - CastKind::Pointer( - PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer, + CastKind::PointerCoercion( + PointerCoercion::UnsafeFnPointer | PointerCoercion::ClosureFnPointer(_) | PointerCoercion::ReifyFnPointer, ), _, _, ) => Err((span, "function pointer casts are not allowed in const fn".into())), - Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), op, cast_ty) => { + Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => { let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) { deref_ty.ty } else { From 87373d7f522031c0adc66eb87864ae86868e4fed Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 7 Jul 2023 18:18:25 +0000 Subject: [PATCH 48/80] Fix failing clippy tests Comments out the C string literals due to https://github.com/rust-lang/rust/pull/113334 Fixes https://github.com/rust-lang/rust-clippy/issues/11121 --- clippy_lints/src/incorrect_impls.rs | 2 +- tests/ui/needless_raw_string.fixed | 7 ++++--- tests/ui/needless_raw_string.rs | 7 ++++--- tests/ui/needless_raw_string.stderr | 8 +------- tests/ui/needless_raw_string_hashes.fixed | 9 +++++---- tests/ui/needless_raw_string_hashes.rs | 9 +++++---- tests/ui/needless_raw_string_hashes.stderr | 20 +------------------- 7 files changed, 21 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs index 13cc0b23ba33d..7b95116ee4e36 100644 --- a/clippy_lints/src/incorrect_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -82,7 +82,7 @@ impl LateLintPass<'_> for IncorrectImpls { cx, hir_ty_to_ty(cx.tcx, imp.self_ty), copy_def_id, - trait_impl.substs, + &[], ) { if impl_item.ident.name == sym::clone { diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed index 6438e46977bbd..b36912efbb2d4 100644 --- a/tests/ui/needless_raw_string.fixed +++ b/tests/ui/needless_raw_string.fixed @@ -10,7 +10,8 @@ fn main() { b"aaa"; br#""aaa""#; br#"\s"#; - c"aaa"; - cr#""aaa""#; - cr#"\s"#; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr#""aaa""#; + // cr#"\s"#; } diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs index f7ddc68265edf..8f48e7dab2a6e 100644 --- a/tests/ui/needless_raw_string.rs +++ b/tests/ui/needless_raw_string.rs @@ -10,7 +10,8 @@ fn main() { br#"aaa"#; br#""aaa""#; br#"\s"#; - cr#"aaa"#; - cr#""aaa""#; - cr#"\s"#; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr#""aaa""#; + // cr#"\s"#; } diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr index 0179978b7b08c..cfb07b647d7c6 100644 --- a/tests/ui/needless_raw_string.stderr +++ b/tests/ui/needless_raw_string.stderr @@ -12,11 +12,5 @@ error: unnecessary raw string literal LL | br#"aaa"#; | ^^^^^^^^^ help: try: `b"aaa"` -error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:13:5 - | -LL | cr#"aaa"#; - | ^^^^^^^^^ help: try: `c"aaa"` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index e4d7d8fb017a9..c8507c7271513 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -12,8 +12,9 @@ fn main() { br#"Hello "world"!"#; br####" "### "## "# "####; br###" "aa" "# "## "###; - cr#"aaa"#; - cr#"Hello "world"!"#; - cr####" "### "## "# "####; - cr###" "aa" "# "## "###; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr##"Hello "world"!"##; + // cr######" "### "## "# "######; + // cr######" "aa" "# "## "######; } diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs index e2d85c52e78cc..912fbde1679db 100644 --- a/tests/ui/needless_raw_string_hashes.rs +++ b/tests/ui/needless_raw_string_hashes.rs @@ -12,8 +12,9 @@ fn main() { br##"Hello "world"!"##; br######" "### "## "# "######; br######" "aa" "# "## "######; - cr#"aaa"#; - cr##"Hello "world"!"##; - cr######" "### "## "# "######; - cr######" "aa" "# "## "######; + // currently disabled: https://github.com/rust-lang/rust/issues/113333 + // cr#"aaa"#; + // cr##"Hello "world"!"##; + // cr######" "### "## "# "######; + // cr######" "aa" "# "## "######; } diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr index dff47a2d04212..30e6783a38e8b 100644 --- a/tests/ui/needless_raw_string_hashes.stderr +++ b/tests/ui/needless_raw_string_hashes.stderr @@ -36,23 +36,5 @@ error: unnecessary hashes around raw string literal LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###` -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:16:5 - | -LL | cr##"Hello "world"!"##; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#` - -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:17:5 - | -LL | cr######" "### "## "# "######; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####` - -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:18:5 - | -LL | cr######" "aa" "# "## "######; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###` - -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors From 5df1f6681dca1a2028a4e6b60d3ab789c00b4cf8 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 7 Jul 2023 20:28:51 +0200 Subject: [PATCH 49/80] Pass correct substs to `implements_trait` in `incorrect_impls` `Copy` does in fact not exist. The substs on the trait_ref contain the `Self` type of the impl as the first parameter, so passing that to `implements_trait`, which then nicely prepends the `Self` type for us does not end will. --- clippy_lints/src/incorrect_impls.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs index 13cc0b23ba33d..ed21df4ff884a 100644 --- a/clippy_lints/src/incorrect_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -1,7 +1,6 @@ use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait}; use rustc_errors::Applicability; -use rustc_hir::{ExprKind, ImplItem, ImplItemKind, ItemKind, Node, UnOp}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir::{ExprKind, ImplItem, ImplItemKind, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -55,9 +54,6 @@ impl LateLintPass<'_> for IncorrectImpls { let Some(Node::Item(item)) = node else { return; }; - let ItemKind::Impl(imp) = item.kind else { - return; - }; let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { return; }; @@ -80,9 +76,9 @@ impl LateLintPass<'_> for IncorrectImpls { && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) && implements_trait( cx, - hir_ty_to_ty(cx.tcx, imp.self_ty), + trait_impl.self_ty(), copy_def_id, - trait_impl.substs, + &[], ) { if impl_item.ident.name == sym::clone { From 31d50a6e213c13b3f1a11f700de1979d5e4868c8 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 8 Jul 2023 17:17:40 +0200 Subject: [PATCH 50/80] Delete `to_string_in_format_args_incremental.rs` It fails CI and passes locally. It passes random directores in `-Cincremental` so maybe something's up. It shouldn't block us here. --- tests/ui/to_string_in_format_args_incremental.rs | 9 --------- tests/ui/to_string_in_format_args_incremental.stderr | 10 ---------- 2 files changed, 19 deletions(-) delete mode 100644 tests/ui/to_string_in_format_args_incremental.rs delete mode 100644 tests/ui/to_string_in_format_args_incremental.stderr diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs deleted file mode 100644 index 67115f7c5a7b7..0000000000000 --- a/tests/ui/to_string_in_format_args_incremental.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@run-rustfix -//@compile-flags: -C incremental=target/debug/test/incr - -// see https://github.com/rust-lang/rust-clippy/issues/10969 - -fn main() { - let s = "Hello, world!"; - println!("{}", s.to_string()); -} diff --git a/tests/ui/to_string_in_format_args_incremental.stderr b/tests/ui/to_string_in_format_args_incremental.stderr deleted file mode 100644 index a992c54291495..0000000000000 --- a/tests/ui/to_string_in_format_args_incremental.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/to_string_in_format_args_incremental.rs:8:21 - | -LL | println!("{}", s.to_string()); - | ^^^^^^^^^^^^ help: remove this - | - = note: `-D clippy::to-string-in-format-args` implied by `-D warnings` - -error: aborting due to previous error - From 2a1fd22f81fd1222a5ceaa554e41095dec34f785 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 15 May 2023 16:50:28 -0500 Subject: [PATCH 51/80] implement `manual_partial_ord_impl` first try at this --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 1 + clippy_lints/src/manual_partial_ord_impl.rs | 132 ++++++++++++++++++++ tests/ui/manual_partial_ord_impl.rs | 57 +++++++++ tests/ui/manual_partial_ord_impl.stderr | 28 +++++ 6 files changed, 220 insertions(+) create mode 100644 clippy_lints/src/manual_partial_ord_impl.rs create mode 100644 tests/ui/manual_partial_ord_impl.rs create mode 100644 tests/ui/manual_partial_ord_impl.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index da070adb8086f..840a46aa83a83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4921,6 +4921,7 @@ Released 2018-09-13 [`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or +[`manual_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_partial_ord_impl [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains [`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index ca97db040792c..7764dd7391fe4 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -277,6 +277,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, + crate::manual_partial_ord_impl::MANUAL_PARTIAL_ORD_IMPL_INFO, crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO, crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO, crate::manual_retain::MANUAL_RETAIN_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 00d46025caa86..36a0cf860d72b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -188,6 +188,7 @@ mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; +mod manual_partial_ord_impl; mod manual_range_patterns; mod manual_rem_euclid; mod manual_retain; diff --git a/clippy_lints/src/manual_partial_ord_impl.rs b/clippy_lints/src/manual_partial_ord_impl.rs new file mode 100644 index 0000000000000..4c43b5e52e85b --- /dev/null +++ b/clippy_lints/src/manual_partial_ord_impl.rs @@ -0,0 +1,132 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{ + def_path_def_ids, diagnostics::span_lint_and_sugg, get_trait_def_id, match_def_path, path_res, ty::implements_trait, +}; +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::*; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::def_id::DefId; +use std::cell::OnceCell; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is + /// necessary. + /// + /// ### Why is this bad? + /// If both `PartialOrd` and `Ord` are implemented, `PartialOrd` will wrap the returned value of + /// `Ord::cmp` in `Some`. Not doing this may silently introduce an error. + /// + /// ### Example + /// ```rust + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// todo!(); + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// Some(self.cmp(other)) + /// } + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub MANUAL_PARTIAL_ORD_IMPL, + nursery, + "default lint description" +} +impl_lint_pass!(ManualPartialOrdImpl => [MANUAL_PARTIAL_ORD_IMPL]); + +#[derive(Clone)] +pub struct ManualPartialOrdImpl { + pub ord_def_id: OnceCell, +} + +impl LateLintPass<'_> for ManualPartialOrdImpl { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if_chain! { + if let ItemKind::Impl(imp) = &item.kind; + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); + if cx.tcx.is_diagnostic_item(sym!(PartialOrd), impl_trait_ref.skip_binder().def_id); + then { + lint_impl_body(self, cx, imp, item); + } + } + } +} + +fn lint_impl_body(conf: &mut ManualPartialOrdImpl, cx: &LateContext<'_>, imp: &Impl<'_>, item: &Item<'_>) { + for imp_item in imp.items { + if_chain! { + if imp_item.ident.name == sym!(partial_cmp); + if let ImplItemKind::Fn(_, id) = cx.tcx.hir().impl_item(imp_item.id).kind; + then { + let body = cx.tcx.hir().body(id); + let ord_def_id = conf.ord_def_id.get_or_init(|| get_trait_def_id(cx, &["core", "cmp", "Ord"]).unwrap()); + if let ExprKind::Block(block, ..) + = body.value.kind && implements_trait(cx, hir_ty_to_ty(cx.tcx, imp.self_ty), *ord_def_id, &[]) + { + if_chain! { + if block.stmts.is_empty(); + if let Some(expr) = block.expr; + if let ExprKind::Call(Expr { kind: ExprKind::Path(path), ..}, [cmp_expr]) = expr.kind; + if let QPath::Resolved(_, some_path) = path; + if let Some(some_seg_one) = some_path.segments.get(0); + if some_seg_one.ident.name == sym!(Some); + if let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind; + if cmp_path.ident.name == sym!(cmp); + if let Res::Local(..) = path_res(cx, other_expr); + then {} + else { + span_lint_and_then( + cx, + MANUAL_PARTIAL_ORD_IMPL, + item.span, + "manual implementation of `PartialOrd` when `Ord` is already implemented", + |diag| { + if let Some(param) = body.params.get(1) + && let PatKind::Binding(_, _, param_ident, ..) = param.pat.kind + { + diag.span_suggestion( + block.span, + "change this to", + format!("{{ Some(self.cmp({})) }}", + param_ident.name), + Applicability::MaybeIncorrect + ); + } else { + diag.help("return the value of `self.cmp` wrapped in `Some` instead"); + }; + } + ); + } + } + } + } + } + } +} diff --git a/tests/ui/manual_partial_ord_impl.rs b/tests/ui/manual_partial_ord_impl.rs new file mode 100644 index 0000000000000..9e2c7e2ec5163 --- /dev/null +++ b/tests/ui/manual_partial_ord_impl.rs @@ -0,0 +1,57 @@ +#![allow(unused)] +#![warn(clippy::manual_partial_ord_impl)] +#![no_main] + +use std::cmp::Ordering; + +// lint + +#[derive(Eq, PartialEq)] +struct A(u32); + +impl Ord for A { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for A { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} + +// do not lint + +#[derive(Eq, PartialEq)] +struct B(u32); + +impl Ord for B { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for B { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// lint, but we cannot give a suggestion since &Self is not named + +#[derive(Eq, PartialEq)] +struct C(u32); + +impl Ord for C { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for C { + fn partial_cmp(&self, _: &Self) -> Option { + todo!(); + } +} + diff --git a/tests/ui/manual_partial_ord_impl.stderr b/tests/ui/manual_partial_ord_impl.stderr new file mode 100644 index 0000000000000..100ddb46e82fb --- /dev/null +++ b/tests/ui/manual_partial_ord_impl.stderr @@ -0,0 +1,28 @@ +error: manual implementation of `PartialOrd` when `Ord` is already implemented + --> $DIR/manual_partial_ord_impl.rs:18:1 + | +LL | / impl PartialOrd for A { +LL | | fn partial_cmp(&self, other: &Self) -> Option { + | | _____________________________________________________________- +LL | || todo!(); +LL | || } + | ||_____- help: change this to: `{ Some(self.cmp(other)) }` +LL | | } + | |__^ + | + = note: `-D clippy::manual-partial-ord-impl` implied by `-D warnings` + +error: manual implementation of `PartialOrd` when `Ord` is already implemented + --> $DIR/manual_partial_ord_impl.rs:52:1 + | +LL | / impl PartialOrd for C { +LL | | fn partial_cmp(&self, _: &Self) -> Option { +LL | | todo!(); +LL | | } +LL | | } + | |_^ + | + = help: return the value of `self.cmp` wrapped in `Some` instead + +error: aborting due to 2 previous errors + From 004e89d4cfde749e9cb33d5ac26bdbe3001a1f3d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 15 May 2023 18:41:41 -0500 Subject: [PATCH 52/80] rename to `manual_partial_ord_and_ord_impl` cargo dev fmt cargo test passes cargo test passes refactor a lil Update bool_comparison.stderr heavily refactor + bump `clippy::version` refactor refactor check bounds to increase accuracy, and add todos --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/manual_partial_ord_impl.rs | 132 ---------------- clippy_lints/src/needless_impls.rs | 145 ++++++++++++++++++ tests/ui/bool_comparison.fixed | 1 + tests/ui/bool_comparison.rs | 1 + tests/ui/bool_comparison.stderr | 44 +++--- tests/ui/derive_ord_xor_partial_ord.rs | 1 + tests/ui/derive_ord_xor_partial_ord.stderr | 16 +- tests/ui/manual_partial_ord_impl.stderr | 28 ---- tests/ui/needless_partial_ord_impl.fixed | 85 ++++++++++ ...d_impl.rs => needless_partial_ord_impl.rs} | 36 ++++- tests/ui/needless_partial_ord_impl.stderr | 28 ++++ 14 files changed, 328 insertions(+), 195 deletions(-) delete mode 100644 clippy_lints/src/manual_partial_ord_impl.rs create mode 100644 clippy_lints/src/needless_impls.rs delete mode 100644 tests/ui/manual_partial_ord_impl.stderr create mode 100644 tests/ui/needless_partial_ord_impl.fixed rename tests/ui/{manual_partial_ord_impl.rs => needless_partial_ord_impl.rs} (52%) create mode 100644 tests/ui/needless_partial_ord_impl.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 840a46aa83a83..fea11bba63f97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4921,7 +4921,6 @@ Released 2018-09-13 [`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or -[`manual_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_partial_ord_impl [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains [`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid @@ -5021,6 +5020,7 @@ Released 2018-09-13 [`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals +[`needless_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_partial_ord_impl [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 7764dd7391fe4..a2231b8fb1db9 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -277,7 +277,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, - crate::manual_partial_ord_impl::MANUAL_PARTIAL_ORD_IMPL_INFO, crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO, crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO, crate::manual_retain::MANUAL_RETAIN_INFO, @@ -470,6 +469,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, crate::needless_if::NEEDLESS_IF_INFO, + crate::needless_impls::NEEDLESS_PARTIAL_ORD_IMPL_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 36a0cf860d72b..1ec5b2e8b0aa8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -188,7 +188,6 @@ mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; -mod manual_partial_ord_impl; mod manual_range_patterns; mod manual_rem_euclid; mod manual_retain; @@ -228,6 +227,7 @@ mod needless_continue; mod needless_else; mod needless_for_each; mod needless_if; +mod needless_impls; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; diff --git a/clippy_lints/src/manual_partial_ord_impl.rs b/clippy_lints/src/manual_partial_ord_impl.rs deleted file mode 100644 index 4c43b5e52e85b..0000000000000 --- a/clippy_lints/src/manual_partial_ord_impl.rs +++ /dev/null @@ -1,132 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{ - def_path_def_ids, diagnostics::span_lint_and_sugg, get_trait_def_id, match_def_path, path_res, ty::implements_trait, -}; -use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::*; -use rustc_hir_analysis::hir_ty_to_ty; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::def_id::DefId; -use std::cell::OnceCell; - -declare_clippy_lint! { - /// ### What it does - /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is - /// necessary. - /// - /// ### Why is this bad? - /// If both `PartialOrd` and `Ord` are implemented, `PartialOrd` will wrap the returned value of - /// `Ord::cmp` in `Some`. Not doing this may silently introduce an error. - /// - /// ### Example - /// ```rust - /// #[derive(Eq, PartialEq)] - /// struct A(u32); - /// - /// impl Ord for A { - /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); - /// } - /// } - /// - /// impl PartialOrd for A { - /// fn partial_cmp(&self, other: &Self) -> Option { - /// todo!(); - /// } - /// } - /// ``` - /// Use instead: - /// ```rust - /// #[derive(Eq, PartialEq)] - /// struct A(u32); - /// - /// impl Ord for A { - /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); - /// } - /// } - /// - /// impl PartialOrd for A { - /// fn partial_cmp(&self, other: &Self) -> Option { - /// Some(self.cmp(other)) - /// } - /// } - /// ``` - #[clippy::version = "1.71.0"] - pub MANUAL_PARTIAL_ORD_IMPL, - nursery, - "default lint description" -} -impl_lint_pass!(ManualPartialOrdImpl => [MANUAL_PARTIAL_ORD_IMPL]); - -#[derive(Clone)] -pub struct ManualPartialOrdImpl { - pub ord_def_id: OnceCell, -} - -impl LateLintPass<'_> for ManualPartialOrdImpl { - fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if_chain! { - if let ItemKind::Impl(imp) = &item.kind; - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); - if cx.tcx.is_diagnostic_item(sym!(PartialOrd), impl_trait_ref.skip_binder().def_id); - then { - lint_impl_body(self, cx, imp, item); - } - } - } -} - -fn lint_impl_body(conf: &mut ManualPartialOrdImpl, cx: &LateContext<'_>, imp: &Impl<'_>, item: &Item<'_>) { - for imp_item in imp.items { - if_chain! { - if imp_item.ident.name == sym!(partial_cmp); - if let ImplItemKind::Fn(_, id) = cx.tcx.hir().impl_item(imp_item.id).kind; - then { - let body = cx.tcx.hir().body(id); - let ord_def_id = conf.ord_def_id.get_or_init(|| get_trait_def_id(cx, &["core", "cmp", "Ord"]).unwrap()); - if let ExprKind::Block(block, ..) - = body.value.kind && implements_trait(cx, hir_ty_to_ty(cx.tcx, imp.self_ty), *ord_def_id, &[]) - { - if_chain! { - if block.stmts.is_empty(); - if let Some(expr) = block.expr; - if let ExprKind::Call(Expr { kind: ExprKind::Path(path), ..}, [cmp_expr]) = expr.kind; - if let QPath::Resolved(_, some_path) = path; - if let Some(some_seg_one) = some_path.segments.get(0); - if some_seg_one.ident.name == sym!(Some); - if let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind; - if cmp_path.ident.name == sym!(cmp); - if let Res::Local(..) = path_res(cx, other_expr); - then {} - else { - span_lint_and_then( - cx, - MANUAL_PARTIAL_ORD_IMPL, - item.span, - "manual implementation of `PartialOrd` when `Ord` is already implemented", - |diag| { - if let Some(param) = body.params.get(1) - && let PatKind::Binding(_, _, param_ident, ..) = param.pat.kind - { - diag.span_suggestion( - block.span, - "change this to", - format!("{{ Some(self.cmp({})) }}", - param_ident.name), - Applicability::MaybeIncorrect - ); - } else { - diag.help("return the value of `self.cmp` wrapped in `Some` instead"); - }; - } - ); - } - } - } - } - } - } -} diff --git a/clippy_lints/src/needless_impls.rs b/clippy_lints/src/needless_impls.rs new file mode 100644 index 0000000000000..4f8741bf3708f --- /dev/null +++ b/clippy_lints/src/needless_impls.rs @@ -0,0 +1,145 @@ +use clippy_utils::{ + diagnostics::span_lint_and_then, get_parent_node, is_res_lang_ctor, path_res, ty::implements_trait, +}; +use rustc_errors::Applicability; +use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, PatKind}; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::EarlyBinder; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; +use std::borrow::Cow; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is + /// necessary. + /// + /// ### Why is this bad? + /// If both `PartialOrd` and `Ord` are implemented, they must agree. This is commonly done by + /// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently + /// introduce an error upon refactoring. + /// + /// ### Example + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// todo!(); + /// } + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// Some(self.cmp(other)) + /// } + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_PARTIAL_ORD_IMPL, + correctness, + "manual implementation of `PartialOrd` when `Ord` is already implemented" +} +declare_lint_pass!(NeedlessImpls => [NEEDLESS_PARTIAL_ORD_IMPL]); + +impl LateLintPass<'_> for NeedlessImpls { + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { + let node = get_parent_node(cx.tcx, impl_item.hir_id()); + let Some(Node::Item(item)) = node else { + return; + }; + let ItemKind::Impl(imp) = item.kind else { + return; + }; + let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { + return; + }; + let trait_impl_def_id = trait_impl.def_id; + if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { + return; + } + let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { + return; + }; + let body = cx.tcx.hir().body(impl_item_id); + let ExprKind::Block(block, ..) = body.value.kind else { + return; + }; + + if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl_def_id) + && impl_item.ident.name == sym::partial_cmp + && let Some(ord_def_id) = cx + .tcx + .diagnostic_items(trait_impl.def_id.krate) + .name_to_id + .get(&sym::Ord) + && implements_trait( + cx, + hir_ty_to_ty(cx.tcx, imp.self_ty), + *ord_def_id, + trait_impl.substs, + ) + { + if block.stmts.is_empty() + && let Some(expr) = block.expr + && let ExprKind::Call( + Expr { + kind: ExprKind::Path(some_path), + hir_id: some_hir_id, + .. + }, + [cmp_expr], + ) = expr.kind + && is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome) + && let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind + && cmp_path.ident.name == sym::cmp + && let Res::Local(..) = path_res(cx, other_expr) + {} else { + span_lint_and_then( + cx, + NEEDLESS_PARTIAL_ORD_IMPL, + item.span, + "manual implementation of `PartialOrd` when `Ord` is already implemented", + |diag| { + let (help, app) = if let Some(other) = body.params.get(0) + && let PatKind::Binding(_, _, other_ident, ..) = other.pat.kind + { + ( + Cow::Owned(format!("{{ Some(self.cmp({})) }}", other_ident.name)), + Applicability::Unspecified, + ) + } else { + (Cow::Borrowed("{ Some(self.cmp(...)) }"), Applicability::HasPlaceholders) + }; + + diag.span_suggestion( + block.span, + "change this to", + help, + app, + ); + } + ); + } + } + } +} diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index d6774c0359842..33221c7777ea8 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -2,6 +2,7 @@ #![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] +#![allow(clippy::needless_partial_ord_impl)] fn main() { let x = true; diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index c0483fd737489..5f909bd2a53fd 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -2,6 +2,7 @@ #![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] +#![allow(clippy::needless_partial_ord_impl)] fn main() { let x = true; diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index f4dded365fba9..19bdf30135803 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,5 +1,5 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:8:8 + --> $DIR/bool_comparison.rs:9:8 | LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -7,127 +7,127 @@ LL | if x == true { = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:13:8 + --> $DIR/bool_comparison.rs:14:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:18:8 + --> $DIR/bool_comparison.rs:19:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:23:8 + --> $DIR/bool_comparison.rs:24:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:28:8 + --> $DIR/bool_comparison.rs:29:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:33:8 + --> $DIR/bool_comparison.rs:34:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:38:8 + --> $DIR/bool_comparison.rs:39:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:43:8 + --> $DIR/bool_comparison.rs:44:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:48:8 + --> $DIR/bool_comparison.rs:49:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:53:8 + --> $DIR/bool_comparison.rs:54:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:58:8 + --> $DIR/bool_comparison.rs:59:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:63:8 + --> $DIR/bool_comparison.rs:64:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:69:8 + --> $DIR/bool_comparison.rs:70:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:74:8 + --> $DIR/bool_comparison.rs:75:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:122:8 + --> $DIR/bool_comparison.rs:123:8 | LL | if a == !b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:123:8 + --> $DIR/bool_comparison.rs:124:8 | LL | if !a == b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:127:8 + --> $DIR/bool_comparison.rs:128:8 | LL | if b == !a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:128:8 + --> $DIR/bool_comparison.rs:129:8 | LL | if !b == a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:152:8 + --> $DIR/bool_comparison.rs:153:8 | LL | if false == m!(func) {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:153:8 + --> $DIR/bool_comparison.rs:154:8 | LL | if m!(func) == false {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:154:8 + --> $DIR/bool_comparison.rs:155:8 | LL | if true == m!(func) {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:155:8 + --> $DIR/bool_comparison.rs:156:8 | LL | if m!(func) == true {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 6f12d36d777dc..5d1a693321e5d 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -1,5 +1,6 @@ #![warn(clippy::derive_ord_xor_partial_ord)] #![allow(clippy::unnecessary_wraps)] +#![allow(clippy::needless_partial_ord_impl)] use std::cmp::Ordering; diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr index 58efbb8541f66..bd14883481404 100644 --- a/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -1,11 +1,11 @@ error: you are deriving `Ord` but have implemented `PartialOrd` explicitly - --> $DIR/derive_ord_xor_partial_ord.rs:21:10 + --> $DIR/derive_ord_xor_partial_ord.rs:22:10 | LL | #[derive(Ord, PartialEq, Eq)] | ^^^ | note: `PartialOrd` implemented here - --> $DIR/derive_ord_xor_partial_ord.rs:24:1 + --> $DIR/derive_ord_xor_partial_ord.rs:25:1 | LL | impl PartialOrd for DeriveOrd { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,20 +13,20 @@ LL | impl PartialOrd for DeriveOrd { = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Ord` but have implemented `PartialOrd` explicitly - --> $DIR/derive_ord_xor_partial_ord.rs:30:10 + --> $DIR/derive_ord_xor_partial_ord.rs:31:10 | LL | #[derive(Ord, PartialEq, Eq)] | ^^^ | note: `PartialOrd` implemented here - --> $DIR/derive_ord_xor_partial_ord.rs:33:1 + --> $DIR/derive_ord_xor_partial_ord.rs:34:1 | LL | impl PartialOrd for DeriveOrdWithExplicitTypeVariable { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` - --> $DIR/derive_ord_xor_partial_ord.rs:42:1 + --> $DIR/derive_ord_xor_partial_ord.rs:43:1 | LL | / impl std::cmp::Ord for DerivePartialOrd { LL | | fn cmp(&self, other: &Self) -> Ordering { @@ -36,14 +36,14 @@ LL | | } | |_^ | note: `PartialOrd` implemented here - --> $DIR/derive_ord_xor_partial_ord.rs:39:10 + --> $DIR/derive_ord_xor_partial_ord.rs:40:10 | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` - --> $DIR/derive_ord_xor_partial_ord.rs:62:5 + --> $DIR/derive_ord_xor_partial_ord.rs:63:5 | LL | / impl Ord for DerivePartialOrdInUseOrd { LL | | fn cmp(&self, other: &Self) -> Ordering { @@ -53,7 +53,7 @@ LL | | } | |_____^ | note: `PartialOrd` implemented here - --> $DIR/derive_ord_xor_partial_ord.rs:59:14 + --> $DIR/derive_ord_xor_partial_ord.rs:60:14 | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ diff --git a/tests/ui/manual_partial_ord_impl.stderr b/tests/ui/manual_partial_ord_impl.stderr deleted file mode 100644 index 100ddb46e82fb..0000000000000 --- a/tests/ui/manual_partial_ord_impl.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: manual implementation of `PartialOrd` when `Ord` is already implemented - --> $DIR/manual_partial_ord_impl.rs:18:1 - | -LL | / impl PartialOrd for A { -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || todo!(); -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(other)) }` -LL | | } - | |__^ - | - = note: `-D clippy::manual-partial-ord-impl` implied by `-D warnings` - -error: manual implementation of `PartialOrd` when `Ord` is already implemented - --> $DIR/manual_partial_ord_impl.rs:52:1 - | -LL | / impl PartialOrd for C { -LL | | fn partial_cmp(&self, _: &Self) -> Option { -LL | | todo!(); -LL | | } -LL | | } - | |_^ - | - = help: return the value of `self.cmp` wrapped in `Some` instead - -error: aborting due to 2 previous errors - diff --git a/tests/ui/needless_partial_ord_impl.fixed b/tests/ui/needless_partial_ord_impl.fixed new file mode 100644 index 0000000000000..7b47773ad766a --- /dev/null +++ b/tests/ui/needless_partial_ord_impl.fixed @@ -0,0 +1,85 @@ +//@run-rustfix +#![allow(unused)] +#![no_main] + +use std::cmp::Ordering; + +// lint + +#[derive(Eq, PartialEq)] +struct A(u32); + +impl Ord for A { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for A { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(self)) } +} + +// do not lint + +#[derive(Eq, PartialEq)] +struct B(u32); + +impl Ord for B { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for B { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// lint, but we can't give a suggestion since &Self is not named + +#[derive(Eq, PartialEq)] +struct C(u32); + +impl Ord for C { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for C { + fn partial_cmp(&self, _: &Self) -> Option { Some(self.cmp(self)) } +} + +// do not lint derived + +#[derive(Eq, Ord, PartialEq, PartialOrd)] +struct D(u32); + +// do not lint if ord is not manually implemented + +#[derive(Eq, PartialEq)] +struct E(u32); + +impl PartialOrd for E { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} + +// do not lint since ord has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Ord for Uwu { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for Uwu { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} diff --git a/tests/ui/manual_partial_ord_impl.rs b/tests/ui/needless_partial_ord_impl.rs similarity index 52% rename from tests/ui/manual_partial_ord_impl.rs rename to tests/ui/needless_partial_ord_impl.rs index 9e2c7e2ec5163..8f5c1337369b8 100644 --- a/tests/ui/manual_partial_ord_impl.rs +++ b/tests/ui/needless_partial_ord_impl.rs @@ -1,5 +1,5 @@ +//@run-rustfix #![allow(unused)] -#![warn(clippy::manual_partial_ord_impl)] #![no_main] use std::cmp::Ordering; @@ -38,7 +38,7 @@ impl PartialOrd for B { } } -// lint, but we cannot give a suggestion since &Self is not named +// lint, but we can't give a suggestion since &Self is not named #[derive(Eq, PartialEq)] struct C(u32); @@ -55,3 +55,35 @@ impl PartialOrd for C { } } +// do not lint derived + +#[derive(Eq, Ord, PartialEq, PartialOrd)] +struct D(u32); + +// do not lint if ord is not manually implemented + +#[derive(Eq, PartialEq)] +struct E(u32); + +impl PartialOrd for E { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} + +// do not lint since ord has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Ord for Uwu { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for Uwu { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} diff --git a/tests/ui/needless_partial_ord_impl.stderr b/tests/ui/needless_partial_ord_impl.stderr new file mode 100644 index 0000000000000..b8978462cc0c2 --- /dev/null +++ b/tests/ui/needless_partial_ord_impl.stderr @@ -0,0 +1,28 @@ +error: manual implementation of `PartialOrd` when `Ord` is already implemented + --> $DIR/needless_partial_ord_impl.rs:18:1 + | +LL | / impl PartialOrd for A { +LL | | fn partial_cmp(&self, other: &Self) -> Option { + | | _____________________________________________________________- +LL | || todo!(); +LL | || } + | ||_____- help: change this to: `{ Some(self.cmp(self)) }` +LL | | } + | |__^ + | + = note: `#[deny(clippy::needless_partial_ord_impl)]` on by default + +error: manual implementation of `PartialOrd` when `Ord` is already implemented + --> $DIR/needless_partial_ord_impl.rs:52:1 + | +LL | / impl PartialOrd for C { +LL | | fn partial_cmp(&self, _: &Self) -> Option { + | | _________________________________________________________- +LL | || todo!(); +LL | || } + | ||_____- help: change this to: `{ Some(self.cmp(self)) }` +LL | | } + | |__^ + +error: aborting due to 2 previous errors + From 844afbfebad063d335e30f01e7eab287535f6470 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 15 Jun 2023 07:11:25 -0500 Subject: [PATCH 53/80] use `other` instead of `self` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/incorrect_impls.rs | 130 +++++++++++++++- clippy_lints/src/lib.rs | 1 - clippy_lints/src/needless_impls.rs | 145 ------------------ tests/ui/bool_comparison.fixed | 2 +- tests/ui/bool_comparison.rs | 2 +- tests/ui/derive.rs | 6 +- tests/ui/derive.stderr | 20 +-- tests/ui/derive_ord_xor_partial_ord.rs | 2 +- ...incorrect_partial_ord_impl_on_ord_type.rs} | 32 +++- ...orrect_partial_ord_impl_on_ord_type.stderr | 28 ++++ tests/ui/needless_partial_ord_impl.fixed | 85 ---------- tests/ui/needless_partial_ord_impl.stderr | 28 ---- 14 files changed, 202 insertions(+), 283 deletions(-) delete mode 100644 clippy_lints/src/needless_impls.rs rename tests/ui/{needless_partial_ord_impl.rs => incorrect_partial_ord_impl_on_ord_type.rs} (72%) create mode 100644 tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr delete mode 100644 tests/ui/needless_partial_ord_impl.fixed delete mode 100644 tests/ui/needless_partial_ord_impl.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index fea11bba63f97..57322887b86d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4834,6 +4834,7 @@ Released 2018-09-13 [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor [`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type +[`incorrect_partial_ord_impl_on_ord_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_partial_ord_impl_on_ord_type [`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask @@ -5020,7 +5021,6 @@ Released 2018-09-13 [`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals -[`needless_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_partial_ord_impl [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a2231b8fb1db9..caff1c4b3be00 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -207,6 +207,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO, crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO, crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO, + crate::incorrect_impls::INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE_INFO, crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO, crate::indexing_slicing::INDEXING_SLICING_INFO, crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO, @@ -469,7 +470,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, crate::needless_if::NEEDLESS_IF_INFO, - crate::needless_impls::NEEDLESS_PARTIAL_ORD_IMPL_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs index ed21df4ff884a..f7894f9c17b07 100644 --- a/clippy_lints/src/incorrect_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -1,10 +1,16 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait}; +use clippy_utils::{ + diagnostics::{span_lint_and_sugg, span_lint_and_then}, + get_parent_node, is_res_lang_ctor, last_path_segment, path_res, + ty::implements_trait, +}; use rustc_errors::Applicability; +use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, PatKind, UnOp}; use rustc_hir::{ExprKind, ImplItem, ImplItemKind, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, symbol}; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -45,10 +51,59 @@ declare_clippy_lint! { correctness, "manual implementation of `Clone` on a `Copy` type" } -declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]); +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is + /// necessary. + /// + /// ### Why is this bad? + /// If both `PartialOrd` and `Ord` are implemented, they must agree. This is commonly done by + /// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently + /// introduce an error upon refactoring. + /// + /// ### Example + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// todo!(); + /// } + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Ord for A { + /// fn cmp(&self, other: &Self) -> Ordering { + /// todo!(); + /// } + /// } + /// + /// impl PartialOrd for A { + /// fn partial_cmp(&self, other: &Self) -> Option { + /// Some(self.cmp(other)) + /// } + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE, + correctness, + "manual implementation of `PartialOrd` when `Ord` is already implemented" +} +declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE, INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE]); impl LateLintPass<'_> for IncorrectImpls { - #[expect(clippy::needless_return)] + #[expect(clippy::too_many_lines)] fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { let node = get_parent_node(cx.tcx, impl_item.hir_id()); let Some(Node::Item(item)) = node else { @@ -68,10 +123,7 @@ impl LateLintPass<'_> for IncorrectImpls { let ExprKind::Block(block, ..) = body.value.kind else { return; }; - // Above is duplicated from the `duplicate_manual_partial_ord_impl` branch. - // Remove it while solving conflicts once that PR is merged. - // Actual implementation; remove this comment once aforementioned PR is merged if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id) && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) && implements_trait( @@ -116,5 +168,71 @@ impl LateLintPass<'_> for IncorrectImpls { return; } } + + if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl_def_id) + && impl_item.ident.name == sym::partial_cmp + && let Some(ord_def_id) = cx + .tcx + .diagnostic_items(trait_impl.def_id.krate) + .name_to_id + .get(&sym::Ord) + && implements_trait( + cx, + hir_ty_to_ty(cx.tcx, imp.self_ty), + *ord_def_id, + trait_impl.substs, + ) + { + if block.stmts.is_empty() + && let Some(expr) = block.expr + && let ExprKind::Call( + Expr { + kind: ExprKind::Path(some_path), + hir_id: some_hir_id, + .. + }, + [cmp_expr], + ) = expr.kind + && is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome) + && let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind + && cmp_path.ident.name == sym::cmp + && let Res::Local(..) = path_res(cx, other_expr) + {} else { + // If lhs and rhs are not the same type, bail. This makes creating a valid + // suggestion tons more complex. + if let Some(lhs) = trait_impl.substs.get(0) + && let Some(rhs) = trait_impl.substs.get(1) + && lhs != rhs + { + return; + } + + span_lint_and_then( + cx, + INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE, + item.span, + "incorrect implementation of `partial_cmp` on an `Ord` type", + |diag| { + let (help, app) = if let Some(other) = body.params.get(1) + && let PatKind::Binding(_, _, other_ident, ..) = other.pat.kind + { + ( + Cow::Owned(format!("{{ Some(self.cmp({})) }}", other_ident.name)), + Applicability::Unspecified, + ) + } else { + (Cow::Borrowed("{ Some(self.cmp(...)) }"), Applicability::HasPlaceholders) + }; + + diag.span_suggestion( + block.span, + "change this to", + help, + app, + ); + } + ); + } + } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1ec5b2e8b0aa8..00d46025caa86 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -227,7 +227,6 @@ mod needless_continue; mod needless_else; mod needless_for_each; mod needless_if; -mod needless_impls; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; diff --git a/clippy_lints/src/needless_impls.rs b/clippy_lints/src/needless_impls.rs deleted file mode 100644 index 4f8741bf3708f..0000000000000 --- a/clippy_lints/src/needless_impls.rs +++ /dev/null @@ -1,145 +0,0 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, get_parent_node, is_res_lang_ctor, path_res, ty::implements_trait, -}; -use rustc_errors::Applicability; -use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, PatKind}; -use rustc_hir_analysis::hir_ty_to_ty; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::EarlyBinder; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; -use std::borrow::Cow; - -declare_clippy_lint! { - /// ### What it does - /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is - /// necessary. - /// - /// ### Why is this bad? - /// If both `PartialOrd` and `Ord` are implemented, they must agree. This is commonly done by - /// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently - /// introduce an error upon refactoring. - /// - /// ### Example - /// ```rust,ignore - /// #[derive(Eq, PartialEq)] - /// struct A(u32); - /// - /// impl Ord for A { - /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); - /// } - /// } - /// - /// impl PartialOrd for A { - /// fn partial_cmp(&self, other: &Self) -> Option { - /// todo!(); - /// } - /// } - /// ``` - /// Use instead: - /// ```rust,ignore - /// #[derive(Eq, PartialEq)] - /// struct A(u32); - /// - /// impl Ord for A { - /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); - /// } - /// } - /// - /// impl PartialOrd for A { - /// fn partial_cmp(&self, other: &Self) -> Option { - /// Some(self.cmp(other)) - /// } - /// } - /// ``` - #[clippy::version = "1.72.0"] - pub NEEDLESS_PARTIAL_ORD_IMPL, - correctness, - "manual implementation of `PartialOrd` when `Ord` is already implemented" -} -declare_lint_pass!(NeedlessImpls => [NEEDLESS_PARTIAL_ORD_IMPL]); - -impl LateLintPass<'_> for NeedlessImpls { - fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { - let node = get_parent_node(cx.tcx, impl_item.hir_id()); - let Some(Node::Item(item)) = node else { - return; - }; - let ItemKind::Impl(imp) = item.kind else { - return; - }; - let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { - return; - }; - let trait_impl_def_id = trait_impl.def_id; - if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { - return; - } - let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { - return; - }; - let body = cx.tcx.hir().body(impl_item_id); - let ExprKind::Block(block, ..) = body.value.kind else { - return; - }; - - if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl_def_id) - && impl_item.ident.name == sym::partial_cmp - && let Some(ord_def_id) = cx - .tcx - .diagnostic_items(trait_impl.def_id.krate) - .name_to_id - .get(&sym::Ord) - && implements_trait( - cx, - hir_ty_to_ty(cx.tcx, imp.self_ty), - *ord_def_id, - trait_impl.substs, - ) - { - if block.stmts.is_empty() - && let Some(expr) = block.expr - && let ExprKind::Call( - Expr { - kind: ExprKind::Path(some_path), - hir_id: some_hir_id, - .. - }, - [cmp_expr], - ) = expr.kind - && is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome) - && let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind - && cmp_path.ident.name == sym::cmp - && let Res::Local(..) = path_res(cx, other_expr) - {} else { - span_lint_and_then( - cx, - NEEDLESS_PARTIAL_ORD_IMPL, - item.span, - "manual implementation of `PartialOrd` when `Ord` is already implemented", - |diag| { - let (help, app) = if let Some(other) = body.params.get(0) - && let PatKind::Binding(_, _, other_ident, ..) = other.pat.kind - { - ( - Cow::Owned(format!("{{ Some(self.cmp({})) }}", other_ident.name)), - Applicability::Unspecified, - ) - } else { - (Cow::Borrowed("{ Some(self.cmp(...)) }"), Applicability::HasPlaceholders) - }; - - diag.span_suggestion( - block.span, - "change this to", - help, - app, - ); - } - ); - } - } - } -} diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 33221c7777ea8..8689f89d2c33a 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -2,7 +2,7 @@ #![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] -#![allow(clippy::needless_partial_ord_impl)] +#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)] fn main() { let x = true; diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 5f909bd2a53fd..a1c94aff94b20 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -2,7 +2,7 @@ #![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] -#![allow(clippy::needless_partial_ord_impl)] +#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)] fn main() { let x = true; diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 44e18bff83fbf..ff4dcbfa2f2d9 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,4 +1,8 @@ -#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)] +#![allow( + clippy::incorrect_clone_impl_on_copy_type, + clippy::incorrect_partial_ord_impl_on_ord_type, + dead_code +)] #![warn(clippy::expl_impl_clone_on_copy)] #[derive(Copy)] diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index d37f7fa733196..f7948e044b7e3 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -1,5 +1,5 @@ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:7:1 + --> $DIR/derive.rs:11:1 | LL | / impl Clone for Qux { LL | | fn clone(&self) -> Self { @@ -9,7 +9,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:7:1 + --> $DIR/derive.rs:11:1 | LL | / impl Clone for Qux { LL | | fn clone(&self) -> Self { @@ -20,7 +20,7 @@ LL | | } = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:31:1 + --> $DIR/derive.rs:35:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | fn clone(&self) -> Self { @@ -30,7 +30,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:31:1 + --> $DIR/derive.rs:35:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | fn clone(&self) -> Self { @@ -40,7 +40,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:42:1 + --> $DIR/derive.rs:46:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -50,7 +50,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:42:1 + --> $DIR/derive.rs:46:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -60,7 +60,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:53:1 + --> $DIR/derive.rs:57:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { @@ -70,7 +70,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:53:1 + --> $DIR/derive.rs:57:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { @@ -80,7 +80,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:73:1 + --> $DIR/derive.rs:77:1 | LL | / impl Clone for Generic2 { LL | | fn clone(&self) -> Self { @@ -90,7 +90,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:73:1 + --> $DIR/derive.rs:77:1 | LL | / impl Clone for Generic2 { LL | | fn clone(&self) -> Self { diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 5d1a693321e5d..1fb3d51c46dc7 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -1,6 +1,6 @@ #![warn(clippy::derive_ord_xor_partial_ord)] #![allow(clippy::unnecessary_wraps)] -#![allow(clippy::needless_partial_ord_impl)] +#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)] use std::cmp::Ordering; diff --git a/tests/ui/needless_partial_ord_impl.rs b/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs similarity index 72% rename from tests/ui/needless_partial_ord_impl.rs rename to tests/ui/incorrect_partial_ord_impl_on_ord_type.rs index 8f5c1337369b8..25fe909a8d396 100644 --- a/tests/ui/needless_partial_ord_impl.rs +++ b/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs @@ -1,4 +1,3 @@ -//@run-rustfix #![allow(unused)] #![no_main] @@ -51,7 +50,7 @@ impl Ord for C { impl PartialOrd for C { fn partial_cmp(&self, _: &Self) -> Option { - todo!(); + todo!(); // don't run rustfix, or else this will cause it to fail to compile } } @@ -87,3 +86,32 @@ impl PartialOrd for Uwu { todo!(); } } + +// do not lint since `Rhs` is not `Self` + +#[derive(Eq, PartialEq)] +struct F(u32); + +impl Ord for F { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for F { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for F { + fn eq(&self, other: &u32) -> bool { + todo!(); + } +} + +impl PartialOrd for F { + fn partial_cmp(&self, other: &u32) -> Option { + todo!(); + } +} diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr b/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr new file mode 100644 index 0000000000000..86b3d37241a77 --- /dev/null +++ b/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr @@ -0,0 +1,28 @@ +error: incorrect implementation of `partial_cmp` on an `Ord` type + --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:17:1 + | +LL | / impl PartialOrd for A { +LL | | fn partial_cmp(&self, other: &Self) -> Option { + | | _____________________________________________________________- +LL | || todo!(); +LL | || } + | ||_____- help: change this to: `{ Some(self.cmp(other)) }` +LL | | } + | |__^ + | + = note: `#[deny(clippy::incorrect_partial_ord_impl_on_ord_type)]` on by default + +error: incorrect implementation of `partial_cmp` on an `Ord` type + --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:51:1 + | +LL | / impl PartialOrd for C { +LL | | fn partial_cmp(&self, _: &Self) -> Option { + | | _________________________________________________________- +LL | || todo!(); // don't run rustfix, or else this will cause it to fail to compile +LL | || } + | ||_____- help: change this to: `{ Some(self.cmp(...)) }` +LL | | } + | |__^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/needless_partial_ord_impl.fixed b/tests/ui/needless_partial_ord_impl.fixed deleted file mode 100644 index 7b47773ad766a..0000000000000 --- a/tests/ui/needless_partial_ord_impl.fixed +++ /dev/null @@ -1,85 +0,0 @@ -//@run-rustfix -#![allow(unused)] -#![no_main] - -use std::cmp::Ordering; - -// lint - -#[derive(Eq, PartialEq)] -struct A(u32); - -impl Ord for A { - fn cmp(&self, other: &Self) -> Ordering { - todo!(); - } -} - -impl PartialOrd for A { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(self)) } -} - -// do not lint - -#[derive(Eq, PartialEq)] -struct B(u32); - -impl Ord for B { - fn cmp(&self, other: &Self) -> Ordering { - todo!(); - } -} - -impl PartialOrd for B { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -// lint, but we can't give a suggestion since &Self is not named - -#[derive(Eq, PartialEq)] -struct C(u32); - -impl Ord for C { - fn cmp(&self, other: &Self) -> Ordering { - todo!(); - } -} - -impl PartialOrd for C { - fn partial_cmp(&self, _: &Self) -> Option { Some(self.cmp(self)) } -} - -// do not lint derived - -#[derive(Eq, Ord, PartialEq, PartialOrd)] -struct D(u32); - -// do not lint if ord is not manually implemented - -#[derive(Eq, PartialEq)] -struct E(u32); - -impl PartialOrd for E { - fn partial_cmp(&self, other: &Self) -> Option { - todo!(); - } -} - -// do not lint since ord has more restrictive bounds - -#[derive(Eq, PartialEq)] -struct Uwu(A); - -impl Ord for Uwu { - fn cmp(&self, other: &Self) -> Ordering { - todo!(); - } -} - -impl PartialOrd for Uwu { - fn partial_cmp(&self, other: &Self) -> Option { - todo!(); - } -} diff --git a/tests/ui/needless_partial_ord_impl.stderr b/tests/ui/needless_partial_ord_impl.stderr deleted file mode 100644 index b8978462cc0c2..0000000000000 --- a/tests/ui/needless_partial_ord_impl.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: manual implementation of `PartialOrd` when `Ord` is already implemented - --> $DIR/needless_partial_ord_impl.rs:18:1 - | -LL | / impl PartialOrd for A { -LL | | fn partial_cmp(&self, other: &Self) -> Option { - | | _____________________________________________________________- -LL | || todo!(); -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(self)) }` -LL | | } - | |__^ - | - = note: `#[deny(clippy::needless_partial_ord_impl)]` on by default - -error: manual implementation of `PartialOrd` when `Ord` is already implemented - --> $DIR/needless_partial_ord_impl.rs:52:1 - | -LL | / impl PartialOrd for C { -LL | | fn partial_cmp(&self, _: &Self) -> Option { - | | _________________________________________________________- -LL | || todo!(); -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(self)) }` -LL | | } - | |__^ - -error: aborting due to 2 previous errors - From a5dfb68491505d8ad2aceb8cb14e1bd7272dcc2a Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 30 Jun 2023 15:16:56 -0500 Subject: [PATCH 54/80] refactor --- clippy_lints/src/incorrect_impls.rs | 76 ++++++------ .../incorrect_clone_impl_on_copy_type.stderr | 4 +- ...correct_partial_ord_impl_on_ord_type.fixed | 114 ++++++++++++++++++ .../incorrect_partial_ord_impl_on_ord_type.rs | 5 +- ...orrect_partial_ord_impl_on_ord_type.stderr | 23 ++-- 5 files changed, 173 insertions(+), 49 deletions(-) create mode 100644 tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs index f7894f9c17b07..25e1cb36b74a1 100644 --- a/clippy_lints/src/incorrect_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -4,13 +4,12 @@ use clippy_utils::{ ty::implements_trait, }; use rustc_errors::Applicability; -use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, PatKind, UnOp}; -use rustc_hir::{ExprKind, ImplItem, ImplItemKind, Node, UnOp}; +use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp}; +use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{sym, symbol}; -use std::borrow::Cow; +use rustc_span::{sym, symbol::kw}; declare_clippy_lint! { /// ### What it does @@ -61,31 +60,39 @@ declare_clippy_lint! { /// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently /// introduce an error upon refactoring. /// + /// ### Limitations + /// Will not lint if `Self` and `Rhs` do not have the same type. + /// /// ### Example - /// ```rust,ignore + /// ```rust + /// # use std::cmp::Ordering; /// #[derive(Eq, PartialEq)] /// struct A(u32); /// /// impl Ord for A { /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); + /// // ... + /// # todo!(); /// } /// } /// /// impl PartialOrd for A { /// fn partial_cmp(&self, other: &Self) -> Option { - /// todo!(); + /// // ... + /// # todo!(); /// } /// } /// ``` /// Use instead: - /// ```rust,ignore + /// ```rust + /// # use std::cmp::Ordering; /// #[derive(Eq, PartialEq)] /// struct A(u32); /// /// impl Ord for A { /// fn cmp(&self, other: &Self) -> Ordering { - /// todo!(); + /// // ... + /// # todo!(); /// } /// } /// @@ -105,17 +112,18 @@ declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE, INCORRE impl LateLintPass<'_> for IncorrectImpls { #[expect(clippy::too_many_lines)] fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { - let node = get_parent_node(cx.tcx, impl_item.hir_id()); - let Some(Node::Item(item)) = node else { + let Some(Node::Item(item)) = get_parent_node(cx.tcx, impl_item.hir_id()) else { return; }; let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { return; }; - let trait_impl_def_id = trait_impl.def_id; if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { return; } + let ItemKind::Impl(imp) = item.kind else { + return; + }; let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { return; }; @@ -124,7 +132,7 @@ impl LateLintPass<'_> for IncorrectImpls { return; }; - if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id) + if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl.def_id) && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) && implements_trait( cx, @@ -136,9 +144,9 @@ impl LateLintPass<'_> for IncorrectImpls { if impl_item.ident.name == sym::clone { if block.stmts.is_empty() && let Some(expr) = block.expr - && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind - && let ExprKind::Path(qpath) = inner.kind - && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower + && let ExprKind::Unary(UnOp::Deref, deref) = expr.kind + && let ExprKind::Path(qpath) = deref.kind + && last_path_segment(&qpath).ident.name == kw::SelfLower {} else { span_lint_and_sugg( cx, @@ -160,7 +168,7 @@ impl LateLintPass<'_> for IncorrectImpls { INCORRECT_CLONE_IMPL_ON_COPY_TYPE, impl_item.span, "incorrect implementation of `clone_from` on a `Copy` type", - "remove this", + "remove it", String::new(), Applicability::MaybeIncorrect, ); @@ -169,7 +177,7 @@ impl LateLintPass<'_> for IncorrectImpls { } } - if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl_def_id) + if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl.def_id) && impl_item.ident.name == sym::partial_cmp && let Some(ord_def_id) = cx .tcx @@ -198,12 +206,9 @@ impl LateLintPass<'_> for IncorrectImpls { && cmp_path.ident.name == sym::cmp && let Res::Local(..) = path_res(cx, other_expr) {} else { - // If lhs and rhs are not the same type, bail. This makes creating a valid + // If `Self` and `Rhs` are not the same type, bail. This makes creating a valid // suggestion tons more complex. - if let Some(lhs) = trait_impl.substs.get(0) - && let Some(rhs) = trait_impl.substs.get(1) - && lhs != rhs - { + if let [lhs, rhs, ..] = trait_impl.substs.as_slice() && lhs != rhs { return; } @@ -213,22 +218,23 @@ impl LateLintPass<'_> for IncorrectImpls { item.span, "incorrect implementation of `partial_cmp` on an `Ord` type", |diag| { - let (help, app) = if let Some(other) = body.params.get(1) - && let PatKind::Binding(_, _, other_ident, ..) = other.pat.kind - { - ( - Cow::Owned(format!("{{ Some(self.cmp({})) }}", other_ident.name)), - Applicability::Unspecified, - ) + let [_, other] = body.params else { + return; + }; + + let suggs = if let Some(other_ident) = other.pat.simple_ident() { + vec![(block.span, format!("{{ Some(self.cmp({})) }}", other_ident.name))] } else { - (Cow::Borrowed("{ Some(self.cmp(...)) }"), Applicability::HasPlaceholders) + vec![ + (block.span, "{ Some(self.cmp(other)) }".to_owned()), + (other.pat.span, "other".to_owned()), + ] }; - diag.span_suggestion( - block.span, + diag.multipart_suggestion( "change this to", - help, - app, + suggs, + Applicability::Unspecified, ); } ); diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/tests/ui/incorrect_clone_impl_on_copy_type.stderr index 0021841aa860f..7bcba8ba45a24 100644 --- a/tests/ui/incorrect_clone_impl_on_copy_type.stderr +++ b/tests/ui/incorrect_clone_impl_on_copy_type.stderr @@ -16,7 +16,7 @@ LL | / fn clone_from(&mut self, source: &Self) { LL | | source.clone(); LL | | *self = source.clone(); LL | | } - | |_____^ help: remove this + | |_____^ help: remove it error: incorrect implementation of `clone` on a `Copy` type --> $DIR/incorrect_clone_impl_on_copy_type.rs:81:29 @@ -34,7 +34,7 @@ LL | / fn clone_from(&mut self, source: &Self) { LL | | source.clone(); LL | | *self = source.clone(); LL | | } - | |_____^ help: remove this + | |_____^ help: remove it error: aborting due to 4 previous errors diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed b/tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed new file mode 100644 index 0000000000000..dd4fdd98822c7 --- /dev/null +++ b/tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed @@ -0,0 +1,114 @@ +//@run-rustfix +#![allow(unused)] +#![no_main] + +use std::cmp::Ordering; + +// lint + +#[derive(Eq, PartialEq)] +struct A(u32); + +impl Ord for A { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for A { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + +// do not lint + +#[derive(Eq, PartialEq)] +struct B(u32); + +impl Ord for B { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for B { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// lint, and give `_` a name + +#[derive(Eq, PartialEq)] +struct C(u32); + +impl Ord for C { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for C { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + +// do not lint derived + +#[derive(Eq, Ord, PartialEq, PartialOrd)] +struct D(u32); + +// do not lint if ord is not manually implemented + +#[derive(Eq, PartialEq)] +struct E(u32); + +impl PartialOrd for E { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} + +// do not lint since ord has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Ord for Uwu { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for Uwu { + fn partial_cmp(&self, other: &Self) -> Option { + todo!(); + } +} + +// do not lint since `Rhs` is not `Self` + +#[derive(Eq, PartialEq)] +struct F(u32); + +impl Ord for F { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for F { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for F { + fn eq(&self, other: &u32) -> bool { + todo!(); + } +} + +impl PartialOrd for F { + fn partial_cmp(&self, other: &u32) -> Option { + todo!(); + } +} diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs b/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs index 25fe909a8d396..522e82299c0a5 100644 --- a/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs +++ b/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs @@ -1,3 +1,4 @@ +//@run-rustfix #![allow(unused)] #![no_main] @@ -37,7 +38,7 @@ impl PartialOrd for B { } } -// lint, but we can't give a suggestion since &Self is not named +// lint, and give `_` a name #[derive(Eq, PartialEq)] struct C(u32); @@ -50,7 +51,7 @@ impl Ord for C { impl PartialOrd for C { fn partial_cmp(&self, _: &Self) -> Option { - todo!(); // don't run rustfix, or else this will cause it to fail to compile + todo!(); } } diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr b/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr index 86b3d37241a77..0e477798c406e 100644 --- a/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr +++ b/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr @@ -1,5 +1,5 @@ error: incorrect implementation of `partial_cmp` on an `Ord` type - --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:17:1 + --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:18:1 | LL | / impl PartialOrd for A { LL | | fn partial_cmp(&self, other: &Self) -> Option { @@ -13,16 +13,19 @@ LL | | } = note: `#[deny(clippy::incorrect_partial_ord_impl_on_ord_type)]` on by default error: incorrect implementation of `partial_cmp` on an `Ord` type - --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:51:1 + --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:52:1 | -LL | / impl PartialOrd for C { -LL | | fn partial_cmp(&self, _: &Self) -> Option { - | | _________________________________________________________- -LL | || todo!(); // don't run rustfix, or else this will cause it to fail to compile -LL | || } - | ||_____- help: change this to: `{ Some(self.cmp(...)) }` -LL | | } - | |__^ +LL | / impl PartialOrd for C { +LL | | fn partial_cmp(&self, _: &Self) -> Option { +LL | | todo!(); +LL | | } +LL | | } + | |_^ + | +help: change this to + | +LL | fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors From 41438c2b90f0324494c6ca22d205bf0acec4c03c Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 4 Jul 2023 12:49:15 -0500 Subject: [PATCH 55/80] Refactor, remove `Constant::to_bits` --- README.md | 2 +- book/src/README.md | 2 +- clippy_lints/src/manual_float_methods.rs | 59 +++++++++++++++--------- clippy_utils/src/consts.rs | 11 ----- tests/ui/manual_float_methods.rs | 21 ++++++++- tests/ui/manual_float_methods.stderr | 12 ++--- 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index d712d3e675074..5d490645d8979 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. diff --git a/book/src/README.md b/book/src/README.md index 3b6270962680e..486ea3df70420 100644 --- a/book/src/README.md +++ b/book/src/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index 0f488627b4e93..09b39634333fc 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -1,5 +1,8 @@ use clippy_utils::{ - consts::constant, diagnostics::span_lint_and_then, is_from_proc_macro, path_to_local, source::snippet_opt, + consts::{constant, Constant}, + diagnostics::span_lint_and_then, + is_from_proc_macro, path_to_local, + source::snippet_opt, }; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -9,10 +12,11 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does - /// Checks for `x == ::INFINITY || x == ::NEG_INFINITY`. + /// Checks for manual `is_infinite` reimplementations + /// (i.e., `x == ::INFINITY || x == ::NEG_INFINITY`). /// /// ### Why is this bad? - /// This should use the dedicated method instead, `is_infinite`. + /// The method `is_infinite` is shorter and more readable. /// /// ### Example /// ```rust @@ -31,20 +35,23 @@ declare_clippy_lint! { } declare_clippy_lint! { /// ### What it does - /// Checks for `x != ::INFINITY && x != ::NEG_INFINITY`. + /// Checks for manual `is_finite` reimplementations + /// (i.e., `x != ::INFINITY && x != ::NEG_INFINITY`). /// /// ### Why is this bad? - /// This should use the dedicated method instead, `is_finite`. + /// The method `is_finite` is shorter and more readable. /// /// ### Example /// ```rust /// # let x = 1.0f32; /// if x != f32::INFINITY && x != f32::NEG_INFINITY {} + /// if x.abs() < f32::INFINITY {} /// ``` /// Use instead: /// ```rust /// # let x = 1.0f32; /// if x.is_finite() {} + /// if x.is_finite() {} /// ``` #[clippy::version = "1.72.0"] pub MANUAL_IS_FINITE, @@ -84,20 +91,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind // Checking all possible scenarios using a function would be a hopeless task, as we have // 16 possible alignments of constants/operands. For now, let's use `partition`. - && let (operands, consts) = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs] + && let (operands, constants) = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs] .into_iter() .partition::>, _>(|i| path_to_local(i).is_some()) && let [first, second] = &*operands - && let Some([const_1, const_2]) = consts + && let Some([const_1, const_2]) = constants .into_iter() - .map(|i| constant(cx, cx.typeck_results(), i).and_then(|c| c.to_bits())) + .map(|i| constant(cx, cx.typeck_results(), i)) .collect::>>() .as_deref() && path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s)) - && (is_infinity(*const_1) && is_neg_infinity(*const_2) - || is_neg_infinity(*const_1) && is_infinity(*const_2)) - && let Some(local_snippet) = snippet_opt(cx, first.span) + // The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in + // case somebody does that for some reason + && (is_infinity(const_1) && is_neg_infinity(const_2) + || is_neg_infinity(const_1) && is_infinity(const_2)) && !is_from_proc_macro(cx, expr) + && let Some(local_snippet) = snippet_opt(cx, first.span) { let variant = match (kind.node, lhs_kind.node, rhs_kind.node) { (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite, @@ -128,31 +137,39 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { "use the dedicated method instead", format!("{local_snippet}.is_finite()"), Applicability::MaybeIncorrect, - ); - diag.span_suggestion_verbose( + ) + .span_suggestion_verbose( expr.span, "this will alter how it handles NaN; if that is a problem, use instead", format!("{local_snippet}.is_finite() || {local_snippet}.is_nan()"), Applicability::MaybeIncorrect, - ); - diag.span_suggestion_verbose( + ) + .span_suggestion_verbose( expr.span, "or, for conciseness", format!("!{local_snippet}.is_infinite()"), Applicability::MaybeIncorrect, ); - } + }, } - } + }, ); } } } -fn is_infinity(bits: u128) -> bool { - bits == 0x7f80_0000 || bits == 0x7ff0_0000_0000_0000 +fn is_infinity(constant: &Constant<'_>) -> bool { + match constant { + Constant::F32(float) => *float == f32::INFINITY, + Constant::F64(float) => *float == f64::INFINITY, + _ => false, + } } -fn is_neg_infinity(bits: u128) -> bool { - bits == 0xff80_0000 || bits == 0xfff0_0000_0000_0000 +fn is_neg_infinity(constant: &Constant<'_>) -> bool { + match constant { + Constant::F32(float) => *float == f32::NEG_INFINITY, + Constant::F64(float) => *float == f64::NEG_INFINITY, + _ => false, + } } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index b9f8eefeb8e7c..87d85d742ce41 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -190,17 +190,6 @@ impl<'tcx> Constant<'tcx> { } } - /// Returns the bit representation if `self` is a bool, integer, or float. - pub fn to_bits(&self) -> Option { - match self { - Constant::Int(int) => Some(*int), - Constant::F32(float) => Some(u128::from(float.to_bits())), - Constant::F64(float) => Some(u128::from(float.to_bits())), - Constant::Bool(bool) => Some(u128::from(*bool)), - _ => None, - } - } - /// Returns the integer value or `None` if `self` or `val_type` is not integer type. pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option { if let Constant::Int(const_int) = *self { diff --git a/tests/ui/manual_float_methods.rs b/tests/ui/manual_float_methods.rs index b772202c003f5..af9076cfb71fc 100644 --- a/tests/ui/manual_float_methods.rs +++ b/tests/ui/manual_float_methods.rs @@ -1,6 +1,7 @@ //@aux-build:proc_macros.rs:proc-macro #![allow(clippy::needless_if, unused)] #![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] +#![feature(inline_const)] #[macro_use] extern crate proc_macros; @@ -8,6 +9,14 @@ extern crate proc_macros; const INFINITE: f32 = f32::INFINITY; const NEG_INFINITE: f32 = f32::NEG_INFINITY; +fn fn_test() -> f64 { + f64::NEG_INFINITY +} + +fn fn_test_not_inf() -> f64 { + 112.0 +} + fn main() { let x = 1.0f32; if x == f32::INFINITY || x == f32::NEG_INFINITY {} @@ -20,8 +29,18 @@ fn main() { // Don't lint if x.is_infinite() {} if x.is_finite() {} - // If they're doing it this way, they probably know what they're doing if x.abs() < f64::INFINITY {} + if f64::INFINITY > x.abs() {} + if f64::abs(x) < f64::INFINITY {} + if f64::INFINITY > f64::abs(x) {} + // Is not evaluated by `clippy_utils::constant` + if x != f64::INFINITY && x != fn_test() {} + // Not -inf + if x != f64::INFINITY && x != fn_test_not_inf() {} + const X: f64 = 1.0f64; + // Will be linted if `const_float_classify` is enabled + if const { X == f64::INFINITY || X == f64::NEG_INFINITY } {} + if const { X != f64::INFINITY && X != f64::NEG_INFINITY } {} external! { let x = 1.0; if x == f32::INFINITY || x == f32::NEG_INFINITY {} diff --git a/tests/ui/manual_float_methods.stderr b/tests/ui/manual_float_methods.stderr index 7f4a4d2e95b39..a56118b316ae3 100644 --- a/tests/ui/manual_float_methods.stderr +++ b/tests/ui/manual_float_methods.stderr @@ -1,5 +1,5 @@ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:13:8 + --> $DIR/manual_float_methods.rs:22:8 | LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` @@ -7,7 +7,7 @@ LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} = note: `-D clippy::manual-is-infinite` implied by `-D warnings` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:14:8 + --> $DIR/manual_float_methods.rs:23:8 | LL | if x != f32::INFINITY && x != f32::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,13 +27,13 @@ LL | if !x.is_infinite() {} | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:15:8 + --> $DIR/manual_float_methods.rs:24:8 | LL | if x == INFINITE || x == NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:16:8 + --> $DIR/manual_float_methods.rs:25:8 | LL | if x != INFINITE && x != NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,13 +52,13 @@ LL | if !x.is_infinite() {} | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> $DIR/manual_float_methods.rs:18:8 + --> $DIR/manual_float_methods.rs:27:8 | LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> $DIR/manual_float_methods.rs:19:8 + --> $DIR/manual_float_methods.rs:28:8 | LL | if x != f64::INFINITY && x != f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 2be695bf290299563c5589b3954bd9d044cfa6b9 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 8 Jul 2023 17:43:34 -0300 Subject: [PATCH 56/80] [significant_drop_tightening] Fix #11128 --- .../src/significant_drop_tightening.rs | 11 +++++---- clippy_utils/src/paths.rs | 1 + tests/ui/significant_drop_tightening.fixed | 23 +++++++++++++++++++ tests/ui/significant_drop_tightening.rs | 23 +++++++++++++++++++ tests/ui/significant_drop_tightening.stderr | 6 ++--- 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index fffa8a380c2f8..3febf74796747 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -1,12 +1,13 @@ use clippy_utils::{ diagnostics::span_lint_and_then, - expr_or_init, get_attr, path_to_local, + expr_or_init, get_attr, match_def_path, path_to_local, paths, source::{indent_of, snippet}, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir::{ self as hir, + def::{DefKind, Res}, intravisit::{walk_expr, Visitor}, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -333,7 +334,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o } }, hir::StmtKind::Semi(expr) => { - if has_drop(expr, &apa.first_bind_ident) { + if has_drop(expr, &apa.first_bind_ident, self.cx) { apa.has_expensive_expr_after_last_attr = false; apa.last_stmt_span = DUMMY_SP; return; @@ -430,11 +431,11 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> { } } -fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident) -> bool { +fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool { if let hir::ExprKind::Call(fun, args) = expr.kind && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind - && let [fun_ident, ..] = fun_path.segments - && fun_ident.ident.name == rustc_span::sym::drop + && let Res::Def(DefKind::Fn, did) = fun_path.res + && match_def_path(lcx, did, &paths::DROP) && let [first_arg, ..] = args && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind && let [first_arg_ps, .. ] = arg_path.segments diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 0e6f01287b561..e8510987225a2 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -57,6 +57,7 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; #[cfg(feature = "internal")] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; +pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"]; #[cfg(feature = "internal")] pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index 7b848ead78467..eb8524167c4a3 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -28,6 +28,29 @@ pub fn issue_10413() { } } +pub fn issue_11128() { + use std::mem::drop as unlock; + + struct Foo { + droppable: Option>, + mutex: Mutex>, + } + + impl Drop for Foo { + fn drop(&mut self) { + if let Some(droppable) = self.droppable.take() { + let lock = self.mutex.lock().unwrap(); + let idx_opt = lock.iter().copied().find(|el| Some(el) == droppable.first()); + if let Some(idx) = idx_opt { + let local_droppable = vec![lock.first().copied().unwrap_or_default()]; + unlock(lock); + drop(local_droppable); + } + } + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index 36f77cf1bdb6e..f7fa65ea92270 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -27,6 +27,29 @@ pub fn issue_10413() { } } +pub fn issue_11128() { + use std::mem::drop as unlock; + + struct Foo { + droppable: Option>, + mutex: Mutex>, + } + + impl Drop for Foo { + fn drop(&mut self) { + if let Some(droppable) = self.droppable.take() { + let lock = self.mutex.lock().unwrap(); + let idx_opt = lock.iter().copied().find(|el| Some(el) == droppable.first()); + if let Some(idx) = idx_opt { + let local_droppable = vec![lock.first().copied().unwrap_or_default()]; + unlock(lock); + drop(local_droppable); + } + } + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index 3bdac0b0a6b7b..ca4fede17c93a 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -23,7 +23,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:56:13 + --> $DIR/significant_drop_tightening.rs:79:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -43,7 +43,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:77:13 + --> $DIR/significant_drop_tightening.rs:100:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -67,7 +67,7 @@ LL + | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:83:17 + --> $DIR/significant_drop_tightening.rs:106:17 | LL | / { LL | | let mutex = Mutex::new(vec![1i32]); From 6384221910ce09cca044511d52c489f6193bca7d Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 8 Jul 2023 18:08:48 -0300 Subject: [PATCH 57/80] Dogfood --- clippy_lints/src/significant_drop_tightening.rs | 5 +++-- clippy_utils/src/paths.rs | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index 3febf74796747..cc2dbae4bc4b5 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -1,6 +1,6 @@ use clippy_utils::{ diagnostics::span_lint_and_then, - expr_or_init, get_attr, match_def_path, path_to_local, paths, + expr_or_init, get_attr, path_to_local, source::{indent_of, snippet}, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; @@ -13,6 +13,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::sym; use rustc_span::{symbol::Ident, Span, DUMMY_SP}; use std::borrow::Cow; @@ -435,7 +436,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_ if let hir::ExprKind::Call(fun, args) = expr.kind && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind && let Res::Def(DefKind::Fn, did) = fun_path.res - && match_def_path(lcx, did, &paths::DROP) + && lcx.tcx.is_diagnostic_item(sym::mem_drop, did) && let [first_arg, ..] = args && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind && let [first_arg_ps, .. ] = arg_path.segments diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index e8510987225a2..0e6f01287b561 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -57,7 +57,6 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; #[cfg(feature = "internal")] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; -pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"]; #[cfg(feature = "internal")] pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; From b4738a6b572c0aa3752a6a9bf6c4036de7feee19 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 8 Jul 2023 19:11:15 -0400 Subject: [PATCH 58/80] Add test for #10535 --- tests/ui/needless_borrow.fixed | 12 ++++++++++++ tests/ui/needless_borrow.rs | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 80cdb4e472d41..1dfbee150d789 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -492,3 +492,15 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +mod issue_10535 { + static SOME_STATIC: String = String::new(); + + static UNIT: () = compute(&SOME_STATIC); + + pub const fn compute(_: T) + where + T: Copy, + { + } +} diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 99f735127eb8e..3c0d73f5f0253 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -492,3 +492,15 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +mod issue_10535 { + static SOME_STATIC: String = String::new(); + + static UNIT: () = compute(&SOME_STATIC); + + pub const fn compute(_: T) + where + T: Copy, + { + } +} From 3bf2138289151bb400b53a9817d6e6ab2cf12f13 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 8 Jul 2023 19:12:10 -0400 Subject: [PATCH 59/80] Fix #10535 --- clippy_lints/src/dereference.rs | 4 ++-- clippy_utils/src/mir/mod.rs | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 73556c1053ecd..12f2f37e3c258 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1296,8 +1296,8 @@ fn referent_used_exactly_once<'tcx>( possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, reference: &Expr<'tcx>, ) -> bool { - let mir = enclosing_mir(cx.tcx, reference.hir_id); - if let Some(local) = expr_local(cx.tcx, reference) + if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id) + && let Some(local) = expr_local(cx.tcx, reference) && let [location] = *local_assignments(mir, local).as_slice() && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index) && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index 26c0015e87e0f..131f3c0aa3946 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -101,21 +101,26 @@ pub fn used_exactly_once(mir: &rustc_middle::mir::Body<'_>, local: rustc_middle: /// Returns the `mir::Body` containing the node associated with `hir_id`. #[allow(clippy::module_name_repetitions)] -pub fn enclosing_mir(tcx: TyCtxt<'_>, hir_id: HirId) -> &Body<'_> { +pub fn enclosing_mir(tcx: TyCtxt<'_>, hir_id: HirId) -> Option<&Body<'_>> { let body_owner_local_def_id = tcx.hir().enclosing_body_owner(hir_id); - tcx.optimized_mir(body_owner_local_def_id.to_def_id()) + if tcx.hir().body_owner_kind(body_owner_local_def_id).is_fn_or_closure() { + Some(tcx.optimized_mir(body_owner_local_def_id.to_def_id())) + } else { + None + } } /// Tries to determine the `Local` corresponding to `expr`, if any. /// This function is expensive and should be used sparingly. pub fn expr_local(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> Option { - let mir = enclosing_mir(tcx, expr.hir_id); - mir.local_decls.iter_enumerated().find_map(|(local, local_decl)| { - if local_decl.source_info.span == expr.span { - Some(local) - } else { - None - } + enclosing_mir(tcx, expr.hir_id).and_then(|mir| { + mir.local_decls.iter_enumerated().find_map(|(local, local_decl)| { + if local_decl.source_info.span == expr.span { + Some(local) + } else { + None + } + }) }) } From d1575d1f544691ec3c5b24834b99df0a7df0534a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 9 Jul 2023 21:59:23 +0200 Subject: [PATCH 60/80] changelog: Fix typo in `needless_pass_by_ref_mut` lint description --- clippy_lints/src/needless_pass_by_ref_mut.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 96cb09c071ace..46c9b6c4141f1 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// ### What it does /// Check if a `&mut` function argument is actually used mutably. /// - /// Be careful if the function is publically reexported as it would break compatibility with + /// Be careful if the function is publicly reexported as it would break compatibility with /// users of this function. /// /// ### Why is this bad? From 23ac72316d7cf0c7979bf94544b2cc8f3ea3f89f Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 23 Jun 2023 23:23:36 +0200 Subject: [PATCH 61/80] adjust applicability and suggest making binding mutable --- clippy_lints/src/methods/filter_next.rs | 51 ++++++++++++++++++++----- tests/ui/methods_unfixable.rs | 10 +++++ tests/ui/methods_unfixable.stderr | 15 ++++++++ 3 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 tests/ui/methods_unfixable.rs create mode 100644 tests/ui/methods_unfixable.stderr diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs index ad71b49461904..ce7f9997b5a63 100644 --- a/clippy_lints/src/methods/filter_next.rs +++ b/clippy_lints/src/methods/filter_next.rs @@ -1,6 +1,7 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; +use rustc_ast::{BindingAnnotation, Mutability}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -8,6 +9,21 @@ use rustc_span::sym; use super::FILTER_NEXT; +fn path_to_local(expr: &hir::Expr<'_>) -> Option { + match expr.kind { + hir::ExprKind::Field(f, _) => path_to_local(f), + hir::ExprKind::Index(recv, _) => path_to_local(recv), + hir::ExprKind::Path(hir::QPath::Resolved( + _, + hir::Path { + res: rustc_hir::def::Res::Local(local), + .. + }, + )) => Some(*local), + _ => None, + } +} + /// lint use of `filter().next()` for `Iterators` pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, @@ -26,15 +42,30 @@ pub(super) fn check<'tcx>( if filter_snippet.lines().count() <= 1 { let iter_snippet = snippet(cx, recv.span, ".."); // add note if not multi-line - span_lint_and_sugg( - cx, - FILTER_NEXT, - expr.span, - msg, - "try", - format!("{iter_snippet}.find({filter_snippet})"), - Applicability::MachineApplicable, - ); + span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| { + let (applicability, pat) = if let Some(id) = path_to_local(recv) + && let Some(hir::Node::Pat(pat)) = cx.tcx.hir().find(id) + && let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind + { + (Applicability::Unspecified, Some((pat.span, ident))) + } else { + (Applicability::MachineApplicable, None) + }; + + diag.span_suggestion( + expr.span, + "try", + format!("{iter_snippet}.find({filter_snippet})"), + applicability, + ); + + if let Some((pat_span, ident)) = pat { + diag.span_help( + pat_span, + format!("you will also need to make `{ident}` mutable, because `find` takes `&mut self`"), + ); + } + }); } else { span_lint(cx, FILTER_NEXT, expr.span, msg); } diff --git a/tests/ui/methods_unfixable.rs b/tests/ui/methods_unfixable.rs new file mode 100644 index 0000000000000..3d88ce4b6bbdc --- /dev/null +++ b/tests/ui/methods_unfixable.rs @@ -0,0 +1,10 @@ +#![warn(clippy::filter_next)] + +fn main() { + issue10029(); +} + +pub fn issue10029() { + let iter = (0..10); + let _ = iter.filter(|_| true).next(); +} diff --git a/tests/ui/methods_unfixable.stderr b/tests/ui/methods_unfixable.stderr new file mode 100644 index 0000000000000..6e101fe16b09b --- /dev/null +++ b/tests/ui/methods_unfixable.stderr @@ -0,0 +1,15 @@ +error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead + --> $DIR/methods_unfixable.rs:9:13 + | +LL | let _ = iter.filter(|_| true).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `iter.find(|_| true)` + | +help: you will also need to make `iter` mutable, because `find` takes `&mut self` + --> $DIR/methods_unfixable.rs:8:9 + | +LL | let iter = (0..10); + | ^^^^ + = note: `-D clippy::filter-next` implied by `-D warnings` + +error: aborting due to previous error + From 103949b241f66085d41f99d5f8ddbc281844df6d Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 20:01:36 +0200 Subject: [PATCH 62/80] Drop uplifted `clippy::fn_null_check` --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/fn_null_check.rs | 102 -------------------------- clippy_lints/src/lib.rs | 2 - clippy_lints/src/renamed_lints.rs | 1 + tests/ui/fn_null_check.rs | 22 ------ tests/ui/fn_null_check.stderr | 43 ----------- tests/ui/rename.fixed | 2 + tests/ui/rename.rs | 2 + tests/ui/rename.stderr | 112 +++++++++++++++-------------- 9 files changed, 64 insertions(+), 223 deletions(-) delete mode 100644 clippy_lints/src/fn_null_check.rs delete mode 100644 tests/ui/fn_null_check.rs delete mode 100644 tests/ui/fn_null_check.stderr diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9d9ee6ba30792..b60f0738f6497 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -171,7 +171,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::float_literal::LOSSY_FLOAT_LITERAL_INFO, crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO, crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO, - crate::fn_null_check::FN_NULL_CHECK_INFO, crate::format::USELESS_FORMAT_INFO, crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO, crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, diff --git a/clippy_lints/src/fn_null_check.rs b/clippy_lints/src/fn_null_check.rs deleted file mode 100644 index 521045a9fed8f..0000000000000 --- a/clippy_lints/src/fn_null_check.rs +++ /dev/null @@ -1,102 +0,0 @@ -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; -use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for comparing a function pointer to null. - /// - /// ### Why is this bad? - /// Function pointers are assumed to not be null. - /// - /// ### Example - /// ```rust,ignore - /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ - /// - /// if (fn_ptr as *const ()).is_null() { ... } - /// ``` - /// Use instead: - /// ```rust,ignore - /// let fn_ptr: Option = /* somehow obtained nullable function pointer */ - /// - /// if fn_ptr.is_none() { ... } - /// ``` - #[clippy::version = "1.68.0"] - pub FN_NULL_CHECK, - correctness, - "`fn()` type assumed to be nullable" -} -declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]); - -fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { - span_lint_and_help( - cx, - FN_NULL_CHECK, - expr.span, - "function pointer assumed to be nullable, even though it isn't", - None, - "try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value", - ); -} - -fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind - && let TyKind::Ptr(_) = cast_ty.kind - { - cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn() - } else { - false - } -} - -impl<'tcx> LateLintPass<'tcx> for FnNullCheck { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - match expr.kind { - // Catching: - // (fn_ptr as * ).is_null() - ExprKind::MethodCall(method_name, receiver, _, _) - if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) => - { - lint_expr(cx, expr); - }, - - ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { - let to_check: &Expr<'_>; - if is_fn_ptr_cast(cx, left) { - to_check = right; - } else if is_fn_ptr_cast(cx, right) { - to_check = left; - } else { - return; - } - - match to_check.kind { - // Catching: - // (fn_ptr as * ) == (0 as ) - ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == std::ptr::null() - ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == - _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => { - lint_expr(cx, expr); - }, - - _ => {}, - } - }, - _ => {}, - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 87329ee5e14ac..365cc4c59ad46 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -131,7 +131,6 @@ mod extra_unused_type_parameters; mod fallible_impl_from; mod float_literal; mod floating_point_arithmetic; -mod fn_null_check; mod format; mod format_args; mod format_impl; @@ -1003,7 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: semicolon_outside_block_ignore_multiline, )) }); - store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse)); store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef)); store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock)); diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index cbcd11debfd76..d24215c229245 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -42,6 +42,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"), ("clippy::forget_copy", "forgetting_copy_types"), ("clippy::forget_ref", "forgetting_references"), + ("clippy::fn_null_check", "incorrect_fn_null_checks"), ("clippy::into_iter_on_array", "array_into_iter"), ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"), ("clippy::invalid_ref", "invalid_value"), diff --git a/tests/ui/fn_null_check.rs b/tests/ui/fn_null_check.rs deleted file mode 100644 index dfdea100c8fd7..0000000000000 --- a/tests/ui/fn_null_check.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(unused)] -#![warn(clippy::fn_null_check)] -#![allow(clippy::cmp_null)] -#![allow(clippy::needless_if)] -#![allow(clippy::ptr_eq)] -#![allow(clippy::zero_ptr)] - -pub const ZPTR: *const () = 0 as *const _; -pub const NOT_ZPTR: *const () = 1 as *const _; - -fn main() { - let fn_ptr = main; - - if (fn_ptr as *mut ()).is_null() {} - if (fn_ptr as *const u8).is_null() {} - if (fn_ptr as *const ()) == std::ptr::null() {} - if (fn_ptr as *const ()) == (0 as *const ()) {} - if (fn_ptr as *const ()) == ZPTR {} - - // no lint - if (fn_ptr as *const ()) == NOT_ZPTR {} -} diff --git a/tests/ui/fn_null_check.stderr b/tests/ui/fn_null_check.stderr deleted file mode 100644 index 5b9f48a961caf..0000000000000 --- a/tests/ui/fn_null_check.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:14:8 - | -LL | if (fn_ptr as *mut ()).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - = note: `-D clippy::fn-null-check` implied by `-D warnings` - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:15:8 - | -LL | if (fn_ptr as *const u8).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:16:8 - | -LL | if (fn_ptr as *const ()) == std::ptr::null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:17:8 - | -LL | if (fn_ptr as *const ()) == (0 as *const ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:18:8 - | -LL | if (fn_ptr as *const ()) == ZPTR {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: aborting due to 5 previous errors - diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index b24c83d9a0da2..cab02bb93c9ce 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(for_loops_over_fallibles)] #![warn(forgetting_copy_types)] #![warn(forgetting_references)] +#![warn(incorrect_fn_null_checks)] #![warn(array_into_iter)] #![warn(invalid_atomic_ordering)] #![warn(invalid_value)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index baa6345a64f83..e5e31452149dd 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(clippy::for_loops_over_fallibles)] #![warn(clippy::forget_copy)] #![warn(clippy::forget_ref)] +#![warn(clippy::fn_null_check)] #![warn(clippy::into_iter_on_array)] #![warn(clippy::invalid_atomic_ordering)] #![warn(clippy::invalid_ref)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index ae25c3b46bd24..783608a084102 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` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,310 +7,316 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54: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_if_conditions` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57: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` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58: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` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59: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` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60: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` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61: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` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62: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` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63: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` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64: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` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66: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` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67: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` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68: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` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69: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` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70: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` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:71: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` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:72: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` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:73: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` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:74: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` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:75: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` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:76: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` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:77: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` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:78: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` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:79: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` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81: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 `cast_ref_to_mut` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:83: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` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:84: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` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85: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` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86: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` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:88: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` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:89: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` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90: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` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91: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` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` +error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks` + --> $DIR/rename.rs:93:9 + | +LL | #![warn(clippy::fn_null_check)] + | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks` + error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:94: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` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:95: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` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:96: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` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:97: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` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:98: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` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:99: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` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:100: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` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:101: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` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:102: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` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:103: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` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:104: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` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 52 previous errors +error: aborting due to 53 previous errors From cd1c8532e99c4c594c6704be6d4274131bb71004 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:29:14 +0200 Subject: [PATCH 63/80] [`unnecessary_literal_unwrap`]: lint `unwrap_unchecked` --- clippy_lints/src/methods/mod.rs | 3 + .../src/methods/unnecessary_literal_unwrap.rs | 16 ++++ tests/ui/unnecessary_literal_unwrap.fixed | 10 +++ tests/ui/unnecessary_literal_unwrap.rs | 10 +++ tests/ui/unnecessary_literal_unwrap.stderr | 74 ++++++++++++++++++- 5 files changed, 112 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c99f7c1fdd9fd..6e936e92cbd85 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4000,6 +4000,9 @@ impl Methods { unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, + ("unwrap_unchecked", []) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + } ("unwrap_err", []) => { unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests); diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index ce93d7c3eb339..13895b67ed0b2 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -67,6 +67,22 @@ pub(super) fn check( (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), (expr.span.with_lo(args[0].span.hi()), ")".to_string()), ]), + ("Some" | "Ok", "unwrap_unchecked", _) => { + let mut suggs = vec![ + (recv.span.with_hi(call_args[0].span.lo()), String::new()), + (expr.span.with_lo(call_args[0].span.hi()), String::new()), + ]; + // try to also remove the unsafe block if present + if let hir::Node::Block(block) = cx.tcx.hir().get_parent(expr.hir_id) + && let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules + { + suggs.extend([ + (block.span.shrink_to_lo().to(expr.span.shrink_to_lo()), String::new()), + (expr.span.shrink_to_hi().to(block.span.shrink_to_hi()), String::new()) + ]); + } + Some(suggs) + }, (_, _, Some(_)) => None, ("Ok", "unwrap_err", None) | ("Err", "unwrap", None) => Some(vec![ ( diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 092bf78feabec..0e7ba6bcbbb8f 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -78,6 +78,15 @@ fn unwrap_from_binding() { let _ = val.unwrap_or(""); } +fn unwrap_unchecked() { + let _ = 1; + let _ = unsafe { 1 + *(&1 as *const i32) }; // needs to keep the unsafe block + let _ = 1 + 1; + let _ = 1; + let _ = unsafe { 1 + *(&1 as *const i32) }; + let _ = 1 + 1; +} + fn main() { unwrap_option_some(); unwrap_option_none(); @@ -85,4 +94,5 @@ fn main() { unwrap_result_err(); unwrap_methods_option(); unwrap_methods_result(); + unwrap_unchecked(); } diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index b9df893d1d2b9..fda7fd36ff9d3 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -78,6 +78,15 @@ fn unwrap_from_binding() { let _ = val.unwrap_or(""); } +fn unwrap_unchecked() { + let _ = unsafe { Some(1).unwrap_unchecked() }; + let _ = unsafe { Some(1).unwrap_unchecked() + *(&1 as *const i32) }; // needs to keep the unsafe block + let _ = unsafe { Some(1).unwrap_unchecked() } + 1; + let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; + let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; + let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; +} + fn main() { unwrap_option_some(); unwrap_option_none(); @@ -85,4 +94,5 @@ fn main() { unwrap_result_err(); unwrap_methods_option(); unwrap_methods_result(); + unwrap_unchecked(); } diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 0c71ee053231c..e5b93c3d9af1b 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -409,5 +409,77 @@ LL - Ok::<_, ()>(1).unwrap_or_else(|_| 2); LL + 1; | -error: aborting due to 36 previous errors +error: used `unwrap_unchecked()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:82:22 + | +LL | let _ = unsafe { Some(1).unwrap_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Some(1).unwrap_unchecked() }; +LL + let _ = 1; + | + +error: used `unwrap_unchecked()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:83:22 + | +LL | let _ = unsafe { Some(1).unwrap_unchecked() + *(&1 as *const i32) }; // needs to keep the unsafe block + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Some(1).unwrap_unchecked() + *(&1 as *const i32) }; // needs to keep the unsafe block +LL + let _ = unsafe { 1 + *(&1 as *const i32) }; // needs to keep the unsafe block + | + +error: used `unwrap_unchecked()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:84:22 + | +LL | let _ = unsafe { Some(1).unwrap_unchecked() } + 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Some(1).unwrap_unchecked() } + 1; +LL + let _ = 1 + 1; + | + +error: used `unwrap_unchecked()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:85:22 + | +LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; +LL + let _ = 1; + | + +error: used `unwrap_unchecked()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:86:22 + | +LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; +LL + let _ = unsafe { 1 + *(&1 as *const i32) }; + | + +error: used `unwrap_unchecked()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:87:22 + | +LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_unchecked()` + | +LL - let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; +LL + let _ = 1 + 1; + | + +error: aborting due to 42 previous errors From 0b5dac09757237a407a1cdfbff16eeb4606f6390 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:49:18 +0200 Subject: [PATCH 64/80] [`unnecessary_literal_unwrap`]: also handle unwrap_err_unchecked --- clippy_lints/src/methods/mod.rs | 5 +---- .../src/methods/unnecessary_literal_unwrap.rs | 2 +- tests/ui/unnecessary_literal_unwrap.fixed | 1 + tests/ui/unnecessary_literal_unwrap.rs | 1 + tests/ui/unnecessary_literal_unwrap.stderr | 14 +++++++++++++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6e936e92cbd85..d6057ce45f6bc 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4000,9 +4000,6 @@ impl Methods { unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, - ("unwrap_unchecked", []) => { - unnecessary_literal_unwrap::check(cx, expr, recv, name, args); - } ("unwrap_err", []) => { unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests); @@ -4022,7 +4019,7 @@ impl Methods { } unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, - ("unwrap_or_default", []) => { + ("unwrap_or_default" | "unwrap_unchecked" | "unwrap_err_unchecked", []) => { unnecessary_literal_unwrap::check(cx, expr, recv, name, args); } ("unwrap_or_else", [u_arg]) => { diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 13895b67ed0b2..54de300e6bc13 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -67,7 +67,7 @@ pub(super) fn check( (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), (expr.span.with_lo(args[0].span.hi()), ")".to_string()), ]), - ("Some" | "Ok", "unwrap_unchecked", _) => { + ("Some" | "Ok", "unwrap_unchecked", _) | ("Err", "unwrap_err_unchecked", _) => { let mut suggs = vec![ (recv.span.with_hi(call_args[0].span.lo()), String::new()), (expr.span.with_lo(call_args[0].span.hi()), String::new()), diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 0e7ba6bcbbb8f..276cd800b8907 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -85,6 +85,7 @@ fn unwrap_unchecked() { let _ = 1; let _ = unsafe { 1 + *(&1 as *const i32) }; let _ = 1 + 1; + let _ = 123; } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index fda7fd36ff9d3..3065778d77901 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -85,6 +85,7 @@ fn unwrap_unchecked() { let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; + let _ = unsafe { Err::<(), i32>(123).unwrap_err_unchecked() }; } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index e5b93c3d9af1b..5823313b736c9 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -481,5 +481,17 @@ LL - let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; LL + let _ = 1 + 1; | -error: aborting due to 42 previous errors +error: used `unwrap_err_unchecked()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:88:22 + | +LL | let _ = unsafe { Err::<(), i32>(123).unwrap_err_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err_unchecked()` + | +LL - let _ = unsafe { Err::<(), i32>(123).unwrap_err_unchecked() }; +LL + let _ = 123; + | + +error: aborting due to 43 previous errors From 31397b489a0601ac53717bef2e3f2b3a945779b1 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Tue, 11 Jul 2023 19:23:01 +0200 Subject: [PATCH 65/80] Update version attribute for 1.71 lints --- clippy_lints/src/items_after_test_module.rs | 2 +- clippy_lints/src/loops/mod.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index 40378ee8205cf..f684847c0c2d4 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -32,7 +32,7 @@ declare_clippy_lint! { /// // [...] /// } /// ``` - #[clippy::version = "1.70.0"] + #[clippy::version = "1.71.0"] pub ITEMS_AFTER_TEST_MODULE, style, "An item was found after the testing module `tests`" diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 529189b52acda..ffd29ab763027 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -601,7 +601,7 @@ declare_clippy_lint! { /// // use `number` /// } /// ``` - #[clippy::version = "1.70.0"] + #[clippy::version = "1.71.0"] pub MANUAL_WHILE_LET_SOME, style, "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 62af42a3961f8..34b74e180cb08 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -106,7 +106,7 @@ declare_clippy_lint! { /// # let mut skip: bool; /// skip = !must_keep(x, y); /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.71.0"] pub NEEDLESS_BOOL_ASSIGN, complexity, "setting the same boolean variable in both branches of an if-statement" From 5ea622c8b237a7322fcd9630f2939f91aeed478f Mon Sep 17 00:00:00 2001 From: xFrednet Date: Tue, 11 Jul 2023 19:21:36 +0200 Subject: [PATCH 66/80] Changelog for Rust 1.71 :crown: --- CHANGELOG.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 038fe32e587df..6b0cdb3cd898a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,60 @@ document. ## Unreleased / Beta / In Rust Nightly -[83e42a23...master](https://github.com/rust-lang/rust-clippy/compare/83e42a23...master) +[435a8ad8...master](https://github.com/rust-lang/rust-clippy/compare/435a8ad8...master) + +## Rust 1.71 +Current beta, released 2023-07-13 + +[View all 78 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-04-11T20%3A05%3A26Z..2023-05-20T13%3A48%3A17Z+base%3Amaster) + +### New Lints + +* [`non_minimal_cfg`] + [#10763](https://github.com/rust-lang/rust-clippy/pull/10763) +* [`manual_next_back`] + [#10769](https://github.com/rust-lang/rust-clippy/pull/10769) +* [`ref_patterns`] + [#10736](https://github.com/rust-lang/rust-clippy/pull/10736) +* [`default_constructed_unit_structs`] + [#10716](https://github.com/rust-lang/rust-clippy/pull/10716) +* [`manual_while_let_some`] + [#10647](https://github.com/rust-lang/rust-clippy/pull/10647) +* [`needless_bool_assign`] + [#10432](https://github.com/rust-lang/rust-clippy/pull/10432) +* [`items_after_test_module`] + [#10578](https://github.com/rust-lang/rust-clippy/pull/10578) + +### Moves and Deprecations + +* Rename `integer_arithmetic` to `arithmetic_side_effects` + [#10674](https://github.com/rust-lang/rust-clippy/pull/10674) +* Moved [`redundant_clone`] to `nursery` (Now allow-by-default) + [#10873](https://github.com/rust-lang/rust-clippy/pull/10873) + +### Enhancements + +* [`invalid_regex`]: Now supports the new syntax introduced after regex v1.8.0 + [#10682](https://github.com/rust-lang/rust-clippy/pull/10682) +* [`semicolon_outside_block`]: Added [`semicolon-outside-block-ignore-multiline`] as a new config value. + [#10656](https://github.com/rust-lang/rust-clippy/pull/10656) +* [`semicolon_inside_block`]: Added [`semicolon-inside-block-ignore-singleline`] as a new config value. + [#10656](https://github.com/rust-lang/rust-clippy/pull/10656) +* [`unnecessary_box_returns`]: Added [`unnecessary-box-size`] as a new config value to set the maximum + size of `T` in `Box` to be linted. + [#10651](https://github.com/rust-lang/rust-clippy/pull/10651) + +### Documentation Improvements + +* `cargo clippy --explain LINT` now shows possible configuration options for the explained lint + [#10751](https://github.com/rust-lang/rust-clippy/pull/10751) +* New config values mentioned in this changelog will now be linked. + [#10889](https://github.com/rust-lang/rust-clippy/pull/10889) +* Several sections of [Clippy's book] have been reworked + [#10652](https://github.com/rust-lang/rust-clippy/pull/10652) + [#10622](https://github.com/rust-lang/rust-clippy/pull/10622) + +[Clippy's book]: https://doc.rust-lang.org/clippy/ ## Rust 1.70 From 7a3756add539d7a7a35ea17d7b2f2a4b762e6910 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Wed, 12 Jul 2023 14:41:39 +0200 Subject: [PATCH 67/80] Changelog: Add disclaimer about the new format --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b0cdb3cd898a..b3b6e3b865fce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,15 @@ document. [435a8ad8...master](https://github.com/rust-lang/rust-clippy/compare/435a8ad8...master) ## Rust 1.71 -Current beta, released 2023-07-13 + +Current stable, released 2023-07-13 + + + +We're trying out a new shorter changelog format, that only contains significant changes. +You can check out the list of merged pull requests for a list of all changes. +If you have any feedback related to the new format, please share it in +[#10847](https://github.com/rust-lang/rust-clippy/issues/10847) [View all 78 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-04-11T20%3A05%3A26Z..2023-05-20T13%3A48%3A17Z+base%3Amaster) @@ -63,7 +71,7 @@ Current beta, released 2023-07-13 ## Rust 1.70 -Current stable, released 2023-06-01 +Released 2023-06-01 [View all 91 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-02-26T01%3A05%3A43Z..2023-04-11T13%3A27%3A30Z+base%3Amaster) From 660ef4ffe8d58ba236555f7c191334b82ce5025f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Jul 2023 06:59:57 -0700 Subject: [PATCH 68/80] Ignore flaky clippy tests. --- tests/ui/empty_line_after_doc_comments.rs | 3 +++ tests/ui/empty_line_after_outer_attribute.rs | 3 +++ tests/ui/needless_arbitrary_self_type_unfixable.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/tests/ui/empty_line_after_doc_comments.rs b/tests/ui/empty_line_after_doc_comments.rs index 83db2a07d334e..cc36ce5f48791 100644 --- a/tests/ui/empty_line_after_doc_comments.rs +++ b/tests/ui/empty_line_after_doc_comments.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::empty_line_after_doc_comments)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index b2d7ddae42746..bc54e0fd2de14 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::empty_line_after_outer_attr)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.rs b/tests/ui/needless_arbitrary_self_type_unfixable.rs index 876f16a3854d9..321aa69a1a527 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -1,4 +1,7 @@ //@aux-build:proc_macro_attr.rs:proc-macro +// Flaky test, see https://github.com/rust-lang/rust/issues/113585. +//@ignore-32bit +//@ignore-64bit #![warn(clippy::needless_arbitrary_self_type)] From c49c177e062a8a5602207d309d2f6e8041fc1b1d Mon Sep 17 00:00:00 2001 From: Panagiotis Foliadis Date: Fri, 7 Jul 2023 21:39:31 +0300 Subject: [PATCH 69/80] [`panic_in_result_fn`] remove `todo!`, `unimplemented!`, `unreachable!` This commit fixes #11025 by removing checks for `todo!`, `unimplemented!` and `unreachable!`. Signed-off-by: Panagiotis Foliadis --- clippy_lints/src/panic_in_result_fn.rs | 10 +-- tests/ui/panic_in_result_fn.stderr | 74 ++----------------- tests/ui/panic_in_result_fn_assertions.stderr | 12 +-- 3 files changed, 16 insertions(+), 80 deletions(-) diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs index 849cd03dd7bf6..a049427d85d9c 100644 --- a/clippy_lints/src/panic_in_result_fn.rs +++ b/clippy_lints/src/panic_in_result_fn.rs @@ -13,7 +13,7 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result. + /// Checks for usage of `panic!` or assertions in a function of type result. /// /// ### Why is this bad? /// For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence panicking macros should be avoided. @@ -37,7 +37,7 @@ declare_clippy_lint! { #[clippy::version = "1.48.0"] pub PANIC_IN_RESULT_FN, restriction, - "functions of type `Result<..>` that contain `panic!()`, `todo!()`, `unreachable()`, `unimplemented()` or assertion" + "functions of type `Result<..>` that contain `panic!()` or assertion" } declare_lint_pass!(PanicInResultFn => [PANIC_IN_RESULT_FN]); @@ -70,7 +70,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir }; if matches!( cx.tcx.item_name(macro_call.def_id).as_str(), - "unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne" + "panic" | "assert" | "assert_eq" | "assert_ne" ) { panics.push(macro_call.span); ControlFlow::Continue(Descend::No) @@ -83,10 +83,10 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir cx, PANIC_IN_RESULT_FN, impl_span, - "used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`", + "used `panic!()` or assertion in a function that returns `Result`", move |diag| { diag.help( - "`unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing", + "`panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing", ); diag.span_note(panics, "return Err() instead of panicking"); }, diff --git a/tests/ui/panic_in_result_fn.stderr b/tests/ui/panic_in_result_fn.stderr index 97787bc84e2c5..b758fc2381248 100644 --- a/tests/ui/panic_in_result_fn.stderr +++ b/tests/ui/panic_in_result_fn.stderr @@ -1,4 +1,4 @@ -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` +error: used `panic!()` or assertion in a function that returns `Result` --> $DIR/panic_in_result_fn.rs:6:5 | LL | / fn result_with_panic() -> Result // should emit lint @@ -7,7 +7,7 @@ LL | | panic!("error"); LL | | } | |_____^ | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing + = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking --> $DIR/panic_in_result_fn.rs:8:9 | @@ -15,55 +15,7 @@ LL | panic!("error"); | ^^^^^^^^^^^^^^^ = note: `-D clippy::panic-in-result-fn` implied by `-D warnings` -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn.rs:11:5 - | -LL | / fn result_with_unimplemented() -> Result // should emit lint -LL | | { -LL | | unimplemented!(); -LL | | } - | |_____^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn.rs:13:9 - | -LL | unimplemented!(); - | ^^^^^^^^^^^^^^^^ - -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn.rs:16:5 - | -LL | / fn result_with_unreachable() -> Result // should emit lint -LL | | { -LL | | unreachable!(); -LL | | } - | |_____^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn.rs:18:9 - | -LL | unreachable!(); - | ^^^^^^^^^^^^^^ - -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn.rs:21:5 - | -LL | / fn result_with_todo() -> Result // should emit lint -LL | | { -LL | | todo!("Finish this"); -LL | | } - | |_____^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn.rs:23:9 - | -LL | todo!("Finish this"); - | ^^^^^^^^^^^^^^^^^^^^ - -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` +error: used `panic!()` or assertion in a function that returns `Result` --> $DIR/panic_in_result_fn.rs:52:1 | LL | / fn function_result_with_panic() -> Result // should emit lint @@ -72,28 +24,12 @@ LL | | panic!("error"); LL | | } | |_^ | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing + = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking --> $DIR/panic_in_result_fn.rs:54:5 | LL | panic!("error"); | ^^^^^^^^^^^^^^^ -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn.rs:67:1 - | -LL | / fn main() -> Result<(), String> { -LL | | todo!("finish main method"); -LL | | Ok(()) -LL | | } - | |_^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn.rs:68:5 - | -LL | todo!("finish main method"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/panic_in_result_fn_assertions.stderr b/tests/ui/panic_in_result_fn_assertions.stderr index eb0aacbb6a441..0dd213a7eede9 100644 --- a/tests/ui/panic_in_result_fn_assertions.stderr +++ b/tests/ui/panic_in_result_fn_assertions.stderr @@ -1,4 +1,4 @@ -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` +error: used `panic!()` or assertion in a function that returns `Result` --> $DIR/panic_in_result_fn_assertions.rs:7:5 | LL | / fn result_with_assert_with_message(x: i32) -> Result // should emit lint @@ -8,7 +8,7 @@ LL | | Ok(true) LL | | } | |_____^ | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing + = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking --> $DIR/panic_in_result_fn_assertions.rs:9:9 | @@ -16,7 +16,7 @@ LL | assert!(x == 5, "wrong argument"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::panic-in-result-fn` implied by `-D warnings` -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` +error: used `panic!()` or assertion in a function that returns `Result` --> $DIR/panic_in_result_fn_assertions.rs:13:5 | LL | / fn result_with_assert_eq(x: i32) -> Result // should emit lint @@ -26,14 +26,14 @@ LL | | Ok(true) LL | | } | |_____^ | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing + = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking --> $DIR/panic_in_result_fn_assertions.rs:15:9 | LL | assert_eq!(x, 5); | ^^^^^^^^^^^^^^^^ -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` +error: used `panic!()` or assertion in a function that returns `Result` --> $DIR/panic_in_result_fn_assertions.rs:19:5 | LL | / fn result_with_assert_ne(x: i32) -> Result // should emit lint @@ -43,7 +43,7 @@ LL | | Ok(true) LL | | } | |_____^ | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing + = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking --> $DIR/panic_in_result_fn_assertions.rs:21:9 | From c5fc61ca9485d8ccf1e0865ed675edfacddd5d57 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 13 Jul 2023 00:24:10 +0200 Subject: [PATCH 70/80] [`arithmetic_side_effect`]: allow different rhs type --- clippy_lints/src/operators/arithmetic_side_effects.rs | 4 ++-- tests/ui/arithmetic_side_effects.rs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 5c240276b76d1..47873f3b071dd 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -19,8 +19,8 @@ use rustc_span::{ const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[ ["f32", "f32"], ["f64", "f64"], - ["std::num::Saturating", "std::num::Saturating"], - ["std::num::Wrapping", "std::num::Wrapping"], + ["std::num::Saturating", "*"], + ["std::num::Wrapping", "*"], ["std::string::String", "str"], ]; const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"]; diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index 4f38e50c81d55..ed75acee8a287 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -481,4 +481,9 @@ pub fn issue_10792() { let _ = 10 / TWO.c; } +pub fn issue_11145() { + let mut x: Wrapping = Wrapping(0_u32); + x += 1; +} + fn main() {} From 4102a309d782522a2a6f378ec748cb3a3a4fed8d Mon Sep 17 00:00:00 2001 From: Mingwei Samuel Date: Wed, 12 Jul 2023 15:01:37 -0700 Subject: [PATCH 71/80] [`tuple_array_conversions`]: move from `complexity` to `nursery` Due to outstanding issues: * https://github.com/rust-lang/rust-clippy/issues/11082 * https://github.com/rust-lang/rust-clippy/issues/11085 * https://github.com/rust-lang/rust-clippy/issues/11100 (https://github.com/rust-lang/rust-clippy/pull/11105) * https://github.com/rust-lang/rust-clippy/issues/11124 * https://github.com/rust-lang/rust-clippy/issues/11144 --- clippy_lints/src/tuple_array_conversions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index bd983306508ba..258617467e9b5 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -16,8 +16,8 @@ declare_clippy_lint! { /// Checks for tuple<=>array conversions that are not done with `.into()`. /// /// ### Why is this bad? - /// It's unnecessary complexity. `.into()` works for tuples<=>arrays at or below 12 elements and - /// conveys the intent a lot better, while also leaving less room for hard to spot bugs! + /// It may be unnecessary complexity. `.into()` works for converting tuples + /// <=> arrays of up to 12 elements and may convey intent more clearly. /// /// ### Example /// ```rust,ignore @@ -31,7 +31,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub TUPLE_ARRAY_CONVERSIONS, - complexity, + pedantic, "checks for tuple<=>array conversions that are not done with `.into()`" } impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); From 050b714c9d638d57408d7ff7d14afd5d206525f2 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Wed, 12 Jul 2023 20:15:54 -0400 Subject: [PATCH 72/80] Add "Known problems" section to `needless_borrow` documentation --- clippy_lints/src/dereference.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 3af552e501680..cdf64b960360d 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -77,6 +77,11 @@ declare_clippy_lint! { /// Suggests that the receiver of the expression borrows /// the expression. /// + /// ### Known problems + /// The lint cannot tell when the implementation of a trait + /// for `&T` and `T` do different things. Removing a borrow + /// in such a case can change the semantics of the code. + /// /// ### Example /// ```rust /// fn fun(_a: &i32) {} From 2811effe3478a3ce7d1bdde936c6ca8fb08de326 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 3 Jul 2023 17:42:48 +0000 Subject: [PATCH 73/80] Add `imports_granularity = "Module"` to rustfmt.toml --- clippy_lints/src/allow_attributes.rs | 3 +- clippy_lints/src/arc_with_non_send_sync.rs | 3 +- clippy_lints/src/attrs.rs | 6 +- clippy_lints/src/blocks_in_if_conditions.rs | 3 +- clippy_lints/src/bool_to_int_with_if.rs | 4 +- clippy_lints/src/borrow_deref_ref.rs | 3 +- clippy_lints/src/box_default.rs | 14 ++--- clippy_lints/src/casts/as_ptr_cast_mut.rs | 6 +- .../src/casts/cast_slice_different_sizes.rs | 6 +- .../src/casts/cast_slice_from_raw_parts.rs | 3 +- clippy_lints/src/casts/ptr_cast_constness.rs | 4 +- clippy_lints/src/copies.rs | 3 +- clippy_lints/src/crate_in_macro_def.rs | 3 +- .../src/default_constructed_unit_structs.rs | 6 +- .../src/default_instead_of_iter_empty.rs | 3 +- clippy_lints/src/default_numeric_fallback.rs | 12 ++-- clippy_lints/src/dereference.rs | 13 ++-- clippy_lints/src/derivable_impls.rs | 5 +- clippy_lints/src/derive.rs | 3 +- clippy_lints/src/disallowed_names.rs | 3 +- clippy_lints/src/doc.rs | 3 +- clippy_lints/src/drop_forget_ref.rs | 3 +- clippy_lints/src/empty_drop.rs | 3 +- .../src/empty_structs_with_brackets.rs | 3 +- clippy_lints/src/endian_bytes.rs | 6 +- clippy_lints/src/entry.rs | 18 +++--- clippy_lints/src/escape.rs | 3 +- clippy_lints/src/excessive_nesting.rs | 11 ++-- .../src/extra_unused_type_parameters.rs | 9 +-- clippy_lints/src/floating_point_arithmetic.rs | 10 ++-- clippy_lints/src/format_args.rs | 6 +- clippy_lints/src/format_impl.rs | 4 +- clippy_lints/src/from_over_into.rs | 3 +- clippy_lints/src/from_raw_with_void_ptr.rs | 3 +- .../src/functions/impl_trait_in_params.rs | 6 +- .../src/functions/misnamed_getters.rs | 3 +- clippy_lints/src/functions/must_use.rs | 9 ++- clippy_lints/src/if_let_mutex.rs | 3 +- clippy_lints/src/implicit_return.rs | 10 ++-- clippy_lints/src/incorrect_impls.rs | 14 ++--- clippy_lints/src/index_refutable_slice.rs | 3 +- clippy_lints/src/inherent_impl.rs | 3 +- clippy_lints/src/instant_subtraction.rs | 3 +- clippy_lints/src/items_after_test_module.rs | 3 +- .../src/iter_not_returning_iterator.rs | 7 ++- clippy_lints/src/large_enum_variant.rs | 6 +- clippy_lints/src/large_futures.rs | 3 +- clippy_lints/src/large_include_file.rs | 3 +- clippy_lints/src/large_stack_frames.rs | 6 +- clippy_lints/src/len_zero.rs | 19 +++--- clippy_lints/src/let_if_seq.rs | 3 +- clippy_lints/src/let_underscore.rs | 3 +- clippy_lints/src/lib.rs | 7 +-- clippy_lints/src/lines_filter_map_ok.rs | 7 +-- clippy_lints/src/loops/manual_find.rs | 14 ++--- clippy_lints/src/loops/manual_flatten.rs | 3 +- .../src/loops/manual_while_let_some.rs | 9 +-- clippy_lints/src/loops/mut_range_bound.rs | 3 +- clippy_lints/src/loops/never_loop.rs | 4 +- .../src/loops/while_immutable_condition.rs | 3 +- .../src/loops/while_let_on_iterator.rs | 12 ++-- clippy_lints/src/macro_use.rs | 3 +- clippy_lints/src/manual_clamp.rs | 14 ++--- clippy_lints/src/manual_float_methods.rs | 10 ++-- clippy_lints/src/manual_is_ascii_check.rs | 8 ++- clippy_lints/src/manual_range_patterns.rs | 9 +-- clippy_lints/src/manual_strip.rs | 3 +- clippy_lints/src/match_result_ok.rs | 3 +- clippy_lints/src/matches/manual_utils.rs | 9 ++- .../src/matches/match_like_matches.rs | 4 +- clippy_lints/src/matches/match_same_arms.rs | 3 +- .../src/matches/redundant_pattern_match.rs | 3 +- .../src/methods/bind_instead_of_map.rs | 3 +- ...se_sensitive_file_extension_comparisons.rs | 6 +- clippy_lints/src/methods/chars_cmp.rs | 3 +- .../src/methods/chars_cmp_with_unwrap.rs | 3 +- clippy_lints/src/methods/clone_on_copy.rs | 4 +- .../src/methods/collapsible_str_replace.rs | 3 +- clippy_lints/src/methods/drain_collect.rs | 9 +-- clippy_lints/src/methods/err_expect.rs | 3 +- clippy_lints/src/methods/filter_map.rs | 4 +- .../src/methods/filter_map_identity.rs | 3 +- clippy_lints/src/methods/flat_map_identity.rs | 3 +- clippy_lints/src/methods/flat_map_option.rs | 3 +- clippy_lints/src/methods/inspect_for_each.rs | 3 +- .../src/methods/is_digit_ascii_radix.rs | 6 +- clippy_lints/src/methods/iter_kv_map.rs | 3 +- clippy_lints/src/methods/iter_skip_next.rs | 3 +- .../methods/manual_saturating_arithmetic.rs | 6 +- clippy_lints/src/methods/manual_try_fold.rs | 18 +++--- clippy_lints/src/methods/map_flatten.rs | 3 +- clippy_lints/src/methods/map_identity.rs | 3 +- clippy_lints/src/methods/mut_mutex_lock.rs | 3 +- clippy_lints/src/methods/needless_collect.rs | 5 +- .../src/methods/obfuscated_if_else.rs | 3 +- .../src/methods/option_map_or_none.rs | 3 +- .../src/methods/option_map_unwrap_or.rs | 9 +-- clippy_lints/src/methods/or_then_unwrap.rs | 6 +- .../src/methods/range_zip_with_len.rs | 3 +- .../src/methods/read_line_without_trim.rs | 14 ++--- clippy_lints/src/methods/seek_from_current.rs | 8 +-- .../methods/suspicious_command_arg_space.rs | 3 +- .../src/methods/suspicious_to_owned.rs | 3 +- clippy_lints/src/methods/type_id_on_box.rs | 6 +- .../src/methods/uninit_assumed_init.rs | 3 +- .../src/methods/unnecessary_filter_map.rs | 3 +- clippy_lints/src/methods/unnecessary_fold.rs | 3 +- .../src/methods/unnecessary_iter_cloned.rs | 3 +- clippy_lints/src/methods/unnecessary_join.rs | 3 +- .../src/methods/unnecessary_literal_unwrap.rs | 3 +- .../src/methods/unnecessary_sort_by.rs | 3 +- .../src/methods/unnecessary_to_owned.rs | 6 +- .../src/methods/unwrap_or_else_default.rs | 8 +-- clippy_lints/src/min_ident_chars.rs | 11 ++-- .../src/missing_enforced_import_rename.rs | 7 ++- clippy_lints/src/missing_fields_in_debug.rs | 20 +++---- .../src/multiple_unsafe_ops_per_block.rs | 12 ++-- clippy_lints/src/needless_bool.rs | 4 +- clippy_lints/src/needless_else.rs | 4 +- clippy_lints/src/needless_for_each.rs | 9 ++- clippy_lints/src/needless_if.rs | 5 +- .../src/needless_parens_on_range_literals.rs | 8 +-- clippy_lints/src/needless_pass_by_ref_mut.rs | 3 +- clippy_lints/src/needless_pass_by_value.rs | 4 +- clippy_lints/src/no_effect.rs | 3 +- .../src/non_send_fields_in_send_ty.rs | 3 +- clippy_lints/src/nonstandard_macro_braces.rs | 6 +- .../src/operators/arithmetic_side_effects.rs | 18 ++---- .../src/operators/assign_op_pattern.rs | 3 +- clippy_lints/src/operators/eq_op.rs | 3 +- .../src/operators/misrefactored_assign_op.rs | 3 +- clippy_lints/src/operators/op_ref.rs | 4 +- clippy_lints/src/option_if_let_else.rs | 5 +- clippy_lints/src/partialeq_to_none.rs | 7 +-- clippy_lints/src/pass_by_ref_or_value.rs | 3 +- clippy_lints/src/ptr.rs | 3 +- clippy_lints/src/question_mark.rs | 11 ++-- clippy_lints/src/ranges.rs | 3 +- clippy_lints/src/raw_strings.rs | 12 ++-- clippy_lints/src/rc_clone_in_vec_init.rs | 3 +- clippy_lints/src/read_zero_byte_vec.rs | 10 ++-- clippy_lints/src/redundant_async_block.rs | 13 ++-- clippy_lints/src/redundant_closure_call.rs | 3 +- clippy_lints/src/returns.rs | 3 +- .../src/significant_drop_tightening.rs | 23 ++++--- clippy_lints/src/single_call_fn.rs | 4 +- .../src/single_component_path_imports.rs | 7 ++- clippy_lints/src/single_range_in_vec_init.rs | 10 ++-- clippy_lints/src/size_of_in_element_count.rs | 3 +- clippy_lints/src/size_of_ref.rs | 4 +- clippy_lints/src/std_instead_of_core.rs | 6 +- clippy_lints/src/strings.rs | 6 +- clippy_lints/src/suspicious_doc_comments.rs | 3 +- .../src/suspicious_xor_used_as_pow.rs | 3 +- clippy_lints/src/swap.rs | 4 +- clippy_lints/src/tests_outside_test_module.rs | 9 ++- .../transmute/transmute_int_to_non_zero.rs | 6 +- .../src/transmute/transmute_undefined_repr.rs | 3 +- .../transmutes_expressible_as_ptr_casts.rs | 3 +- clippy_lints/src/transmute/utils.rs | 3 +- clippy_lints/src/tuple_array_conversions.rs | 12 ++-- clippy_lints/src/types/borrowed_box.rs | 5 +- clippy_lints/src/types/box_collection.rs | 3 +- clippy_lints/src/types/linked_list.rs | 3 +- clippy_lints/src/types/option_option.rs | 3 +- clippy_lints/src/types/rc_buffer.rs | 3 +- clippy_lints/src/types/rc_mutex.rs | 3 +- .../src/types/redundant_allocation.rs | 3 +- clippy_lints/src/types/vec_box.rs | 3 +- clippy_lints/src/unnecessary_box_returns.rs | 6 +- .../src/unnecessary_owned_empty_strings.rs | 3 +- .../src/unnecessary_struct_initialization.rs | 5 +- clippy_lints/src/unnecessary_wraps.rs | 3 +- clippy_lints/src/unnested_or_patterns.rs | 3 +- clippy_lints/src/unused_unit.rs | 3 +- clippy_lints/src/unwrap.rs | 4 +- clippy_lints/src/use_self.rs | 11 ++-- clippy_lints/src/useless_conversion.rs | 3 +- .../src/utils/internal_lints/invalid_paths.rs | 3 +- .../internal_lints/lint_without_lint_pass.rs | 3 +- .../internal_lints/metadata_collector.rs | 19 +++--- .../utils/internal_lints/msrv_attr_impl.rs | 3 +- clippy_lints/src/visibility.rs | 6 +- clippy_lints/src/wildcard_imports.rs | 6 +- clippy_utils/src/attrs.rs | 3 +- clippy_utils/src/check_proc_macro.rs | 18 +++--- clippy_utils/src/consts.rs | 6 +- clippy_utils/src/eager_or_lazy.rs | 6 +- clippy_utils/src/hir_utils.rs | 3 +- clippy_utils/src/lib.rs | 13 ++-- clippy_utils/src/mir/possible_borrower.rs | 12 ++-- clippy_utils/src/qualify_min_const_fn.rs | 4 +- clippy_utils/src/source.rs | 3 +- clippy_utils/src/ty.rs | 10 ++-- clippy_utils/src/usage.rs | 6 +- lintcheck/src/config.rs | 3 +- lintcheck/src/main.rs | 4 +- lintcheck/src/recursive.rs | 3 +- rustfmt.toml | 1 + .../auxiliary/proc_macros.rs | 11 ++-- tests/ui-toml/unwrap_used/unwrap_used.rs | 4 +- tests/ui-toml/unwrap_used/unwrap_used.stderr | 56 ++++++++--------- tests/ui/as_conversions.rs | 3 +- tests/ui/as_conversions.stderr | 6 +- tests/ui/auxiliary/macro_use_helper.rs | 3 +- tests/ui/auxiliary/proc_macro_attr.rs | 4 +- tests/ui/auxiliary/proc_macros.rs | 11 ++-- tests/ui/default_trait_access.fixed | 3 +- tests/ui/default_trait_access.rs | 3 +- tests/ui/default_trait_access.stderr | 16 ++--- tests/ui/get_first.fixed | 4 +- tests/ui/get_first.rs | 4 +- tests/ui/get_first.stderr | 6 +- tests/ui/get_unwrap.fixed | 4 +- tests/ui/get_unwrap.rs | 4 +- tests/ui/get_unwrap.stderr | 60 +++++++++---------- tests/ui/issue-7447.rs | 5 +- tests/ui/issue-7447.stderr | 4 +- tests/ui/iter_cloned_collect.fixed | 3 +- tests/ui/iter_cloned_collect.rs | 3 +- tests/ui/iter_cloned_collect.stderr | 10 ++-- tests/ui/let_underscore_lock.rs | 3 +- tests/ui/let_underscore_lock.stderr | 8 +-- tests/ui/let_underscore_untyped.rs | 3 +- tests/ui/let_underscore_untyped.stderr | 20 +++---- tests/ui/manual_retain.fixed | 7 +-- tests/ui/manual_retain.rs | 7 +-- tests/ui/manual_retain.stderr | 38 ++++++------ tests/ui/manual_try_fold.rs | 4 +- tests/ui/manual_try_fold.stderr | 8 +-- tests/ui/match_as_ref.fixed | 4 +- tests/ui/match_as_ref.rs | 4 +- tests/ui/match_as_ref.stderr | 2 +- tests/ui/methods.rs | 5 +- tests/ui/methods.stderr | 4 +- tests/ui/min_ident_chars.rs | 3 +- tests/ui/min_ident_chars.stderr | 58 +++++++++--------- tests/ui/min_max.rs | 4 +- tests/ui/min_max.stderr | 26 ++++---- tests/ui/missing_doc.rs | 4 +- tests/ui/mut_key.rs | 3 +- tests/ui/mut_key.stderr | 36 +++++------ tests/ui/needless_if.fixed | 3 +- tests/ui/needless_if.rs | 3 +- tests/ui/needless_if.stderr | 14 ++--- tests/ui/or_fun_call.fixed | 3 +- tests/ui/or_fun_call.rs | 3 +- tests/ui/or_fun_call.stderr | 56 ++++++++--------- tests/ui/redundant_allocation.rs | 9 +-- tests/ui/redundant_allocation.stderr | 40 ++++++------- tests/ui/redundant_allocation_fixable.fixed | 12 +--- tests/ui/redundant_allocation_fixable.rs | 12 +--- tests/ui/redundant_allocation_fixable.stderr | 24 ++++---- .../redundant_pattern_matching_ipaddr.fixed | 6 +- tests/ui/redundant_pattern_matching_ipaddr.rs | 6 +- .../redundant_pattern_matching_ipaddr.stderr | 36 +++++------ tests/ui/significant_drop_in_scrutinee.rs | 3 +- tests/ui/significant_drop_in_scrutinee.stderr | 52 ++++++++-------- tests/ui/single_component_path_imports.fixed | 4 ++ tests/ui/single_component_path_imports.rs | 4 ++ tests/ui/single_component_path_imports.stderr | 4 +- ...gle_component_path_imports_nested_first.rs | 2 + ...component_path_imports_nested_first.stderr | 4 +- ...ingle_component_path_imports_self_after.rs | 1 + ...ngle_component_path_imports_self_before.rs | 1 + tests/ui/unnecessary_to_owned.fixed | 3 +- tests/ui/unnecessary_to_owned.rs | 3 +- tests/ui/unsafe_removed_from_name.rs | 8 +++ tests/ui/unsafe_removed_from_name.stderr | 16 ++++- tests/ui/unused_peekable.rs | 3 +- tests/ui/unused_peekable.stderr | 16 ++--- tests/ui/wildcard_imports.fixed | 1 + tests/ui/wildcard_imports.rs | 1 + tests/ui/wildcard_imports.stderr | 24 ++++---- .../wildcard_imports_2021.edition2018.fixed | 1 + .../wildcard_imports_2021.edition2018.stderr | 24 ++++---- .../wildcard_imports_2021.edition2021.fixed | 1 + .../wildcard_imports_2021.edition2021.stderr | 24 ++++---- tests/ui/wildcard_imports_2021.rs | 1 + 279 files changed, 990 insertions(+), 1055 deletions(-) diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index eb21184713e89..e1ef514edfd18 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -1,5 +1,6 @@ use ast::{AttrStyle, Attribute}; -use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_from_proc_macro; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_lint::{LateContext, LateLintPass, LintContext}; diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 98ee8a9a8806c..7adcd9ad05559 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -2,8 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::last_path_segment; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_hir::{Expr, ExprKind}; -use rustc_lint::LateContext; -use rustc_lint::LateLintPass; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::GenericArgKind; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 2ba78f99569ab..2a5be2756151a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,12 +1,10 @@ //! checks for attributes +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::is_from_proc_macro; use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; -use clippy_utils::{ - diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}, - is_from_proc_macro, -}; use if_chain::if_chain; use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs index 569bf27c3e716..1593d7b0fb386 100644 --- a/clippy_lints/src/blocks_in_if_conditions.rs +++ b/clippy_lints/src/blocks_in_if_conditions.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::get_parent_expr; -use clippy_utils::higher; use clippy_utils::source::snippet_block_with_applicability; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::{for_each_expr, Descend}; +use clippy_utils::{get_parent_expr, higher}; use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs index bdb3a01160272..1828dd651527a 100644 --- a/clippy_lints/src/bool_to_int_with_if.rs +++ b/clippy_lints/src/bool_to_int_with_if.rs @@ -4,7 +4,9 @@ use rustc_hir::{Block, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use clippy_utils::{diagnostics::span_lint_and_then, in_constant, is_else_clause, is_integer_literal, sugg::Sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::{in_constant, is_else_clause, is_integer_literal}; use rustc_errors::Applicability; declare_clippy_lint! { diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index 814108ed8a7c2..b3dbbb08f8ebf 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -1,9 +1,8 @@ use crate::reference::DEREF_ADDROF; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_from_proc_macro; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_parent_expr, is_lint_allowed}; +use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; use rustc_errors::Applicability; use rustc_hir::{ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index e42c3fe243256..fa9c525fc08d9 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -1,12 +1,10 @@ -use clippy_utils::{ - diagnostics::span_lint_and_sugg, get_parent_node, is_default_equivalent, macros::macro_backtrace, match_path, - path_def_id, paths, ty::expr_sig, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::macros::macro_backtrace; +use clippy_utils::ty::expr_sig; +use clippy_utils::{get_parent_node, is_default_equivalent, match_path, path_def_id, paths}; use rustc_errors::Applicability; -use rustc_hir::{ - intravisit::{walk_ty, Visitor}, - Block, Expr, ExprKind, Local, Node, QPath, TyKind, -}; +use rustc_hir::intravisit::{walk_ty, Visitor}; +use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::print::with_forced_trimmed_paths; diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs index 1633ffd589c38..e3d1f7df29455 100644 --- a/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -3,10 +3,8 @@ use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_middle::{ - mir::Mutability, - ty::{self, Ty, TypeAndMut}, -}; +use rustc_middle::mir::Mutability; +use rustc_middle::ty::{self, Ty, TypeAndMut}; use super::AS_PTR_CAST_MUT; diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 27cc5a1c3f04c..4d9cc4cacc3e9 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,10 +1,12 @@ +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::{diagnostics::span_lint_and_then, source}; +use clippy_utils::source; use if_chain::if_chain; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, layout::LayoutOf, Ty, TypeAndMut}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, Ty, TypeAndMut}; use super::CAST_SLICE_DIFFERENT_SIZES; 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 1233c632a7948..5e0123842b041 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -4,7 +4,8 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{def_id::DefId, Expr, ExprKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index f0c1df0143072..ce1ab10910ccb 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -1,6 +1,6 @@ -use clippy_utils::msrvs::POINTER_CAST_CONSTNESS; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{Msrv, POINTER_CAST_CONSTNESS}; use clippy_utils::sugg::Sugg; -use clippy_utils::{diagnostics::span_lint_and_sugg, msrvs::Msrv}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 1c321f46e2da4..e3a09636e2496 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -10,8 +10,7 @@ use core::iter; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def_id::DefIdSet; -use rustc_hir::intravisit; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind}; +use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::query::Key; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 7436e9ce811b1..726674d88f17c 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -5,7 +5,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::sym, Span}; +use rustc_span::symbol::sym; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index ca9514ccc7d00..a294c69378774 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -1,5 +1,7 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, is_ty_alias, match_def_path, paths}; -use hir::{def::Res, ExprKind}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{is_ty_alias, match_def_path, paths}; +use hir::def::Res; +use hir::ExprKind; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index f296b80d283d8..572990aaba109 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::last_path_segment; use clippy_utils::source::snippet_with_context; -use clippy_utils::{match_def_path, paths}; +use clippy_utils::{last_path_segment, match_def_path, paths}; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index e53a9877b20ca..0708b1cabdb51 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -4,15 +4,11 @@ use clippy_utils::{get_parent_node, numeric_literal}; use if_chain::if_chain; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; -use rustc_hir::{ - intravisit::{walk_expr, walk_stmt, Visitor}, - Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind, -}; +use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor}; +use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::{ - lint::in_external_macro, - ty::{self, FloatTy, IntTy, PolyFnSig, Ty}, -}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::iter; diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index cdf64b960360d..1b3bd268bf555 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -12,12 +12,11 @@ use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch}; use rustc_errors::Applicability; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{ - self as hir, - def_id::{DefId, LocalDefId}, - BindingAnnotation, Body, BodyId, BorrowKind, Closure, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem, - ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem, + self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Closure, Expr, ExprKind, FnRetTy, GenericArg, HirId, + ImplItem, ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem, TraitItemKind, TyKind, UnOp, }; use rustc_index::bit_set::BitSet; @@ -30,9 +29,11 @@ use rustc_middle::ty::{ ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::sym, Span, Symbol}; +use rustc_span::symbol::sym; +use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{Obligation, ObligationCause}; use std::collections::VecDeque; declare_clippy_lint! { diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index ec0ca50cfec70..0ff3ddd67deb9 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -3,10 +3,9 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_errors::Applicability; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::{ - self as hir, - def::{CtorKind, CtorOf, DefKind, Res}, - Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, + self as hir, Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, PointerCast}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index a005a360e9cef..aea8cf2f9aba4 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::paths; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; -use clippy_utils::{is_lint_allowed, match_def_path}; +use clippy_utils::{is_lint_allowed, match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs index 6e6615f08ee71..04c2d44137a3b 100644 --- a/clippy_lints/src/disallowed_names.rs +++ b/clippy_lints/src/disallowed_names.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint, is_test_module_or_function}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_test_module_or_function; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{Item, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 87d88f707529c..2f474bf38e6ef 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -31,9 +31,8 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::source_map::{BytePos, FilePathMapping, SourceMap, Span}; use rustc_span::{sym, FileName, Pos}; -use std::io; use std::ops::Range; -use std::thread; +use std::{io, thread}; use url::Url; declare_clippy_lint! { diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 976ce47e8694a..14122abbf2c2b 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_note; -use clippy_utils::get_parent_node; -use clippy_utils::is_must_use_func_call; use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; +use clippy_utils::{get_parent_node, is_must_use_func_call}; use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/empty_drop.rs b/clippy_lints/src/empty_drop.rs index ec063c0f777e3..209fb66fa40f9 100644 --- a/clippy_lints/src/empty_drop.rs +++ b/clippy_lints/src/empty_drop.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, peel_blocks}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::peel_blocks; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node}; diff --git a/clippy_lints/src/empty_structs_with_brackets.rs b/clippy_lints/src/empty_structs_with_brackets.rs index c3a020433de85..282157181abb3 100644 --- a/clippy_lints/src/empty_structs_with_brackets.rs +++ b/clippy_lints/src/empty_structs_with_brackets.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; use rustc_ast::ast::{Item, ItemKind, VariantData}; use rustc_errors::Applicability; use rustc_lexer::TokenKind; diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index f470987833e42..dda14b4df533b 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -1,8 +1,10 @@ use crate::Lint; -use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_lint_allowed; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::{lint::in_external_macro, ty::Ty}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Symbol; use std::borrow::Cow; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 86e94a62a7844..49aae6b374547 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,18 +1,14 @@ -use clippy_utils::higher; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}; use clippy_utils::{ - can_move_expr_to_closure_no_visit, - diagnostics::span_lint_and_sugg, - is_expr_final_block_expr, is_expr_used_or_unified, match_def_path, paths, peel_hir_expr_while, - source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}, - SpanlessEq, + can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, match_def_path, + paths, peel_hir_expr_while, SpanlessEq, }; use core::fmt::{self, Write}; use rustc_errors::Applicability; -use rustc_hir::{ - hir_id::HirIdSet, - intravisit::{walk_expr, Visitor}, - Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp, -}; +use rustc_hir::hir_id::HirIdSet; +use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::{Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{Span, SyntaxContext, DUMMY_SP}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index a51a8ee09f6e5..dbe3453e7bfa0 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir; -use rustc_hir::intravisit; -use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind}; +use rustc_hir::{self, intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index d04d833e6304e..8911f1872c2cd 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -1,9 +1,8 @@ -use clippy_utils::{diagnostics::span_lint_and_help, source::snippet}; -use rustc_ast::{ - node_id::NodeSet, - visit::{walk_block, walk_item, Visitor}, - Block, Crate, Inline, Item, ItemKind, ModKind, NodeId, -}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; +use rustc_ast::node_id::NodeSet; +use rustc_ast::visit::{walk_block, walk_item, Visitor}; +use rustc_ast::{Block, Crate, Inline, Item, ItemKind, ModKind, NodeId}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index 126bed6789c4a..c18006a71c26e 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; -use clippy_utils::is_from_proc_macro; -use clippy_utils::trait_ref_of_method; +use clippy_utils::{is_from_proc_macro, trait_ref_of_method}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor}; @@ -12,10 +11,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{ - def_id::{DefId, LocalDefId}, - Span, -}; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 5e0fcd743392d..29e5315f88b7f 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -1,10 +1,8 @@ -use clippy_utils::consts::{ - constant, constant_simple, Constant, - Constant::{Int, F32, F64}, -}; +use clippy_utils::consts::Constant::{Int, F32, F64}; +use clippy_utils::consts::{constant, constant_simple, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{ - diagnostics::span_lint_and_sugg, eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, - numeric_literal, peel_blocks, sugg, + eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, numeric_literal, peel_blocks, sugg, }; use if_chain::if_chain; use rustc_errors::Applicability; diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 08e45ed7d0ec8..d27f5c243664b 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -14,10 +14,8 @@ use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, FormatPlaceholder, FormatTrait, }; -use rustc_errors::{ - Applicability, - SuggestionStyle::{CompletelyHidden, ShowCode}, -}; +use rustc_errors::Applicability; +use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index 3ddee1842a30c..66b74d3b5abb3 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -7,8 +7,8 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Span; -use rustc_span::{sym, symbol::kw, Symbol}; +use rustc_span::symbol::kw; +use rustc_span::{sym, Span, Symbol}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 92d67ef359dca..9584bec40eec4 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -10,7 +10,8 @@ use rustc_hir::{ TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::{hir::nested_filter::OnlyBodies, ty}; +use rustc_middle::hir::nested_filter::OnlyBodies; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{kw, sym}; use rustc_span::{Span, Symbol}; diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs index 096508dc4f11e..5e859d97c6242 100644 --- a/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/clippy_lints/src/from_raw_with_void_ptr.rs @@ -4,8 +4,7 @@ use clippy_utils::{match_def_path, path_def_id, paths}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::RawPtr; -use rustc_middle::ty::TypeAndMut; +use rustc_middle::ty::{RawPtr, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; diff --git a/clippy_lints/src/functions/impl_trait_in_params.rs b/clippy_lints/src/functions/impl_trait_in_params.rs index d3d0d91c1be73..597fca8888516 100644 --- a/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/clippy_lints/src/functions/impl_trait_in_params.rs @@ -1,6 +1,8 @@ -use clippy_utils::{diagnostics::span_lint_and_then, is_in_test_function}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_in_test_function; -use rustc_hir::{intravisit::FnKind, Body, HirId}; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, HirId}; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs index b244b91331436..169b70f046392 100644 --- a/clippy_lints/src/functions/misnamed_getters.rs +++ b/clippy_lints/src/functions/misnamed_getters.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::Applicability; -use rustc_hir::{intravisit::FnKind, Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety}; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index d0ad26282642c..c211ca6793785 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,14 +1,13 @@ use hir::FnSig; use rustc_ast::ast::Attribute; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, def::Res, QPath}; +use rustc_hir::{self as hir, QPath}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::{ - lint::in_external_macro, - ty::{self, Ty}, -}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty}; use rustc_span::{sym, Span, Symbol}; use clippy_utils::attrs::is_proc_macro; diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index 9ea8c494cfcda..e614a8f694fb7 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::higher; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::SpanlessEq; +use clippy_utils::{higher, SpanlessEq}; use if_chain::if_chain; use rustc_errors::Diagnostic; use rustc_hir::intravisit::{self as visit, Visitor}; diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 372b6ead3fe46..a6b035d510628 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,9 +1,7 @@ -use clippy_utils::{ - diagnostics::span_lint_hir_and_then, - get_async_fn_body, is_async_fn, - source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}, - visitors::for_each_expr, -}; +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}; +use clippy_utils::visitors::for_each_expr; +use clippy_utils::{get_async_fn_body, is_async_fn}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs index 25e1cb36b74a1..166908ef4e46c 100644 --- a/clippy_lints/src/incorrect_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -1,15 +1,15 @@ -use clippy_utils::{ - diagnostics::{span_lint_and_sugg, span_lint_and_then}, - get_parent_node, is_res_lang_ctor, last_path_segment, path_res, - ty::implements_trait, -}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::ty::implements_trait; +use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, path_res}; use rustc_errors::Applicability; -use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{sym, symbol::kw}; +use rustc_span::sym; +use rustc_span::symbol::kw; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 7a269e98ff13b..01a7c497cbe70 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -13,7 +13,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::Ident, Span}; +use rustc_span::symbol::Ident; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 7c41699f307aa..77e541d5b1677 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -3,7 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_lint_allowed; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{def_id::LocalDefId, Item, ItemKind, Node}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 34e9991582c01..8df7dfb8b9e5a 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -7,7 +7,8 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{source_map::Spanned, sym}; +use rustc_span::source_map::Spanned; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index f684847c0c2d4..55a43e9156282 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{is_from_proc_macro, is_in_cfg_test}; use rustc_hir::{HirId, ItemId, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index c924d7361ce3b..c16717deee072 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -1,5 +1,8 @@ -use clippy_utils::{diagnostics::span_lint, get_parent_node, ty::implements_trait}; -use rustc_hir::{def_id::LocalDefId, FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::get_parent_node; +use clippy_utils::ty::implements_trait; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 1c99bd2f3d02e..9caaec4e5ccf2 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,10 +1,8 @@ //! lint when there is a large size difference between variants on an enum +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{ - diagnostics::span_lint_and_then, - ty::{approx_ty_size, is_copy, AdtVariantInfo}, -}; +use clippy_utils::ty::{approx_ty_size, is_copy, AdtVariantInfo}; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index 087c4a65250a9..d67d5899350a8 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -1,5 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait}; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index 424c0d9e79828..566901de34754 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -2,8 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_lint_allowed; use clippy_utils::macros::root_macro_call_first_node; use rustc_ast::LitKind; -use rustc_hir::Expr; -use rustc_hir::ExprKind; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 9c0cc978a391f..7aa1446d53d59 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -4,11 +4,9 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::fn_has_unsatisfiable_preds; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; -use rustc_hir::Body; -use rustc_hir::FnDecl; +use rustc_hir::{Body, FnDecl}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_tool_lint; -use rustc_session::impl_lint_pass; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; declare_clippy_lint! { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 17bd89efaee03..e64d46bd6e383 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,22 +1,23 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_context; -use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators, sugg::Sugg}; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def::Res; +use rustc_hir::def_id::{DefId, DefIdSet}; +use rustc_hir::lang_items::LangItem; use rustc_hir::{ - def::Res, def_id::DefId, lang_items::LangItem, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, - GenericBound, ImplItem, ImplItemKind, ImplicitSelfKind, Item, ItemKind, Mutability, Node, PathSegment, PrimTy, - QPath, TraitItemRef, TyKind, TypeBindingKind, + AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, + ImplicitSelfKind, Item, ItemKind, Mutability, Node, PathSegment, PrimTy, QPath, TraitItemRef, TyKind, + TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{ - source_map::{Span, Spanned, Symbol}, - symbol::sym, -}; +use rustc_span::source_map::{Span, Spanned, Symbol}; +use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index db41bc67da1a7..2f6f36c396044 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::path_to_local_id; use clippy_utils::source::snippet; -use clippy_utils::{path_to_local_id, visitors::is_local_used}; +use clippy_utils::visitors::is_local_used; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index e661418092080..b505a4e0af9ea 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::is_from_proc_macro; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; -use clippy_utils::{is_must_use_func_call, paths}; +use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths}; use rustc_hir::{Local, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cebe2e44c0fba..a60da13d053cf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -348,11 +348,10 @@ mod zero_div_zero; mod zero_sized_map_values; // end lints modules, do not remove this comment, it’s used in `update_lints` +use crate::utils::conf::metadata::get_configuration_metadata; +use crate::utils::conf::TryConf; pub use crate::utils::conf::{lookup_conf_file, Conf}; -use crate::utils::{ - conf::{metadata::get_configuration_metadata, TryConf}, - FindAll, -}; +use crate::utils::FindAll; /// Register all pre expansion lints /// diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs index 09b2032e20fbe..49425ff0a8e05 100644 --- a/clippy_lints/src/lines_filter_map_ok.rs +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -1,7 +1,6 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths, - ty::match_type, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::match_type; +use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths}; use rustc_errors::Applicability; use rustc_hir::{Body, Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs index 4bb9936e9cde7..0aaa66e6bceee 100644 --- a/clippy_lints/src/loops/manual_find.rs +++ b/clippy_lints/src/loops/manual_find.rs @@ -1,14 +1,14 @@ use super::utils::make_iterator_snippet; use super::MANUAL_FIND; -use clippy_utils::{ - diagnostics::span_lint_and_then, higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt, - source::snippet_with_applicability, ty::implements_trait, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::implements_trait; +use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{ - def::Res, lang_items::LangItem, BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind, -}; +use rustc_hir::def::Res; +use rustc_hir::lang_items::LangItem; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs index 1e02a30e35fe4..559a2c03f1460 100644 --- a/clippy_lints/src/loops/manual_flatten.rs +++ b/clippy_lints/src/loops/manual_flatten.rs @@ -1,9 +1,8 @@ use super::utils::make_iterator_snippet; use super::MANUAL_FLATTEN; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::higher; use clippy_utils::visitors::is_local_used; -use clippy_utils::{path_to_local_id, peel_blocks_with_stmt}; +use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs index cb9c84be4c7a6..ca584a454d035 100644 --- a/clippy_lints/src/loops/manual_while_let_some.rs +++ b/clippy_lints/src/loops/manual_while_let_some.rs @@ -1,9 +1,6 @@ -use clippy_utils::{ - diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, - match_def_path, paths, - source::snippet, - SpanlessEq, -}; +use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::{match_def_path, paths, SpanlessEq}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 4dae93f6028d4..b83d148b5f247 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -7,7 +7,8 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; -use rustc_middle::{mir::FakeReadCause, ty}; +use rustc_middle::mir::FakeReadCause; +use rustc_middle::ty; use rustc_span::source_map::Span; pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index ee338c6beb06d..7da9121fbb383 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -1,9 +1,9 @@ use super::utils::make_iterator_snippet; use super::NEVER_LOOP; -use clippy_utils::consts::constant; +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet; -use clippy_utils::{consts::Constant, diagnostics::span_lint_and_then}; use rustc_errors::Applicability; use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs index d1a1f773f87b3..7f24f3c5dc281 100644 --- a/clippy_lints/src/loops/while_immutable_condition.rs +++ b/clippy_lints/src/loops/while_immutable_condition.rs @@ -6,8 +6,7 @@ use if_chain::if_chain; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::HirIdSet; -use rustc_hir::{Expr, ExprKind, QPath}; +use rustc_hir::{Expr, ExprKind, HirIdSet, QPath}; use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index 55989f8a44650..ed6af90ef04a0 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -1,18 +1,18 @@ use super::WHILE_LET_ON_ITERATOR; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{ - get_enclosing_loop_or_multi_call_closure, is_refutable, is_res_lang_ctor, is_trait_method, visitors::is_res_used, -}; +use clippy_utils::visitors::is_res_used; +use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp}; +use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::ty::adjustment::Adjust; -use rustc_span::{symbol::sym, Symbol}; +use rustc_span::symbol::sym; +use rustc_span::Symbol; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! { diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index cb3bda961333b..70c5182472aad 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -8,7 +8,8 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{edition::Edition, sym, Span}; +use rustc_span::edition::Edition; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 440362b96b470..e75666e61f555 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -4,21 +4,19 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::is_const_evaluatable; -use clippy_utils::MaybePath; use clippy_utils::{ eq_expr_value, in_constant, is_diag_trait_item, is_trait_method, path_res, path_to_local_id, peel_blocks, - peel_blocks_with_stmt, + peel_blocks_with_stmt, MaybePath, }; use itertools::Itertools; -use rustc_errors::Applicability; -use rustc_errors::Diagnostic; -use rustc_hir::{ - def::Res, Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind, -}; +use rustc_errors::{Applicability, Diagnostic}; +use rustc_hir::def::Res; +use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::sym, Span}; +use rustc_span::symbol::sym; +use rustc_span::Span; use std::ops::Deref; declare_clippy_lint! { diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index 09b39634333fc..085c73a5f9fbf 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -1,9 +1,7 @@ -use clippy_utils::{ - consts::{constant, Constant}, - diagnostics::span_lint_and_then, - is_from_proc_macro, path_to_local, - source::snippet_opt, -}; +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs index 31264261f5dbd..f264424470da1 100644 --- a/clippy_lints/src/manual_is_ascii_check.rs +++ b/clippy_lints/src/manual_is_ascii_check.rs @@ -1,12 +1,16 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::macros::root_macro_call; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::{diagnostics::span_lint_and_sugg, higher, in_constant, macros::root_macro_call, sugg::Sugg}; +use clippy_utils::sugg::Sugg; +use clippy_utils::{higher, in_constant}; use rustc_ast::ast::RangeLimits; use rustc_ast::LitKind::{Byte, Char}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{def_id::DefId, sym, Span}; +use rustc_span::def_id::DefId; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs index 64d4c8e456658..39d8b20d38d02 100644 --- a/clippy_lints/src/manual_range_patterns.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -2,13 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::Expr; -use rustc_hir::ExprKind; -use rustc_hir::PatKind; -use rustc_hir::RangeEnd; -use rustc_hir::UnOp; -use rustc_lint::LintContext; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 93d977a5c96b8..2b9def1a6884a 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -8,8 +8,7 @@ use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::BinOpKind; -use rustc_hir::{BorrowKind, Expr, ExprKind}; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs index 6ec9784038c37..841c020f2d3de 100644 --- a/clippy_lints/src/match_result_ok.rs +++ b/clippy_lints/src/match_result_ok.rs @@ -1,8 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; -use clippy_utils::is_res_lang_ctor; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{higher, is_res_lang_ctor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, PatKind}; diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs index 5b7644a538323..6b611f567ae28 100644 --- a/clippy_lints/src/matches/manual_utils.rs +++ b/clippy_lints/src/matches/manual_utils.rs @@ -1,14 +1,17 @@ -use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF}; +use crate::map_unit_fn::OPTION_MAP_UNIT_FN; +use crate::matches::MATCH_AS_REF; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function}; use clippy_utils::{ can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id, - peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, sugg::Sugg, CaptureKind, + peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind, }; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::LangItem::{OptionNone, OptionSome}; -use rustc_hir::{def::Res, BindingAnnotation, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath}; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_span::{sym, SyntaxContext}; diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index 69f6c59beb35d..e2ddf11abe2ca 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -1,9 +1,7 @@ use super::REDUNDANT_PATTERN_MATCHING; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_lint_allowed; -use clippy_utils::is_wild; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::span_contains_comment; +use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment}; use rustc_ast::{Attribute, LitKind}; use rustc_errors::Applicability; use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath}; diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index 3d2fbea63f5e8..0553b41328e52 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -2,8 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; -use core::iter; -use core::slice; +use core::{iter, slice}; use rustc_arena::DroplessArena; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index 43d2ab9f60e38..bddd57c98102c 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -12,7 +12,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk}; use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Ty}; use rustc_span::{sym, Symbol}; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 883a5505827e1..3a8cc41748ebf 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -1,7 +1,8 @@ use super::{contains_return, BIND_INSTEAD_OF_MAP}; use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, snippet_with_context}; -use clippy_utils::{peel_blocks, visitors::find_all_ret_expressions}; +use clippy_utils::visitors::find_all_ret_expressions; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index 7711aa78b2391..41b5cc12d6db6 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; -use clippy_utils::source::{indent_of, reindent_multiline}; +use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_lang_item; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::LateContext; -use rustc_span::{source_map::Spanned, Span}; +use rustc_span::source_map::Spanned; +use rustc_span::Span; use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS; diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs index 079df2226d1e2..0e41f3c210769 100644 --- a/clippy_lints/src/methods/chars_cmp.rs +++ b/clippy_lints/src/methods/chars_cmp.rs @@ -4,8 +4,7 @@ use clippy_utils::{method_chain_args, path_def_id}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_lint::LateContext; -use rustc_lint::Lint; +use rustc_lint::{LateContext, Lint}; use rustc_middle::ty; /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs index 8984b2cf8fd50..c9d50a5b03db6 100644 --- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs +++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -5,8 +5,7 @@ use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_lint::LateContext; -use rustc_lint::Lint; +use rustc_lint::{LateContext, Lint}; /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. pub(super) fn check( diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 65fd50dff5846..7eb325ee7b5e7 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -5,7 +5,9 @@ use clippy_utils::ty::is_copy; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths}; +use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::print::with_forced_trimmed_paths; +use rustc_middle::ty::{self}; use rustc_span::symbol::{sym, Symbol}; use super::CLONE_ON_COPY; diff --git a/clippy_lints/src/methods/collapsible_str_replace.rs b/clippy_lints/src/methods/collapsible_str_replace.rs index 5e01ed90ff099..5409ede6008b6 100644 --- a/clippy_lints/src/methods/collapsible_str_replace.rs +++ b/clippy_lints/src/methods/collapsible_str_replace.rs @@ -8,8 +8,7 @@ use rustc_hir as hir; use rustc_lint::LateContext; use std::collections::VecDeque; -use super::method_call; -use super::COLLAPSIBLE_STR_REPLACE; +use super::{method_call, COLLAPSIBLE_STR_REPLACE}; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index d0c79dc11b071..6a82d8f756ad0 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -4,17 +4,12 @@ use clippy_utils::is_range_full; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_lang_item; use rustc_errors::Applicability; -use rustc_hir::Expr; -use rustc_hir::ExprKind; -use rustc_hir::LangItem; -use rustc_hir::Path; -use rustc_hir::QPath; +use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath}; use rustc_lint::LateContext; use rustc_middle::query::Key; use rustc_middle::ty; use rustc_middle::ty::Ty; -use rustc_span::sym; -use rustc_span::Symbol; +use rustc_span::{sym, Symbol}; /// Checks if both types match the given diagnostic item, e.g.: /// diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs index ae03da0d3f9ce..98f470dff8a28 100644 --- a/clippy_lints/src/methods/err_expect.rs +++ b/clippy_lints/src/methods/err_expect.rs @@ -1,8 +1,7 @@ use super::ERR_EXPECT; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::ty::has_debug_impl; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item}; use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_middle::ty; diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index fc80f2eeae015..597a423b53779 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -13,9 +13,7 @@ use rustc_span::source_map::Span; use rustc_span::symbol::{sym, Symbol}; use std::borrow::Cow; -use super::MANUAL_FILTER_MAP; -use super::MANUAL_FIND_MAP; -use super::OPTION_FILTER_MAP; +use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP}; fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { match &expr.kind { diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs index d1b5e945dfdaa..3337b250c0e79 100644 --- a/clippy_lints/src/methods/filter_map_identity.rs +++ b/clippy_lints/src/methods/filter_map_identity.rs @@ -3,7 +3,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::FILTER_MAP_IDENTITY; diff --git a/clippy_lints/src/methods/flat_map_identity.rs b/clippy_lints/src/methods/flat_map_identity.rs index 6f911d79d0bc5..84a21de0ac860 100644 --- a/clippy_lints/src/methods/flat_map_identity.rs +++ b/clippy_lints/src/methods/flat_map_identity.rs @@ -3,7 +3,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::FLAT_MAP_IDENTITY; diff --git a/clippy_lints/src/methods/flat_map_option.rs b/clippy_lints/src/methods/flat_map_option.rs index 615bde9413349..367a8ae82bd8f 100644 --- a/clippy_lints/src/methods/flat_map_option.rs +++ b/clippy_lints/src/methods/flat_map_option.rs @@ -4,7 +4,8 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::FLAT_MAP_OPTION; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/clippy_lints/src/methods/inspect_for_each.rs b/clippy_lints/src/methods/inspect_for_each.rs index 7fd3ef1a622a0..23cc192c38e3e 100644 --- a/clippy_lints/src/methods/inspect_for_each.rs +++ b/clippy_lints/src/methods/inspect_for_each.rs @@ -2,7 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_trait_method; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::INSPECT_FOR_EACH; diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index 301aff5ae6ac0..120f3d5f42c7e 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,10 +1,10 @@ //! Lint for `c.is_digit(10)` use super::IS_DIGIT_ASCII_RADIX; +use clippy_utils::consts::{constant_full_int, FullInt}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::{ - consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, source::snippet_with_applicability, -}; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index c87f5daab6f24..674d345174819 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -9,8 +9,7 @@ use clippy_utils::visitors::is_local_used; use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty; -use rustc_span::sym; -use rustc_span::Span; +use rustc_span::{sym, Span}; /// lint use of: /// - `hashmap.iter().map(|(_, v)| v)` diff --git a/clippy_lints/src/methods/iter_skip_next.rs b/clippy_lints/src/methods/iter_skip_next.rs index 279175e20c37f..39af52141bbc8 100644 --- a/clippy_lints/src/methods/iter_skip_next.rs +++ b/clippy_lints/src/methods/iter_skip_next.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_trait_method; -use clippy_utils::path_to_local; use clippy_utils::source::snippet; +use clippy_utils::{is_trait_method, path_to_local}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{BindingAnnotation, Node, PatKind}; diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index a7284c6449776..7e62e7ad909eb 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -24,10 +24,8 @@ pub fn check( let Some(mm) = is_min_or_max(cx, unwrap_arg) else { return }; if ty.is_signed() { - use self::{ - MinMax::{Max, Min}, - Sign::{Neg, Pos}, - }; + use self::MinMax::{Max, Min}; + use self::Sign::{Neg, Pos}; let Some(sign) = lit_sign(arith_rhs) else { return; diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index 576a58499b154..dabed0affcf44 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -1,15 +1,11 @@ -use clippy_utils::{ - diagnostics::span_lint_and_sugg, - is_from_proc_macro, - msrvs::{Msrv, ITERATOR_TRY_FOLD}, - source::snippet_opt, - ty::implements_trait, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{Msrv, ITERATOR_TRY_FOLD}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; -use rustc_hir::{ - def::{DefKind, Res}, - Expr, ExprKind, -}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::Span; diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs index 361ffcb5ef3fb..349caa6ea6c24 100644 --- a/clippy_lints/src/methods/map_flatten.rs +++ b/clippy_lints/src/methods/map_flatten.rs @@ -6,7 +6,8 @@ use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::{symbol::sym, Span}; +use rustc_span::symbol::sym; +use rustc_span::Span; use super::MAP_FLATTEN; diff --git a/clippy_lints/src/methods/map_identity.rs b/clippy_lints/src/methods/map_identity.rs index 0f25ef82ed42a..7be1ce483f63f 100644 --- a/clippy_lints/src/methods/map_identity.rs +++ b/clippy_lints/src/methods/map_identity.rs @@ -4,7 +4,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::MAP_IDENTITY; diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index d0aa39d06275a..161a7aa7fd4ff 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{expr_custom_deref_adjustment, ty::is_type_diagnostic_item}; +use clippy_utils::expr_custom_deref_adjustment; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index ac209d014062e..60fd64ec97f5a 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -4,10 +4,9 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection}; use clippy_utils::{ - can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id, - CaptureKind, + can_move_expr_to_closure, fn_def_id, get_enclosing_block, get_parent_node, higher, is_trait_method, path_to_local, + path_to_local_id, CaptureKind, }; -use clippy_utils::{fn_def_id, higher}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; diff --git a/clippy_lints/src/methods/obfuscated_if_else.rs b/clippy_lints/src/methods/obfuscated_if_else.rs index eada530d670da..697eab32a33b0 100644 --- a/clippy_lints/src/methods/obfuscated_if_else.rs +++ b/clippy_lints/src/methods/obfuscated_if_else.rs @@ -1,5 +1,6 @@ use super::OBFUSCATED_IF_ELSE; -use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_with_applicability}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs index 41ceef19e3a97..cb6a2306857d7 100644 --- a/clippy_lints/src/methods/option_map_or_none.rs +++ b/clippy_lints/src/methods/option_map_or_none.rs @@ -8,8 +8,7 @@ use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; use rustc_span::symbol::sym; -use super::OPTION_MAP_OR_NONE; -use super::RESULT_MAP_OR_INTO_OPTION; +use super::{OPTION_MAP_OR_NONE, RESULT_MAP_OR_INTO_OPTION}; // The expression inside a closure may or may not have surrounding braces // which causes problems when generating a suggestion. diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index f4f158c0439ed..fcbe005fb286a 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,17 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_copy; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_path, Visitor}; -use rustc_hir::ExprKind; -use rustc_hir::Node; -use rustc_hir::PatKind; -use rustc_hir::QPath; -use rustc_hir::{self, HirId, Path}; +use rustc_hir::{self, ExprKind, HirId, Node, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/methods/or_then_unwrap.rs b/clippy_lints/src/methods/or_then_unwrap.rs index d65082173b3fc..7b0bdcf99e736 100644 --- a/clippy_lints/src/methods/or_then_unwrap.rs +++ b/clippy_lints/src/methods/or_then_unwrap.rs @@ -1,8 +1,10 @@ +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::{diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res}; +use clippy_utils::{is_res_lang_ctor, path_res}; use rustc_errors::Applicability; -use rustc_hir::{lang_items::LangItem, Expr, ExprKind}; +use rustc_hir::lang_items::LangItem; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::{sym, Span}; diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs index 867a3b4023770..f253d8de91f9e 100644 --- a/clippy_lints/src/methods/range_zip_with_len.rs +++ b/clippy_lints/src/methods/range_zip_with_len.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet; -use clippy_utils::{higher, SpanlessEq}; -use clippy_utils::{is_integer_const, is_trait_method}; +use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/read_line_without_trim.rs b/clippy_lints/src/methods/read_line_without_trim.rs index 49e4f1acaa6f6..8add0656101e5 100644 --- a/clippy_lints/src/methods/read_line_without_trim.rs +++ b/clippy_lints/src/methods/read_line_without_trim.rs @@ -1,13 +1,13 @@ use std::ops::ControlFlow; -use clippy_utils::{ - diagnostics::span_lint_and_then, get_parent_expr, match_def_path, source::snippet, ty::is_type_diagnostic_item, - visitors::for_each_local_use_after_expr, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::visitors::for_each_local_use_after_expr; +use clippy_utils::{get_parent_expr, match_def_path}; use rustc_errors::Applicability; -use rustc_hir::Expr; -use rustc_hir::QPath; -use rustc_hir::{def::Res, ExprKind}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::sym; diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs index c028e954381dd..f3d6a15ede01b 100644 --- a/clippy_lints/src/methods/seek_from_current.rs +++ b/clippy_lints/src/methods/seek_from_current.rs @@ -3,10 +3,10 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use clippy_utils::{ - diagnostics::span_lint_and_sugg, get_trait_def_id, match_def_path, paths, source::snippet_with_applicability, - ty::implements_trait, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::implements_trait; +use clippy_utils::{get_trait_def_id, match_def_path, paths}; use super::SEEK_FROM_CURRENT; diff --git a/clippy_lints/src/methods/suspicious_command_arg_space.rs b/clippy_lints/src/methods/suspicious_command_arg_space.rs index 73632c5a357dd..bc8f017676415 100644 --- a/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::paths; use clippy_utils::ty::match_type; -use rustc_ast as ast; use rustc_errors::{Applicability, Diagnostic}; -use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::Span; +use {rustc_ast as ast, rustc_hir as hir}; use super::SUSPICIOUS_COMMAND_ARG_SPACE; diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs index e818f1892e510..9eb8d6e6e787d 100644 --- a/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/clippy_lints/src/methods/suspicious_to_owned.rs @@ -5,7 +5,8 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_middle::ty::{self, print::with_forced_trimmed_paths}; +use rustc_middle::ty::print::with_forced_trimmed_paths; +use rustc_middle::ty::{self}; use rustc_span::sym; use super::SUSPICIOUS_TO_OWNED; diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index 88adba504aa58..35137c97101e6 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -4,10 +4,8 @@ use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; -use rustc_middle::ty::adjustment::Adjustment; -use rustc_middle::ty::Ty; -use rustc_middle::ty::{self, ExistentialPredicate}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{sym, Span}; fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { diff --git a/clippy_lints/src/methods/uninit_assumed_init.rs b/clippy_lints/src/methods/uninit_assumed_init.rs index a1c6294737cf8..bc9c518dbcf0a 100644 --- a/clippy_lints/src/methods/uninit_assumed_init.rs +++ b/clippy_lints/src/methods/uninit_assumed_init.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_path_diagnostic_item, ty::is_uninit_value_valid_for_ty}; +use clippy_utils::is_path_diagnostic_item; +use clippy_utils::ty::is_uninit_value_valid_for_ty; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 1cef6226ad4ff..cc64a2e794875 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -11,8 +11,7 @@ use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::sym; -use super::UNNECESSARY_FILTER_MAP; -use super::UNNECESSARY_FIND_MAP; +use super::{UNNECESSARY_FILTER_MAP, UNNECESSARY_FIND_MAP}; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>, name: &str) { if !is_trait_method(cx, expr, sym::Iterator) { diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index 8ec15a1c1b765..6e23754bf46ee 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -8,7 +8,8 @@ use rustc_hir as hir; use rustc_hir::PatKind; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::{source_map::Span, sym}; +use rustc_span::source_map::Span; +use rustc_span::sym; use super::UNNECESSARY_FOLD; diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 52a4ff7d1ae4f..0c72c13a3caa7 100644 --- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -5,7 +5,8 @@ use clippy_utils::source::snippet_opt; use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; use clippy_utils::{fn_def_id, get_parent_expr}; use rustc_errors::Applicability; -use rustc_hir::{def_id::DefId, Expr, ExprKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::{sym, Symbol}; diff --git a/clippy_lints/src/methods/unnecessary_join.rs b/clippy_lints/src/methods/unnecessary_join.rs index 087e1e4343b70..d0c62fb56dc20 100644 --- a/clippy_lints/src/methods/unnecessary_join.rs +++ b/clippy_lints/src/methods/unnecessary_join.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_lang_item}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 54de300e6bc13..111bcaaecec37 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, last_path_segment, path_res, MaybePath}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_res_lang_ctor, last_path_segment, path_res, MaybePath}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 67618f7038add..54b76bd04fe0d 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -6,7 +6,8 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, subst::GenericArgKind}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self}; use rustc_span::sym; use rustc_span::symbol::Ident; use std::iter; diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 16ef24bd4e345..dcfec52fd713f 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -7,7 +7,8 @@ use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; use rustc_errors::Applicability; -use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node}; +use rustc_hir::def_id::DefId; +use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, Node}; use rustc_hir_typeck::{FnCtxt, Inherited}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; @@ -16,7 +17,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; -use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{Obligation, ObligationCause}; use super::UNNECESSARY_TO_OWNED; diff --git a/clippy_lints/src/methods/unwrap_or_else_default.rs b/clippy_lints/src/methods/unwrap_or_else_default.rs index 045f739e64ded..474a33b67e1c6 100644 --- a/clippy_lints/src/methods/unwrap_or_else_default.rs +++ b/clippy_lints/src/methods/unwrap_or_else_default.rs @@ -1,10 +1,10 @@ //! Lint for `some_result_or_option.unwrap_or_else(Default::default)` use super::UNWRAP_OR_ELSE_DEFAULT; -use clippy_utils::{ - diagnostics::span_lint_and_sugg, is_default_equivalent_call, source::snippet_with_applicability, - ty::is_type_diagnostic_item, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_default_equivalent_call; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index 23593e0d4d97b..2a60f2faca0ae 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -1,10 +1,9 @@ -use clippy_utils::{diagnostics::span_lint, is_from_proc_macro}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_from_proc_macro; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{ - def::{DefKind, Res}, - intravisit::{walk_item, Visitor}, - GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, -}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::intravisit::{walk_item, Visitor}; +use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs index 773174679dbdc..96d83e114a410 100644 --- a/clippy_lints/src/missing_enforced_import_rename.rs +++ b/clippy_lints/src/missing_enforced_import_rename.rs @@ -1,8 +1,11 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_hir::{def::Res, def_id::DefId, Item, ItemKind, UseKind}; +use rustc_hir::def::Res; +use rustc_hir::def_id::DefId; +use rustc_hir::{Item, ItemKind, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Symbol; diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index 497514fbcd606..2f63b9b9f0b8e 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -1,23 +1,17 @@ use std::ops::ControlFlow; -use clippy_utils::{ - diagnostics::span_lint_and_then, - is_path_lang_item, paths, - ty::match_type, - visitors::{for_each_expr, Visitable}, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::match_type; +use clippy_utils::visitors::{for_each_expr, Visitable}; +use clippy_utils::{is_path_lang_item, paths}; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::Block; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - def::{DefKind, Res}, - Expr, ImplItemKind, LangItem, Node, + Block, Expr, ExprKind, Impl, ImplItem, ImplItemKind, Item, ItemKind, LangItem, Node, QPath, TyKind, VariantData, }; -use rustc_hir::{ExprKind, Impl, ItemKind, QPath, TyKind}; -use rustc_hir::{ImplItem, Item, VariantData}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; -use rustc_middle::ty::TypeckResults; +use rustc_middle::ty::{Ty, TypeckResults}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, Span, Symbol}; diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index e6fd65f001a6e..fe35126aab216 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -1,12 +1,8 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, - visitors::{for_each_expr_with_closures, Descend, Visitable}, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::visitors::{for_each_expr_with_closures, Descend, Visitable}; use core::ops::ControlFlow::Continue; -use hir::{ - def::{DefKind, Res}, - BlockCheckMode, ExprKind, QPath, UnOp, Unsafety, -}; +use hir::def::{DefKind, Res}; +use hir::{BlockCheckMode, ExprKind, QPath, UnOp, Unsafety}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 34b74e180cb08..46457400abcbe 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,9 +6,9 @@ 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::{ - get_parent_node, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, + get_parent_node, higher, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, + SpanlessEq, }; -use clippy_utils::{higher, SpanlessEq}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp}; diff --git a/clippy_lints/src/needless_else.rs b/clippy_lints/src/needless_else.rs index 23d4a7b9586d1..03bab86c6d7c2 100644 --- a/clippy_lints/src/needless_else.rs +++ b/clippy_lints/src/needless_else.rs @@ -1,5 +1,5 @@ -use clippy_utils::source::snippet_opt; -use clippy_utils::{diagnostics::span_lint_and_sugg, source::trim_span}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{snippet_opt, trim_span}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs index c3b633fd6a038..463e188fc8e0f 100644 --- a/clippy_lints/src/needless_for_each.rs +++ b/clippy_lints/src/needless_for_each.rs @@ -1,11 +1,10 @@ use rustc_errors::Applicability; -use rustc_hir::{ - intravisit::{walk_expr, Visitor}, - Closure, Expr, ExprKind, Stmt, StmtKind, -}; +use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::{Closure, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{source_map::Span, sym, Symbol}; +use rustc_span::source_map::Span; +use rustc_span::{sym, Symbol}; use if_chain::if_chain; diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index ad5c3e1dc8229..1ed7ea6b32554 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -1,4 +1,7 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, higher::If, is_from_proc_macro, source::snippet_opt}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher::If; +use clippy_utils::is_from_proc_macro; +use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; diff --git a/clippy_lints/src/needless_parens_on_range_literals.rs b/clippy_lints/src/needless_parens_on_range_literals.rs index da1b9d99931a5..d17a383e8829e 100644 --- a/clippy_lints/src/needless_parens_on_range_literals.rs +++ b/clippy_lints/src/needless_parens_on_range_literals.rs @@ -1,8 +1,6 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, - higher, - source::{snippet, snippet_with_applicability}, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::higher; +use clippy_utils::source::{snippet, snippet_with_applicability}; use rustc_ast::ast; use rustc_errors::Applicability; diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 46c9b6c4141f1..cdb7ee4830547 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -5,8 +5,7 @@ use clippy_utils::{is_from_proc_macro, is_self}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, FnDecl, HirId, Impl, ItemKind, Mutability, Node, PatKind}; -use rustc_hir::{HirIdMap, HirIdSet}; +use rustc_hir::{Body, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind}; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 5d299f9355d56..f35f120c8520c 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -10,9 +10,9 @@ use rustc_ast::ast::Attribute; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind, + BindingAnnotation, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, + QPath, TyKind, }; -use rustc_hir::{HirIdSet, LangItem}; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index a4c7da7e48db3..e6d3e72d1e621 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,8 +1,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::peel_blocks; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; -use clippy_utils::{get_parent_node, is_lint_allowed}; +use clippy_utils::{get_parent_node, is_lint_allowed, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ 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 7eaa7db78a470..24875855de347 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -7,7 +7,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::{FieldDef, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs index 2d79a5c90081c..bd194b93584e3 100644 --- a/clippy_lints/src/nonstandard_macro_braces.rs +++ b/clippy_lints/src/nonstandard_macro_braces.rs @@ -1,7 +1,5 @@ -use std::{ - fmt, - hash::{Hash, Hasher}, -}; +use std::fmt; +use std::hash::{Hash, Hasher}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 5c240276b76d1..41e8377e15e74 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,20 +1,14 @@ use super::ARITHMETIC_SIDE_EFFECTS; -use clippy_utils::is_from_proc_macro; -use clippy_utils::{ - consts::{constant, constant_simple, Constant}, - diagnostics::span_lint, - is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary, -}; -use rustc_ast as ast; +use clippy_utils::consts::{constant, constant_simple, Constant}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; -use rustc_span::{ - source_map::{Span, Spanned}, - Symbol, -}; +use rustc_span::source_map::{Span, Spanned}; +use rustc_span::Symbol; +use {rustc_ast as ast, rustc_hir as hir}; const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[ ["f32", "f32"], diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs index 9bbf385fb5999..c4572a09db619 100644 --- a/clippy_lints/src/operators/assign_op_pattern.rs +++ b/clippy_lints/src/operators/assign_op_pattern.rs @@ -1,9 +1,8 @@ -use clippy_utils::binop_traits; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr; -use clippy_utils::{eq_expr_value, trait_ref_of_method}; +use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method}; use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; diff --git a/clippy_lints/src/operators/eq_op.rs b/clippy_lints/src/operators/eq_op.rs index 78965b7d6f74b..88d566318414a 100644 --- a/clippy_lints/src/operators/eq_op.rs +++ b/clippy_lints/src/operators/eq_op.rs @@ -1,6 +1,7 @@ +use clippy_utils::ast_utils::is_useless_with_eq_exprs; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace}; -use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function}; +use clippy_utils::{eq_expr_value, is_in_test_function}; use rustc_hir::{BinOpKind, Expr}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/operators/misrefactored_assign_op.rs b/clippy_lints/src/operators/misrefactored_assign_op.rs index 015f6c14e7612..5eabb349ec107 100644 --- a/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::eq_expr_value; use clippy_utils::source::snippet_opt; -use clippy_utils::sugg; +use clippy_utils::{eq_expr_value, sugg}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs index d7917e86a861f..932dd470f9ebd 100644 --- a/clippy_lints/src/operators/op_ref.rs +++ b/clippy_lints/src/operators/op_ref.rs @@ -4,7 +4,9 @@ use clippy_utils::source::snippet; use clippy_utils::ty::{implements_trait, is_copy}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{def::Res, def_id::DefId, BinOpKind, BorrowKind, Expr, ExprKind, GenericArg, ItemKind, QPath, TyKind}; +use rustc_hir::def::Res; +use rustc_hir::def_id::DefId; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, GenericArg, ItemKind, QPath, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index abdccc47f5475..40da002f4ff0d 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -6,10 +6,9 @@ use clippy_utils::{ }; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; -use rustc_hir::{ - def::Res, Arm, BindingAnnotation, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp, -}; +use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::SyntaxContext; diff --git a/clippy_lints/src/partialeq_to_none.rs b/clippy_lints/src/partialeq_to_none.rs index 456ded3fc0268..d9f5d1642d767 100644 --- a/clippy_lints/src/partialeq_to_none.rs +++ b/clippy_lints/src/partialeq_to_none.rs @@ -1,7 +1,6 @@ -use clippy_utils::{ - diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_operators, sugg, - ty::is_type_diagnostic_item, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_operators, sugg}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 0d78c3048ba12..a8e16f2cb3355 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -1,5 +1,4 @@ -use std::cmp; -use std::iter; +use std::{cmp, iter}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 866a04466c909..71c65e925e3f7 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -28,8 +28,7 @@ use rustc_span::sym; use rustc_span::symbol::Symbol; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use std::fmt; -use std::iter; +use std::{fmt, iter}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 9840d464b75fd..f5502cffb6693 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -4,10 +4,9 @@ use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ - eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, pat_and_expr_can_be_question_mark, - path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, + eq_expr_value, get_parent_node, higher, in_constant, is_else_clause, 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, }; -use clippy_utils::{higher, is_path_lang_item}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -17,9 +16,9 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::declare_tool_lint; -use rustc_session::impl_lint_pass; -use rustc_span::{sym, symbol::Symbol}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::sym; +use rustc_span::symbol::Symbol; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index d2018aba9e3dd..3287675a82de1 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,10 +1,9 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::higher; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_parent_expr, in_constant, is_integer_const, path_to_local}; +use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local}; use if_chain::if_chain; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index 0e964ec4724d9..ccabb577cb722 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -1,10 +1,10 @@ -use std::{iter::once, ops::ControlFlow}; +use std::iter::once; +use std::ops::ControlFlow; -use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet}; -use rustc_ast::{ - ast::{Expr, ExprKind}, - token::LitKind, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use rustc_ast::ast::{Expr, ExprKind}; +use rustc_ast::token::LitKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/rc_clone_in_vec_init.rs b/clippy_lints/src/rc_clone_in_vec_init.rs index e82aa3a7b9897..a2e7ae6d79ab5 100644 --- a/clippy_lints/src/rc_clone_in_vec_init.rs +++ b/clippy_lints/src/rc_clone_in_vec_init.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::VecArgs; -use clippy_utils::last_path_segment; use clippy_utils::macros::root_macro_call_first_node; -use clippy_utils::paths; use clippy_utils::source::{indent_of, snippet}; use clippy_utils::ty::match_type; +use clippy_utils::{last_path_segment, paths}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index fa107858863a4..2bf90815caadc 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -1,9 +1,7 @@ -use clippy_utils::{ - diagnostics::{span_lint, span_lint_and_sugg}, - higher::{get_vec_init_kind, VecInitKind}, - source::snippet, - visitors::for_each_expr, -}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; +use clippy_utils::source::snippet; +use clippy_utils::visitors::for_each_expr; use core::ops::ControlFlow; use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 05e52e6b38b12..534b2762ba769 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -1,15 +1,14 @@ use std::ops::ControlFlow; -use clippy_utils::{ - diagnostics::span_lint_and_sugg, - peel_blocks, - source::{snippet, walk_span_to_context}, - visitors::for_each_expr, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::peel_blocks; +use clippy_utils::source::{snippet, walk_span_to_context}; +use clippy_utils::visitors::for_each_expr; use rustc_errors::Applicability; use rustc_hir::{AsyncGeneratorKind, Closure, Expr, ExprKind, GeneratorKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::{lint::in_external_macro, ty::UpvarCapture}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::UpvarCapture; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index b6ce4ebc28f2e..4e3efe97b8c61 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -6,8 +6,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit as hir_visit; -use rustc_hir::intravisit::Visitor as HirVisitor; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index ad0167a3d3271..0212deda14606 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -9,7 +9,8 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index cc2dbae4bc4b5..bf1059a8b2904 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -1,20 +1,17 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, - expr_or_init, get_attr, path_to_local, - source::{indent_of, snippet}, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::{indent_of, snippet}; +use clippy_utils::{expr_or_init, get_attr, path_to_local}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Applicability; -use rustc_hir::{ - self as hir, - def::{DefKind, Res}, - intravisit::{walk_expr, Visitor}, -}; +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::{subst::GenericArgKind, Ty, TypeAndMut}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{Ty, TypeAndMut}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::sym; -use rustc_span::{symbol::Ident, Span, DUMMY_SP}; +use rustc_span::symbol::Ident; +use rustc_span::{sym, Span, DUMMY_SP}; use std::borrow::Cow; declare_clippy_lint! { diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index 42753d2e95114..7bbe98e0a7f95 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{is_from_proc_macro, is_in_test_function}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl}; +use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index 5743dd21c2835..9c21d70c82cc3 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -1,11 +1,14 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use rustc_ast::node_id::{NodeId, NodeMap}; +use rustc_ast::ptr::P; use rustc_ast::visit::{walk_expr, Visitor}; -use rustc_ast::{ptr::P, Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind}; +use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{edition::Edition, symbol::kw, Span, Symbol}; +use rustc_span::edition::Edition; +use rustc_span::symbol::kw; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs index dfe8be7a6a619..321c89889887c 100644 --- a/clippy_lints/src/single_range_in_vec_init.rs +++ b/clippy_lints/src/single_range_in_vec_init.rs @@ -1,7 +1,9 @@ -use clippy_utils::{ - diagnostics::span_lint_and_then, get_trait_def_id, higher::VecArgs, macros::root_macro_call_first_node, - source::snippet_opt, ty::implements_trait, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::get_trait_def_id; +use clippy_utils::higher::VecArgs; +use clippy_utils::macros::root_macro_call_first_node; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, QPath}; diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index ac4e29e9dfdfa..a91dd21269c59 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -4,8 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; -use rustc_hir::BinOpKind; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/size_of_ref.rs b/clippy_lints/src/size_of_ref.rs index 8abec06c641cc..89ac8cd8ca975 100644 --- a/clippy_lints/src/size_of_ref.rs +++ b/clippy_lints/src/size_of_ref.rs @@ -1,4 +1,6 @@ -use clippy_utils::{diagnostics::span_lint_and_help, path_def_id, ty::peel_mid_ty_refs}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::path_def_id; +use clippy_utils::ty::peel_mid_ty_refs; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index a13bc7a518871..f239165276ffe 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -1,9 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_help; +use rustc_hir::def::Res; use rustc_hir::def_id::DefId; -use rustc_hir::{def::Res, HirId, Path, PathSegment}; +use rustc_hir::{HirId, Path, PathSegment}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{sym, symbol::kw, Span}; +use rustc_span::symbol::kw; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 8658009eba43f..58724852b3c4d 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,8 +1,10 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_lang_item; -use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq}; -use clippy_utils::{get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls}; +use clippy_utils::{ + get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls, + peel_blocks, SpanlessEq, +}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; diff --git a/clippy_lints/src/suspicious_doc_comments.rs b/clippy_lints/src/suspicious_doc_comments.rs index e5746ca99cac1..8be4ec3dc64c3 100644 --- a/clippy_lints/src/suspicious_doc_comments.rs +++ b/clippy_lints/src/suspicious_doc_comments.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}; use if_chain::if_chain; -use rustc_ast::{token::CommentKind, AttrKind, AttrStyle, Attribute, Item}; +use rustc_ast::token::CommentKind; +use rustc_ast::{AttrKind, AttrStyle, Attribute, Item}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/suspicious_xor_used_as_pow.rs b/clippy_lints/src/suspicious_xor_used_as_pow.rs index 9c0dc8096d0dc..6fa49afe0ecd7 100644 --- a/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -1,4 +1,5 @@ -use clippy_utils::{numeric_literal::NumericLiteral, source::snippet_with_context}; +use clippy_utils::numeric_literal::NumericLiteral; +use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index f7eef03d1d473..98158ed0aee88 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -11,8 +11,8 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use rustc_span::SyntaxContext; -use rustc_span::{sym, symbol::Ident, Span}; +use rustc_span::symbol::Ident; +use rustc_span::{sym, Span, SyntaxContext}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/tests_outside_test_module.rs b/clippy_lints/src/tests_outside_test_module.rs index 0a0a77082e02f..b356666d852aa 100644 --- a/clippy_lints/src/tests_outside_test_module.rs +++ b/clippy_lints/src/tests_outside_test_module.rs @@ -1,8 +1,11 @@ -use clippy_utils::{diagnostics::span_lint_and_note, is_in_cfg_test, is_in_test_function}; -use rustc_hir::{intravisit::FnKind, Body, FnDecl}; +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::{is_in_cfg_test, is_in_test_function}; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, FnDecl}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{def_id::LocalDefId, Span}; +use rustc_span::def_id::LocalDefId; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does 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 5503653253c55..c0d0d2b93dc03 100644 --- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs +++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs @@ -4,10 +4,8 @@ use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::{ - query::Key, - ty::{self, Ty}, -}; +use rustc_middle::query::Key; +use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; /// Checks for `transmute_int_to_non_zero` lint. diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 5e24213d07fd2..13b7eeb43a6f4 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -3,8 +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::SubstsRef; -use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy}; +use rustc_middle::ty::{self, IntTy, SubstsRef, Ty, TypeAndMut, UintTy}; #[expect(clippy::too_many_lines)] pub(super) fn check<'tcx>( 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 85cd74f23ef7e..513a913f56adb 100644 --- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -6,7 +6,8 @@ use rustc_ast::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; use rustc_lint::LateContext; -use rustc_middle::ty::{cast::CastKind, Ty}; +use rustc_middle::ty::cast::CastKind; +use rustc_middle::ty::Ty; /// Checks for `transmutes_expressible_as_ptr_casts` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs index 62efd13b8d909..1cf6cf8548a64 100644 --- a/clippy_lints/src/transmute/utils.rs +++ b/clippy_lints/src/transmute/utils.rs @@ -2,7 +2,8 @@ use rustc_hir as hir; use rustc_hir::Expr; use rustc_hir_typeck::{cast, FnCtxt, Inherited}; use rustc_lint::LateContext; -use rustc_middle::ty::{cast::CastKind, Ty}; +use rustc_middle::ty::cast::CastKind; +use rustc_middle::ty::Ty; use rustc_span::DUMMY_SP; // check if the component types of the transmuted collection and the result have different ABI, diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 258617467e9b5..2e00ed042a8b6 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -1,13 +1,11 @@ -use clippy_utils::{ - diagnostics::span_lint_and_help, - is_from_proc_macro, - msrvs::{self, Msrv}, - path_to_local, -}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind, HirId, Node, Pat}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::{lint::in_external_macro, ty}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use std::iter::once; diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index acdf54710691e..306ca5724da1f 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -2,8 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{self as hir, GenericArg, GenericBounds, GenericParamKind}; -use rustc_hir::{HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind}; +use rustc_hir::{ + self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind, +}; use rustc_lint::LateContext; use rustc_span::sym; diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs index 43665a922d444..4a5a94f26302e 100644 --- a/clippy_lints/src/types/box_collection.rs +++ b/clippy_lints/src/types/box_collection.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{path_def_id, qpath_generic_tys}; -use rustc_hir::{self as hir, def_id::DefId, QPath}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; use rustc_span::{sym, Symbol}; diff --git a/clippy_lints/src/types/linked_list.rs b/clippy_lints/src/types/linked_list.rs index 5fb708741e58a..fba804bbe088a 100644 --- a/clippy_lints/src/types/linked_list.rs +++ b/clippy_lints/src/types/linked_list.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; -use rustc_hir::{self as hir, def_id::DefId}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/types/option_option.rs b/clippy_lints/src/types/option_option.rs index 8767e3c30a68a..60622903af1d6 100644 --- a/clippy_lints/src/types/option_option.rs +++ b/clippy_lints/src/types/option_option.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::{path_def_id, qpath_generic_tys}; use if_chain::if_chain; -use rustc_hir::{self as hir, def_id::DefId, QPath}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index 855137b14d84b..8239630ac2d89 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -2,7 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{path_def_id, qpath_generic_tys}; use rustc_errors::Applicability; -use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/types/rc_mutex.rs b/clippy_lints/src/types/rc_mutex.rs index a75972cf3ddbe..a616c3e4ea831 100644 --- a/clippy_lints/src/types/rc_mutex.rs +++ b/clippy_lints/src/types/rc_mutex.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{path_def_id, qpath_generic_tys}; use if_chain::if_chain; -use rustc_hir::{self as hir, def_id::DefId, QPath}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index f7adc9d35558b..d369c6df91996 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -2,7 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::{path_def_id, qpath_generic_tys}; use rustc_errors::Applicability; -use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, QPath, TyKind}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::LateContext; use rustc_middle::ty::TypeVisitableExt; diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs index d3062f3d2e360..decc183ad9613 100644 --- a/clippy_lints/src/types/vec_box.rs +++ b/clippy_lints/src/types/vec_box.rs @@ -3,7 +3,8 @@ use clippy_utils::last_path_segment; use clippy_utils::source::snippet; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, GenericArg, QPath, TyKind}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index e7449639f3af3..58ccd47f83759 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -1,6 +1,8 @@ -use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::approx_ty_size; use rustc_errors::Applicability; -use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Symbol; diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs index 6e802794f5aa3..57a4a429e1294 100644 --- a/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_lang_item}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_lang_item; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; diff --git a/clippy_lints/src/unnecessary_struct_initialization.rs b/clippy_lints/src/unnecessary_struct_initialization.rs index 084b031982d8c..f4111186c642c 100644 --- a/clippy_lints/src/unnecessary_struct_initialization.rs +++ b/clippy_lints/src/unnecessary_struct_initialization.rs @@ -1,4 +1,7 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_expr, path_to_local, source::snippet, ty::is_copy}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_copy; +use clippy_utils::{get_parent_expr, path_to_local}; use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index 5073eb02bd84a..f34f8d0e35383 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; -use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty, visitors::find_all_ret_expressions}; +use clippy_utils::visitors::find_all_ret_expressions; +use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index a57bf7ee82255..c1cc7471d537c 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -6,7 +6,8 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::over; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Mutability, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; +use rustc_ast::PatKind::*; +use rustc_ast::{self as ast, Mutability, Pat, PatKind, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs index cad8da18c2fbc..95e74718d806f 100644 --- a/clippy_lints/src/unused_unit.rs +++ b/clippy_lints/src/unused_unit.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{position_before_rarrow, snippet_opt}; use if_chain::if_chain; -use rustc_ast::{ast, visit::FnKind, ClosureBinder}; +use rustc_ast::visit::FnKind; +use rustc_ast::{ast, ClosureBinder}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 377d3fb6f4e1c..c99b0290c0c0e 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::higher; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{path_to_local, usage::is_potentially_mutated}; +use clippy_utils::usage::is_potentially_mutated; +use clippy_utils::{higher, path_to_local}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 5a02987453c41..fcf77e8eab9ab 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -5,13 +5,12 @@ use clippy_utils::ty::same_type_and_consts; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; +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, - def::{CtorOf, DefKind, Res}, - def_id::LocalDefId, - intravisit::{walk_inf, walk_ty, Visitor}, - 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, GenericArg, 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}; diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index b6c11cfb35568..c9c092c508f63 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::is_ty_alias; use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; -use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths}; +use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; diff --git a/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 9afe02c1e47da..94b56304bcab4 100644 --- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -7,7 +7,8 @@ use rustc_hir::def::DefKind; use rustc_hir::Item; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, fast_reject::SimplifiedType, FloatTy}; +use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::{self, FloatTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; 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 f718207654f44..87380f14f9a4d 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 @@ -3,10 +3,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::{is_lint_allowed, match_def_path, paths}; use if_chain::if_chain; -use rustc_ast as ast; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::Visitor; @@ -18,6 +16,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{sym, Span}; +use {rustc_ast as ast, rustc_hir as hir}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 107a62806a82b..f49c3fadb0780 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -8,11 +8,8 @@ //! a simple mistake) use crate::renamed_lints::RENAMED_LINTS; -use crate::utils::{ - collect_configs, - internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type}, - ClippyConfiguration, -}; +use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type}; +use crate::utils::{collect_configs, ClippyConfiguration}; use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::{match_type, walk_ptrs_ty_depth}; @@ -21,22 +18,22 @@ use if_chain::if_chain; use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{ - self as hir, def::DefKind, intravisit, intravisit::Visitor, Closure, ExprKind, Item, ItemKind, Mutability, QPath, -}; +use rustc_hir::def::DefKind; +use rustc_hir::intravisit::Visitor; +use rustc_hir::{self as hir, intravisit, Closure, ExprKind, Item, ItemKind, Mutability, QPath}; use rustc_lint::{CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Ident; use rustc_span::{sym, Loc, Span, Symbol}; -use serde::{ser::SerializeStruct, Serialize, Serializer}; +use serde::ser::SerializeStruct; +use serde::{Serialize, Serializer}; use std::collections::{BTreeSet, BinaryHeap}; use std::fmt; use std::fmt::Write as _; use std::fs::{self, OpenOptions}; use std::io::prelude::*; -use std::path::Path; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; /// This is the json output file of the lint collector. 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 09f0f0d0adb6f..14855e9c3319c 100644 --- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -7,7 +7,8 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{self, subst::GenericArgKind}; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs index 43248bccc13d5..4963765200196 100644 --- a/clippy_lints/src/visibility.rs +++ b/clippy_lints/src/visibility.rs @@ -1,10 +1,12 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; use rustc_ast::ast::{Item, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::kw, Span}; +use rustc_span::symbol::kw; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 2a3d86988bb04..d09d02a7dfda9 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -3,10 +3,8 @@ use clippy_utils::is_test_module_or_function; use clippy_utils::source::{snippet, snippet_with_applicability}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{ - def::{DefKind, Res}, - Item, ItemKind, PathSegment, UseKind, -}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Item, ItemKind, PathSegment, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index e4cc86f680053..51771f78d4ff3 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -1,5 +1,4 @@ -use rustc_ast::ast; -use rustc_ast::attr; +use rustc_ast::{ast, attr}; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::sym; diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 62792d60652ba..89f8a65c5ae0d 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -12,20 +12,20 @@ //! code was written, and check if the span contains that text. Note this will only work correctly //! if the span is not from a `macro_rules` based macro. -use rustc_ast::{ - ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy}, - token::CommentKind, - AttrStyle, -}; +use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy}; +use rustc_ast::token::CommentKind; +use rustc_ast::AttrStyle; +use rustc_hir::intravisit::FnKind; use rustc_hir::{ - intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, - Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, - TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, Impl, ImplItem, + ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, TraitItemKind, Ty, + TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::{symbol::Ident, Span, Symbol}; +use rustc_span::symbol::Ident; +use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; /// The search pattern to look for. Used by `span_matches_pat` diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 87d85d742ce41..c61dc530e13e1 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -9,11 +9,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; -use rustc_middle::mir; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt}; -use rustc_middle::ty::{List, SubstsRef}; -use rustc_middle::{bug, span_bug}; +use rustc_middle::ty::{self, EarlyBinder, FloatTy, List, ScalarInt, SubstsRef, Ty, TyCtxt}; +use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; use std::cmp::Ordering::{self, Equal}; diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index eda739bceb5c5..29b73ab4cd512 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -12,14 +12,14 @@ use crate::ty::{all_predicates_of, is_copy}; use crate::visitors::is_const_evaluatable; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; +use rustc_hir::{Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; use rustc_span::{sym, Symbol}; -use std::cmp; -use std::ops; +use std::{cmp, ops}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] enum EagernessSuggestion { diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 3e1d735641468..fb359ee3bbe01 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -5,10 +5,9 @@ use crate::tokenize_with_text; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHasher; use rustc_hir::def::Res; -use rustc_hir::HirIdMap; use rustc_hir::{ ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, - GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, + GenericArgs, Guard, HirId, HirIdMap, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lexer::{tokenize, TokenKind}; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 1ac106d5d596d..5b433ed95bc2c 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -74,8 +74,7 @@ pub use self::hir_utils::{ use core::ops::ControlFlow; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; -use std::sync::OnceLock; -use std::sync::{Mutex, MutexGuard}; +use std::sync::{Mutex, MutexGuard, OnceLock}; use if_chain::if_chain; use itertools::Itertools; @@ -87,8 +86,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; -use rustc_hir::LangItem::OptionSome; -use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; +use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local, @@ -106,15 +104,14 @@ use rustc_middle::ty::fast_reject::SimplifiedType::{ ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType, PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType, }; +use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - layout::IntegerExt, BorrowKind, ClosureKind, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UpvarCapture, + BorrowKind, ClosureKind, FloatTy, IntTy, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UintTy, UpvarCapture, }; -use rustc_middle::ty::{FloatTy, IntTy, UintTy}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; -use rustc_span::sym; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::abi::Integer; use crate::consts::{constant, miri_to_const, Constant}; diff --git a/clippy_utils/src/mir/possible_borrower.rs b/clippy_utils/src/mir/possible_borrower.rs index 920ce8e655be0..703985b9d4b3f 100644 --- a/clippy_utils/src/mir/possible_borrower.rs +++ b/clippy_utils/src/mir/possible_borrower.rs @@ -1,11 +1,15 @@ -use super::{possible_origin::PossibleOriginVisitor, transitive_relation::TransitiveRelation}; +use super::possible_origin::PossibleOriginVisitor; +use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::LateContext; -use rustc_middle::mir::{self, visit::Visitor as _, Mutability}; -use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt}; -use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor}; +use rustc_middle::mir::visit::Visitor as _; +use rustc_middle::mir::{self, Mutability}; +use rustc_middle::ty::visit::TypeVisitor; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_mir_dataflow::impls::MaybeStorageLive; +use rustc_mir_dataflow::{Analysis, ResultsCursor}; use std::borrow::Cow; use std::ops::ControlFlow; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index c9938caefb067..a216d8c4f918c 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -15,9 +15,9 @@ use rustc_middle::mir::{ Terminator, TerminatorKind, }; use rustc_middle::traits::{ImplSource, ObligationCause}; +use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; -use rustc_middle::ty::{BoundConstness, TraitRef}; +use rustc_middle::ty::{self, BoundConstness, TraitRef, Ty, TyCtxt}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 582337b47e813..dc4ee72568176 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -8,8 +8,7 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource}; use rustc_lint::{LateContext, LintContext}; use rustc_session::Session; use rustc_span::source_map::{original_sp, SourceMap}; -use rustc_span::{hygiene, SourceFile}; -use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP}; +use rustc_span::{hygiene, BytePos, Pos, SourceFile, Span, SpanData, SyntaxContext, DUMMY_SP}; use std::borrow::Cow; use std::ops::Range; diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 9c39d22c61b2a..d73972b1c446b 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -9,18 +9,16 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; -use rustc_infer::infer::{ - type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, - TyCtxtInferExt, -}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; +use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ - self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, + self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, IntTy, List, ParamEnv, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; -use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Size, VariantIdx}; diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index 9855085216feb..efb23825abb9e 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -1,16 +1,14 @@ -use crate as utils; use crate::visitors::{for_each_expr, for_each_expr_with_closures, Descend}; use core::ops::ControlFlow; -use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::HirIdSet; -use rustc_hir::{Expr, ExprKind, HirId, Node}; +use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, Node}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty; +use {crate as utils, rustc_hir as hir}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option { diff --git a/lintcheck/src/config.rs b/lintcheck/src/config.rs index 3f01e9bb0a717..e678d40795ee8 100644 --- a/lintcheck/src/config.rs +++ b/lintcheck/src/config.rs @@ -1,5 +1,6 @@ use clap::Parser; -use std::{num::NonZeroUsize, path::PathBuf}; +use std::num::NonZeroUsize; +use std::path::PathBuf; #[derive(Clone, Debug, Parser)] pub(crate) struct LintcheckConfig { diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index de56a6f82757d..3a022b343a43c 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -15,16 +15,14 @@ use crate::config::LintcheckConfig; use crate::recursive::LintcheckServer; use std::collections::{HashMap, HashSet}; -use std::env; use std::env::consts::EXE_SUFFIX; use std::fmt::{self, Write as _}; -use std::fs; use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::thread; use std::time::Duration; +use std::{env, fs, thread}; use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel}; use cargo_metadata::Message; diff --git a/lintcheck/src/recursive.rs b/lintcheck/src/recursive.rs index 49072e65192f2..994fa3c3b239a 100644 --- a/lintcheck/src/recursive.rs +++ b/lintcheck/src/recursive.rs @@ -3,8 +3,7 @@ //! [`LintcheckServer`] to ask if it should be skipped, and if not sends the stderr of running //! clippy on the crate to the server -use crate::ClippyWarning; -use crate::RecursiveOptions; +use crate::{ClippyWarning, RecursiveOptions}; use std::collections::HashSet; use std::io::{BufRead, BufReader, Read, Write}; diff --git a/rustfmt.toml b/rustfmt.toml index 18b2a33469da3..4248f42f654b1 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,5 +4,6 @@ match_block_trailing_comma = true wrap_comments = true edition = "2021" error_on_line_overflow = true +imports_granularity = "Module" version = "Two" ignore = ["tests/ui/crashes/ice-10912.rs"] diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs index ebadd4e440a95..60fbaaea3d340 100644 --- a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs +++ b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs @@ -7,13 +7,10 @@ extern crate proc_macro; use core::mem; -use proc_macro::{ - token_stream::IntoIter, - Delimiter::{self, Brace, Parenthesis}, - Group, Ident, Literal, Punct, - Spacing::{self, Alone, Joint}, - Span, TokenStream, TokenTree as TT, -}; +use proc_macro::token_stream::IntoIter; +use proc_macro::Delimiter::{self, Brace, Parenthesis}; +use proc_macro::Spacing::{self, Alone, Joint}; +use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT}; type Result = core::result::Result; diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index dde1c6d7c37d6..e300ba18c3309 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -9,9 +9,7 @@ #![warn(clippy::unwrap_used)] #![warn(clippy::get_unwrap)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, VecDeque}; struct GetFalsePositive { arr: [u32; 3], diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index aed29a51c1dd5..4c9bdfa9dba73 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -1,5 +1,5 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:38:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` @@ -7,7 +7,7 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::get-unwrap` implied by `-D warnings` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:38:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +16,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:41:17 + --> $DIR/unwrap_used.rs:39:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:41:17 + --> $DIR/unwrap_used.rs:39:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,13 +30,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:42:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:42:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,13 +44,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:43:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:43:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,13 +58,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:44:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:44:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,13 +72,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:45:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:45:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,13 +86,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:49:21 + --> $DIR/unwrap_used.rs:47:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:49:22 + --> $DIR/unwrap_used.rs:47:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,13 +100,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:54:9 + --> $DIR/unwrap_used.rs:52:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:54:10 + --> $DIR/unwrap_used.rs:52:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,13 +114,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:55:9 + --> $DIR/unwrap_used.rs:53:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:55:10 + --> $DIR/unwrap_used.rs:53:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,13 +128,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:56:9 + --> $DIR/unwrap_used.rs:54:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:56:10 + --> $DIR/unwrap_used.rs:54:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,13 +142,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:57:9 + --> $DIR/unwrap_used.rs:55:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:57:10 + --> $DIR/unwrap_used.rs:55:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,13 +156,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:69:17 + --> $DIR/unwrap_used.rs:67:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:69:17 + --> $DIR/unwrap_used.rs:67:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,13 +170,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:70:17 + --> $DIR/unwrap_used.rs:68:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:70:17 + --> $DIR/unwrap_used.rs:68:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,13 +184,13 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:77:13 + --> $DIR/unwrap_used.rs:75:13 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:95:17 + --> $DIR/unwrap_used.rs:93:17 | LL | let _ = Box::new([0]).get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&Box::new([0])[1]` diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index 427842a51d9bd..69f1c541c4eed 100644 --- a/tests/ui/as_conversions.rs +++ b/tests/ui/as_conversions.rs @@ -4,8 +4,7 @@ #![allow(clippy::borrow_as_ptr, unused)] extern crate proc_macros; -use proc_macros::external; -use proc_macros::with_span; +use proc_macros::{external, with_span}; fn main() { let i = 0u32 as u64; diff --git a/tests/ui/as_conversions.stderr b/tests/ui/as_conversions.stderr index ca41d1378aa09..54037a6499787 100644 --- a/tests/ui/as_conversions.stderr +++ b/tests/ui/as_conversions.stderr @@ -1,5 +1,5 @@ error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:11:13 + --> $DIR/as_conversions.rs:10:13 | LL | let i = 0u32 as u64; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let i = 0u32 as u64; = note: `-D clippy::as-conversions` implied by `-D warnings` error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:13:13 + --> $DIR/as_conversions.rs:12:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64; = help: consider using a safe wrapper for this conversion error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:13:13 + --> $DIR/as_conversions.rs:12:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs index cab216b51ac71..f20df6f0f09e6 100644 --- a/tests/ui/auxiliary/macro_use_helper.rs +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -15,8 +15,7 @@ pub mod inner { // RE-EXPORT // this will stick in `inner` module - pub use macro_rules::mut_mut; - pub use macro_rules::try_err; + pub use macro_rules::{mut_mut, try_err}; pub mod nested { pub use macro_rules::string_add; diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index fdfe5fc418122..c58795575160b 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -8,11 +8,11 @@ extern crate syn; use proc_macro::TokenStream; use quote::{quote, quote_spanned}; -use syn::parse_macro_input; use syn::spanned::Spanned; use syn::token::Star; use syn::{ - parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem, Type, + parse_macro_input, parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, + TraitItem, Type, }; #[proc_macro_attribute] diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 4d008c8cb59fc..43df654389b1e 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -5,13 +5,10 @@ extern crate proc_macro; use core::mem; -use proc_macro::{ - token_stream::IntoIter, - Delimiter::{self, Brace, Parenthesis}, - Group, Ident, Literal, Punct, - Spacing::{self, Alone, Joint}, - Span, TokenStream, TokenTree as TT, -}; +use proc_macro::token_stream::IntoIter; +use proc_macro::Delimiter::{self, Brace, Parenthesis}; +use proc_macro::Spacing::{self, Alone, Joint}; +use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT}; type Result = core::result::Result; diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed index 14eb6d572cfac..6e541473cb354 100644 --- a/tests/ui/default_trait_access.fixed +++ b/tests/ui/default_trait_access.fixed @@ -7,9 +7,8 @@ extern crate proc_macros; use proc_macros::with_span; -use std::default; use std::default::Default as D2; -use std::string; +use std::{default, string}; fn main() { let s1: String = String::default(); diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index aa2ced0a7f035..2ffeb32fbdce5 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -7,9 +7,8 @@ extern crate proc_macros; use proc_macros::with_span; -use std::default; use std::default::Default as D2; -use std::string; +use std::{default, string}; fn main() { let s1: String = Default::default(); diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index e4f73c08d190a..103fccf6a1d35 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,5 +1,5 @@ error: calling `String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:15:22 + --> $DIR/default_trait_access.rs:14:22 | LL | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `String::default()` @@ -11,43 +11,43 @@ LL | #![deny(clippy::default_trait_access)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:19:22 + --> $DIR/default_trait_access.rs:18:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `String::default()` error: calling `String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:21:22 + --> $DIR/default_trait_access.rs:20:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()` error: calling `String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:25:22 + --> $DIR/default_trait_access.rs:24:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()` error: calling `GenericDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:35:46 + --> $DIR/default_trait_access.rs:34:46 | LL | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: calling `TupleDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:41:36 + --> $DIR/default_trait_access.rs:40:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: calling `ArrayDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:43:36 + --> $DIR/default_trait_access.rs:42:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: calling `TupleStructDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:47:42 + --> $DIR/default_trait_access.rs:46:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` diff --git a/tests/ui/get_first.fixed b/tests/ui/get_first.fixed index a29c0918a6dd8..bc2f86566bc07 100644 --- a/tests/ui/get_first.fixed +++ b/tests/ui/get_first.fixed @@ -1,9 +1,7 @@ //@run-rustfix #![warn(clippy::get_first)] #![allow(clippy::useless_vec)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, VecDeque}; struct Bar { arr: [u32; 3], diff --git a/tests/ui/get_first.rs b/tests/ui/get_first.rs index 2062f3ec23a04..bc0e233fdee55 100644 --- a/tests/ui/get_first.rs +++ b/tests/ui/get_first.rs @@ -1,9 +1,7 @@ //@run-rustfix #![warn(clippy::get_first)] #![allow(clippy::useless_vec)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, VecDeque}; struct Bar { arr: [u32; 3], diff --git a/tests/ui/get_first.stderr b/tests/ui/get_first.stderr index 4e267ba9a3b48..0899a5905f300 100644 --- a/tests/ui/get_first.stderr +++ b/tests/ui/get_first.stderr @@ -1,5 +1,5 @@ error: accessing first element with `x.get(0)` - --> $DIR/get_first.rs:20:13 + --> $DIR/get_first.rs:18:13 | LL | let _ = x.get(0); // Use x.first() | ^^^^^^^^ help: try: `x.first()` @@ -7,13 +7,13 @@ LL | let _ = x.get(0); // Use x.first() = note: `-D clippy::get-first` implied by `-D warnings` error: accessing first element with `y.get(0)` - --> $DIR/get_first.rs:25:13 + --> $DIR/get_first.rs:23:13 | LL | let _ = y.get(0); // Use y.first() | ^^^^^^^^ help: try: `y.first()` error: accessing first element with `z.get(0)` - --> $DIR/get_first.rs:30:13 + --> $DIR/get_first.rs:28:13 | LL | let _ = z.get(0); // Use z.first() | ^^^^^^^^ help: try: `z.first()` diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 56ee37f02d26d..fda334407a9bc 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -9,9 +9,7 @@ #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, VecDeque}; struct GetFalsePositive { arr: [u32; 3], diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index af3a619adc5e9..eaf6b005a36b0 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -9,9 +9,7 @@ #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, VecDeque}; struct GetFalsePositive { arr: [u32; 3], diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index e705bebac57a4..c567ed319b5b9 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,5 +1,5 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:38:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` @@ -11,7 +11,7 @@ LL | #![deny(clippy::get_unwrap)] | ^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:38:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,13 +20,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:39:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:39:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:42:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:42:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,13 +48,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:43:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:43:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,13 +62,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:44:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:44:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,13 +76,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:45:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:45:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,13 +90,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:49:21 + --> $DIR/get_unwrap.rs:47:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:49:22 + --> $DIR/get_unwrap.rs:47:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,13 +104,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:54:9 + --> $DIR/get_unwrap.rs:52:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:54:10 + --> $DIR/get_unwrap.rs:52:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +118,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:55:9 + --> $DIR/get_unwrap.rs:53:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:55:10 + --> $DIR/get_unwrap.rs:53:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,13 +132,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:56:9 + --> $DIR/get_unwrap.rs:54:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:56:10 + --> $DIR/get_unwrap.rs:54:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,13 +146,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:57:9 + --> $DIR/get_unwrap.rs:55:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:57:10 + --> $DIR/get_unwrap.rs:55:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,13 +160,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:69:17 + --> $DIR/get_unwrap.rs:67:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:69:17 + --> $DIR/get_unwrap.rs:67:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,13 +174,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:70:17 + --> $DIR/get_unwrap.rs:68:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:70:17 + --> $DIR/get_unwrap.rs:68:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,25 +188,25 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:80:24 + --> $DIR/get_unwrap.rs:78:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:83:18 + --> $DIR/get_unwrap.rs:81:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:86:18 + --> $DIR/get_unwrap.rs:84:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:103:33 + --> $DIR/get_unwrap.rs:101:33 | LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` diff --git a/tests/ui/issue-7447.rs b/tests/ui/issue-7447.rs index fdb77f322579f..de4362c4df70e 100644 --- a/tests/ui/issue-7447.rs +++ b/tests/ui/issue-7447.rs @@ -1,4 +1,7 @@ -use std::{borrow::Cow, collections::BTreeMap, marker::PhantomData, sync::Arc}; +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::marker::PhantomData; +use std::sync::Arc; fn byte_view<'a>(s: &'a ByteView<'_>) -> BTreeMap<&'a str, ByteView<'a>> { panic!() diff --git a/tests/ui/issue-7447.stderr b/tests/ui/issue-7447.stderr index 8d8c29f138587..7a113740c6a47 100644 --- a/tests/ui/issue-7447.stderr +++ b/tests/ui/issue-7447.stderr @@ -1,5 +1,5 @@ error: sub-expression diverges - --> $DIR/issue-7447.rs:23:15 + --> $DIR/issue-7447.rs:26:15 | LL | byte_view(panic!()); | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | byte_view(panic!()); = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges - --> $DIR/issue-7447.rs:24:19 + --> $DIR/issue-7447.rs:27:19 | LL | group_entries(panic!()); | ^^^^^^^^ diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index 2baea06f84ba9..636f572a343e3 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -3,8 +3,7 @@ #![allow(unused)] #![allow(clippy::useless_vec)] -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{HashSet, VecDeque}; fn main() { let v = [1, 2, 3, 4, 5]; diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index 9eac94eb8d975..518cb75affe5d 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -3,8 +3,7 @@ #![allow(unused)] #![allow(clippy::useless_vec)] -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{HashSet, VecDeque}; fn main() { let v = [1, 2, 3, 4, 5]; diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr index b38cf547dc5fb..b2cc497bf433a 100644 --- a/tests/ui/iter_cloned_collect.stderr +++ b/tests/ui/iter_cloned_collect.stderr @@ -1,5 +1,5 @@ error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:11:27 + --> $DIR/iter_cloned_collect.rs:10:27 | LL | let v2: Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` @@ -7,13 +7,13 @@ LL | let v2: Vec = v.iter().cloned().collect(); = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:16:38 + --> $DIR/iter_cloned_collect.rs:15:38 | LL | let _: Vec = vec![1, 2, 3].iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:21:24 + --> $DIR/iter_cloned_collect.rs:20:24 | LL | .to_bytes() | ________________________^ @@ -23,13 +23,13 @@ LL | | .collect(); | |______________________^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:29:24 + --> $DIR/iter_cloned_collect.rs:28:24 | LL | let _: Vec<_> = arr.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:32:26 + --> $DIR/iter_cloned_collect.rs:31:26 | LL | let _: Vec = v.iter().copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` diff --git a/tests/ui/let_underscore_lock.rs b/tests/ui/let_underscore_lock.rs index 4dff4d766bcc3..87f12e2789f09 100644 --- a/tests/ui/let_underscore_lock.rs +++ b/tests/ui/let_underscore_lock.rs @@ -3,7 +3,8 @@ extern crate parking_lot; fn main() { - use parking_lot::{lock_api::RawMutex, Mutex, RwLock}; + use parking_lot::lock_api::RawMutex; + use parking_lot::{Mutex, RwLock}; let p_m: Mutex<()> = Mutex::const_new(RawMutex::INIT, ()); let _ = p_m.lock(); diff --git a/tests/ui/let_underscore_lock.stderr b/tests/ui/let_underscore_lock.stderr index f137d4112092d..5027e6b3cbc77 100644 --- a/tests/ui/let_underscore_lock.stderr +++ b/tests/ui/let_underscore_lock.stderr @@ -1,5 +1,5 @@ error: non-binding `let` on a synchronization lock - --> $DIR/let_underscore_lock.rs:9:5 + --> $DIR/let_underscore_lock.rs:10:5 | LL | let _ = p_m.lock(); | ^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = p_m.lock(); = note: `-D clippy::let-underscore-lock` implied by `-D warnings` error: non-binding `let` on a synchronization lock - --> $DIR/let_underscore_lock.rs:12:5 + --> $DIR/let_underscore_lock.rs:13:5 | LL | let _ = p_m1.lock(); | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = p_m1.lock(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding `let` on a synchronization lock - --> $DIR/let_underscore_lock.rs:15:5 + --> $DIR/let_underscore_lock.rs:16:5 | LL | let _ = p_rw.read(); | ^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _ = p_rw.read(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding `let` on a synchronization lock - --> $DIR/let_underscore_lock.rs:16:5 + --> $DIR/let_underscore_lock.rs:17:5 | LL | let _ = p_rw.write(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs index 431d83778e34f..18630c27f4171 100644 --- a/tests/ui/let_underscore_untyped.rs +++ b/tests/ui/let_underscore_untyped.rs @@ -7,8 +7,9 @@ extern crate proc_macros; use proc_macros::with_span; use clippy_utils::is_from_proc_macro; +use std::boxed::Box; +use std::fmt::Display; use std::future::Future; -use std::{boxed::Box, fmt::Display}; fn a() -> u32 { 1 diff --git a/tests/ui/let_underscore_untyped.stderr b/tests/ui/let_underscore_untyped.stderr index bbf2508af10b7..e0c39b6eeafef 100644 --- a/tests/ui/let_underscore_untyped.stderr +++ b/tests/ui/let_underscore_untyped.stderr @@ -1,60 +1,60 @@ error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:50:5 + --> $DIR/let_underscore_untyped.rs:51:5 | LL | let _ = a(); | ^^^^^^^^^^^^ | help: consider adding a type annotation - --> $DIR/let_underscore_untyped.rs:50:10 + --> $DIR/let_underscore_untyped.rs:51:10 | LL | let _ = a(); | ^ = note: `-D clippy::let-underscore-untyped` implied by `-D warnings` error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:51:5 + --> $DIR/let_underscore_untyped.rs:52:5 | LL | let _ = b(1); | ^^^^^^^^^^^^^ | help: consider adding a type annotation - --> $DIR/let_underscore_untyped.rs:51:10 + --> $DIR/let_underscore_untyped.rs:52:10 | LL | let _ = b(1); | ^ error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:53:5 + --> $DIR/let_underscore_untyped.rs:54:5 | LL | let _ = d(&1); | ^^^^^^^^^^^^^^ | help: consider adding a type annotation - --> $DIR/let_underscore_untyped.rs:53:10 + --> $DIR/let_underscore_untyped.rs:54:10 | LL | let _ = d(&1); | ^ error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:54:5 + --> $DIR/let_underscore_untyped.rs:55:5 | LL | let _ = e(); | ^^^^^^^^^^^^ | help: consider adding a type annotation - --> $DIR/let_underscore_untyped.rs:54:10 + --> $DIR/let_underscore_untyped.rs:55:10 | LL | let _ = e(); | ^ error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:55:5 + --> $DIR/let_underscore_untyped.rs:56:5 | LL | let _ = f(); | ^^^^^^^^^^^^ | help: consider adding a type annotation - --> $DIR/let_underscore_untyped.rs:55:10 + --> $DIR/let_underscore_untyped.rs:56:10 | LL | let _ = f(); | ^ diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index 09fb0d758524e..c95d40fecba61 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -1,12 +1,7 @@ //@run-rustfix #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] -use std::collections::BTreeMap; -use std::collections::BTreeSet; -use std::collections::BinaryHeap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; fn main() { binary_heap_retain(); diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index 7fee4c95cea5a..9a3434f489def 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -1,12 +1,7 @@ //@run-rustfix #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] -use std::collections::BTreeMap; -use std::collections::BTreeSet; -use std::collections::BinaryHeap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; fn main() { binary_heap_retain(); diff --git a/tests/ui/manual_retain.stderr b/tests/ui/manual_retain.stderr index 89316ce1d9981..0936a23841ced 100644 --- a/tests/ui/manual_retain.stderr +++ b/tests/ui/manual_retain.stderr @@ -1,5 +1,5 @@ error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:51:5 + --> $DIR/manual_retain.rs:46:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` @@ -7,13 +7,13 @@ LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect() = note: `-D clippy::manual-retain` implied by `-D warnings` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:52:5 + --> $DIR/manual_retain.rs:47:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:53:5 + --> $DIR/manual_retain.rs:48:5 | LL | / btree_map = btree_map LL | | .into_iter() @@ -22,37 +22,37 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:75:5 + --> $DIR/manual_retain.rs:70:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:76:5 + --> $DIR/manual_retain.rs:71:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:77:5 + --> $DIR/manual_retain.rs:72:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:107:5 + --> $DIR/manual_retain.rs:102:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:108:5 + --> $DIR/manual_retain.rs:103:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:109:5 + --> $DIR/manual_retain.rs:104:5 | LL | / hash_map = hash_map LL | | .into_iter() @@ -61,61 +61,61 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:130:5 + --> $DIR/manual_retain.rs:125:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:131:5 + --> $DIR/manual_retain.rs:126:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:132:5 + --> $DIR/manual_retain.rs:127:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:161:5 + --> $DIR/manual_retain.rs:156:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:173:5 + --> $DIR/manual_retain.rs:168:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:174:5 + --> $DIR/manual_retain.rs:169:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:175:5 + --> $DIR/manual_retain.rs:170:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:197:5 + --> $DIR/manual_retain.rs:192:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:198:5 + --> $DIR/manual_retain.rs:193:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:199:5 + --> $DIR/manual_retain.rs:194:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs index 4521e9fa1a502..05c658579a5f8 100644 --- a/tests/ui/manual_try_fold.rs +++ b/tests/ui/manual_try_fold.rs @@ -3,9 +3,7 @@ #![warn(clippy::manual_try_fold)] #![feature(try_trait_v2)] -use std::ops::ControlFlow; -use std::ops::FromResidual; -use std::ops::Try; +use std::ops::{ControlFlow, FromResidual, Try}; #[macro_use] extern crate proc_macros; diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr index a0cf5b3b5fc8a..f1bb97c6d0f3c 100644 --- a/tests/ui/manual_try_fold.stderr +++ b/tests/ui/manual_try_fold.stderr @@ -1,5 +1,5 @@ error: usage of `Iterator::fold` on a type that implements `Try` - --> $DIR/manual_try_fold.rs:61:10 + --> $DIR/manual_try_fold.rs:59:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` @@ -7,19 +7,19 @@ LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) = note: `-D clippy::manual-try-fold` implied by `-D warnings` error: usage of `Iterator::fold` on a type that implements `Try` - --> $DIR/manual_try_fold.rs:65:10 + --> $DIR/manual_try_fold.rs:63:10 | LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)` error: usage of `Iterator::fold` on a type that implements `Try` - --> $DIR/manual_try_fold.rs:68:10 + --> $DIR/manual_try_fold.rs:66:10 | LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` error: usage of `Iterator::fold` on a type that implements `Try` - --> $DIR/manual_try_fold.rs:98:10 + --> $DIR/manual_try_fold.rs:96:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` diff --git a/tests/ui/match_as_ref.fixed b/tests/ui/match_as_ref.fixed index 8fa3f5325871d..61d414bdf4be5 100644 --- a/tests/ui/match_as_ref.fixed +++ b/tests/ui/match_as_ref.fixed @@ -12,7 +12,9 @@ fn match_as_ref() { } mod issue4437 { - use std::{error::Error, fmt, num::ParseIntError}; + use std::error::Error; + use std::fmt; + use std::num::ParseIntError; #[derive(Debug)] struct E { diff --git a/tests/ui/match_as_ref.rs b/tests/ui/match_as_ref.rs index 02a17791426cf..cd39514c59ac6 100644 --- a/tests/ui/match_as_ref.rs +++ b/tests/ui/match_as_ref.rs @@ -18,7 +18,9 @@ fn match_as_ref() { } mod issue4437 { - use std::{error::Error, fmt, num::ParseIntError}; + use std::error::Error; + use std::fmt; + use std::num::ParseIntError; #[derive(Debug)] struct E { diff --git a/tests/ui/match_as_ref.stderr b/tests/ui/match_as_ref.stderr index 252abf74bca30..2e6955eb8056e 100644 --- a/tests/ui/match_as_ref.stderr +++ b/tests/ui/match_as_ref.stderr @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: try: `mut_owned.as_mut()` error: use `as_ref()` instead - --> $DIR/match_as_ref.rs:30:13 + --> $DIR/match_as_ref.rs:32:13 | LL | / match self.source { LL | | Some(ref s) => Some(s), diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 589eab5cdfc54..cb1f695c651cb 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -25,10 +25,7 @@ #[macro_use] extern crate option_helpers; -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::ops::Mul; use std::rc::{self, Rc}; use std::sync::{self, Arc}; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 73ec48643e063..6be38b24fbda2 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:106:5 + --> $DIR/methods.rs:103:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:127:13 + --> $DIR/methods.rs:124:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index b5b9e66aa7a02..0fab224a29d3a 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -3,8 +3,7 @@ #![warn(clippy::min_ident_chars)] extern crate proc_macros; -use proc_macros::external; -use proc_macros::with_span; +use proc_macros::{external, with_span}; struct A { a: u32, diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr index 66a63f6575656..4dff6588bb18b 100644 --- a/tests/ui/min_ident_chars.stderr +++ b/tests/ui/min_ident_chars.stderr @@ -1,5 +1,5 @@ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:9:8 + --> $DIR/min_ident_chars.rs:8:8 | LL | struct A { | ^ @@ -7,169 +7,169 @@ LL | struct A { = note: `-D clippy::min-ident-chars` implied by `-D warnings` error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:10:5 + --> $DIR/min_ident_chars.rs:9:5 | LL | a: u32, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:12:5 + --> $DIR/min_ident_chars.rs:11:5 | LL | A: u32, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:13:5 + --> $DIR/min_ident_chars.rs:12:5 | LL | I: u32, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:16:8 + --> $DIR/min_ident_chars.rs:15:8 | LL | struct B(u32); | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:18:8 + --> $DIR/min_ident_chars.rs:17:8 | LL | struct O { | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:19:5 + --> $DIR/min_ident_chars.rs:18:5 | LL | o: u32, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:24:6 + --> $DIR/min_ident_chars.rs:23:6 | LL | enum C { | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:25:5 + --> $DIR/min_ident_chars.rs:24:5 | LL | D, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:26:5 + --> $DIR/min_ident_chars.rs:25:5 | LL | E, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:27:5 + --> $DIR/min_ident_chars.rs:26:5 | LL | F, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:51:9 + --> $DIR/min_ident_chars.rs:50:9 | LL | let h = 1; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:52:9 + --> $DIR/min_ident_chars.rs:51:9 | LL | let e = 2; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:53:9 + --> $DIR/min_ident_chars.rs:52:9 | LL | let l = 3; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:54:9 + --> $DIR/min_ident_chars.rs:53:9 | LL | let l = 4; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:55:9 + --> $DIR/min_ident_chars.rs:54:9 | LL | let o = 6; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:59:10 + --> $DIR/min_ident_chars.rs:58:10 | LL | let (h, o, w) = (1, 2, 3); | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:59:13 + --> $DIR/min_ident_chars.rs:58:13 | LL | let (h, o, w) = (1, 2, 3); | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:60:10 + --> $DIR/min_ident_chars.rs:59:10 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:60:14 + --> $DIR/min_ident_chars.rs:59:14 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:60:17 + --> $DIR/min_ident_chars.rs:59:17 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:62:16 + --> $DIR/min_ident_chars.rs:61:16 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:62:19 + --> $DIR/min_ident_chars.rs:61:19 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:62:29 + --> $DIR/min_ident_chars.rs:61:29 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:66:9 + --> $DIR/min_ident_chars.rs:65:9 | LL | let o = 1; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:67:9 + --> $DIR/min_ident_chars.rs:66:9 | LL | let o = O { o }; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:81:4 + --> $DIR/min_ident_chars.rs:80:4 | LL | fn b() {} | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:82:21 + --> $DIR/min_ident_chars.rs:81:21 | LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:82:29 + --> $DIR/min_ident_chars.rs:81:29 | LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 24e52afd69170..1215a02286c28 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -1,9 +1,7 @@ #![warn(clippy::all)] #![allow(clippy::manual_clamp)] -use std::cmp::max as my_max; -use std::cmp::min as my_min; -use std::cmp::{max, min}; +use std::cmp::{max as my_max, max, min as my_min, min}; const LARGE: usize = 3; diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index 069d9068657eb..402b094f4f77b 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,5 +1,5 @@ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:24:5 + --> $DIR/min_max.rs:22:5 | LL | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ @@ -7,73 +7,73 @@ LL | min(1, max(3, x)); = note: `-D clippy::min-max` implied by `-D warnings` error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:25:5 + --> $DIR/min_max.rs:23:5 | LL | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:26:5 + --> $DIR/min_max.rs:24:5 | LL | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:27:5 + --> $DIR/min_max.rs:25:5 | LL | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:29:5 + --> $DIR/min_max.rs:27:5 | LL | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:39:5 + --> $DIR/min_max.rs:37:5 | LL | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:40:5 + --> $DIR/min_max.rs:38:5 | LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:45:5 + --> $DIR/min_max.rs:43:5 | LL | x.min(1).max(3); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:46:5 + --> $DIR/min_max.rs:44:5 | LL | x.max(3).min(1); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:47:5 + --> $DIR/min_max.rs:45:5 | LL | f.max(3f32).min(1f32); | ^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:53:5 + --> $DIR/min_max.rs:51:5 | LL | max(x.min(1), 3); | ^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:56:5 + --> $DIR/min_max.rs:54:5 | LL | s.max("Zoo").min("Apple"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:57:5 + --> $DIR/min_max.rs:55:5 | LL | s.min("Apple").max("Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index cff1706a8426e..83ebf09c8a3fc 100644 --- a/tests/ui/missing_doc.rs +++ b/tests/ui/missing_doc.rs @@ -96,10 +96,8 @@ mod internal_impl { } /// dox pub mod public_interface { - pub use crate::internal_impl::documented as foo; pub use crate::internal_impl::globbed::*; - pub use crate::internal_impl::undocumented1 as bar; - pub use crate::internal_impl::{documented, undocumented2}; + pub use crate::internal_impl::{documented as foo, documented, undocumented1 as bar, undocumented2}; } fn main() {} diff --git a/tests/ui/mut_key.rs b/tests/ui/mut_key.rs index 1c0ba664580a4..15d68c08984fa 100644 --- a/tests/ui/mut_key.rs +++ b/tests/ui/mut_key.rs @@ -2,7 +2,8 @@ use std::cell::Cell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::Relaxed; use std::sync::Arc; struct Key(AtomicUsize); diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index fe1eeb31d07a1..02a0da86a4b83 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -1,5 +1,5 @@ error: mutable key type - --> $DIR/mut_key.rs:30:32 + --> $DIR/mut_key.rs:31:32 | LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash = note: `-D clippy::mutable-key-type` implied by `-D warnings` error: mutable key type - --> $DIR/mut_key.rs:30:72 + --> $DIR/mut_key.rs:31:72 | LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^ error: this argument is a mutable reference, but not used mutably - --> $DIR/mut_key.rs:30:32 + --> $DIR/mut_key.rs:31:32 | LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&HashMap` @@ -21,91 +21,91 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` error: mutable key type - --> $DIR/mut_key.rs:31:5 + --> $DIR/mut_key.rs:32:5 | LL | let _other: HashMap = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:58:22 + --> $DIR/mut_key.rs:59:22 | LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:70:5 + --> $DIR/mut_key.rs:71:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:71:5 + --> $DIR/mut_key.rs:72:5 | LL | let _map = HashMap::<&mut Cell, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:72:5 + --> $DIR/mut_key.rs:73:5 | LL | let _map = HashMap::<&mut usize, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:74:5 + --> $DIR/mut_key.rs:75:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:75:5 + --> $DIR/mut_key.rs:76:5 | LL | let _map = HashMap::, ()>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:76:5 + --> $DIR/mut_key.rs:77:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:77:5 + --> $DIR/mut_key.rs:78:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:78:5 + --> $DIR/mut_key.rs:79:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:79:5 + --> $DIR/mut_key.rs:80:5 | LL | let _map = HashMap::>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:80:5 + --> $DIR/mut_key.rs:81:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:82:5 + --> $DIR/mut_key.rs:83:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:83:5 + --> $DIR/mut_key.rs:84:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:84:5 + --> $DIR/mut_key.rs:85:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index 5e6e140c2db38..6001c9e93011a 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -16,8 +16,7 @@ #![warn(clippy::needless_if)] extern crate proc_macros; -use proc_macros::external; -use proc_macros::with_span; +use proc_macros::{external, with_span}; fn maybe_side_effect() -> bool { true diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs index eb28ce73be8f9..c6be4766dd8a1 100644 --- a/tests/ui/needless_if.rs +++ b/tests/ui/needless_if.rs @@ -16,8 +16,7 @@ #![warn(clippy::needless_if)] extern crate proc_macros; -use proc_macros::external; -use proc_macros::with_span; +use proc_macros::{external, with_span}; fn maybe_side_effect() -> bool { true diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr index 5cb42c36921d2..14de400953bd6 100644 --- a/tests/ui/needless_if.stderr +++ b/tests/ui/needless_if.stderr @@ -1,5 +1,5 @@ error: this `if` branch is empty - --> $DIR/needless_if.rs:28:5 + --> $DIR/needless_if.rs:27:5 | LL | if (true) {} | ^^^^^^^^^^^^ help: you can remove it @@ -7,13 +7,13 @@ LL | if (true) {} = note: `-D clippy::needless-if` implied by `-D warnings` error: this `if` branch is empty - --> $DIR/needless_if.rs:30:5 + --> $DIR/needless_if.rs:29:5 | LL | if maybe_side_effect() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` error: this `if` branch is empty - --> $DIR/needless_if.rs:35:5 + --> $DIR/needless_if.rs:34:5 | LL | / if { LL | | return; @@ -28,7 +28,7 @@ LL + }); | error: this `if` branch is empty - --> $DIR/needless_if.rs:47:5 + --> $DIR/needless_if.rs:46:5 | LL | / if { LL | | if let true = true && true { true } else { false } @@ -44,19 +44,19 @@ LL + } && true); | error: this `if` branch is empty - --> $DIR/needless_if.rs:85:5 + --> $DIR/needless_if.rs:84:5 | LL | if { maybe_side_effect() } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });` error: this `if` branch is empty - --> $DIR/needless_if.rs:87:5 + --> $DIR/needless_if.rs:86:5 | LL | if { maybe_side_effect() } && true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);` error: this `if` branch is empty - --> $DIR/needless_if.rs:91:5 + --> $DIR/needless_if.rs:90:5 | LL | if true {} | ^^^^^^^^^^ help: you can remove it: `true;` diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 703debb7a26ae..6deff0f3240a2 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -9,8 +9,7 @@ clippy::useless_vec )] -use std::collections::BTreeMap; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::time::Duration; /// Checks implementation of the `OR_FUN_CALL` lint. diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index bb86fe0d45fa0..b05b33e6ee2b3 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -9,8 +9,7 @@ clippy::useless_vec )] -use std::collections::BTreeMap; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::time::Duration; /// Checks implementation of the `OR_FUN_CALL` lint. diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 3965ae52aed1f..7342b0c2914b0 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:54:22 + --> $DIR/or_fun_call.rs:53:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(make)` @@ -7,163 +7,163 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:57:14 + --> $DIR/or_fun_call.rs:56:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:60:21 + --> $DIR/or_fun_call.rs:59:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:63:14 + --> $DIR/or_fun_call.rs:62:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:66:19 + --> $DIR/or_fun_call.rs:65:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:69:24 + --> $DIR/or_fun_call.rs:68:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:72:23 + --> $DIR/or_fun_call.rs:71:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:75:18 + --> $DIR/or_fun_call.rs:74:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(::default)` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:78:18 + --> $DIR/or_fun_call.rs:77:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:81:14 + --> $DIR/or_fun_call.rs:80:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:84:21 + --> $DIR/or_fun_call.rs:83:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:87:19 + --> $DIR/or_fun_call.rs:86:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:90:23 + --> $DIR/or_fun_call.rs:89:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:93:21 + --> $DIR/or_fun_call.rs:92:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:96:25 + --> $DIR/or_fun_call.rs:95:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:99:21 + --> $DIR/or_fun_call.rs:98:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:107:21 + --> $DIR/or_fun_call.rs:106:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:109:21 + --> $DIR/or_fun_call.rs:108:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:133:35 + --> $DIR/or_fun_call.rs:132:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:172:14 + --> $DIR/or_fun_call.rs:171:14 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:178:14 + --> $DIR/or_fun_call.rs:177:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:180:14 + --> $DIR/or_fun_call.rs:179:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:194:14 + --> $DIR/or_fun_call.rs:193:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:207:14 + --> $DIR/or_fun_call.rs:206:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:219:14 + --> $DIR/or_fun_call.rs:218:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:230:10 + --> $DIR/or_fun_call.rs:229:10 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:255:25 + --> $DIR/or_fun_call.rs:254:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:256:25 + --> $DIR/or_fun_call.rs:255:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs index 574d34aed2d87..9eb58a3e53f6a 100644 --- a/tests/ui/redundant_allocation.rs +++ b/tests/ui/redundant_allocation.rs @@ -8,8 +8,7 @@ pub struct SubT { } mod outer_box { - use crate::MyStruct; - use crate::SubT; + use crate::{MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -28,8 +27,7 @@ mod outer_box { } mod outer_rc { - use crate::MyStruct; - use crate::SubT; + use crate::{MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -48,8 +46,7 @@ mod outer_rc { } mod outer_arc { - use crate::MyStruct; - use crate::SubT; + use crate::{MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr index e0826fefa6cfb..a9a1eed702b43 100644 --- a/tests/ui/redundant_allocation.stderr +++ b/tests/ui/redundant_allocation.stderr @@ -1,5 +1,5 @@ error: usage of `Box>` - --> $DIR/redundant_allocation.rs:17:30 + --> $DIR/redundant_allocation.rs:16:30 | LL | pub fn box_test6(foo: Box>) {} | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | pub fn box_test6(foo: Box>) {} = note: `-D clippy::redundant-allocation` implied by `-D warnings` error: usage of `Box>` - --> $DIR/redundant_allocation.rs:19:30 + --> $DIR/redundant_allocation.rs:18:30 | LL | pub fn box_test7(foo: Box>) {} | ^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | pub fn box_test7(foo: Box>) {} = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> $DIR/redundant_allocation.rs:21:27 + --> $DIR/redundant_allocation.rs:20:27 | LL | pub fn box_test8() -> Box>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | pub fn box_test8() -> Box>> { = help: consider using just `Box>` or `Rc>` error: usage of `Box>` - --> $DIR/redundant_allocation.rs:25:30 + --> $DIR/redundant_allocation.rs:24:30 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> $DIR/redundant_allocation.rs:25:46 + --> $DIR/redundant_allocation.rs:24:46 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box>` or `Arc>` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:37:24 + --> $DIR/redundant_allocation.rs:35:24 | LL | pub fn rc_test5(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | pub fn rc_test5(a: Rc>) {} = help: consider using just `Rc` or `Box` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:39:24 + --> $DIR/redundant_allocation.rs:37:24 | LL | pub fn rc_test7(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | pub fn rc_test7(a: Rc>) {} = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:41:26 + --> $DIR/redundant_allocation.rs:39:26 | LL | pub fn rc_test8() -> Rc>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | pub fn rc_test8() -> Rc>> { = help: consider using just `Rc>` or `Box>` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:45:29 + --> $DIR/redundant_allocation.rs:43:29 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:45:44 + --> $DIR/redundant_allocation.rs:43:44 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc>` or `Arc>` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:57:25 + --> $DIR/redundant_allocation.rs:54:25 | LL | pub fn arc_test5(a: Arc>) {} | ^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | pub fn arc_test5(a: Arc>) {} = help: consider using just `Arc` or `Box` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:59:25 + --> $DIR/redundant_allocation.rs:56:25 | LL | pub fn arc_test6(a: Arc>) {} | ^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | pub fn arc_test6(a: Arc>) {} = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> $DIR/redundant_allocation.rs:61:27 + --> $DIR/redundant_allocation.rs:58:27 | LL | pub fn arc_test8() -> Arc>> { | ^^^^^^^^^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | pub fn arc_test8() -> Arc>> { = help: consider using just `Arc>` or `Box>` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:65:30 + --> $DIR/redundant_allocation.rs:62:30 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> $DIR/redundant_allocation.rs:65:45 + --> $DIR/redundant_allocation.rs:62:45 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc>` or `Rc>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:87:27 + --> $DIR/redundant_allocation.rs:84:27 | LL | pub fn test_rc_box(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | pub fn test_rc_box(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:119:31 + --> $DIR/redundant_allocation.rs:116:31 | LL | pub fn test_rc_box_str(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | pub fn test_rc_box_str(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:120:33 + --> $DIR/redundant_allocation.rs:117:33 | LL | pub fn test_rc_box_slice(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL | pub fn test_rc_box_slice(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:121:32 + --> $DIR/redundant_allocation.rs:118:32 | LL | pub fn test_rc_box_path(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | pub fn test_rc_box_path(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:122:34 + --> $DIR/redundant_allocation.rs:119:34 | LL | pub fn test_rc_box_custom(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_allocation_fixable.fixed b/tests/ui/redundant_allocation_fixable.fixed index edb7715f42cdc..b97863daf2263 100644 --- a/tests/ui/redundant_allocation_fixable.fixed +++ b/tests/ui/redundant_allocation_fixable.fixed @@ -16,9 +16,7 @@ pub enum MyEnum { } mod outer_box { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -35,9 +33,7 @@ mod outer_box { } mod outer_rc { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -54,9 +50,7 @@ mod outer_rc { } mod outer_arc { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; diff --git a/tests/ui/redundant_allocation_fixable.rs b/tests/ui/redundant_allocation_fixable.rs index c59422dd96604..bffb6f8c00020 100644 --- a/tests/ui/redundant_allocation_fixable.rs +++ b/tests/ui/redundant_allocation_fixable.rs @@ -16,9 +16,7 @@ pub enum MyEnum { } mod outer_box { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -35,9 +33,7 @@ mod outer_box { } mod outer_rc { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; @@ -54,9 +50,7 @@ mod outer_rc { } mod outer_arc { - use crate::MyEnum; - use crate::MyStruct; - use crate::SubT; + use crate::{MyEnum, MyStruct, SubT}; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; diff --git a/tests/ui/redundant_allocation_fixable.stderr b/tests/ui/redundant_allocation_fixable.stderr index 8dd4a6a268749..524ca5bf467dc 100644 --- a/tests/ui/redundant_allocation_fixable.stderr +++ b/tests/ui/redundant_allocation_fixable.stderr @@ -1,5 +1,5 @@ error: usage of `Box<&T>` - --> $DIR/redundant_allocation_fixable.rs:26:30 + --> $DIR/redundant_allocation_fixable.rs:24:30 | LL | pub fn box_test1(foo: Box<&T>) {} | ^^^^^^^ help: try: `&T` @@ -8,7 +8,7 @@ LL | pub fn box_test1(foo: Box<&T>) {} = note: `-D clippy::redundant-allocation` implied by `-D warnings` error: usage of `Box<&MyStruct>` - --> $DIR/redundant_allocation_fixable.rs:28:27 + --> $DIR/redundant_allocation_fixable.rs:26:27 | LL | pub fn box_test2(foo: Box<&MyStruct>) {} | ^^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -16,7 +16,7 @@ LL | pub fn box_test2(foo: Box<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Box<&MyStruct>` allocates a pointer on the heap error: usage of `Box<&MyEnum>` - --> $DIR/redundant_allocation_fixable.rs:30:27 + --> $DIR/redundant_allocation_fixable.rs:28:27 | LL | pub fn box_test3(foo: Box<&MyEnum>) {} | ^^^^^^^^^^^^ help: try: `&MyEnum` @@ -24,7 +24,7 @@ LL | pub fn box_test3(foo: Box<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Box<&MyEnum>` allocates a pointer on the heap error: usage of `Box>` - --> $DIR/redundant_allocation_fixable.rs:34:30 + --> $DIR/redundant_allocation_fixable.rs:32:30 | LL | pub fn box_test5(foo: Box>) {} | ^^^^^^^^^^^ help: try: `Box` @@ -32,7 +32,7 @@ LL | pub fn box_test5(foo: Box>) {} = note: `Box` is already on the heap, `Box>` makes an extra allocation error: usage of `Rc<&T>` - --> $DIR/redundant_allocation_fixable.rs:45:29 + --> $DIR/redundant_allocation_fixable.rs:41:29 | LL | pub fn rc_test1(foo: Rc<&T>) {} | ^^^^^^ help: try: `&T` @@ -40,7 +40,7 @@ LL | pub fn rc_test1(foo: Rc<&T>) {} = note: `&T` is already a pointer, `Rc<&T>` allocates a pointer on the heap error: usage of `Rc<&MyStruct>` - --> $DIR/redundant_allocation_fixable.rs:47:26 + --> $DIR/redundant_allocation_fixable.rs:43:26 | LL | pub fn rc_test2(foo: Rc<&MyStruct>) {} | ^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -48,7 +48,7 @@ LL | pub fn rc_test2(foo: Rc<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Rc<&MyStruct>` allocates a pointer on the heap error: usage of `Rc<&MyEnum>` - --> $DIR/redundant_allocation_fixable.rs:49:26 + --> $DIR/redundant_allocation_fixable.rs:45:26 | LL | pub fn rc_test3(foo: Rc<&MyEnum>) {} | ^^^^^^^^^^^ help: try: `&MyEnum` @@ -56,7 +56,7 @@ LL | pub fn rc_test3(foo: Rc<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Rc<&MyEnum>` allocates a pointer on the heap error: usage of `Rc>` - --> $DIR/redundant_allocation_fixable.rs:53:24 + --> $DIR/redundant_allocation_fixable.rs:49:24 | LL | pub fn rc_test6(a: Rc>) {} | ^^^^^^^^^^^^ help: try: `Rc` @@ -64,7 +64,7 @@ LL | pub fn rc_test6(a: Rc>) {} = note: `Rc` is already on the heap, `Rc>` makes an extra allocation error: usage of `Arc<&T>` - --> $DIR/redundant_allocation_fixable.rs:64:30 + --> $DIR/redundant_allocation_fixable.rs:58:30 | LL | pub fn arc_test1(foo: Arc<&T>) {} | ^^^^^^^ help: try: `&T` @@ -72,7 +72,7 @@ LL | pub fn arc_test1(foo: Arc<&T>) {} = note: `&T` is already a pointer, `Arc<&T>` allocates a pointer on the heap error: usage of `Arc<&MyStruct>` - --> $DIR/redundant_allocation_fixable.rs:66:27 + --> $DIR/redundant_allocation_fixable.rs:60:27 | LL | pub fn arc_test2(foo: Arc<&MyStruct>) {} | ^^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -80,7 +80,7 @@ LL | pub fn arc_test2(foo: Arc<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Arc<&MyStruct>` allocates a pointer on the heap error: usage of `Arc<&MyEnum>` - --> $DIR/redundant_allocation_fixable.rs:68:27 + --> $DIR/redundant_allocation_fixable.rs:62:27 | LL | pub fn arc_test3(foo: Arc<&MyEnum>) {} | ^^^^^^^^^^^^ help: try: `&MyEnum` @@ -88,7 +88,7 @@ LL | pub fn arc_test3(foo: Arc<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Arc<&MyEnum>` allocates a pointer on the heap error: usage of `Arc>` - --> $DIR/redundant_allocation_fixable.rs:72:25 + --> $DIR/redundant_allocation_fixable.rs:66:25 | LL | pub fn arc_test7(a: Arc>) {} | ^^^^^^^^^^^^^^ help: try: `Arc` diff --git a/tests/ui/redundant_pattern_matching_ipaddr.fixed b/tests/ui/redundant_pattern_matching_ipaddr.fixed index 75ed143446c9f..02f197aa26a33 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -8,10 +8,8 @@ clippy::uninlined_format_args )] -use std::net::{ - IpAddr::{self, V4, V6}, - Ipv4Addr, Ipv6Addr, -}; +use std::net::IpAddr::{self, V4, V6}; +use std::net::{Ipv4Addr, Ipv6Addr}; fn main() { let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); diff --git a/tests/ui/redundant_pattern_matching_ipaddr.rs b/tests/ui/redundant_pattern_matching_ipaddr.rs index 9ac77409f7919..5c1e1810f5506 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -8,10 +8,8 @@ clippy::uninlined_format_args )] -use std::net::{ - IpAddr::{self, V4, V6}, - Ipv4Addr, Ipv6Addr, -}; +use std::net::IpAddr::{self, V4, V6}; +use std::net::{Ipv4Addr, Ipv6Addr}; fn main() { let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); diff --git a/tests/ui/redundant_pattern_matching_ipaddr.stderr b/tests/ui/redundant_pattern_matching_ipaddr.stderr index f34dc70983300..bec8d30884d00 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:16:12 | LL | if let V4(_) = &ipaddr {} | -------^^^^^---------- help: try: `if ipaddr.is_ipv4()` @@ -7,31 +7,31 @@ LL | if let V4(_) = &ipaddr {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:22:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:22:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:26:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:36:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:34:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:41:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:39:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:46:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:44:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:51:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:49:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => true, @@ -67,49 +67,49 @@ LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:56:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:54:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:64:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:62:20 | LL | let _ = if let V4(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:66:19 + --> $DIR/redundant_pattern_matching_ipaddr.rs:64:19 | LL | } else if let V6(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:76:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:80:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:80:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:84:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:86:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:84:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -118,7 +118,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:91:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:89:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 8c48b21f18846..17df9f88fff70 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -7,8 +7,7 @@ use std::num::ParseIntError; use std::ops::Deref; use std::sync::atomic::{AtomicU64, Ordering}; -use std::sync::RwLock; -use std::sync::{Mutex, MutexGuard}; +use std::sync::{Mutex, MutexGuard, RwLock}; struct State {} diff --git a/tests/ui/significant_drop_in_scrutinee.stderr b/tests/ui/significant_drop_in_scrutinee.stderr index 75063a8c987e9..b56ace200a8ba 100644 --- a/tests/ui/significant_drop_in_scrutinee.stderr +++ b/tests/ui/significant_drop_in_scrutinee.stderr @@ -1,5 +1,5 @@ error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:56:11 + --> $DIR/significant_drop_in_scrutinee.rs:55:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:142:11 + --> $DIR/significant_drop_in_scrutinee.rs:141:11 | LL | match s.lock_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:163:11 + --> $DIR/significant_drop_in_scrutinee.rs:162:11 | LL | match s.lock_m_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:211:11 + --> $DIR/significant_drop_in_scrutinee.rs:210:11 | LL | match counter.temp_increment().len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:234:16 + --> $DIR/significant_drop_in_scrutinee.rs:233:16 | LL | match (mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ match (value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:243:22 + --> $DIR/significant_drop_in_scrutinee.rs:242:22 | LL | match (true, mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL ~ match (true, value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:253:16 + --> $DIR/significant_drop_in_scrutinee.rs:252:16 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL ~ match (value, true, mutex2.lock().unwrap().s.len()) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:253:54 + --> $DIR/significant_drop_in_scrutinee.rs:252:54 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL ~ match (mutex1.lock().unwrap().s.len(), true, value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:264:15 + --> $DIR/significant_drop_in_scrutinee.rs:263:15 | LL | match mutex3.lock().unwrap().s.as_str() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:274:22 + --> $DIR/significant_drop_in_scrutinee.rs:273:22 | LL | match (true, mutex3.lock().unwrap().s.as_str()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:293:11 + --> $DIR/significant_drop_in_scrutinee.rs:292:11 | LL | match mutex.lock().unwrap().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:300:11 + --> $DIR/significant_drop_in_scrutinee.rs:299:11 | LL | match 1 < mutex.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:318:11 + --> $DIR/significant_drop_in_scrutinee.rs:317:11 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,7 +244,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:329:11 + --> $DIR/significant_drop_in_scrutinee.rs:328:11 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:364:11 + --> $DIR/significant_drop_in_scrutinee.rs:363:11 | LL | match get_mutex_guard().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -284,7 +284,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:381:11 + --> $DIR/significant_drop_in_scrutinee.rs:380:11 | LL | match match i { | ___________^ @@ -316,7 +316,7 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:407:11 + --> $DIR/significant_drop_in_scrutinee.rs:406:11 | LL | match if i > 1 { | ___________^ @@ -349,7 +349,7 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:461:11 + --> $DIR/significant_drop_in_scrutinee.rs:460:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +367,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:489:11 + --> $DIR/significant_drop_in_scrutinee.rs:488:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -380,7 +380,7 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:508:11 + --> $DIR/significant_drop_in_scrutinee.rs:507:11 | LL | match mutex.lock().unwrap().i = i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -399,7 +399,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:514:11 + --> $DIR/significant_drop_in_scrutinee.rs:513:11 | LL | match i = mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:520:11 + --> $DIR/significant_drop_in_scrutinee.rs:519:11 | LL | match mutex.lock().unwrap().i += 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -437,7 +437,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:526:11 + --> $DIR/significant_drop_in_scrutinee.rs:525:11 | LL | match i += mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -456,7 +456,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:589:11 + --> $DIR/significant_drop_in_scrutinee.rs:588:11 | LL | match rwlock.read().unwrap().to_number() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -467,7 +467,7 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> $DIR/significant_drop_in_scrutinee.rs:599:14 + --> $DIR/significant_drop_in_scrutinee.rs:598:14 | LL | for s in rwlock.read().unwrap().iter() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +478,7 @@ LL | } = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> $DIR/significant_drop_in_scrutinee.rs:614:11 + --> $DIR/significant_drop_in_scrutinee.rs:613:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index d4d2cbbe57ac9..b6b6b0288c52c 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -4,8 +4,12 @@ use core; + + use serde as edres; + pub use serde; + use std; macro_rules! m { diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index 80d72115f435d..a8c4d8990856e 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -3,9 +3,13 @@ #![allow(unused_imports)] use core; + use regex; + use serde as edres; + pub use serde; + use std; macro_rules! m { diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr index d69a86470a5e5..853a2fe0e7bf8 100644 --- a/tests/ui/single_component_path_imports.stderr +++ b/tests/ui/single_component_path_imports.stderr @@ -1,5 +1,5 @@ error: this import is redundant - --> $DIR/single_component_path_imports.rs:6:1 + --> $DIR/single_component_path_imports.rs:7:1 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely @@ -7,7 +7,7 @@ LL | use regex; = note: `-D clippy::single-component-path-imports` implied by `-D warnings` error: this import is redundant - --> $DIR/single_component_path_imports.rs:29:5 + --> $DIR/single_component_path_imports.rs:33:5 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely diff --git a/tests/ui/single_component_path_imports_nested_first.rs b/tests/ui/single_component_path_imports_nested_first.rs index c75beb7478618..d6243c19f554b 100644 --- a/tests/ui/single_component_path_imports_nested_first.rs +++ b/tests/ui/single_component_path_imports_nested_first.rs @@ -2,7 +2,9 @@ #![allow(unused_imports)] use regex; + use serde as edres; + pub use serde; fn main() { diff --git a/tests/ui/single_component_path_imports_nested_first.stderr b/tests/ui/single_component_path_imports_nested_first.stderr index 330f285202d0c..ff148355e1215 100644 --- a/tests/ui/single_component_path_imports_nested_first.stderr +++ b/tests/ui/single_component_path_imports_nested_first.stderr @@ -7,7 +7,7 @@ LL | use regex; = note: `-D clippy::single-component-path-imports` implied by `-D warnings` error: this import is redundant - --> $DIR/single_component_path_imports_nested_first.rs:13:10 + --> $DIR/single_component_path_imports_nested_first.rs:15:10 | LL | use {regex, serde}; | ^^^^^ @@ -15,7 +15,7 @@ LL | use {regex, serde}; = help: remove this import error: this import is redundant - --> $DIR/single_component_path_imports_nested_first.rs:13:17 + --> $DIR/single_component_path_imports_nested_first.rs:15:17 | LL | use {regex, serde}; | ^^^^^ diff --git a/tests/ui/single_component_path_imports_self_after.rs b/tests/ui/single_component_path_imports_self_after.rs index 48e8e530261be..5723d480a2e1b 100644 --- a/tests/ui/single_component_path_imports_self_after.rs +++ b/tests/ui/single_component_path_imports_self_after.rs @@ -2,6 +2,7 @@ #![allow(unused_imports)] use self::regex::{Regex as xeger, RegexSet as tesxeger}; +#[rustfmt::skip] pub use self::{ regex::{Regex, RegexSet}, some_mod::SomeType, diff --git a/tests/ui/single_component_path_imports_self_before.rs b/tests/ui/single_component_path_imports_self_before.rs index 4fb0cf40b6e00..8a4fbf0dc5b6a 100644 --- a/tests/ui/single_component_path_imports_self_before.rs +++ b/tests/ui/single_component_path_imports_self_before.rs @@ -4,6 +4,7 @@ use regex; use self::regex::{Regex as xeger, RegexSet as tesxeger}; +#[rustfmt::skip] pub use self::{ regex::{Regex, RegexSet}, some_mod::SomeType, diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 592a53f3a8198..cb7562351e8e4 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -477,7 +477,8 @@ mod issue_10021 { mod issue_10033 { #![allow(dead_code)] - use std::{fmt::Display, ops::Deref}; + use std::fmt::Display; + use std::ops::Deref; fn _main() { let f = Foo; diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index f2e48b1c4a6a7..f82ddb2d25df1 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -477,7 +477,8 @@ mod issue_10021 { mod issue_10033 { #![allow(dead_code)] - use std::{fmt::Display, ops::Deref}; + use std::fmt::Display; + use std::ops::Deref; fn _main() { let f = Foo; diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index d29888ac62f6b..04f6ef29a9a15 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -8,9 +8,13 @@ use std::cell::UnsafeCell as TotallySafeCellAgain; // Shouldn't error use std::cell::RefCell as ProbablyNotUnsafe; + use std::cell::RefCell as RefCellThatCantBeUnsafe; + use std::cell::UnsafeCell as SuperDangerousUnsafeCell; + use std::cell::UnsafeCell as Dangerunsafe; + use std::cell::UnsafeCell as Bombsawayunsafe; mod mod_with_some_unsafe_things { @@ -20,8 +24,12 @@ mod mod_with_some_unsafe_things { use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; +// merged imports +use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; + // Shouldn't error use mod_with_some_unsafe_things::Safe as IPromiseItsSafeThisTime; + use mod_with_some_unsafe_things::Unsafe as SuperUnsafeModThing; #[allow(clippy::unsafe_removed_from_name)] diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 4f871cbe41b06..090d917bd3846 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -13,10 +13,22 @@ LL | use std::cell::UnsafeCell as TotallySafeCellAgain; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed `unsafe` from the name of `Unsafe` in use as `LieAboutModSafety` - --> $DIR/unsafe_removed_from_name.rs:21:1 + --> $DIR/unsafe_removed_from_name.rs:25:1 | LL | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: removed `unsafe` from the name of `Unsafe` in use as `A` + --> $DIR/unsafe_removed_from_name.rs:28:1 + | +LL | use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: removed `unsafe` from the name of `Unsafe` in use as `B` + --> $DIR/unsafe_removed_from_name.rs:28:1 + | +LL | use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/unused_peekable.rs b/tests/ui/unused_peekable.rs index 7374dfdf92e87..b227f8660f53c 100644 --- a/tests/ui/unused_peekable.rs +++ b/tests/ui/unused_peekable.rs @@ -1,8 +1,7 @@ #![warn(clippy::unused_peekable)] #![allow(clippy::no_effect)] -use std::iter::Empty; -use std::iter::Peekable; +use std::iter::{Empty, Peekable}; fn main() { invalid(); diff --git a/tests/ui/unused_peekable.stderr b/tests/ui/unused_peekable.stderr index 54788f2fa2f4c..d969232fdf3b1 100644 --- a/tests/ui/unused_peekable.stderr +++ b/tests/ui/unused_peekable.stderr @@ -1,5 +1,5 @@ error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:14:9 + --> $DIR/unused_peekable.rs:13:9 | LL | let peekable = std::iter::empty::().peekable(); | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | let peekable = std::iter::empty::().peekable(); = note: `-D clippy::unused-peekable` implied by `-D warnings` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:18:9 + --> $DIR/unused_peekable.rs:17:9 | LL | let new_local = old_local; | ^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let new_local = old_local; = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:22:9 + --> $DIR/unused_peekable.rs:21:9 | LL | let by_mut_ref = &mut by_mut_ref_test; | ^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let by_mut_ref = &mut by_mut_ref_test; = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:29:9 + --> $DIR/unused_peekable.rs:28:9 | LL | let peekable_from_fn = returns_peekable(); | ^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let peekable_from_fn = returns_peekable(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:32:13 + --> $DIR/unused_peekable.rs:31:13 | LL | let mut peekable_using_iterator_method = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let mut peekable_using_iterator_method = std::iter::empty::().peek = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:37:9 + --> $DIR/unused_peekable.rs:36:9 | LL | let passed_along_ref = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let passed_along_ref = std::iter::empty::().peekable(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:42:9 + --> $DIR/unused_peekable.rs:41:9 | LL | let _by_ref = by_ref_test.by_ref(); | ^^^^^^^ @@ -56,7 +56,7 @@ LL | let _by_ref = by_ref_test.by_ref(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> $DIR/unused_peekable.rs:44:13 + --> $DIR/unused_peekable.rs:43:13 | LL | let mut peekable_in_for_loop = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 2961b062ec37c..67173f40654fe 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -112,6 +112,7 @@ mod in_fn_test { } fn test_inner_nested() { + #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; inner_foo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 28508a2538b28..8223b69301813 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -112,6 +112,7 @@ mod in_fn_test { } fn test_inner_nested() { + #[rustfmt::skip] use self::{inner::*, inner2::*}; inner_foo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index c96b3041a005f..f7baf234c2f8b 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -55,37 +55,37 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:115:20 + --> $DIR/wildcard_imports.rs:116:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:115:30 + --> $DIR/wildcard_imports.rs:116:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:122:13 + --> $DIR/wildcard_imports.rs:123:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:151:9 + --> $DIR/wildcard_imports.rs:152:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:160:9 + --> $DIR/wildcard_imports.rs:161:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:161:9 + --> $DIR/wildcard_imports.rs:162:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:172:13 + --> $DIR/wildcard_imports.rs:173:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:207:17 + --> $DIR/wildcard_imports.rs:208:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:215:13 + --> $DIR/wildcard_imports.rs:216:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:224:17 + --> $DIR/wildcard_imports.rs:225:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:233:13 + --> $DIR/wildcard_imports.rs:234:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:241:13 + --> $DIR/wildcard_imports.rs:242:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.edition2018.fixed b/tests/ui/wildcard_imports_2021.edition2018.fixed index 3aea013fb3a76..8a63375676eff 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -106,6 +106,7 @@ mod in_fn_test { } fn test_inner_nested() { + #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; inner_foo(); diff --git a/tests/ui/wildcard_imports_2021.edition2018.stderr b/tests/ui/wildcard_imports_2021.edition2018.stderr index acca9f651b474..af9ae6e786c96 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -55,37 +55,37 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:109:20 + --> $DIR/wildcard_imports_2021.rs:110:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:109:30 + --> $DIR/wildcard_imports_2021.rs:110:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:116:13 + --> $DIR/wildcard_imports_2021.rs:117:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:145:9 + --> $DIR/wildcard_imports_2021.rs:146:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:154:9 + --> $DIR/wildcard_imports_2021.rs:155:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:155:9 + --> $DIR/wildcard_imports_2021.rs:156:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:166:13 + --> $DIR/wildcard_imports_2021.rs:167:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:201:17 + --> $DIR/wildcard_imports_2021.rs:202:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:209:13 + --> $DIR/wildcard_imports_2021.rs:210:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:218:17 + --> $DIR/wildcard_imports_2021.rs:219:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:227:13 + --> $DIR/wildcard_imports_2021.rs:228:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:235:13 + --> $DIR/wildcard_imports_2021.rs:236:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.edition2021.fixed b/tests/ui/wildcard_imports_2021.edition2021.fixed index 3aea013fb3a76..8a63375676eff 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -106,6 +106,7 @@ mod in_fn_test { } fn test_inner_nested() { + #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; inner_foo(); diff --git a/tests/ui/wildcard_imports_2021.edition2021.stderr b/tests/ui/wildcard_imports_2021.edition2021.stderr index acca9f651b474..af9ae6e786c96 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -55,37 +55,37 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:109:20 + --> $DIR/wildcard_imports_2021.rs:110:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:109:30 + --> $DIR/wildcard_imports_2021.rs:110:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:116:13 + --> $DIR/wildcard_imports_2021.rs:117:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:145:9 + --> $DIR/wildcard_imports_2021.rs:146:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:154:9 + --> $DIR/wildcard_imports_2021.rs:155:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:155:9 + --> $DIR/wildcard_imports_2021.rs:156:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:166:13 + --> $DIR/wildcard_imports_2021.rs:167:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:201:17 + --> $DIR/wildcard_imports_2021.rs:202:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:209:13 + --> $DIR/wildcard_imports_2021.rs:210:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:218:17 + --> $DIR/wildcard_imports_2021.rs:219:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:227:13 + --> $DIR/wildcard_imports_2021.rs:228:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:235:13 + --> $DIR/wildcard_imports_2021.rs:236:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.rs b/tests/ui/wildcard_imports_2021.rs index 40c2d07527d1e..52cd2c82854fd 100644 --- a/tests/ui/wildcard_imports_2021.rs +++ b/tests/ui/wildcard_imports_2021.rs @@ -106,6 +106,7 @@ mod in_fn_test { } fn test_inner_nested() { + #[rustfmt::skip] use self::{inner::*, inner2::*}; inner_foo(); From ea36a9df753432df2dad471384543377e8f78129 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 13 Jul 2023 13:29:41 +0000 Subject: [PATCH 74/80] Set `unnecessary_cast` suggestion to `MaybeIncorrect` for pointer casts Removing casts may cause type inference to stop working which requires manual intervention --- clippy_lints/src/casts/unnecessary_cast.rs | 2 +- tests/ui/unnecessary_cast_unfixable.rs | 22 ++++++++++++++++++++++ tests/ui/unnecessary_cast_unfixable.stderr | 16 ++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ui/unnecessary_cast_unfixable.rs create mode 100644 tests/ui/unnecessary_cast_unfixable.stderr diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 71cf2aea0f8da..ae56f38d9ad57 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -56,7 +56,7 @@ pub(super) fn check<'tcx>( &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"), "try", cast_str.clone(), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } diff --git a/tests/ui/unnecessary_cast_unfixable.rs b/tests/ui/unnecessary_cast_unfixable.rs new file mode 100644 index 0000000000000..0e027f6042e6f --- /dev/null +++ b/tests/ui/unnecessary_cast_unfixable.rs @@ -0,0 +1,22 @@ +#![warn(clippy::unnecessary_cast)] + +fn main() { + let _ = std::ptr::null() as *const u8; +} + +mod issue11113 { + #[repr(C)] + struct Vtbl { + query: unsafe extern "system" fn(), + } + + struct TearOff { + object: *mut std::ffi::c_void, + } + + impl TearOff { + unsafe fn query(&self) { + ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)() + } + } +} diff --git a/tests/ui/unnecessary_cast_unfixable.stderr b/tests/ui/unnecessary_cast_unfixable.stderr new file mode 100644 index 0000000000000..eecf245686a84 --- /dev/null +++ b/tests/ui/unnecessary_cast_unfixable.stderr @@ -0,0 +1,16 @@ +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast_unfixable.rs:4:13 + | +LL | let _ = std::ptr::null() as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::null()` + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + +error: casting raw pointers to the same type and constness is unnecessary (`*mut issue11113::Vtbl` -> `*mut issue11113::Vtbl`) + --> $DIR/unnecessary_cast_unfixable.rs:19:16 + | +LL | ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*(self.object as *mut *mut _)` + +error: aborting due to 2 previous errors + From 36279f1b631c345d22111809536edf70522d256e Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 13 Jul 2023 20:06:12 +0000 Subject: [PATCH 75/80] Trigger a rebuild when CLIPPY_CONF_DIR changes --- src/driver.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/driver.rs b/src/driver.rs index 1eb288b153a5a..ee17feed77a00 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -130,6 +130,13 @@ impl rustc_driver::Callbacks for ClippyCallbacks { config.parse_sess_created = Some(Box::new(move |parse_sess| { track_clippy_args(parse_sess, &clippy_args_var); track_files(parse_sess); + + // Trigger a rebuild if CLIPPY_CONF_DIR changes. The value must be a valid string so + // changes between dirs that are invalid UTF-8 will not trigger rebuilds + parse_sess.env_depinfo.get_mut().insert(( + Symbol::intern("CLIPPY_CONF_DIR"), + env::var("CLIPPY_CONF_DIR").ok().map(|dir| Symbol::intern(&dir)), + )); })); config.register_lints = Some(Box::new(move |sess, lint_store| { // technically we're ~guaranteed that this is none but might as well call anything that From faa07d334a9639684ff1913be1d50b895d5cb0fc Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 14 Jul 2023 13:36:23 +0200 Subject: [PATCH 76/80] Bump Clippy version -> 0.1.73 --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- declare_clippy_lint/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e7a5dbe030d14..0fb3a3a984b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.72" +version = "0.1.73" 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/Cargo.toml b/clippy_lints/Cargo.toml index c23054443bb96..11136867ff0aa 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.72" +version = "0.1.73" 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_utils/Cargo.toml b/clippy_utils/Cargo.toml index cfe686eb9b01d..3926b954ec8cd 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.72" +version = "0.1.73" edition = "2021" publish = false diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 4dc906d00db16..3633ed31d739f 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.72" +version = "0.1.73" edition = "2021" publish = false From 753c30f3476957a2de2e158aa8e33131ea80d507 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 14 Jul 2023 13:36:32 +0200 Subject: [PATCH 77/80] Bump nightly version -> 2023-07-14 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4475d914cedb0..b658101a10d83 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-06-29" +channel = "nightly-2023-07-14" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] From 498db80d5c391dd1206a5ba699b5b18df66f0331 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 16 Jul 2023 21:37:53 +0200 Subject: [PATCH 78/80] don't hide lifetimes for `LateContext` --- clippy_dev/src/new_lint.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index f11aa547bd734..f39bc06e6d732 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -358,6 +358,10 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let mod_file_path = ty_dir.join("mod.rs"); let context_import = setup_mod_file(&mod_file_path, lint)?; + let pass_lifetimes = match context_import { + "LateContext" => "<'_>", + _ => "", + }; let name_upper = lint.name.to_uppercase(); let mut lint_file_contents = String::new(); @@ -372,7 +376,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R use super::{name_upper}; // TODO: Adjust the parameters as necessary - pub(super) fn check(cx: &{context_import}, msrv: &Msrv) {{ + pub(super) fn check(cx: &{context_import}{pass_lifetimes}, msrv: &Msrv) {{ if !msrv.meets(todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ return; }} @@ -389,7 +393,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R use super::{name_upper}; // TODO: Adjust the parameters as necessary - pub(super) fn check(cx: &{context_import}) {{ + pub(super) fn check(cx: &{context_import}{pass_lifetimes}) {{ todo!(); }} "# From c2490bdc44aaa1feda8a21c616820ed434419ef5 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 17 Jul 2023 10:22:41 +0200 Subject: [PATCH 79/80] Update Cargo.lock/toml Remove clippy_test_deps from Cargo.toml --- Cargo.lock | 35 +++++++++++++---------------------- Cargo.toml | 1 - 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2390850b56754..fb619d3870f3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,16 +513,25 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.72" +version = "0.1.73" dependencies = [ "clippy_lints", + "clippy_utils", + "derive-new", "filetime", + "futures", + "if_chain", "itertools", + "parking_lot 0.12.1", + "quote", "regex", "rustc_tools_util", + "serde", + "syn 2.0.8", "tempfile", "termize", "tester", + "tokio", "toml 0.7.5", "ui_test", "walkdir", @@ -543,7 +552,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.72" +version = "0.1.73" dependencies = [ "arrayvec", "cargo_metadata", @@ -566,27 +575,9 @@ dependencies = [ "url", ] -[[package]] -name = "clippy_test_deps" -version = "0.1.0" -dependencies = [ - "clippy_lints", - "clippy_utils", - "derive-new", - "futures", - "if_chain", - "itertools", - "parking_lot 0.12.1", - "quote", - "regex", - "serde", - "syn 2.0.8", - "tokio", -] - [[package]] name = "clippy_utils" -version = "0.1.72" +version = "0.1.73" dependencies = [ "arrayvec", "if_chain", @@ -847,7 +838,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.72" +version = "0.1.73" dependencies = [ "itertools", "quote", diff --git a/Cargo.toml b/Cargo.toml index 53bf9a8af2c1b..d2e84d5426f9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ members = [ "src/tools/cargotest", "src/tools/clippy", "src/tools/clippy/clippy_dev", - "src/tools/clippy/clippy_test_deps", "src/tools/compiletest", "src/tools/error_index_generator", "src/tools/linkchecker", From 8ca13e83389f537ba389ce5fbd288b750bbdf7d4 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 17 Jul 2023 10:22:49 +0200 Subject: [PATCH 80/80] Another fix for incorrect_impls --- src/tools/clippy/clippy_lints/src/incorrect_impls.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs index c5da6039ac39e..e6c42ebb8329b 100644 --- a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs +++ b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs @@ -4,7 +4,6 @@ use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, path_re use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -121,7 +120,7 @@ impl LateLintPass<'_> for IncorrectImpls { if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { return; } - let ItemKind::Impl(imp) = item.kind else { + let ItemKind::Impl(_) = item.kind else { return; }; let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { @@ -186,9 +185,9 @@ impl LateLintPass<'_> for IncorrectImpls { .get(&sym::Ord) && implements_trait( cx, - hir_ty_to_ty(cx.tcx, imp.self_ty), + trait_impl.self_ty(), *ord_def_id, - trait_impl.args, + &[], ) { if block.stmts.is_empty()