`assertions_on_constants`: Suggest using a const block when using a named constant (#15774)
changelog: [`assertions_on_constants`]: Suggest using a const block when
the assertion uses a named constant.
diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs
index 4dd8f01..bddf470 100644
--- a/clippy_lints/src/double_parens.rs
+++ b/clippy_lints/src/double_parens.rs
@@ -1,5 +1,7 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast::{Expr, ExprKind};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{HasSession, snippet_with_applicability, snippet_with_context};
+use rustc_ast::ast::{Expr, ExprKind, MethodCall};
+use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -24,7 +26,7 @@
/// Use instead:
/// ```no_run
/// fn simple_no_parens() -> i32 {
- /// 0
+ /// (0)
/// }
///
/// # fn foo(bar: usize) {}
@@ -40,29 +42,54 @@
impl EarlyLintPass for DoubleParens {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- let span = match &expr.kind {
- ExprKind::Paren(in_paren) if matches!(in_paren.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => expr.span,
- ExprKind::Call(_, params)
- if let [param] = &**params
- && let ExprKind::Paren(_) = param.kind =>
- {
- param.span
+ match &expr.kind {
+ // ((..))
+ // ^^^^^^ expr
+ // ^^^^ inner
+ ExprKind::Paren(inner) if matches!(inner.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => {
+ // suggest removing the outer parens
+ if expr.span.eq_ctxt(inner.span) {
+ let mut applicability = Applicability::MachineApplicable;
+ // We don't need to use `snippet_with_context` here, because:
+ // - if `inner`'s `ctxt` is from macro, we don't lint in the first place (see the check above)
+ // - otherwise, calling `snippet_with_applicability` on a not-from-macro span is fine
+ let sugg = snippet_with_applicability(cx.sess(), inner.span, "_", &mut applicability);
+ span_lint_and_sugg(
+ cx,
+ DOUBLE_PARENS,
+ expr.span,
+ "unnecessary parentheses",
+ "remove them",
+ sugg.to_string(),
+ applicability,
+ );
+ }
},
- ExprKind::MethodCall(call)
- if let [arg] = &*call.args
- && let ExprKind::Paren(_) = arg.kind =>
+
+ // func((n))
+ // ^^^^^^^^^ expr
+ // ^^^ arg
+ // ^ inner
+ ExprKind::Call(_, args) | ExprKind::MethodCall(box MethodCall { args, .. })
+ if let [arg] = &**args
+ && let ExprKind::Paren(inner) = &arg.kind =>
{
- arg.span
+ // suggest removing the inner parens
+ if expr.span.eq_ctxt(arg.span) {
+ let mut applicability = Applicability::MachineApplicable;
+ let sugg = snippet_with_context(cx.sess(), inner.span, arg.span.ctxt(), "_", &mut applicability).0;
+ span_lint_and_sugg(
+ cx,
+ DOUBLE_PARENS,
+ arg.span,
+ "unnecessary parentheses",
+ "remove them",
+ sugg.to_string(),
+ applicability,
+ );
+ }
},
- _ => return,
- };
- if !expr.span.from_expansion() {
- span_lint(
- cx,
- DOUBLE_PARENS,
- span,
- "consider removing unnecessary double parentheses",
- );
+ _ => {},
}
}
}
diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index b50d91f..f9fee29 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -79,6 +79,7 @@
&& !is_in_const_context(cx)
&& self.msrv.meets(cx, msrvs::BOOL_THEN)
&& !contains_return(then_block.stmts)
+ && then_block.expr.is_none_or(|expr| !contains_return(expr))
{
let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(cx, msrvs::BOOL_THEN_SOME) {
sym::then_some
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 0a955d2..c2c99904 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -482,7 +482,7 @@
store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
store.register_late_pass(|_| Box::new(misc::LintPass));
store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
- store.register_late_pass(|_| Box::new(mut_mut::MutMut));
+ store.register_late_pass(|_| Box::new(mut_mut::MutMut::default()));
store.register_late_pass(|_| Box::new(unnecessary_mut_passed::UnnecessaryMutPassed));
store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
store.register_late_pass(|_| Box::new(len_zero::LenZero));
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index e39916f..95ecef5 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_non_aggregate_primitive_type;
use clippy_utils::{
@@ -269,14 +269,11 @@
),
|diag| {
if !expr.span.from_expansion() {
- let suggestion = format!("{top_crate}::mem::take({})", snippet(cx, dest.span, ""));
+ let mut applicability = Applicability::MachineApplicable;
+ let (dest_snip, _) = snippet_with_context(cx, dest.span, expr.span.ctxt(), "", &mut applicability);
+ let suggestion = format!("{top_crate}::mem::take({dest_snip})");
- diag.span_suggestion(
- expr.span,
- "consider using",
- suggestion,
- Applicability::MachineApplicable,
- );
+ diag.span_suggestion(expr.span, "consider using", suggestion, applicability);
}
},
);
diff --git a/clippy_lints/src/methods/lib.rs b/clippy_lints/src/methods/lib.rs
new file mode 100644
index 0000000..8403828
--- /dev/null
+++ b/clippy_lints/src/methods/lib.rs
@@ -0,0 +1,70 @@
+use clippy_utils::sym;
+use clippy_utils::ty::{implements_trait, is_copy};
+use rustc_hir::Mutability;
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, Ty};
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub(super) enum SelfKind {
+ Value,
+ Ref,
+ RefMut,
+ No, // When we want the first argument type to be different than `Self`
+}
+
+impl SelfKind {
+ pub(super) fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
+ fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
+ if ty == parent_ty {
+ true
+ } else if let Some(boxed_ty) = ty.boxed_ty() {
+ boxed_ty == parent_ty
+ } else if let ty::Adt(adt_def, args) = ty.kind()
+ && matches!(cx.tcx.get_diagnostic_name(adt_def.did()), Some(sym::Rc | sym::Arc))
+ {
+ args.types().next() == Some(parent_ty)
+ } else {
+ false
+ }
+ }
+
+ fn matches_ref<'a>(cx: &LateContext<'a>, mutability: Mutability, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
+ if let ty::Ref(_, t, m) = *ty.kind() {
+ return m == mutability && t == parent_ty;
+ }
+
+ let trait_sym = match mutability {
+ Mutability::Not => sym::AsRef,
+ Mutability::Mut => sym::AsMut,
+ };
+
+ let Some(trait_def_id) = cx.tcx.get_diagnostic_item(trait_sym) else {
+ return false;
+ };
+ implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])
+ }
+
+ fn matches_none<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
+ !matches_value(cx, parent_ty, ty)
+ && !matches_ref(cx, Mutability::Not, parent_ty, ty)
+ && !matches_ref(cx, Mutability::Mut, parent_ty, ty)
+ }
+
+ match self {
+ Self::Value => matches_value(cx, parent_ty, ty),
+ Self::Ref => matches_ref(cx, Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty),
+ Self::RefMut => matches_ref(cx, Mutability::Mut, parent_ty, ty),
+ Self::No => matches_none(cx, parent_ty, ty),
+ }
+ }
+
+ #[must_use]
+ pub(super) fn description(self) -> &'static str {
+ match self {
+ Self::Value => "`self` by value",
+ Self::Ref => "`self` by reference",
+ Self::RefMut => "`self` by mutable reference",
+ Self::No => "no `self`",
+ }
+ }
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index a1cdab9..8c2948e 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -55,6 +55,7 @@
mod iter_with_drain;
mod iterator_step_by_zero;
mod join_absolute_paths;
+mod lib;
mod manual_c_str_literals;
mod manual_contains;
mod manual_inspect;
@@ -102,6 +103,7 @@
mod search_is_some;
mod seek_from_current;
mod seek_to_start_instead_of_rewind;
+mod should_implement_trait;
mod single_char_add_str;
mod skip_while_next;
mod sliced_string_as_bytes;
@@ -146,20 +148,18 @@
use clippy_config::Conf;
use clippy_utils::consts::{ConstEvalCtxt, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint;
use clippy_utils::macros::FormatArgsStorage;
use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
-use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty, sym};
+use clippy_utils::ty::contains_ty_adt_constructor_opaque;
+use clippy_utils::{contains_return, is_trait_method, iter_input_pats, peel_blocks, return_ty, sym};
pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES;
-use rustc_abi::ExternAbi;
use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind};
+use rustc_hir::{self as hir, Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::{self, TraitRef, Ty};
+use rustc_middle::ty::TraitRef;
use rustc_session::impl_lint_pass;
-use rustc_span::{Span, Symbol, kw};
+use rustc_span::{Span, Symbol};
declare_clippy_lint! {
/// ### What it does
@@ -4889,48 +4889,17 @@
if impl_item.span.in_external_macro(cx.sess().source_map()) {
return;
}
- let name = impl_item.ident.name;
- let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
- let item = cx.tcx.hir_expect_item(parent);
- let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
- let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind {
+ let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
+ let item = cx.tcx.hir_expect_item(parent);
+ let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
+ let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
+
let method_sig = cx.tcx.fn_sig(impl_item.owner_id).instantiate_identity();
let method_sig = cx.tcx.instantiate_bound_regions_with_erased(method_sig);
let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
- // if this impl block implements a trait, lint in trait definition instead
- if !implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
- // check missing trait implementations
- for method_config in &TRAIT_METHODS {
- if name == method_config.method_name
- && sig.decl.inputs.len() == method_config.param_count
- && method_config.output_type.matches(&sig.decl.output)
- // in case there is no first arg, since we already have checked the number of arguments
- // it's should be always true
- && first_arg_ty_opt.is_none_or(|first_arg_ty| method_config
- .self_kind.matches(cx, self_ty, first_arg_ty)
- )
- && fn_header_equals(method_config.fn_header, sig.header)
- && method_config.lifetime_param_cond(impl_item)
- {
- span_lint_and_help(
- cx,
- SHOULD_IMPLEMENT_TRAIT,
- impl_item.span,
- format!(
- "method `{}` can be confused for the standard trait method `{}::{}`",
- method_config.method_name, method_config.trait_name, method_config.method_name
- ),
- None,
- format!(
- "consider implementing the trait `{}` or choosing a less ambiguous method name",
- method_config.trait_name
- ),
- );
- }
- }
- }
+ should_implement_trait::check_impl_item(cx, impl_item, self_ty, implements_trait, first_arg_ty_opt, sig);
if sig.decl.implicit_self.has_implicit_self()
&& !(self.avoid_breaking_exported_api
@@ -4940,7 +4909,7 @@
{
wrong_self_convention::check(
cx,
- name,
+ impl_item.ident.name,
self_ty,
first_arg_ty,
first_arg.pat.span,
@@ -4948,21 +4917,14 @@
false,
);
}
- }
- // if this impl block implements a trait, lint in trait definition instead
- if implements_trait {
- return;
- }
-
- if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
- let ret_ty = return_ty(cx, impl_item.owner_id);
-
- if contains_ty_adt_constructor_opaque(cx, ret_ty, self_ty) {
- return;
- }
-
- if name == sym::new && ret_ty != self_ty {
+ // if this impl block implements a trait, lint in trait definition instead
+ if !implements_trait
+ && impl_item.ident.name == sym::new
+ && let ret_ty = return_ty(cx, impl_item.owner_id)
+ && ret_ty != self_ty
+ && !contains_ty_adt_constructor_opaque(cx, ret_ty, self_ty)
+ {
span_lint(
cx,
NEW_RET_NO_SELF,
@@ -4978,41 +4940,41 @@
return;
}
- if let TraitItemKind::Fn(ref sig, _) = item.kind
- && sig.decl.implicit_self.has_implicit_self()
- && let Some(first_arg_hir_ty) = sig.decl.inputs.first()
- && let Some(&first_arg_ty) = cx
- .tcx
- .fn_sig(item.owner_id)
- .instantiate_identity()
- .inputs()
- .skip_binder()
- .first()
- {
- let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty();
- wrong_self_convention::check(
- cx,
- item.ident.name,
- self_ty,
- first_arg_ty,
- first_arg_hir_ty.span,
- false,
- true,
- );
- }
+ if let TraitItemKind::Fn(ref sig, _) = item.kind {
+ if sig.decl.implicit_self.has_implicit_self()
+ && let Some(first_arg_hir_ty) = sig.decl.inputs.first()
+ && let Some(&first_arg_ty) = cx
+ .tcx
+ .fn_sig(item.owner_id)
+ .instantiate_identity()
+ .inputs()
+ .skip_binder()
+ .first()
+ {
+ let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty();
+ wrong_self_convention::check(
+ cx,
+ item.ident.name,
+ self_ty,
+ first_arg_ty,
+ first_arg_hir_ty.span,
+ false,
+ true,
+ );
+ }
- if item.ident.name == sym::new
- && let TraitItemKind::Fn(_, _) = item.kind
- && let ret_ty = return_ty(cx, item.owner_id)
- && let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty()
- && !ret_ty.contains(self_ty)
- {
- span_lint(
- cx,
- NEW_RET_NO_SELF,
- item.span,
- "methods called `new` usually return `Self`",
- );
+ if item.ident.name == sym::new
+ && let ret_ty = return_ty(cx, item.owner_id)
+ && let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty()
+ && !ret_ty.contains(self_ty)
+ {
+ span_lint(
+ cx,
+ NEW_RET_NO_SELF,
+ item.span,
+ "methods called `new` usually return `Self`",
+ );
+ }
}
}
}
@@ -5720,183 +5682,3 @@
lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info);
lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info);
}
-
-const FN_HEADER: hir::FnHeader = hir::FnHeader {
- safety: hir::HeaderSafety::Normal(hir::Safety::Safe),
- constness: hir::Constness::NotConst,
- asyncness: hir::IsAsync::NotAsync,
- abi: ExternAbi::Rust,
-};
-
-struct ShouldImplTraitCase {
- trait_name: &'static str,
- method_name: Symbol,
- param_count: usize,
- fn_header: hir::FnHeader,
- // implicit self kind expected (none, self, &self, ...)
- self_kind: SelfKind,
- // checks against the output type
- output_type: OutType,
- // certain methods with explicit lifetimes can't implement the equivalent trait method
- lint_explicit_lifetime: bool,
-}
-impl ShouldImplTraitCase {
- const fn new(
- trait_name: &'static str,
- method_name: Symbol,
- param_count: usize,
- fn_header: hir::FnHeader,
- self_kind: SelfKind,
- output_type: OutType,
- lint_explicit_lifetime: bool,
- ) -> ShouldImplTraitCase {
- ShouldImplTraitCase {
- trait_name,
- method_name,
- param_count,
- fn_header,
- self_kind,
- output_type,
- lint_explicit_lifetime,
- }
- }
-
- fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
- self.lint_explicit_lifetime
- || !impl_item.generics.params.iter().any(|p| {
- matches!(
- p.kind,
- hir::GenericParamKind::Lifetime {
- kind: hir::LifetimeParamKind::Explicit
- }
- )
- })
- }
-}
-
-#[rustfmt::skip]
-const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
- ShouldImplTraitCase::new("std::ops::Add", sym::add, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::convert::AsMut", sym::as_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
- ShouldImplTraitCase::new("std::convert::AsRef", sym::as_ref, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
- ShouldImplTraitCase::new("std::ops::BitAnd", sym::bitand, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::BitOr", sym::bitor, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::BitXor", sym::bitxor, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::borrow::Borrow", sym::borrow, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
- ShouldImplTraitCase::new("std::borrow::BorrowMut", sym::borrow_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
- ShouldImplTraitCase::new("std::clone::Clone", sym::clone, 1, FN_HEADER, SelfKind::Ref, OutType::Any, true),
- ShouldImplTraitCase::new("std::cmp::Ord", sym::cmp, 2, FN_HEADER, SelfKind::Ref, OutType::Any, true),
- ShouldImplTraitCase::new("std::default::Default", kw::Default, 0, FN_HEADER, SelfKind::No, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Deref", sym::deref, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
- ShouldImplTraitCase::new("std::ops::DerefMut", sym::deref_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
- ShouldImplTraitCase::new("std::ops::Div", sym::div, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Drop", sym::drop, 1, FN_HEADER, SelfKind::RefMut, OutType::Unit, true),
- ShouldImplTraitCase::new("std::cmp::PartialEq", sym::eq, 2, FN_HEADER, SelfKind::Ref, OutType::Bool, true),
- ShouldImplTraitCase::new("std::iter::FromIterator", sym::from_iter, 1, FN_HEADER, SelfKind::No, OutType::Any, true),
- ShouldImplTraitCase::new("std::str::FromStr", sym::from_str, 1, FN_HEADER, SelfKind::No, OutType::Any, true),
- ShouldImplTraitCase::new("std::hash::Hash", sym::hash, 2, FN_HEADER, SelfKind::Ref, OutType::Unit, true),
- ShouldImplTraitCase::new("std::ops::Index", sym::index, 2, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
- ShouldImplTraitCase::new("std::ops::IndexMut", sym::index_mut, 2, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
- ShouldImplTraitCase::new("std::iter::IntoIterator", sym::into_iter, 1, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Mul", sym::mul, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Neg", sym::neg, 1, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::iter::Iterator", sym::next, 1, FN_HEADER, SelfKind::RefMut, OutType::Any, false),
- ShouldImplTraitCase::new("std::ops::Not", sym::not, 1, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Rem", sym::rem, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Shl", sym::shl, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Shr", sym::shr, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
- ShouldImplTraitCase::new("std::ops::Sub", sym::sub, 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
-];
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-enum SelfKind {
- Value,
- Ref,
- RefMut,
- No, // When we want the first argument type to be different than `Self`
-}
-
-impl SelfKind {
- fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
- fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
- if ty == parent_ty {
- true
- } else if let Some(boxed_ty) = ty.boxed_ty() {
- boxed_ty == parent_ty
- } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
- if let ty::Adt(_, args) = ty.kind() {
- args.types().next() == Some(parent_ty)
- } else {
- false
- }
- } else {
- false
- }
- }
-
- fn matches_ref<'a>(cx: &LateContext<'a>, mutability: hir::Mutability, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
- if let ty::Ref(_, t, m) = *ty.kind() {
- return m == mutability && t == parent_ty;
- }
-
- let trait_sym = match mutability {
- hir::Mutability::Not => sym::AsRef,
- hir::Mutability::Mut => sym::AsMut,
- };
-
- let Some(trait_def_id) = cx.tcx.get_diagnostic_item(trait_sym) else {
- return false;
- };
- implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])
- }
-
- fn matches_none<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
- !matches_value(cx, parent_ty, ty)
- && !matches_ref(cx, hir::Mutability::Not, parent_ty, ty)
- && !matches_ref(cx, hir::Mutability::Mut, parent_ty, ty)
- }
-
- match self {
- Self::Value => matches_value(cx, parent_ty, ty),
- Self::Ref => matches_ref(cx, hir::Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty),
- Self::RefMut => matches_ref(cx, hir::Mutability::Mut, parent_ty, ty),
- Self::No => matches_none(cx, parent_ty, ty),
- }
- }
-
- #[must_use]
- fn description(self) -> &'static str {
- match self {
- Self::Value => "`self` by value",
- Self::Ref => "`self` by reference",
- Self::RefMut => "`self` by mutable reference",
- Self::No => "no `self`",
- }
- }
-}
-
-#[derive(Clone, Copy)]
-enum OutType {
- Unit,
- Bool,
- Any,
- Ref,
-}
-
-impl OutType {
- fn matches(self, ty: &hir::FnRetTy<'_>) -> bool {
- let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[]));
- match (self, ty) {
- (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true,
- (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true,
- (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true,
- (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true,
- (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)),
- _ => false,
- }
- }
-}
-
-fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
- expected.constness == actual.constness && expected.safety == actual.safety && expected.asyncness == actual.asyncness
-}
diff --git a/clippy_lints/src/methods/should_implement_trait.rs b/clippy_lints/src/methods/should_implement_trait.rs
new file mode 100644
index 0000000..5f13b8c
--- /dev/null
+++ b/clippy_lints/src/methods/should_implement_trait.rs
@@ -0,0 +1,171 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{is_bool, sym};
+use rustc_abi::ExternAbi;
+use rustc_hir as hir;
+use rustc_hir::{FnSig, ImplItem};
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+use rustc_span::edition::Edition::{self, Edition2015, Edition2021};
+use rustc_span::{Symbol, kw};
+
+use super::SHOULD_IMPLEMENT_TRAIT;
+use super::lib::SelfKind;
+
+pub(super) fn check_impl_item<'tcx>(
+ cx: &LateContext<'tcx>,
+ impl_item: &'tcx ImplItem<'_>,
+ self_ty: Ty<'tcx>,
+ impl_implements_trait: bool,
+ first_arg_ty_opt: Option<Ty<'tcx>>,
+ sig: &FnSig<'_>,
+) {
+ // if this impl block implements a trait, lint in trait definition instead
+ if !impl_implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
+ // check missing trait implementations
+ for method_config in &TRAIT_METHODS {
+ if impl_item.ident.name == method_config.method_name
+ && sig.decl.inputs.len() == method_config.param_count
+ && method_config.output_type.matches(&sig.decl.output)
+ // in case there is no first arg, since we already have checked the number of arguments
+ // it's should be always true
+ && first_arg_ty_opt
+ .is_none_or(|first_arg_ty| method_config.self_kind.matches(cx, self_ty, first_arg_ty))
+ && fn_header_equals(method_config.fn_header, sig.header)
+ && method_config.lifetime_param_cond(impl_item)
+ && method_config.in_prelude_since <= cx.tcx.sess.edition()
+ {
+ span_lint_and_help(
+ cx,
+ SHOULD_IMPLEMENT_TRAIT,
+ impl_item.span,
+ format!(
+ "method `{}` can be confused for the standard trait method `{}::{}`",
+ method_config.method_name, method_config.trait_name, method_config.method_name
+ ),
+ None,
+ format!(
+ "consider implementing the trait `{}` or choosing a less ambiguous method name",
+ method_config.trait_name
+ ),
+ );
+ }
+ }
+ }
+}
+
+const FN_HEADER: hir::FnHeader = hir::FnHeader {
+ safety: hir::HeaderSafety::Normal(hir::Safety::Safe),
+ constness: hir::Constness::NotConst,
+ asyncness: hir::IsAsync::NotAsync,
+ abi: ExternAbi::Rust,
+};
+
+struct ShouldImplTraitCase {
+ trait_name: &'static str,
+ method_name: Symbol,
+ param_count: usize,
+ fn_header: hir::FnHeader,
+ // implicit self kind expected (none, self, &self, ...)
+ self_kind: SelfKind,
+ // checks against the output type
+ output_type: OutType,
+ // certain methods with explicit lifetimes can't implement the equivalent trait method
+ lint_explicit_lifetime: bool,
+ in_prelude_since: Edition,
+}
+impl ShouldImplTraitCase {
+ #[expect(clippy::too_many_arguments)]
+ const fn new(
+ trait_name: &'static str,
+ method_name: Symbol,
+ param_count: usize,
+ fn_header: hir::FnHeader,
+ self_kind: SelfKind,
+ output_type: OutType,
+ lint_explicit_lifetime: bool,
+ in_prelude_since: Edition,
+ ) -> ShouldImplTraitCase {
+ ShouldImplTraitCase {
+ trait_name,
+ method_name,
+ param_count,
+ fn_header,
+ self_kind,
+ output_type,
+ lint_explicit_lifetime,
+ in_prelude_since,
+ }
+ }
+
+ fn lifetime_param_cond(&self, impl_item: &ImplItem<'_>) -> bool {
+ self.lint_explicit_lifetime
+ || !impl_item.generics.params.iter().any(|p| {
+ matches!(
+ p.kind,
+ hir::GenericParamKind::Lifetime {
+ kind: hir::LifetimeParamKind::Explicit
+ }
+ )
+ })
+ }
+}
+
+#[rustfmt::skip]
+const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
+ ShouldImplTraitCase::new("std::ops::Add", sym::add, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::convert::AsMut", sym::as_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::convert::AsRef", sym::as_ref, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::BitAnd", sym::bitand, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::BitOr", sym::bitor, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::BitXor", sym::bitxor, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::borrow::Borrow", sym::borrow, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::borrow::BorrowMut", sym::borrow_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::clone::Clone", sym::clone, 1, FN_HEADER, SelfKind::Ref, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::cmp::Ord", sym::cmp, 2, FN_HEADER, SelfKind::Ref, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::default::Default", kw::Default, 0, FN_HEADER, SelfKind::No, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Deref", sym::deref, 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::DerefMut", sym::deref_mut, 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Div", sym::div, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Drop", sym::drop, 1, FN_HEADER, SelfKind::RefMut, OutType::Unit, true, Edition2015),
+ ShouldImplTraitCase::new("std::cmp::PartialEq", sym::eq, 2, FN_HEADER, SelfKind::Ref, OutType::Bool, true, Edition2015),
+ ShouldImplTraitCase::new("std::iter::FromIterator", sym::from_iter, 1, FN_HEADER, SelfKind::No, OutType::Any, true, Edition2021),
+ ShouldImplTraitCase::new("std::str::FromStr", sym::from_str, 1, FN_HEADER, SelfKind::No, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::hash::Hash", sym::hash, 2, FN_HEADER, SelfKind::Ref, OutType::Unit, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Index", sym::index, 2, FN_HEADER, SelfKind::Ref, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::IndexMut", sym::index_mut, 2, FN_HEADER, SelfKind::RefMut, OutType::Ref, true, Edition2015),
+ ShouldImplTraitCase::new("std::iter::IntoIterator", sym::into_iter, 1, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Mul", sym::mul, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Neg", sym::neg, 1, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::iter::Iterator", sym::next, 1, FN_HEADER, SelfKind::RefMut, OutType::Any, false, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Not", sym::not, 1, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Rem", sym::rem, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Shl", sym::shl, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Shr", sym::shr, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+ ShouldImplTraitCase::new("std::ops::Sub", sym::sub, 2, FN_HEADER, SelfKind::Value, OutType::Any, true, Edition2015),
+];
+
+#[derive(Clone, Copy)]
+enum OutType {
+ Unit,
+ Bool,
+ Any,
+ Ref,
+}
+
+impl OutType {
+ fn matches(self, ty: &hir::FnRetTy<'_>) -> bool {
+ let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[]));
+ match (self, ty) {
+ (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true,
+ (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true,
+ (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true,
+ (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true,
+ (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)),
+ _ => false,
+ }
+ }
+}
+
+fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
+ expected.constness == actual.constness && expected.safety == actual.safety && expected.asyncness == actual.asyncness
+}
diff --git a/clippy_lints/src/methods/wrong_self_convention.rs b/clippy_lints/src/methods/wrong_self_convention.rs
index ad9b3c3..74b297c 100644
--- a/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/clippy_lints/src/methods/wrong_self_convention.rs
@@ -1,12 +1,13 @@
-use crate::methods::SelfKind;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::is_copy;
+use itertools::Itertools;
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
use std::fmt;
use super::WRONG_SELF_CONVENTION;
+use super::lib::SelfKind;
#[rustfmt::skip]
const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [
@@ -61,20 +62,20 @@
impl fmt::Display for Convention {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
- Self::Eq(this) => format!("`{this}`").fmt(f),
- Self::StartsWith(this) => format!("`{this}*`").fmt(f),
- Self::EndsWith(this) => format!("`*{this}`").fmt(f),
- Self::NotEndsWith(this) => format!("`~{this}`").fmt(f),
+ Self::Eq(this) => write!(f, "`{this}`"),
+ Self::StartsWith(this) => write!(f, "`{this}*`"),
+ Self::EndsWith(this) => write!(f, "`*{this}`"),
+ Self::NotEndsWith(this) => write!(f, "`~{this}`"),
Self::IsSelfTypeCopy(is_true) => {
- format!("`self` type is{} `Copy`", if is_true { "" } else { " not" }).fmt(f)
+ write!(f, "`self` type is{} `Copy`", if is_true { "" } else { " not" })
},
Self::ImplementsTrait(is_true) => {
let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") };
- format!("method{negation} implement{s_suffix} a trait").fmt(f)
+ write!(f, "method{negation} implement{s_suffix} a trait")
},
Self::IsTraitItem(is_true) => {
let suffix = if is_true { " is" } else { " is not" };
- format!("method{suffix} a trait item").fmt(f)
+ write!(f, "method{suffix} a trait item")
},
}
}
@@ -115,18 +116,9 @@
let s = conventions
.iter()
- .filter_map(|conv| {
- if (cut_ends_with_conv && matches!(conv, Convention::NotEndsWith(_)))
- || matches!(conv, Convention::ImplementsTrait(_))
- || matches!(conv, Convention::IsTraitItem(_))
- {
- None
- } else {
- Some(conv.to_string())
- }
- })
- .collect::<Vec<_>>()
- .join(" and ");
+ .filter(|conv| !(cut_ends_with_conv && matches!(conv, Convention::NotEndsWith(_))))
+ .filter(|conv| !matches!(conv, Convention::ImplementsTrait(_) | Convention::IsTraitItem(_)))
+ .format(" and ");
format!("methods with the following characteristics: ({s})")
} else {
@@ -140,11 +132,7 @@
first_arg_span,
format!(
"{suggestion} usually take {}",
- &self_kinds
- .iter()
- .map(|k| k.description())
- .collect::<Vec<_>>()
- .join(" or ")
+ self_kinds.iter().map(|k| k.description()).format(" or ")
),
None,
"consider choosing a less ambiguous name",
diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs
index d98c70e..588afd8 100644
--- a/clippy_lints/src/mut_mut.rs
+++ b/clippy_lints/src/mut_mut.rs
@@ -1,31 +1,51 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_hir};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::higher;
-use rustc_hir::{self as hir, AmbigArg, intravisit};
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir::{self as hir, AmbigArg, BorrowKind, Expr, ExprKind, HirId, Mutability, TyKind, intravisit};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for instances of `mut mut` references.
///
/// ### Why is this bad?
- /// Multiple `mut`s don't add anything meaningful to the
- /// source. This is either a copy'n'paste error, or it shows a fundamental
- /// misunderstanding of references.
+ /// This is usually just a typo or a misunderstanding of how references work.
///
/// ### Example
/// ```no_run
- /// # let mut y = 1;
- /// let x = &mut &mut y;
+ /// let x = &mut &mut 1;
+ ///
+ /// let mut x = &mut 1;
+ /// let y = &mut x;
+ ///
+ /// fn foo(x: &mut &mut u32) {}
+ /// ```
+ /// Use instead
+ /// ```no_run
+ /// let x = &mut 1;
+ ///
+ /// let mut x = &mut 1;
+ /// let y = &mut *x; // reborrow
+ ///
+ /// fn foo(x: &mut u32) {}
/// ```
#[clippy::version = "pre 1.29.0"]
pub MUT_MUT,
pedantic,
- "usage of double-mut refs, e.g., `&mut &mut ...`"
+ "usage of double mut-refs, e.g., `&mut &mut ...`"
}
-declare_lint_pass!(MutMut => [MUT_MUT]);
+impl_lint_pass!(MutMut => [MUT_MUT]);
+
+#[derive(Default)]
+pub(crate) struct MutMut {
+ seen_tys: FxHashSet<HirId>,
+}
impl<'tcx> LateLintPass<'tcx> for MutMut {
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
@@ -33,17 +53,48 @@
}
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_, AmbigArg>) {
- if let hir::TyKind::Ref(_, mty) = ty.kind
- && mty.mutbl == hir::Mutability::Mut
- && let hir::TyKind::Ref(_, mty) = mty.ty.kind
- && mty.mutbl == hir::Mutability::Mut
+ if let TyKind::Ref(_, mty) = ty.kind
+ && mty.mutbl == Mutability::Mut
+ && let TyKind::Ref(_, mty2) = mty.ty.kind
+ && mty2.mutbl == Mutability::Mut
&& !ty.span.in_external_macro(cx.sess().source_map())
{
- span_lint(
+ if self.seen_tys.contains(&ty.hir_id) {
+ // we have 2+ `&mut`s, e.g., `&mut &mut &mut x`
+ // and we have already flagged on the outermost `&mut &mut (&mut x)`,
+ // so don't flag the inner `&mut &mut (x)`
+ return;
+ }
+
+ // if there is an even longer chain, like `&mut &mut &mut x`, suggest peeling off
+ // all extra ones at once
+ let (mut t, mut t2) = (mty.ty, mty2.ty);
+ let mut many_muts = false;
+ loop {
+ // this should allow us to remember all the nested types, so that the `contains`
+ // above fails faster
+ self.seen_tys.insert(t.hir_id);
+ if let TyKind::Ref(_, next) = t2.kind
+ && next.mutbl == Mutability::Mut
+ {
+ (t, t2) = (t2, next.ty);
+ many_muts = true;
+ } else {
+ break;
+ }
+ }
+
+ let mut applicability = Applicability::MaybeIncorrect;
+ let sugg = snippet_with_applicability(cx.sess(), t.span, "..", &mut applicability);
+ let suffix = if many_muts { "s" } else { "" };
+ span_lint_and_sugg(
cx,
MUT_MUT,
ty.span,
- "generally you want to avoid `&mut &mut _` if possible",
+ "a type of form `&mut &mut _`",
+ format!("remove the extra `&mut`{suffix}"),
+ sugg.to_string(),
+ applicability,
);
}
}
@@ -54,7 +105,7 @@
}
impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if expr.span.in_external_macro(self.cx.sess().source_map()) {
return;
}
@@ -68,24 +119,60 @@
// Let's ignore the generated code.
intravisit::walk_expr(self, arg);
intravisit::walk_expr(self, body);
- } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e) = expr.kind {
- if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) = e.kind {
- span_lint_hir(
+ } else if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e) = expr.kind {
+ if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e2) = e.kind {
+ if !expr.span.eq_ctxt(e.span) {
+ return;
+ }
+
+ // if there is an even longer chain, like `&mut &mut &mut x`, suggest peeling off
+ // all extra ones at once
+ let (mut e, mut e2) = (e, e2);
+ let mut many_muts = false;
+ loop {
+ if !e.span.eq_ctxt(e2.span) {
+ return;
+ }
+ if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, next) = e2.kind {
+ (e, e2) = (e2, next);
+ many_muts = true;
+ } else {
+ break;
+ }
+ }
+
+ let mut applicability = Applicability::MaybeIncorrect;
+ let sugg = Sugg::hir_with_applicability(self.cx, e, "..", &mut applicability);
+ let suffix = if many_muts { "s" } else { "" };
+ span_lint_hir_and_then(
self.cx,
MUT_MUT,
expr.hir_id,
expr.span,
- "generally you want to avoid `&mut &mut _` if possible",
+ "an expression of form `&mut &mut _`",
+ |diag| {
+ diag.span_suggestion(
+ expr.span,
+ format!("remove the extra `&mut`{suffix}"),
+ sugg,
+ applicability,
+ );
+ },
);
- } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind()
+ } else if let ty::Ref(_, ty, Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind()
&& ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env())
{
- span_lint_hir(
+ let mut applicability = Applicability::MaybeIncorrect;
+ let sugg = Sugg::hir_with_applicability(self.cx, e, "..", &mut applicability).mut_addr_deref();
+ span_lint_hir_and_then(
self.cx,
MUT_MUT,
expr.hir_id,
expr.span,
- "this expression mutably borrows a mutable reference. Consider reborrowing",
+ "this expression mutably borrows a mutable reference",
+ |diag| {
+ diag.span_suggestion(expr.span, "reborrow instead", sugg, applicability);
+ },
);
}
}
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index b598a39..6fc034b 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::return_ty;
-use clippy_utils::source::snippet;
+use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::DiagExt;
use rustc_errors::Applicability;
use rustc_hir as hir;
@@ -58,116 +58,132 @@
impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- if let hir::ItemKind::Impl(hir::Impl {
+ let hir::ItemKind::Impl(hir::Impl {
of_trait: None,
generics,
self_ty: impl_self_ty,
..
}) = item.kind
+ else {
+ return;
+ };
+
+ for assoc_item in cx
+ .tcx
+ .associated_items(item.owner_id.def_id)
+ .filter_by_name_unhygienic(sym::new)
{
- for assoc_item in cx
- .tcx
- .associated_items(item.owner_id.def_id)
- .filter_by_name_unhygienic(sym::new)
+ if let AssocKind::Fn { has_self: false, .. } = assoc_item.kind
+ && let assoc_item_hir_id = cx.tcx.local_def_id_to_hir_id(assoc_item.def_id.expect_local())
+ && let impl_item = cx.tcx.hir_node(assoc_item_hir_id).expect_impl_item()
+ && !impl_item.span.in_external_macro(cx.sess().source_map())
+ && let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind
+ && let id = impl_item.owner_id
+ // can't be implemented for unsafe new
+ && !sig.header.is_unsafe()
+ // shouldn't be implemented when it is hidden in docs
+ && !cx.tcx.is_doc_hidden(impl_item.owner_id.def_id)
+ // when the result of `new()` depends on a parameter we should not require
+ // an impl of `Default`
+ && impl_item.generics.params.is_empty()
+ && sig.decl.inputs.is_empty()
+ && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id)
+ && let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
+ && self_ty == return_ty(cx, impl_item.owner_id)
+ && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
{
- if let AssocKind::Fn { has_self: false, .. } = assoc_item.kind {
- let impl_item = cx
- .tcx
- .hir_node_by_def_id(assoc_item.def_id.expect_local())
- .expect_impl_item();
- if impl_item.span.in_external_macro(cx.sess().source_map()) {
- return;
- }
- if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind {
- let id = impl_item.owner_id;
- if sig.header.is_unsafe() {
- // can't be implemented for unsafe new
- return;
- }
- if cx.tcx.is_doc_hidden(impl_item.owner_id.def_id) {
- // shouldn't be implemented when it is hidden in docs
- return;
- }
- if !impl_item.generics.params.is_empty() {
- // when the result of `new()` depends on a parameter we should not require
- // an impl of `Default`
- return;
- }
- if sig.decl.inputs.is_empty()
- && cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id)
- && let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
- && self_ty == return_ty(cx, impl_item.owner_id)
- && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+ if self.impling_types.is_none() {
+ let mut impls = HirIdSet::default();
+ for &d in cx.tcx.local_trait_impls(default_trait_id) {
+ let ty = cx.tcx.type_of(d).instantiate_identity();
+ if let Some(ty_def) = ty.ty_adt_def()
+ && let Some(local_def_id) = ty_def.did().as_local()
{
- if self.impling_types.is_none() {
- let mut impls = HirIdSet::default();
- for &d in cx.tcx.local_trait_impls(default_trait_id) {
- let ty = cx.tcx.type_of(d).instantiate_identity();
- if let Some(ty_def) = ty.ty_adt_def()
- && let Some(local_def_id) = ty_def.did().as_local()
- {
- impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
- }
- }
- self.impling_types = Some(impls);
- }
-
- // Check if a Default implementation exists for the Self type, regardless of
- // generics
- if let Some(ref impling_types) = self.impling_types
- && let self_def = cx.tcx.type_of(item.owner_id).instantiate_identity()
- && let Some(self_def) = self_def.ty_adt_def()
- && let Some(self_local_did) = self_def.did().as_local()
- && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did)
- && impling_types.contains(&self_id)
- {
- return;
- }
-
- let generics_sugg = snippet(cx, generics.span, "");
- let where_clause_sugg = if generics.has_where_clause_predicates {
- format!("\n{}\n", snippet(cx, generics.where_clause_span, ""))
- } else {
- String::new()
- };
- let self_ty_fmt = self_ty.to_string();
- let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt);
- span_lint_hir_and_then(
- cx,
- NEW_WITHOUT_DEFAULT,
- id.into(),
- impl_item.span,
- format!("you should consider adding a `Default` implementation for `{self_type_snip}`"),
- |diag| {
- diag.suggest_prepend_item(
- cx,
- item.span,
- "try adding this",
- &create_new_without_default_suggest_msg(
- &self_type_snip,
- &generics_sugg,
- &where_clause_sugg,
- ),
- Applicability::MachineApplicable,
- );
- },
- );
+ impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
}
}
+ self.impling_types = Some(impls);
}
+
+ // Check if a Default implementation exists for the Self type, regardless of
+ // generics
+ if let Some(ref impling_types) = self.impling_types
+ && let self_def = cx.tcx.type_of(item.owner_id).instantiate_identity()
+ && let Some(self_def) = self_def.ty_adt_def()
+ && let Some(self_local_did) = self_def.did().as_local()
+ && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did)
+ && impling_types.contains(&self_id)
+ {
+ return;
+ }
+
+ let mut app = Applicability::MachineApplicable;
+ let attrs_sugg = {
+ let mut sugg = String::new();
+ for attr in cx.tcx.hir_attrs(assoc_item_hir_id) {
+ if !attr.has_name(sym::cfg_trace) {
+ // This might be some other attribute that the `impl Default` ought to inherit.
+ // But it could also be one of the many attributes that:
+ // - can't be put on an impl block -- like `#[inline]`
+ // - we can't even build a suggestion for, since `Attribute::span` may panic.
+ //
+ // Because of all that, remain on the safer side -- don't inherit this attr, and just
+ // reduce the applicability
+ app = Applicability::MaybeIncorrect;
+ continue;
+ }
+
+ sugg.push_str(&snippet_with_applicability(cx.sess(), attr.span(), "_", &mut app));
+ sugg.push('\n');
+ }
+ sugg
+ };
+ let generics_sugg = snippet_with_applicability(cx, generics.span, "", &mut app);
+ let where_clause_sugg = if generics.has_where_clause_predicates {
+ format!(
+ "\n{}\n",
+ snippet_with_applicability(cx, generics.where_clause_span, "", &mut app)
+ )
+ } else {
+ String::new()
+ };
+ let self_ty_fmt = self_ty.to_string();
+ let self_type_snip = snippet_with_applicability(cx, impl_self_ty.span, &self_ty_fmt, &mut app);
+ span_lint_hir_and_then(
+ cx,
+ NEW_WITHOUT_DEFAULT,
+ id.into(),
+ impl_item.span,
+ format!("you should consider adding a `Default` implementation for `{self_type_snip}`"),
+ |diag| {
+ diag.suggest_prepend_item(
+ cx,
+ item.span,
+ "try adding this",
+ &create_new_without_default_suggest_msg(
+ &attrs_sugg,
+ &self_type_snip,
+ &generics_sugg,
+ &where_clause_sugg,
+ ),
+ app,
+ );
+ },
+ );
}
}
}
}
fn create_new_without_default_suggest_msg(
+ attrs_sugg: &str,
self_type_snip: &str,
generics_sugg: &str,
where_clause_sugg: &str,
) -> String {
#[rustfmt::skip]
format!(
-"impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
+"{attrs_sugg}impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
fn default() -> Self {{
Self::new()
}}
diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs
index d5b6c17..424aa14 100644
--- a/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/clippy_lints/src/unit_types/let_unit_value.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
-use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_context};
+use clippy_utils::source::{snippet_indent, walk_span_to_context};
use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source};
use core::ops::ControlFlow;
use rustc_ast::{FormatArgs, FormatArgumentKind};
@@ -74,10 +74,10 @@
"this let-binding has unit value",
|diag| {
let mut suggestions = Vec::new();
+ let init_new_span = walk_span_to_context(init.span, local.span.ctxt()).unwrap();
// Suggest omitting the `let` binding
- let mut app = Applicability::MachineApplicable;
- let snip = snippet_with_context(cx, init.span, local.span.ctxt(), "()", &mut app).0;
+ let app = Applicability::MachineApplicable;
// If this is a binding pattern, we need to add suggestions to remove any usages
// of the variable
@@ -89,35 +89,48 @@
walk_body(&mut visitor, body);
let mut has_in_format_capture = false;
- suggestions.extend(visitor.spans.iter().filter_map(|span| match span {
+ suggestions.extend(visitor.spans.into_iter().filter_map(|span| match span {
MaybeInFormatCapture::Yes => {
has_in_format_capture = true;
None
},
- MaybeInFormatCapture::No(span) => Some((*span, "()".to_string())),
+ MaybeInFormatCapture::No(span) => Some((span, "()".to_string())),
}));
if has_in_format_capture {
+ // In a case like this:
+ // ```
+ // let unit = returns_unit();
+ // eprintln!("{unit}");
+ // ```
+ // we can't remove the `unit` binding and replace its uses with a `()`,
+ // because the `eprintln!` would break.
+ //
+ // So do the following instead:
+ // ```
+ // let unit = ();
+ // returns_unit();
+ // eprintln!("{unit}");
+ // ```
+ // TODO: find a less awkward way to do this
suggestions.push((
- init.span,
- format!("();\n{}", reindent_multiline(&snip, false, indent_of(cx, local.span))),
+ init_new_span.shrink_to_lo(),
+ format!("();\n{}", snippet_indent(cx, local.span).as_deref().unwrap_or("")),
));
- diag.multipart_suggestion(
- "replace variable usages with `()`",
- suggestions,
- Applicability::MachineApplicable,
- );
+ diag.multipart_suggestion_verbose("replace variable usages with `()`", suggestions, app);
return;
}
}
- suggestions.push((local.span, format!("{snip};")));
+ // let local = returns_unit();
+ // ^^^^^^^^^^^^ remove this
+ suggestions.push((local.span.until(init_new_span), String::new()));
let message = if suggestions.len() == 1 {
"omit the `let` binding"
} else {
"omit the `let` binding and replace variable usages with `()`"
};
- diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
+ diag.multipart_suggestion_verbose(message, suggestions, app);
},
);
}
@@ -132,6 +145,12 @@
macro_call: Option<&'a FormatArgs>,
}
+/// Whether the unit variable is captured in a `format!`:
+///
+/// ```ignore
+/// let unit = ();
+/// eprintln!("{unit}");
+/// ```
enum MaybeInFormatCapture {
Yes,
No(Span),
diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
index ecb43dc..b28e46a 100644
--- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
+++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
@@ -1,5 +1,3 @@
-#![allow(clippy::uninlined_format_args)]
-
fn main() {}
#[warn(clippy::cognitive_complexity)]
@@ -8,7 +6,7 @@
let x = vec![1, 2, 3];
for i in x {
if i == 1 {
- println!("{}", i);
+ println!("{i}");
}
}
}
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 627498d..95b0508 100644
--- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
+++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
@@ -11,7 +11,7 @@
| ^^^^^^^^^^^^^^^^^
error: the function has a cognitive complexity of (3/2)
- --> tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs:6:4
+ --> tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs:4:4
|
LL | fn cognitive_complexity() {
| ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
index 2877871..36540bf 100644
--- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
+++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
@@ -1,4 +1,3 @@
-#![allow(clippy::uninlined_format_args)]
#![deny(clippy::index_refutable_slice)]
fn below_limit() {
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 f958b92..da76bb2 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
@@ -1,4 +1,3 @@
-#![allow(clippy::uninlined_format_args)]
#![deny(clippy::index_refutable_slice)]
fn below_limit() {
diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
index e1a8941..022deb3 100644
--- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
+++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
@@ -1,11 +1,11 @@
error: this binding can be a slice pattern to avoid indexing
- --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:6:17
+ --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:5:17
|
LL | if let Some(slice) = slice {
| ^^^^^
|
note: the lint level is defined here
- --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:2:9
+ --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:1:9
|
LL | #![deny(clippy::index_refutable_slice)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/bind_instead_of_map.fixed b/tests/ui/bind_instead_of_map.fixed
index 80e010e2..fa35a01 100644
--- a/tests/ui/bind_instead_of_map.fixed
+++ b/tests/ui/bind_instead_of_map.fixed
@@ -1,5 +1,4 @@
#![deny(clippy::bind_instead_of_map)]
-#![allow(clippy::uninlined_format_args)]
// need a main anyway, use it get rid of unused warnings too
pub fn main() {
diff --git a/tests/ui/bind_instead_of_map.rs b/tests/ui/bind_instead_of_map.rs
index 09aa848..403077e 100644
--- a/tests/ui/bind_instead_of_map.rs
+++ b/tests/ui/bind_instead_of_map.rs
@@ -1,5 +1,4 @@
#![deny(clippy::bind_instead_of_map)]
-#![allow(clippy::uninlined_format_args)]
// need a main anyway, use it get rid of unused warnings too
pub fn main() {
diff --git a/tests/ui/bind_instead_of_map.stderr b/tests/ui/bind_instead_of_map.stderr
index 08f85fb..3f8d631 100644
--- a/tests/ui/bind_instead_of_map.stderr
+++ b/tests/ui/bind_instead_of_map.stderr
@@ -1,5 +1,5 @@
error: using `Option.and_then(Some)`, which is a no-op
- --> tests/ui/bind_instead_of_map.rs:8:13
+ --> tests/ui/bind_instead_of_map.rs:7:13
|
LL | let _ = x.and_then(Some);
| ^^^^^^^^^^^^^^^^ help: use the expression directly: `x`
@@ -11,13 +11,13 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
- --> tests/ui/bind_instead_of_map.rs:10:13
+ --> tests/ui/bind_instead_of_map.rs:9:13
|
LL | let _ = x.and_then(|o| Some(o + 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map(|o| o + 1)`
error: using `Result.and_then(Ok)`, which is a no-op
- --> tests/ui/bind_instead_of_map.rs:17:13
+ --> tests/ui/bind_instead_of_map.rs:16:13
|
LL | let _ = x.and_then(Ok);
| ^^^^^^^^^^^^^^ help: use the expression directly: `x`
diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
index e848f06..1646b57 100644
--- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
+++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
@@ -1,6 +1,5 @@
#![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
#![allow(dead_code)]
-#![allow(clippy::uninlined_format_args)]
//@no-rustfix
// branches_sharing_code at the top and bottom of the if blocks
@@ -70,7 +69,7 @@
let b = 0xffff00ff;
let e_id = gen_id(a, b);
- println!("From the a `{}` to the b `{}`", a, b);
+ println!("From the a `{a}` to the b `{b}`");
let pack = DataPack {
id: e_id,
@@ -83,7 +82,7 @@
let b = 0xffff00ff;
let e_id = gen_id(a, b);
- println!("The new ID is '{}'", e_id);
+ println!("The new ID is '{e_id}'");
let pack = DataPack {
id: e_id,
diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
index 40f3453..f5c51f7 100644
--- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
+++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
@@ -1,5 +1,5 @@
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:17:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:16:5
|
LL | / if x == 7 {
LL | |
@@ -10,7 +10,7 @@
| |_________________________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:31:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:30:5
|
LL | / let _u = 9;
LL | | }
@@ -34,7 +34,7 @@
|
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:35:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:34:5
|
LL | / if x == 99 {
LL | |
@@ -45,7 +45,7 @@
| |____________________________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:48:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:47:5
|
LL | / let _overlap_end = r * r * r;
LL | | let z = "end";
@@ -67,7 +67,7 @@
|
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:66:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:65:5
|
LL | / if (x > 7 && y < 13) || (x + y) % 2 == 1 {
LL | |
@@ -78,7 +78,7 @@
| |________________________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:88:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:87:5
|
LL | / let pack = DataPack {
LL | | id: e_id,
@@ -108,7 +108,7 @@
|
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:101:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:100:5
|
LL | / let _ = if x == 7 {
... |
@@ -116,7 +116,7 @@
| |___________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:112:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:111:5
|
LL | / x << 2
LL | | };
@@ -134,7 +134,7 @@
|
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:115:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:114:5
|
LL | / if x == 9 {
... |
@@ -142,7 +142,7 @@
| |___________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:126:5
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:125:5
|
LL | / x * 4
LL | | }
@@ -160,7 +160,7 @@
|
error: all if blocks contain the same code at both the start and the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:158:9
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:157:9
|
LL | / if false {
LL | |
@@ -168,7 +168,7 @@
| |______________________^
|
note: this code is shared at the end
- --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:166:9
+ --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:165:9
|
LL | / let y = 1;
LL | | }
diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed
index b55c22f..44cb66a 100644
--- a/tests/ui/cast_abs_to_unsigned.fixed
+++ b/tests/ui/cast_abs_to_unsigned.fixed
@@ -1,11 +1,11 @@
#![warn(clippy::cast_abs_to_unsigned)]
-#![allow(clippy::uninlined_format_args, unused)]
+#![allow(unused)]
fn main() {
let x: i32 = -42;
let y: u32 = x.unsigned_abs();
//~^ cast_abs_to_unsigned
- println!("The absolute value of {} is {}", x, y);
+ println!("The absolute value of {x} is {y}");
let a: i32 = -3;
let _: usize = a.unsigned_abs() as usize;
diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs
index 466aa6a..555b909 100644
--- a/tests/ui/cast_abs_to_unsigned.rs
+++ b/tests/ui/cast_abs_to_unsigned.rs
@@ -1,11 +1,11 @@
#![warn(clippy::cast_abs_to_unsigned)]
-#![allow(clippy::uninlined_format_args, unused)]
+#![allow(unused)]
fn main() {
let x: i32 = -42;
let y: u32 = x.abs() as u32;
//~^ cast_abs_to_unsigned
- println!("The absolute value of {} is {}", x, y);
+ println!("The absolute value of {x} is {y}");
let a: i32 = -3;
let _: usize = a.abs() as usize;
diff --git a/tests/ui/crashes/ice-4775.rs b/tests/ui/crashes/ice-4775.rs
index dd6c6b8..e8c47b4 100644
--- a/tests/ui/crashes/ice-4775.rs
+++ b/tests/ui/crashes/ice-4775.rs
@@ -7,7 +7,7 @@
impl<const N: usize> ArrayWrapper<{ N }> {
pub fn ice(&self) {
for i in self.0.iter() {
- println!("{}", i);
+ println!("{i}");
}
}
}
diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed
index d3fe09a..e3bf603 100644
--- a/tests/ui/default_trait_access.fixed
+++ b/tests/ui/default_trait_access.fixed
@@ -1,7 +1,6 @@
//@aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
-#![allow(clippy::uninlined_format_args)]
extern crate proc_macros;
@@ -63,6 +62,7 @@
let _s21: String = with_span!(s Default::default());
+ #[expect(clippy::uninlined_format_args)]
println!(
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]",
s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20,
diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs
index cdffb2a..8cc065e 100644
--- a/tests/ui/default_trait_access.rs
+++ b/tests/ui/default_trait_access.rs
@@ -1,7 +1,6 @@
//@aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
-#![allow(clippy::uninlined_format_args)]
extern crate proc_macros;
@@ -63,6 +62,7 @@
let _s21: String = with_span!(s Default::default());
+ #[expect(clippy::uninlined_format_args)]
println!(
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]",
s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20,
diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr
index aa7eb4f..aa89516 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
- --> tests/ui/default_trait_access.rs:13:22
+ --> tests/ui/default_trait_access.rs:12:22
|
LL | let s1: String = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
@@ -11,43 +11,43 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: calling `String::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:18:22
+ --> tests/ui/default_trait_access.rs:17:22
|
LL | let s3: String = D2::default();
| ^^^^^^^^^^^^^ help: try: `String::default()`
error: calling `String::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:21:22
+ --> tests/ui/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
- --> tests/ui/default_trait_access.rs:26:22
+ --> tests/ui/default_trait_access.rs:25:22
|
LL | let s6: String = default::Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
error: calling `GenericDerivedDefault::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:37:46
+ --> tests/ui/default_trait_access.rs:36:46
|
LL | let s11: GenericDerivedDefault<String> = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()`
error: calling `TupleDerivedDefault::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:44:36
+ --> tests/ui/default_trait_access.rs:43:36
|
LL | let s14: TupleDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()`
error: calling `ArrayDerivedDefault::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:47:36
+ --> tests/ui/default_trait_access.rs:46:36
|
LL | let s15: ArrayDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()`
error: calling `TupleStructDerivedDefault::default()` is more clear than this expression
- --> tests/ui/default_trait_access.rs:52:42
+ --> tests/ui/default_trait_access.rs:51:42
|
LL | let s17: TupleStructDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()`
diff --git a/tests/ui/double_parens.fixed b/tests/ui/double_parens.fixed
new file mode 100644
index 0000000..dedc513
--- /dev/null
+++ b/tests/ui/double_parens.fixed
@@ -0,0 +1,99 @@
+#![warn(clippy::double_parens)]
+#![expect(clippy::eq_op, clippy::no_effect)]
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
+
+fn dummy_fn<T>(_: T) {}
+
+struct DummyStruct;
+
+impl DummyStruct {
+ fn dummy_method<T>(&self, _: T) {}
+}
+
+fn simple_double_parens() -> i32 {
+ (0)
+ //~^ double_parens
+}
+
+fn fn_double_parens() {
+ dummy_fn(0);
+ //~^ double_parens
+}
+
+fn method_double_parens(x: DummyStruct) {
+ x.dummy_method(0);
+ //~^ double_parens
+}
+
+fn tuple_double_parens() -> (i32, i32) {
+ (1, 2)
+ //~^ double_parens
+}
+
+#[allow(clippy::unused_unit)]
+fn unit_double_parens() {
+ ()
+ //~^ double_parens
+}
+
+fn fn_tuple_ok() {
+ dummy_fn((1, 2));
+}
+
+fn method_tuple_ok(x: DummyStruct) {
+ x.dummy_method((1, 2));
+}
+
+fn fn_unit_ok() {
+ dummy_fn(());
+}
+
+fn method_unit_ok(x: DummyStruct) {
+ x.dummy_method(());
+}
+
+// Issue #3206
+fn inside_macro() {
+ assert_eq!((1, 2), (1, 2), "Error");
+ assert_eq!((1, 2), (1, 2), "Error");
+ //~^ double_parens
+}
+
+fn issue9000(x: DummyStruct) {
+ macro_rules! foo {
+ () => {(100)}
+ }
+ // don't lint: the inner paren comes from the macro expansion
+ (foo!());
+ dummy_fn(foo!());
+ x.dummy_method(foo!());
+
+ macro_rules! baz {
+ ($n:literal) => {($n)}
+ }
+ // don't lint: don't get confused by the expression inside the inner paren
+ // having the same `ctxt` as the overall expression
+ // (this is a bug that happened during the development of the fix)
+ (baz!(100));
+ dummy_fn(baz!(100));
+ x.dummy_method(baz!(100));
+
+ // should lint: both parens are from inside the macro
+ macro_rules! bar {
+ () => {(100)}
+ //~^ double_parens
+ }
+ bar!();
+
+ // should lint: both parens are from outside the macro;
+ // make sure to suggest the macro unexpanded
+ (vec![1, 2]);
+ //~^ double_parens
+ dummy_fn(vec![1, 2]);
+ //~^ double_parens
+ x.dummy_method(vec![1, 2]);
+ //~^ double_parens
+}
+
+fn main() {}
diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs
index 7c97601..27f2524 100644
--- a/tests/ui/double_parens.rs
+++ b/tests/ui/double_parens.rs
@@ -1,5 +1,5 @@
#![warn(clippy::double_parens)]
-#![allow(dead_code, clippy::eq_op)]
+#![expect(clippy::eq_op, clippy::no_effect)]
#![feature(custom_inner_attributes)]
#![rustfmt::skip]
@@ -8,38 +8,33 @@
struct DummyStruct;
impl DummyStruct {
- fn dummy_method<T>(self, _: T) {}
+ fn dummy_method<T>(&self, _: T) {}
}
fn simple_double_parens() -> i32 {
((0))
//~^ double_parens
-
-
}
fn fn_double_parens() {
dummy_fn((0));
//~^ double_parens
-
}
fn method_double_parens(x: DummyStruct) {
x.dummy_method((0));
//~^ double_parens
-
}
fn tuple_double_parens() -> (i32, i32) {
((1, 2))
//~^ double_parens
-
}
+#[allow(clippy::unused_unit)]
fn unit_double_parens() {
(())
//~^ double_parens
-
}
fn fn_tuple_ok() {
@@ -63,7 +58,42 @@
assert_eq!((1, 2), (1, 2), "Error");
assert_eq!(((1, 2)), (1, 2), "Error");
//~^ double_parens
+}
+fn issue9000(x: DummyStruct) {
+ macro_rules! foo {
+ () => {(100)}
+ }
+ // don't lint: the inner paren comes from the macro expansion
+ (foo!());
+ dummy_fn(foo!());
+ x.dummy_method(foo!());
+
+ macro_rules! baz {
+ ($n:literal) => {($n)}
+ }
+ // don't lint: don't get confused by the expression inside the inner paren
+ // having the same `ctxt` as the overall expression
+ // (this is a bug that happened during the development of the fix)
+ (baz!(100));
+ dummy_fn(baz!(100));
+ x.dummy_method(baz!(100));
+
+ // should lint: both parens are from inside the macro
+ macro_rules! bar {
+ () => {((100))}
+ //~^ double_parens
+ }
+ bar!();
+
+ // should lint: both parens are from outside the macro;
+ // make sure to suggest the macro unexpanded
+ ((vec![1, 2]));
+ //~^ double_parens
+ dummy_fn((vec![1, 2]));
+ //~^ double_parens
+ x.dummy_method((vec![1, 2]));
+ //~^ double_parens
}
fn main() {}
diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr
index e119f54..3a740e4 100644
--- a/tests/ui/double_parens.stderr
+++ b/tests/ui/double_parens.stderr
@@ -1,41 +1,70 @@
-error: consider removing unnecessary double parentheses
+error: unnecessary parentheses
--> tests/ui/double_parens.rs:15:5
|
LL | ((0))
- | ^^^^^
+ | ^^^^^ help: remove them: `(0)`
|
= note: `-D clippy::double-parens` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::double_parens)]`
-error: consider removing unnecessary double parentheses
- --> tests/ui/double_parens.rs:22:14
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:20:14
|
LL | dummy_fn((0));
- | ^^^
+ | ^^^ help: remove them: `0`
-error: consider removing unnecessary double parentheses
- --> tests/ui/double_parens.rs:28:20
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:25:20
|
LL | x.dummy_method((0));
- | ^^^
+ | ^^^ help: remove them: `0`
-error: consider removing unnecessary double parentheses
- --> tests/ui/double_parens.rs:34:5
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:30:5
|
LL | ((1, 2))
- | ^^^^^^^^
+ | ^^^^^^^^ help: remove them: `(1, 2)`
-error: consider removing unnecessary double parentheses
- --> tests/ui/double_parens.rs:40:5
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:36:5
|
LL | (())
- | ^^^^
+ | ^^^^ help: remove them: `()`
-error: consider removing unnecessary double parentheses
- --> tests/ui/double_parens.rs:64:16
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:59:16
|
LL | assert_eq!(((1, 2)), (1, 2), "Error");
- | ^^^^^^^^
+ | ^^^^^^^^ help: remove them: `(1, 2)`
-error: aborting due to 6 previous errors
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:84:16
+ |
+LL | () => {((100))}
+ | ^^^^^^^ help: remove them: `(100)`
+...
+LL | bar!();
+ | ------ in this macro invocation
+ |
+ = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:91:5
+ |
+LL | ((vec![1, 2]));
+ | ^^^^^^^^^^^^^^ help: remove them: `(vec![1, 2])`
+
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:93:14
+ |
+LL | dummy_fn((vec![1, 2]));
+ | ^^^^^^^^^^^^ help: remove them: `vec![1, 2]`
+
+error: unnecessary parentheses
+ --> tests/ui/double_parens.rs:95:20
+ |
+LL | x.dummy_method((vec![1, 2]));
+ | ^^^^^^^^^^^^ help: remove them: `vec![1, 2]`
+
+error: aborting due to 10 previous errors
diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs
index 1393478..ec4cecf 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, clippy::useless_vec)]
+#![allow(clippy::useless_vec)]
//@no-rustfix: suggestion does not remove the `+= 1`
fn main() {
let mut vec = vec![1, 2, 3, 4];
@@ -89,13 +89,13 @@
for _v in &vec {
index += 1
}
- println!("index: {}", index);
+ println!("index: {index}");
// should not trigger the lint because the count is conditional #1219
let text = "banana";
let mut count = 0;
for ch in text.chars() {
- println!("{}", count);
+ println!("{count}");
if ch == 'a' {
continue;
}
@@ -106,7 +106,7 @@
let text = "banana";
let mut count = 0;
for ch in text.chars() {
- println!("{}", count);
+ println!("{count}");
if ch == 'a' {
count += 1;
}
@@ -118,7 +118,7 @@
for ch in text.chars() {
//~^ explicit_counter_loop
- println!("{}", count);
+ println!("{count}");
count += 1;
if ch == 'a' {
continue;
@@ -131,7 +131,7 @@
for ch in text.chars() {
//~^ explicit_counter_loop
- println!("{}", count);
+ println!("{count}");
count += 1;
for i in 0..2 {
let _ = 123;
@@ -142,7 +142,7 @@
let text = "banana";
let mut count = 0;
for ch in text.chars() {
- println!("{}", count);
+ println!("{count}");
count += 1;
for i in 0..2 {
count += 1;
@@ -157,7 +157,7 @@
let mut skips = 0;
let erasures = vec![];
for i in 0..10 {
- println!("{}", skips);
+ println!("{skips}");
while erasures.contains(&(i + skips)) {
skips += 1;
}
@@ -166,7 +166,7 @@
// should not trigger the lint because the count is incremented multiple times
let mut skips = 0;
for i in 0..10 {
- println!("{}", skips);
+ println!("{skips}");
let mut j = 0;
while j < 5 {
skips += 1;
@@ -177,7 +177,7 @@
// should not trigger the lint because the count is incremented multiple times
let mut skips = 0;
for i in 0..10 {
- println!("{}", skips);
+ println!("{skips}");
for j in 0..5 {
skips += 1;
}
@@ -205,7 +205,7 @@
for _v in slice {
index += 1
}
- let _closure = || println!("index: {}", index);
+ let _closure = || println!("index: {index}");
}
}
@@ -217,7 +217,7 @@
let mut count = 0;
for _i in slice {
count += 1;
- println!("{}", count);
+ println!("{count}");
}
}
}
diff --git a/tests/ui/explicit_write.fixed b/tests/ui/explicit_write.fixed
index 024999f..ab28c1c 100644
--- a/tests/ui/explicit_write.fixed
+++ b/tests/ui/explicit_write.fixed
@@ -1,6 +1,5 @@
#![warn(clippy::explicit_write)]
#![allow(unused_imports)]
-#![allow(clippy::uninlined_format_args)]
fn stdout() -> String {
String::new()
@@ -40,7 +39,7 @@
//~^ explicit_write
let value = 1;
- eprintln!("with {}", value);
+ eprintln!("with {value}");
//~^ explicit_write
eprintln!("with {} {}", 2, value);
//~^ explicit_write
@@ -49,7 +48,7 @@
eprintln!("macro arg {}", one!());
//~^ explicit_write
let width = 2;
- eprintln!("{:w$}", value, w = width);
+ eprintln!("{value:w$}", w = width);
//~^ explicit_write
}
// these should not warn, different destination
diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs
index c83c760..975ee10 100644
--- a/tests/ui/explicit_write.rs
+++ b/tests/ui/explicit_write.rs
@@ -1,6 +1,5 @@
#![warn(clippy::explicit_write)]
#![allow(unused_imports)]
-#![allow(clippy::uninlined_format_args)]
fn stdout() -> String {
String::new()
@@ -40,7 +39,7 @@
//~^ explicit_write
let value = 1;
- writeln!(std::io::stderr(), "with {}", value).unwrap();
+ writeln!(std::io::stderr(), "with {value}").unwrap();
//~^ explicit_write
writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
//~^ explicit_write
@@ -49,7 +48,7 @@
writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
//~^ explicit_write
let width = 2;
- writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
+ writeln!(std::io::stderr(), "{value:w$}", w = width).unwrap();
//~^ explicit_write
}
// these should not warn, different destination
diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr
index 670a041..ef4b2a0 100644
--- a/tests/ui/explicit_write.stderr
+++ b/tests/ui/explicit_write.stderr
@@ -1,5 +1,5 @@
error: use of `write!(stdout(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:23:9
+ --> tests/ui/explicit_write.rs:22:9
|
LL | write!(std::io::stdout(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `print!("test")`
@@ -8,76 +8,76 @@
= help: to override `-D warnings` add `#[allow(clippy::explicit_write)]`
error: use of `write!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:25:9
+ --> tests/ui/explicit_write.rs:24:9
|
LL | write!(std::io::stderr(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")`
error: use of `writeln!(stdout(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:27:9
+ --> tests/ui/explicit_write.rs:26:9
|
LL | writeln!(std::io::stdout(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:29:9
+ --> tests/ui/explicit_write.rs:28:9
|
LL | writeln!(std::io::stderr(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test")`
error: use of `stdout().write_fmt(...).unwrap()`
- --> tests/ui/explicit_write.rs:31:9
+ --> tests/ui/explicit_write.rs:30:9
|
LL | std::io::stdout().write_fmt(format_args!("test")).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `print!("test")`
error: use of `stderr().write_fmt(...).unwrap()`
- --> tests/ui/explicit_write.rs:33:9
+ --> tests/ui/explicit_write.rs:32:9
|
LL | std::io::stderr().write_fmt(format_args!("test")).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")`
error: use of `writeln!(stdout(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:37:9
+ --> tests/ui/explicit_write.rs:36:9
|
LL | writeln!(std::io::stdout(), "test\ntest").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test\ntest")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:39:9
+ --> tests/ui/explicit_write.rs:38:9
|
LL | writeln!(std::io::stderr(), "test\ntest").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test\ntest")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:43:9
- |
-LL | writeln!(std::io::stderr(), "with {}", value).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {}", value)`
-
-error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:45:9
- |
-LL | writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {} {}", 2, value)`
-
-error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:47:9
+ --> tests/ui/explicit_write.rs:42:9
|
LL | writeln!(std::io::stderr(), "with {value}").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {value}")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:49:9
+ --> tests/ui/explicit_write.rs:44:9
+ |
+LL | writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {} {}", 2, value)`
+
+error: use of `writeln!(stderr(), ...).unwrap()`
+ --> tests/ui/explicit_write.rs:46:9
+ |
+LL | writeln!(std::io::stderr(), "with {value}").unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {value}")`
+
+error: use of `writeln!(stderr(), ...).unwrap()`
+ --> tests/ui/explicit_write.rs:48:9
|
LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("macro arg {}", one!())`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> tests/ui/explicit_write.rs:52:9
+ --> tests/ui/explicit_write.rs:51:9
|
-LL | writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("{:w$}", value, w = width)`
+LL | writeln!(std::io::stderr(), "{value:w$}", w = width).unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("{value:w$}", w = width)`
error: aborting due to 13 previous errors
diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs
index 1c62c1e..28bb115 100644
--- a/tests/ui/fallible_impl_from.rs
+++ b/tests/ui/fallible_impl_from.rs
@@ -1,5 +1,4 @@
#![deny(clippy::fallible_impl_from)]
-#![allow(clippy::uninlined_format_args)]
// docs example
struct Foo(i32);
@@ -62,7 +61,7 @@
fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
if s.parse::<u32>().ok().unwrap() != 42 {
- panic!("{:?}", s);
+ panic!("{s:?}");
}
Invalid
}
diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr
index 402494b..25ecc8b 100644
--- a/tests/ui/fallible_impl_from.stderr
+++ b/tests/ui/fallible_impl_from.stderr
@@ -1,5 +1,5 @@
error: consider implementing `TryFrom` instead
- --> tests/ui/fallible_impl_from.rs:6:1
+ --> tests/ui/fallible_impl_from.rs:5:1
|
LL | / impl From<String> for Foo {
LL | |
@@ -11,7 +11,7 @@
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> tests/ui/fallible_impl_from.rs:10:13
+ --> tests/ui/fallible_impl_from.rs:9:13
|
LL | Foo(s.parse().unwrap())
| ^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider implementing `TryFrom` instead
- --> tests/ui/fallible_impl_from.rs:29:1
+ --> tests/ui/fallible_impl_from.rs:28:1
|
LL | / impl From<usize> for Invalid {
LL | |
@@ -34,13 +34,13 @@
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> tests/ui/fallible_impl_from.rs:34:13
+ --> tests/ui/fallible_impl_from.rs:33:13
|
LL | panic!();
| ^^^^^^^^
error: consider implementing `TryFrom` instead
- --> tests/ui/fallible_impl_from.rs:40:1
+ --> tests/ui/fallible_impl_from.rs:39:1
|
LL | / impl From<Option<String>> for Invalid {
LL | |
@@ -52,7 +52,7 @@
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> tests/ui/fallible_impl_from.rs:44:17
+ --> tests/ui/fallible_impl_from.rs:43:17
|
LL | let s = s.unwrap();
| ^^^^^^^^^^
@@ -65,7 +65,7 @@
| ^^^^^^^^^^^^^^^^^
error: consider implementing `TryFrom` instead
- --> tests/ui/fallible_impl_from.rs:60:1
+ --> tests/ui/fallible_impl_from.rs:59:1
|
LL | / impl<'a> From<&'a mut <Box<u32> as ProjStrTrait>::ProjString> for Invalid {
LL | |
@@ -77,12 +77,12 @@
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> tests/ui/fallible_impl_from.rs:64:12
+ --> tests/ui/fallible_impl_from.rs:63:12
|
LL | if s.parse::<u32>().ok().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL | panic!("{:?}", s);
- | ^^^^^^^^^^^^^^^^^
+LL | panic!("{s:?}");
+ | ^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
diff --git a/tests/ui/if_then_some_else_none.fixed b/tests/ui/if_then_some_else_none.fixed
index 0fd1306..7da9401 100644
--- a/tests/ui/if_then_some_else_none.fixed
+++ b/tests/ui/if_then_some_else_none.fixed
@@ -206,3 +206,15 @@
}
let _: Option<u32> = mac!(true, 42);
}
+
+mod issue15770 {
+ fn maybe_error() -> Result<u32, &'static str> {
+ Err("error!")
+ }
+
+ pub fn trying(b: bool) -> Result<(), &'static str> {
+ let _x: Option<u32> = if b { Some(maybe_error()?) } else { None };
+ // Process _x locally
+ Ok(())
+ }
+}
diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs
index 640828a..02962f8 100644
--- a/tests/ui/if_then_some_else_none.rs
+++ b/tests/ui/if_then_some_else_none.rs
@@ -262,3 +262,15 @@
}
let _: Option<u32> = mac!(true, 42);
}
+
+mod issue15770 {
+ fn maybe_error() -> Result<u32, &'static str> {
+ Err("error!")
+ }
+
+ pub fn trying(b: bool) -> Result<(), &'static str> {
+ let _x: Option<u32> = if b { Some(maybe_error()?) } else { None };
+ // Process _x locally
+ Ok(())
+ }
+}
diff --git a/tests/ui/index_refutable_slice/if_let_slice_binding.fixed b/tests/ui/index_refutable_slice/if_let_slice_binding.fixed
index 050cdfc..dc7e09b 100644
--- a/tests/ui/index_refutable_slice/if_let_slice_binding.fixed
+++ b/tests/ui/index_refutable_slice/if_let_slice_binding.fixed
@@ -1,5 +1,5 @@
#![deny(clippy::index_refutable_slice)]
-#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes, clippy::collapsible_if)]
+#![allow(clippy::needless_lifetimes, clippy::collapsible_if)]
enum SomeEnum<T> {
One(T),
@@ -60,7 +60,7 @@
println!("{:?}", slice_1);
}
- println!("{:?}", slice);
+ println!("{slice:?}");
// This should not suggest using the `ref` keyword as the scrutinee is already
// a reference
@@ -70,7 +70,7 @@
println!("{:?}", slice_0);
}
- println!("{:?}", slice);
+ println!("{slice:?}");
}
fn slice_index_above_limit() {
@@ -113,7 +113,7 @@
println!("This is interesting {}", slice[0]);
}
}
- println!("{:?}", slice_wrapped);
+ println!("{slice_wrapped:?}");
}
fn check_slice_in_struct() {
@@ -152,7 +152,7 @@
println!("This is super awesome! {}", slice_0);
}
}
- println!("Complete wrap: {:?}", wrap);
+ println!("Complete wrap: {wrap:?}");
}
/// This would be a nice additional feature to have in the future, but adding it
@@ -164,14 +164,14 @@
if let Some(ref mut slice) = slice {
slice[0] = String::from("Mr. Penguin");
}
- println!("Use after modification: {:?}", slice);
+ println!("Use after modification: {slice:?}");
// Mut access on reference
let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
if let Some(slice) = &mut slice {
slice[0] = String::from("Lord Meow Meow");
}
- println!("Use after modification: {:?}", slice);
+ println!("Use after modification: {slice:?}");
}
/// The lint will ignore bindings with sub patterns as it would be hard
diff --git a/tests/ui/index_refutable_slice/if_let_slice_binding.rs b/tests/ui/index_refutable_slice/if_let_slice_binding.rs
index 91429bf..f39ace1 100644
--- a/tests/ui/index_refutable_slice/if_let_slice_binding.rs
+++ b/tests/ui/index_refutable_slice/if_let_slice_binding.rs
@@ -1,5 +1,5 @@
#![deny(clippy::index_refutable_slice)]
-#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes, clippy::collapsible_if)]
+#![allow(clippy::needless_lifetimes, clippy::collapsible_if)]
enum SomeEnum<T> {
One(T),
@@ -60,7 +60,7 @@
println!("{:?}", slice[1]);
}
- println!("{:?}", slice);
+ println!("{slice:?}");
// This should not suggest using the `ref` keyword as the scrutinee is already
// a reference
@@ -70,7 +70,7 @@
println!("{:?}", slice[0]);
}
- println!("{:?}", slice);
+ println!("{slice:?}");
}
fn slice_index_above_limit() {
@@ -113,7 +113,7 @@
println!("This is interesting {}", slice[0]);
}
}
- println!("{:?}", slice_wrapped);
+ println!("{slice_wrapped:?}");
}
fn check_slice_in_struct() {
@@ -152,7 +152,7 @@
println!("This is super awesome! {}", slice[0]);
}
}
- println!("Complete wrap: {:?}", wrap);
+ println!("Complete wrap: {wrap:?}");
}
/// This would be a nice additional feature to have in the future, but adding it
@@ -164,14 +164,14 @@
if let Some(ref mut slice) = slice {
slice[0] = String::from("Mr. Penguin");
}
- println!("Use after modification: {:?}", slice);
+ println!("Use after modification: {slice:?}");
// Mut access on reference
let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
if let Some(slice) = &mut slice {
slice[0] = String::from("Lord Meow Meow");
}
- println!("Use after modification: {:?}", slice);
+ println!("Use after modification: {slice:?}");
}
/// The lint will ignore bindings with sub patterns as it would be hard
diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs
index 701a865..4e1668e 100644
--- a/tests/ui/infinite_iter.rs
+++ b/tests/ui/infinite_iter.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::uninlined_format_args, clippy::double_ended_iterator_last)]
+#![allow(clippy::double_ended_iterator_last)]
use std::iter::repeat;
fn square_is_lower_64(x: &u32) -> bool {
@@ -30,7 +30,7 @@
.rev()
.cycle()
.map(|x| x + 1_u32)
- .for_each(|x| println!("{}", x));
+ .for_each(|x| println!("{x}"));
// infinite iter
(0..3_u32).flat_map(|x| x..).sum::<u32>();
// infinite iter
diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr
index b9e7c00..3db9731 100644
--- a/tests/ui/infinite_iter.stderr
+++ b/tests/ui/infinite_iter.stderr
@@ -30,8 +30,8 @@
LL | | .rev()
LL | | .cycle()
LL | | .map(|x| x + 1_u32)
-LL | | .for_each(|x| println!("{}", x));
- | |________________________________________^
+LL | | .for_each(|x| println!("{x}"));
+ | |______________________________________^
error: infinite iteration detected
--> tests/ui/infinite_iter.rs:37:5
diff --git a/tests/ui/issue_2356.fixed b/tests/ui/issue_2356.fixed
index 46ba653..3e066df 100644
--- a/tests/ui/issue_2356.fixed
+++ b/tests/ui/issue_2356.fixed
@@ -1,6 +1,5 @@
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
-#![allow(clippy::uninlined_format_args)]
use std::iter::Iterator;
@@ -16,7 +15,7 @@
fn foo2<I: Iterator<Item = usize>>(mut it: I) {
for e in it {
//~^ while_let_on_iterator
- println!("{:?}", e);
+ println!("{e:?}");
}
}
}
diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs
index defe258..98600d1 100644
--- a/tests/ui/issue_2356.rs
+++ b/tests/ui/issue_2356.rs
@@ -1,6 +1,5 @@
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
-#![allow(clippy::uninlined_format_args)]
use std::iter::Iterator;
@@ -16,7 +15,7 @@
fn foo2<I: Iterator<Item = usize>>(mut it: I) {
while let Some(e) = it.next() {
//~^ while_let_on_iterator
- println!("{:?}", e);
+ println!("{e:?}");
}
}
}
diff --git a/tests/ui/issue_2356.stderr b/tests/ui/issue_2356.stderr
index eae2ce9..ddee91f 100644
--- a/tests/ui/issue_2356.stderr
+++ b/tests/ui/issue_2356.stderr
@@ -1,5 +1,5 @@
error: this loop could be written as a `for` loop
- --> tests/ui/issue_2356.rs:17:9
+ --> tests/ui/issue_2356.rs:16:9
|
LL | while let Some(e) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for e in it`
diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs
index 664f0b8..b2a0112 100644
--- a/tests/ui/issue_4266.rs
+++ b/tests/ui/issue_4266.rs
@@ -1,5 +1,4 @@
#![allow(dead_code)]
-#![allow(clippy::uninlined_format_args)]
async fn sink1<'a>(_: &'a str) {} // lint
//~^ needless_lifetimes
@@ -39,7 +38,7 @@
// rust-lang/rust#61115
// ok
async fn print(s: &str) {
- println!("{}", s);
+ println!("{s}");
}
fn main() {}
diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr
index 0e18102..b80a738 100644
--- a/tests/ui/issue_4266.stderr
+++ b/tests/ui/issue_4266.stderr
@@ -1,5 +1,5 @@
error: the following explicit lifetimes could be elided: 'a
- --> tests/ui/issue_4266.rs:4:16
+ --> tests/ui/issue_4266.rs:3:16
|
LL | async fn sink1<'a>(_: &'a str) {} // lint
| ^^ ^^
@@ -8,13 +8,13 @@
= help: to override `-D warnings` add `#[allow(clippy::needless_lifetimes)]`
error: the following explicit lifetimes could be elided: 'a
- --> tests/ui/issue_4266.rs:10:21
+ --> tests/ui/issue_4266.rs:9:21
|
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
| ^^ ^^ ^^
error: methods called `new` usually take no `self`
- --> tests/ui/issue_4266.rs:32:22
+ --> tests/ui/issue_4266.rs:31:22
|
LL | pub async fn new(&mut self) -> Self {
| ^^^^^^^^^
diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed
index 381d4ca..e8517f1 100644
--- a/tests/ui/let_unit.fixed
+++ b/tests/ui/let_unit.fixed
@@ -1,5 +1,10 @@
#![warn(clippy::let_unit_value)]
-#![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
+#![allow(
+ clippy::no_effect,
+ clippy::needless_late_init,
+ path_statements,
+ clippy::match_single_binding
+)]
macro_rules! let_and_return {
($n:expr) => {{
@@ -15,12 +20,12 @@
if true {
// do not lint this, since () is explicit
let _a = ();
- let () = dummy();
+ let () = returns_unit();
let () = ();
- () = dummy();
+ () = returns_unit();
() = ();
let _a: () = ();
- let _a: () = dummy();
+ let _a: () = returns_unit();
}
consume_units_with_for_loop(); // should be fine as well
@@ -30,7 +35,7 @@
let_and_return!(()) // should be fine
}
-fn dummy() {}
+fn returns_unit() {}
// Related to issue #1964
fn consume_units_with_for_loop() {
@@ -181,8 +186,6 @@
pub async fn issue11502(a: ()) {}
pub fn issue12594() {
- fn returns_unit() {}
-
fn returns_result<T>(res: T) -> Result<T, ()> {
Ok(res)
}
@@ -199,13 +202,30 @@
}
}
-fn issue15061() {
- fn return_unit() {}
- fn do_something(x: ()) {}
+fn takes_unit(x: ()) {}
+fn issue15061() {
let res = ();
- return_unit();
+ returns_unit();
//~^ let_unit_value
- do_something(());
+ takes_unit(());
+ println!("{res:?}");
+}
+
+fn issue15771() {
+ match "Example String" {
+ _ => returns_unit(),
+ //~^ let_unit_value
+ }
+
+ if true {}
+ //~^ let_unit_value
+}
+
+fn issue_15784() {
+ let res = ();
+ eprintln!("I return unit");
+ //~^ let_unit_value
+ takes_unit(());
println!("{res:?}");
}
diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs
index cdfc749..3f6f013 100644
--- a/tests/ui/let_unit.rs
+++ b/tests/ui/let_unit.rs
@@ -1,5 +1,10 @@
#![warn(clippy::let_unit_value)]
-#![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
+#![allow(
+ clippy::no_effect,
+ clippy::needless_late_init,
+ path_statements,
+ clippy::match_single_binding
+)]
macro_rules! let_and_return {
($n:expr) => {{
@@ -15,12 +20,12 @@
if true {
// do not lint this, since () is explicit
let _a = ();
- let () = dummy();
+ let () = returns_unit();
let () = ();
- () = dummy();
+ () = returns_unit();
() = ();
let _a: () = ();
- let _a: () = dummy();
+ let _a: () = returns_unit();
}
consume_units_with_for_loop(); // should be fine as well
@@ -30,7 +35,7 @@
let_and_return!(()) // should be fine
}
-fn dummy() {}
+fn returns_unit() {}
// Related to issue #1964
fn consume_units_with_for_loop() {
@@ -181,8 +186,6 @@
pub async fn issue11502(a: ()) {}
pub fn issue12594() {
- fn returns_unit() {}
-
fn returns_result<T>(res: T) -> Result<T, ()> {
Ok(res)
}
@@ -199,12 +202,28 @@
}
}
-fn issue15061() {
- fn return_unit() {}
- fn do_something(x: ()) {}
+fn takes_unit(x: ()) {}
- let res = return_unit();
+fn issue15061() {
+ let res = returns_unit();
//~^ let_unit_value
- do_something(res);
+ takes_unit(res);
+ println!("{res:?}");
+}
+
+fn issue15771() {
+ match "Example String" {
+ _ => _ = returns_unit(),
+ //~^ let_unit_value
+ }
+
+ _ = if true {}
+ //~^ let_unit_value
+}
+
+fn issue_15784() {
+ let res = eprintln!("I return unit");
+ //~^ let_unit_value
+ takes_unit(res);
println!("{res:?}");
}
diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr
index 637c9ff..8ced32a 100644
--- a/tests/ui/let_unit.stderr
+++ b/tests/ui/let_unit.stderr
@@ -1,14 +1,19 @@
error: this let-binding has unit value
- --> tests/ui/let_unit.rs:11:5
+ --> tests/ui/let_unit.rs:16:5
|
LL | let _x = println!("x");
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `println!("x");`
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::let-unit-value` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
+help: omit the `let` binding
+ |
+LL - let _x = println!("x");
+LL + println!("x");
+ |
error: this let-binding has unit value
- --> tests/ui/let_unit.rs:60:5
+ --> tests/ui/let_unit.rs:65:5
|
LL | / let _ = v
LL | |
@@ -21,18 +26,12 @@
|
help: omit the `let` binding
|
-LL ~ v
-LL +
-LL + .into_iter()
-LL + .map(|i| i * 2)
-LL + .filter(|i| i.is_multiple_of(2))
-LL + .map(|_| ())
-LL + .next()
-LL + .unwrap();
+LL - let _ = v
+LL + v
|
error: this let-binding has unit value
- --> tests/ui/let_unit.rs:110:5
+ --> tests/ui/let_unit.rs:115:5
|
LL | / let x = match Some(0) {
LL | |
@@ -45,17 +44,12 @@
|
help: omit the `let` binding
|
-LL ~ match Some(0) {
-LL +
-LL + None => f2(1),
-LL + Some(0) => f(),
-LL + Some(1) => f2(3),
-LL + Some(_) => (),
-LL + };
+LL - let x = match Some(0) {
+LL + match Some(0) {
|
error: this let-binding has unit value
- --> tests/ui/let_unit.rs:192:9
+ --> tests/ui/let_unit.rs:195:9
|
LL | let res = returns_unit();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,18 +63,56 @@
|
error: this let-binding has unit value
- --> tests/ui/let_unit.rs:206:5
+ --> tests/ui/let_unit.rs:208:5
|
-LL | let res = return_unit();
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let res = returns_unit();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: replace variable usages with `()`
|
LL ~ let res = ();
-LL ~ return_unit();
+LL ~ returns_unit();
LL |
-LL ~ do_something(());
+LL ~ takes_unit(());
|
-error: aborting due to 5 previous errors
+error: this let-binding has unit value
+ --> tests/ui/let_unit.rs:216:14
+ |
+LL | _ => _ = returns_unit(),
+ | ^^^^^^^^^^^^^^^^^^
+ |
+help: omit the `let` binding
+ |
+LL - _ => _ = returns_unit(),
+LL + _ => returns_unit(),
+ |
+
+error: this let-binding has unit value
+ --> tests/ui/let_unit.rs:220:5
+ |
+LL | _ = if true {}
+ | ^^^^^^^^^^^^^^
+ |
+help: omit the `let` binding
+ |
+LL - _ = if true {}
+LL + if true {}
+ |
+
+error: this let-binding has unit value
+ --> tests/ui/let_unit.rs:225:5
+ |
+LL | let res = eprintln!("I return unit");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace variable usages with `()`
+ |
+LL ~ let res = ();
+LL ~ eprintln!("I return unit");
+LL |
+LL ~ takes_unit(());
+ |
+
+error: aborting due to 8 previous errors
diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed
index e29fb87..7e899a4 100644
--- a/tests/ui/match_single_binding.fixed
+++ b/tests/ui/match_single_binding.fixed
@@ -4,7 +4,6 @@
clippy::let_unit_value,
clippy::no_effect,
clippy::toplevel_ref_arg,
- clippy::uninlined_format_args,
clippy::useless_vec
)]
@@ -32,11 +31,11 @@
// Lint
let (x, y, z) = (a, b, c);
{
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
}
// Lint
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
// Ok
foo!(a);
// Ok
@@ -47,7 +46,7 @@
// Ok
let d = Some(5);
match d {
- Some(d) => println!("{}", d),
+ Some(d) => println!("{d}"),
_ => println!("None"),
}
// Lint
@@ -55,7 +54,7 @@
// Lint
{
let x = 29;
- println!("x has a value of {}", x);
+ println!("x has a value of {x}");
}
// Lint
{
@@ -67,18 +66,18 @@
// Lint
let p = Point { x: 0, y: 7 };
let Point { x, y } = p;
- println!("Coords: ({}, {})", x, y);
+ println!("Coords: ({x}, {y})");
// Lint
let Point { x: x1, y: y1 } = p;
- println!("Coords: ({}, {})", x1, y1);
+ println!("Coords: ({x1}, {y1})");
// Lint
let x = 5;
let ref r = x;
- println!("Got a reference to {}", r);
+ println!("Got a reference to {r}");
// Lint
let mut x = 5;
let ref mut mr = x;
- println!("Got a mutable reference to {}", mr);
+ println!("Got a mutable reference to {mr}");
// Lint
let Point { x, y } = coords();
let product = x * y;
@@ -122,7 +121,7 @@
let (pre, suf) = val.split_at(idx);
val = {
- println!("{}", pre);
+ println!("{pre}");
suf
};
@@ -210,20 +209,20 @@
let x = 1;
{
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
}
println!("x = {x}");
}
fn not_used_later(a: i32, b: i32, c: i32) {
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z)
+ println!("{x} {y} {z}")
}
#[allow(irrefutable_let_patterns)]
fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) {
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
let x = 1;
println!("x = {x}");
}
@@ -231,27 +230,27 @@
#[allow(irrefutable_let_patterns)]
fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) {
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {x} {y}");
if let (x, y, z) = (a, b, c) {
- println!("{} {} {}", x, y, z)
+ println!("{x} {y} {z}")
}
{
let x: i32 = 1;
{
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
}
if let (x, y, z) = (a, x, c) {
- println!("{} {} {}", x, y, z)
+ println!("{x} {y} {z}")
}
}
{
let (x, y, z) = (a, b, c);
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
let fn_ = |y| {
- println!("{} {} {}", a, b, y);
+ println!("{a} {b} {y}");
};
fn_(c);
}
diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs
index ede1ab3..37a96f2 100644
--- a/tests/ui/match_single_binding.rs
+++ b/tests/ui/match_single_binding.rs
@@ -4,7 +4,6 @@
clippy::let_unit_value,
clippy::no_effect,
clippy::toplevel_ref_arg,
- clippy::uninlined_format_args,
clippy::useless_vec
)]
@@ -33,13 +32,13 @@
match (a, b, c) {
//~^ match_single_binding
(x, y, z) => {
- println!("{} {} {}", x, y, z);
+ println!("{x} {y} {z}");
},
}
// Lint
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
// Ok
foo!(a);
@@ -51,7 +50,7 @@
// Ok
let d = Some(5);
match d {
- Some(d) => println!("{}", d),
+ Some(d) => println!("{d}"),
_ => println!("None"),
}
// Lint
@@ -64,7 +63,7 @@
//~^ match_single_binding
_ => {
let x = 29;
- println!("x has a value of {}", x);
+ println!("x has a value of {x}");
},
}
// Lint
@@ -81,24 +80,24 @@
let p = Point { x: 0, y: 7 };
match p {
//~^ match_single_binding
- Point { x, y } => println!("Coords: ({}, {})", x, y),
+ Point { x, y } => println!("Coords: ({x}, {y})"),
}
// Lint
match p {
//~^ match_single_binding
- Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1),
+ Point { x: x1, y: y1 } => println!("Coords: ({x1}, {y1})"),
}
// Lint
let x = 5;
match x {
//~^ match_single_binding
- ref r => println!("Got a reference to {}", r),
+ ref r => println!("Got a reference to {r}"),
}
// Lint
let mut x = 5;
match x {
//~^ match_single_binding
- ref mut mr => println!("Got a mutable reference to {}", mr),
+ ref mut mr => println!("Got a mutable reference to {mr}"),
}
// Lint
let product = match coords() {
@@ -150,7 +149,7 @@
val = match val.split_at(idx) {
//~^ match_single_binding
(pre, suf) => {
- println!("{}", pre);
+ println!("{pre}");
suf
},
};
@@ -273,7 +272,7 @@
let x = 1;
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
println!("x = {x}");
}
@@ -281,7 +280,7 @@
fn not_used_later(a: i32, b: i32, c: i32) {
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
}
@@ -289,7 +288,7 @@
fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) {
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
let x = 1;
println!("x = {x}");
@@ -299,30 +298,30 @@
fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) {
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {x} {y}"),
}
if let (x, y, z) = (a, b, c) {
- println!("{} {} {}", x, y, z)
+ println!("{x} {y} {z}")
}
{
let x: i32 = 1;
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
if let (x, y, z) = (a, x, c) {
- println!("{} {} {}", x, y, z)
+ println!("{x} {y} {z}")
}
}
{
match (a, b, c) {
//~^ match_single_binding
- (x, y, z) => println!("{} {} {}", x, y, z),
+ (x, y, z) => println!("{x} {y} {z}"),
}
let fn_ = |y| {
- println!("{} {} {}", a, b, y);
+ println!("{a} {b} {y}");
};
fn_(c);
}
diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr
index eea7177..82fc43a 100644
--- a/tests/ui/match_single_binding.stderr
+++ b/tests/ui/match_single_binding.stderr
@@ -1,10 +1,10 @@
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:33:5
+ --> tests/ui/match_single_binding.rs:32:5
|
LL | / match (a, b, c) {
LL | |
LL | | (x, y, z) => {
-LL | | println!("{} {} {}", x, y, z);
+LL | | println!("{x} {y} {z}");
LL | | },
LL | | }
| |_____^
@@ -15,27 +15,27 @@
|
LL ~ let (x, y, z) = (a, b, c);
LL + {
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
LL + }
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:40:5
+ --> tests/ui/match_single_binding.rs:39:5
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_____^
|
help: consider using a `let` statement
|
LL ~ let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
|
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:58:5
+ --> tests/ui/match_single_binding.rs:57:5
|
LL | / match a {
LL | |
@@ -44,13 +44,13 @@
| |_____^ help: consider using the match body instead: `println!("whatever");`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:63:5
+ --> tests/ui/match_single_binding.rs:62:5
|
LL | / match a {
LL | |
LL | | _ => {
LL | | let x = 29;
-LL | | println!("x has a value of {}", x);
+LL | | println!("x has a value of {x}");
LL | | },
LL | | }
| |_____^
@@ -59,12 +59,12 @@
|
LL ~ {
LL + let x = 29;
-LL + println!("x has a value of {}", x);
+LL + println!("x has a value of {x}");
LL + }
|
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:71:5
+ --> tests/ui/match_single_binding.rs:70:5
|
LL | / match a {
LL | |
@@ -86,67 +86,67 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:82:5
+ --> tests/ui/match_single_binding.rs:81:5
|
LL | / match p {
LL | |
-LL | | Point { x, y } => println!("Coords: ({}, {})", x, y),
+LL | | Point { x, y } => println!("Coords: ({x}, {y})"),
LL | | }
| |_____^
|
help: consider using a `let` statement
|
LL ~ let Point { x, y } = p;
-LL + println!("Coords: ({}, {})", x, y);
+LL + println!("Coords: ({x}, {y})");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:87:5
+ --> tests/ui/match_single_binding.rs:86:5
|
LL | / match p {
LL | |
-LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1),
+LL | | Point { x: x1, y: y1 } => println!("Coords: ({x1}, {y1})"),
LL | | }
| |_____^
|
help: consider using a `let` statement
|
LL ~ let Point { x: x1, y: y1 } = p;
-LL + println!("Coords: ({}, {})", x1, y1);
+LL + println!("Coords: ({x1}, {y1})");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:93:5
+ --> tests/ui/match_single_binding.rs:92:5
|
LL | / match x {
LL | |
-LL | | ref r => println!("Got a reference to {}", r),
+LL | | ref r => println!("Got a reference to {r}"),
LL | | }
| |_____^
|
help: consider using a `let` statement
|
LL ~ let ref r = x;
-LL + println!("Got a reference to {}", r);
+LL + println!("Got a reference to {r}");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:99:5
+ --> tests/ui/match_single_binding.rs:98:5
|
LL | / match x {
LL | |
-LL | | ref mut mr => println!("Got a mutable reference to {}", mr),
+LL | | ref mut mr => println!("Got a mutable reference to {mr}"),
LL | | }
| |_____^
|
help: consider using a `let` statement
|
LL ~ let ref mut mr = x;
-LL + println!("Got a mutable reference to {}", mr);
+LL + println!("Got a mutable reference to {mr}");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:104:5
+ --> tests/ui/match_single_binding.rs:103:5
|
LL | / let product = match coords() {
LL | |
@@ -161,7 +161,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:113:18
+ --> tests/ui/match_single_binding.rs:112:18
|
LL | .map(|i| match i.unwrap() {
| __________________^
@@ -179,7 +179,7 @@
|
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:140:5
+ --> tests/ui/match_single_binding.rs:139:5
|
LL | / match x {
LL | |
@@ -189,12 +189,12 @@
| |_____^ help: consider using the match body instead: `println!("Not an array index start")`
error: this assignment could be simplified
- --> tests/ui/match_single_binding.rs:150:5
+ --> tests/ui/match_single_binding.rs:149:5
|
LL | / val = match val.split_at(idx) {
LL | |
LL | | (pre, suf) => {
-LL | | println!("{}", pre);
+LL | | println!("{pre}");
LL | | suf
LL | | },
LL | | };
@@ -204,13 +204,13 @@
|
LL ~ let (pre, suf) = val.split_at(idx);
LL + val = {
-LL + println!("{}", pre);
+LL + println!("{pre}");
LL + suf
LL ~ };
|
error: this match could be replaced by its scrutinee and body
- --> tests/ui/match_single_binding.rs:164:16
+ --> tests/ui/match_single_binding.rs:163:16
|
LL | let _ = || match side_effects() {
| ________________^
@@ -228,7 +228,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:171:5
+ --> tests/ui/match_single_binding.rs:170:5
|
LL | / match r {
LL | |
@@ -253,7 +253,7 @@
|
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:185:5
+ --> tests/ui/match_single_binding.rs:184:5
|
LL | / match 1 {
LL | |
@@ -262,7 +262,7 @@
| |_____^ help: consider using the match body instead: `();`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:190:13
+ --> tests/ui/match_single_binding.rs:189:13
|
LL | let a = match 1 {
| _____________^
@@ -272,7 +272,7 @@
| |_____^ help: consider using the match body instead: `()`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:195:5
+ --> tests/ui/match_single_binding.rs:194:5
|
LL | / match 1 {
LL | |
@@ -281,7 +281,7 @@
| |_____^ help: consider using the match body instead: `side_effects();`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:200:13
+ --> tests/ui/match_single_binding.rs:199:13
|
LL | let b = match 1 {
| _____________^
@@ -291,7 +291,7 @@
| |_____^ help: consider using the match body instead: `side_effects()`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:205:5
+ --> tests/ui/match_single_binding.rs:204:5
|
LL | / match 1 {
LL | |
@@ -300,7 +300,7 @@
| |_____^ help: consider using the match body instead: `println!("1");`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:210:13
+ --> tests/ui/match_single_binding.rs:209:13
|
LL | let c = match 1 {
| _____________^
@@ -310,7 +310,7 @@
| |_____^ help: consider using the match body instead: `println!("1")`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:216:9
+ --> tests/ui/match_single_binding.rs:215:9
|
LL | / match 1 {
LL | |
@@ -319,7 +319,7 @@
| |_________^ help: consider using the match body instead: `()`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:220:9
+ --> tests/ui/match_single_binding.rs:219:9
|
LL | / match 1 {
LL | |
@@ -328,7 +328,7 @@
| |_________^ help: consider using the match body instead: `side_effects()`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:224:9
+ --> tests/ui/match_single_binding.rs:223:9
|
LL | / match 1 {
LL | |
@@ -337,7 +337,7 @@
| |_________^ help: consider using the match body instead: `println!("1")`
error: this match could be replaced by its scrutinee and body
- --> tests/ui/match_single_binding.rs:239:5
+ --> tests/ui/match_single_binding.rs:238:5
|
LL | / match dbg!(3) {
LL | | _ => println!("here"),
@@ -351,7 +351,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:243:5
+ --> tests/ui/match_single_binding.rs:242:5
|
LL | / match dbg!(3) {
LL | | id!(a) => println!("found {a}"),
@@ -365,7 +365,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:247:5
+ --> tests/ui/match_single_binding.rs:246:5
|
LL | / let id!(_a) = match dbg!(3) {
LL | | id!(b) => dbg!(b + 1),
@@ -379,7 +379,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:255:21
+ --> tests/ui/match_single_binding.rs:254:21
|
LL | inner: [(); match 1 {
| _____________________^
@@ -397,7 +397,7 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:263:13
+ --> tests/ui/match_single_binding.rs:262:13
|
LL | / match 1 {
LL | |
@@ -412,11 +412,11 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:274:9
+ --> tests/ui/match_single_binding.rs:273:9
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_________^
|
@@ -424,61 +424,61 @@
|
LL ~ {
LL + let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
LL + }
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:282:9
+ --> tests/ui/match_single_binding.rs:281:9
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_________^
|
help: consider using a `let` statement
|
LL ~ let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z)
+LL + println!("{x} {y} {z}")
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:290:9
+ --> tests/ui/match_single_binding.rs:289:9
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_________^
|
help: consider using a `let` statement
|
LL ~ let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:300:9
+ --> tests/ui/match_single_binding.rs:299:9
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {x} {y}"),
LL | | }
| |_________^
|
help: consider using a `let` statement
|
LL ~ let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {x} {y}");
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:310:13
+ --> tests/ui/match_single_binding.rs:309:13
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_____________^
|
@@ -486,27 +486,27 @@
|
LL ~ {
LL + let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
LL + }
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding.rs:320:13
+ --> tests/ui/match_single_binding.rs:319:13
|
LL | / match (a, b, c) {
LL | |
-LL | | (x, y, z) => println!("{} {} {}", x, y, z),
+LL | | (x, y, z) => println!("{x} {y} {z}"),
LL | | }
| |_____________^
|
help: consider using a `let` statement
|
LL ~ let (x, y, z) = (a, b, c);
-LL + println!("{} {} {}", x, y, z);
+LL + println!("{x} {y} {z}");
|
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:335:12
+ --> tests/ui/match_single_binding.rs:334:12
|
LL | && match b {
| ____________^
@@ -516,7 +516,7 @@
| |_________^ help: consider using the match body instead: `b < c`
error: this match could be replaced by its body itself
- --> tests/ui/match_single_binding.rs:341:12
+ --> tests/ui/match_single_binding.rs:340:12
|
LL | && match (a, b) {
| ____________^
diff --git a/tests/ui/match_single_binding2.fixed b/tests/ui/match_single_binding2.fixed
index 988121f..f009874 100644
--- a/tests/ui/match_single_binding2.fixed
+++ b/tests/ui/match_single_binding2.fixed
@@ -1,6 +1,5 @@
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
-#![allow(clippy::uninlined_format_args)]
fn main() {
// Lint (additional curly braces needed, see #6572)
@@ -29,7 +28,7 @@
#[rustfmt::skip]
Some((first, _second)) => {
let (a, b) = get_tup();
- println!("a {:?} and b {:?}", a, b)
+ println!("a {a:?} and b {b:?}")
},
None => println!("nothing"),
}
diff --git a/tests/ui/match_single_binding2.rs b/tests/ui/match_single_binding2.rs
index a4fb2bd..5416f64 100644
--- a/tests/ui/match_single_binding2.rs
+++ b/tests/ui/match_single_binding2.rs
@@ -1,6 +1,5 @@
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
-#![allow(clippy::uninlined_format_args)]
fn main() {
// Lint (additional curly braces needed, see #6572)
@@ -30,7 +29,7 @@
Some((first, _second)) => {
match get_tup() {
//~^ match_single_binding
- (a, b) => println!("a {:?} and b {:?}", a, b),
+ (a, b) => println!("a {a:?} and b {b:?}"),
}
},
None => println!("nothing"),
diff --git a/tests/ui/match_single_binding2.stderr b/tests/ui/match_single_binding2.stderr
index a24cbe3..65b8aa6 100644
--- a/tests/ui/match_single_binding2.stderr
+++ b/tests/ui/match_single_binding2.stderr
@@ -1,5 +1,5 @@
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding2.rs:17:36
+ --> tests/ui/match_single_binding2.rs:16:36
|
LL | Some((iter, _item)) => match iter.size_hint() {
| ____________________________________^
@@ -19,22 +19,22 @@
|
error: this match could be written as a `let` statement
- --> tests/ui/match_single_binding2.rs:31:13
+ --> tests/ui/match_single_binding2.rs:30:13
|
LL | / match get_tup() {
LL | |
-LL | | (a, b) => println!("a {:?} and b {:?}", a, b),
+LL | | (a, b) => println!("a {a:?} and b {b:?}"),
LL | | }
| |_____________^
|
help: consider using a `let` statement
|
LL ~ let (a, b) = get_tup();
-LL + println!("a {:?} and b {:?}", a, b)
+LL + println!("a {a:?} and b {b:?}")
|
error: this match could be replaced by its scrutinee and body
- --> tests/ui/match_single_binding2.rs:43:5
+ --> tests/ui/match_single_binding2.rs:42:5
|
LL | / match side_effects() {
LL | |
@@ -49,7 +49,7 @@
|
error: this match could be replaced by its scrutinee and body
- --> tests/ui/match_single_binding2.rs:51:5
+ --> tests/ui/match_single_binding2.rs:50:5
|
LL | / match match x {
LL | |
diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed
index 870ef23..94ad1aa 100644
--- a/tests/ui/mem_replace.fixed
+++ b/tests/ui/mem_replace.fixed
@@ -179,3 +179,9 @@
let mut an_option = Some(0);
let replaced = mem::replace(&mut an_option, Some(1));
}
+
+fn issue15785() {
+ let mut text = String::from("foo");
+ let replaced = std::mem::take(dbg!(&mut text));
+ //~^ mem_replace_with_default
+}
diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs
index b4ed5ea..ac79660 100644
--- a/tests/ui/mem_replace.rs
+++ b/tests/ui/mem_replace.rs
@@ -179,3 +179,9 @@
let mut an_option = Some(0);
let replaced = mem::replace(&mut an_option, Some(1));
}
+
+fn issue15785() {
+ let mut text = String::from("foo");
+ let replaced = std::mem::replace(dbg!(&mut text), String::default());
+ //~^ mem_replace_with_default
+}
diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr
index fb4a367..104c985 100644
--- a/tests/ui/mem_replace.stderr
+++ b/tests/ui/mem_replace.stderr
@@ -181,5 +181,11 @@
LL | let replaced = mem::replace(if b { &mut opt1 } else { &mut opt2 }, Some(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `(if b { &mut opt1 } else { &mut opt2 }).replace(1)`
-error: aborting due to 29 previous errors
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+ --> tests/ui/mem_replace.rs:185:20
+ |
+LL | let replaced = std::mem::replace(dbg!(&mut text), String::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(dbg!(&mut text))`
+
+error: aborting due to 30 previous errors
diff --git a/tests/ui/mut_mut.fixed b/tests/ui/mut_mut.fixed
new file mode 100644
index 0000000..f9a7f5d
--- /dev/null
+++ b/tests/ui/mut_mut.fixed
@@ -0,0 +1,92 @@
+//@aux-build:proc_macros.rs
+
+#![warn(clippy::mut_mut)]
+#![allow(unused)]
+#![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};
+
+fn fun(x: &mut u32) {
+ //~^ mut_mut
+}
+
+fn less_fun(x: *mut *mut u32) {
+ let y = x;
+}
+
+macro_rules! mut_ptr {
+ ($p:expr) => {
+ &mut $p
+ };
+}
+
+#[allow(unused_mut, unused_variables)]
+#[inline_macros]
+fn main() {
+ let mut x = &mut 1u32;
+ //~^ mut_mut
+ {
+ let mut y = &mut *x;
+ //~^ mut_mut
+ }
+
+ {
+ let y: &mut u32 = &mut 2;
+ //~^ mut_mut
+ //~| mut_mut
+ }
+
+ {
+ let y: &mut u32 = &mut 2;
+ //~^ mut_mut
+ //~| mut_mut
+ }
+
+ let mut z = inline!(&mut $(&mut 3u32));
+}
+
+fn issue939() {
+ let array = [5, 6, 7, 8, 9];
+ let mut args = array.iter().skip(2);
+ for &arg in &mut args {
+ println!("{}", arg);
+ }
+
+ let args = &mut args;
+ for arg in args {
+ println!(":{}", arg);
+ }
+}
+
+fn issue6922() {
+ // do not lint from an external macro
+ external!(let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;);
+}
+
+mod issue9035 {
+ use std::fmt::Display;
+
+ struct Foo<'a> {
+ inner: &'a mut dyn Display,
+ }
+
+ impl Foo<'_> {
+ fn foo(&mut self) {
+ let hlp = &mut self.inner;
+ bar(hlp);
+ }
+ }
+
+ fn bar(_: &mut impl Display) {}
+}
+
+fn allow_works() {
+ #[allow(clippy::mut_mut)]
+ let _ = &mut &mut 1;
+}
diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs
index bbcdbc8..bbec480 100644
--- a/tests/ui/mut_mut.rs
+++ b/tests/ui/mut_mut.rs
@@ -12,9 +12,8 @@
extern crate proc_macros;
use proc_macros::{external, inline_macros};
-fn fun(x: &mut &mut u32) -> bool {
+fn fun(x: &mut &mut u32) {
//~^ mut_mut
- **x > 0
}
fn less_fun(x: *mut *mut u32) {
@@ -37,23 +36,19 @@
//~^ mut_mut
}
- if fun(x) {
+ {
let y: &mut &mut u32 = &mut &mut 2;
//~^ mut_mut
//~| mut_mut
- **y + **x;
}
- if fun(x) {
+ {
let y: &mut &mut &mut u32 = &mut &mut &mut 2;
//~^ mut_mut
//~| mut_mut
- //~| mut_mut
- ***y + **x;
}
let mut z = inline!(&mut $(&mut 3u32));
- //~^ mut_mut
}
fn issue939() {
diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr
index 74b0c9b..85e9c56 100644
--- a/tests/ui/mut_mut.stderr
+++ b/tests/ui/mut_mut.stderr
@@ -1,61 +1,47 @@
-error: generally you want to avoid `&mut &mut _` if possible
+error: a type of form `&mut &mut _`
--> tests/ui/mut_mut.rs:15:11
|
-LL | fn fun(x: &mut &mut u32) -> bool {
- | ^^^^^^^^^^^^^
+LL | fn fun(x: &mut &mut u32) {
+ | ^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut u32`
|
= note: `-D clippy::mut-mut` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::mut_mut)]`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:33:17
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut.rs:32:17
|
LL | let mut x = &mut &mut 1u32;
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut 1u32`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:55:25
- |
-LL | let mut z = inline!(&mut $(&mut 3u32));
- | ^
- |
- = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: this expression mutably borrows a mutable reference. Consider reborrowing
- --> tests/ui/mut_mut.rs:36:21
+error: this expression mutably borrows a mutable reference
+ --> tests/ui/mut_mut.rs:35:21
|
LL | let mut y = &mut x;
- | ^^^^^^
+ | ^^^^^^ help: reborrow instead: `&mut *x`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:41:32
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut.rs:40:32
|
LL | let y: &mut &mut u32 = &mut &mut 2;
- | ^^^^^^^^^^^
+ | ^^^^^^^^^^^ help: remove the extra `&mut`: `&mut 2`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:41:16
+error: a type of form `&mut &mut _`
+ --> tests/ui/mut_mut.rs:40:16
|
LL | let y: &mut &mut u32 = &mut &mut 2;
- | ^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut u32`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:48:37
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut.rs:46:37
|
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
- | ^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut 2`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:48:16
+error: a type of form `&mut &mut _`
+ --> tests/ui/mut_mut.rs:46:16
|
LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut u32`
-error: generally you want to avoid `&mut &mut _` if possible
- --> tests/ui/mut_mut.rs:48:21
- |
-LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2;
- | ^^^^^^^^^^^^^
-
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
diff --git a/tests/ui/mut_mut_unfixable.rs b/tests/ui/mut_mut_unfixable.rs
new file mode 100644
index 0000000..271cb7b
--- /dev/null
+++ b/tests/ui/mut_mut_unfixable.rs
@@ -0,0 +1,42 @@
+//@no-rustfix
+
+#![warn(clippy::mut_mut)]
+#![allow(unused)]
+#![expect(clippy::no_effect)]
+
+//! removing the extra `&mut`s will break the derefs
+
+fn fun(x: &mut &mut u32) -> bool {
+ //~^ mut_mut
+ **x > 0
+}
+
+fn main() {
+ let mut x = &mut &mut 1u32;
+ //~^ mut_mut
+ {
+ let mut y = &mut x;
+ //~^ mut_mut
+ ***y + **x;
+ }
+
+ if fun(x) {
+ let y = &mut &mut 2;
+ //~^ mut_mut
+ **y + **x;
+ }
+
+ if fun(x) {
+ let y = &mut &mut &mut 2;
+ //~^ mut_mut
+ ***y + **x;
+ }
+
+ if fun(x) {
+ // The lint will remove the extra `&mut`, but the result will still be a `&mut` of an expr
+ // of type `&mut _` (x), so the lint will fire again. That's because we've decided that
+ // doing both fixes in one run is not worth it, given how improbable code like this is.
+ let y = &mut &mut x;
+ //~^ mut_mut
+ }
+}
diff --git a/tests/ui/mut_mut_unfixable.stderr b/tests/ui/mut_mut_unfixable.stderr
new file mode 100644
index 0000000..cf66eb2
--- /dev/null
+++ b/tests/ui/mut_mut_unfixable.stderr
@@ -0,0 +1,41 @@
+error: a type of form `&mut &mut _`
+ --> tests/ui/mut_mut_unfixable.rs:9:11
+ |
+LL | fn fun(x: &mut &mut u32) -> bool {
+ | ^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut u32`
+ |
+ = note: `-D clippy::mut-mut` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]`
+
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut_unfixable.rs:15:17
+ |
+LL | let mut x = &mut &mut 1u32;
+ | ^^^^^^^^^^^^^^ help: remove the extra `&mut`: `&mut 1u32`
+
+error: this expression mutably borrows a mutable reference
+ --> tests/ui/mut_mut_unfixable.rs:18:21
+ |
+LL | let mut y = &mut x;
+ | ^^^^^^ help: reborrow instead: `&mut *x`
+
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut_unfixable.rs:24:17
+ |
+LL | let y = &mut &mut 2;
+ | ^^^^^^^^^^^ help: remove the extra `&mut`: `&mut 2`
+
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut_unfixable.rs:30:17
+ |
+LL | let y = &mut &mut &mut 2;
+ | ^^^^^^^^^^^^^^^^ help: remove the extra `&mut`s: `&mut 2`
+
+error: an expression of form `&mut &mut _`
+ --> tests/ui/mut_mut_unfixable.rs:39:17
+ |
+LL | let y = &mut &mut x;
+ | ^^^^^^^^^^^ help: remove the extra `&mut`: `&mut x`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/new_without_default.fixed b/tests/ui/new_without_default.fixed
index 277c335cd..9a5e90b 100644
--- a/tests/ui/new_without_default.fixed
+++ b/tests/ui/new_without_default.fixed
@@ -1,5 +1,4 @@
#![allow(
- dead_code,
clippy::missing_safety_doc,
clippy::extra_unused_lifetimes,
clippy::extra_unused_type_parameters,
@@ -322,3 +321,91 @@
Self { _kv: None }
}
}
+
+// From issue #14552, but with `#[cfg]`s that are actually `true` in the uitest context
+
+pub struct NewWithCfg;
+#[cfg(not(test))]
+impl Default for NewWithCfg {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl NewWithCfg {
+ #[cfg(not(test))]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWith2Cfgs;
+#[cfg(not(test))]
+#[cfg(panic = "unwind")]
+impl Default for NewWith2Cfgs {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl NewWith2Cfgs {
+ #[cfg(not(test))]
+ #[cfg(panic = "unwind")]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWithExtraneous;
+impl Default for NewWithExtraneous {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl NewWithExtraneous {
+ #[inline]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWithCfgAndExtraneous;
+#[cfg(not(test))]
+impl Default for NewWithCfgAndExtraneous {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl NewWithCfgAndExtraneous {
+ #[cfg(not(test))]
+ #[inline]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+mod issue15778 {
+ pub struct Foo(Vec<i32>);
+
+ impl Foo {
+ pub fn new() -> Self {
+ Self(Vec::new())
+ }
+ }
+
+ impl<'a> IntoIterator for &'a Foo {
+ type Item = &'a i32;
+
+ type IntoIter = std::slice::Iter<'a, i32>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.0.as_slice().iter()
+ }
+ }
+}
diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs
index f284489..f7466aa 100644
--- a/tests/ui/new_without_default.rs
+++ b/tests/ui/new_without_default.rs
@@ -1,5 +1,4 @@
#![allow(
- dead_code,
clippy::missing_safety_doc,
clippy::extra_unused_lifetimes,
clippy::extra_unused_type_parameters,
@@ -265,3 +264,63 @@
Self { _kv: None }
}
}
+
+// From issue #14552, but with `#[cfg]`s that are actually `true` in the uitest context
+
+pub struct NewWithCfg;
+impl NewWithCfg {
+ #[cfg(not(test))]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWith2Cfgs;
+impl NewWith2Cfgs {
+ #[cfg(not(test))]
+ #[cfg(panic = "unwind")]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWithExtraneous;
+impl NewWithExtraneous {
+ #[inline]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+pub struct NewWithCfgAndExtraneous;
+impl NewWithCfgAndExtraneous {
+ #[cfg(not(test))]
+ #[inline]
+ pub fn new() -> Self {
+ //~^ new_without_default
+ unimplemented!()
+ }
+}
+
+mod issue15778 {
+ pub struct Foo(Vec<i32>);
+
+ impl Foo {
+ pub fn new() -> Self {
+ Self(Vec::new())
+ }
+ }
+
+ impl<'a> IntoIterator for &'a Foo {
+ type Item = &'a i32;
+
+ type IntoIter = std::slice::Iter<'a, i32>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.0.as_slice().iter()
+ }
+ }
+}
diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr
index 70a65ab..1e0d5e2 100644
--- a/tests/ui/new_without_default.stderr
+++ b/tests/ui/new_without_default.stderr
@@ -1,5 +1,5 @@
error: you should consider adding a `Default` implementation for `Foo`
- --> tests/ui/new_without_default.rs:13:5
+ --> tests/ui/new_without_default.rs:12:5
|
LL | / pub fn new() -> Foo {
LL | |
@@ -20,7 +20,7 @@
|
error: you should consider adding a `Default` implementation for `Bar`
- --> tests/ui/new_without_default.rs:23:5
+ --> tests/ui/new_without_default.rs:22:5
|
LL | / pub fn new() -> Self {
LL | |
@@ -39,7 +39,7 @@
|
error: you should consider adding a `Default` implementation for `LtKo<'c>`
- --> tests/ui/new_without_default.rs:89:5
+ --> tests/ui/new_without_default.rs:88:5
|
LL | / pub fn new() -> LtKo<'c> {
LL | |
@@ -58,7 +58,7 @@
|
error: you should consider adding a `Default` implementation for `Const`
- --> tests/ui/new_without_default.rs:123:5
+ --> tests/ui/new_without_default.rs:122:5
|
LL | / pub const fn new() -> Const {
LL | |
@@ -76,7 +76,7 @@
|
error: you should consider adding a `Default` implementation for `NewNotEqualToDerive`
- --> tests/ui/new_without_default.rs:184:5
+ --> tests/ui/new_without_default.rs:183:5
|
LL | / pub fn new() -> Self {
LL | |
@@ -95,7 +95,7 @@
|
error: you should consider adding a `Default` implementation for `FooGenerics<T>`
- --> tests/ui/new_without_default.rs:194:5
+ --> tests/ui/new_without_default.rs:193:5
|
LL | / pub fn new() -> Self {
LL | |
@@ -114,7 +114,7 @@
|
error: you should consider adding a `Default` implementation for `BarGenerics<T>`
- --> tests/ui/new_without_default.rs:203:5
+ --> tests/ui/new_without_default.rs:202:5
|
LL | / pub fn new() -> Self {
LL | |
@@ -133,7 +133,7 @@
|
error: you should consider adding a `Default` implementation for `Foo<T>`
- --> tests/ui/new_without_default.rs:216:9
+ --> tests/ui/new_without_default.rs:215:9
|
LL | / pub fn new() -> Self {
LL | |
@@ -154,7 +154,7 @@
|
error: you should consider adding a `Default` implementation for `MyStruct<K, V>`
- --> tests/ui/new_without_default.rs:263:5
+ --> tests/ui/new_without_default.rs:262:5
|
LL | / pub fn new() -> Self {
LL | |
@@ -174,5 +174,84 @@
LL + }
|
-error: aborting due to 9 previous errors
+error: you should consider adding a `Default` implementation for `NewWithCfg`
+ --> tests/ui/new_without_default.rs:273:5
+ |
+LL | / pub fn new() -> Self {
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+help: try adding this
+ |
+LL + #[cfg(not(test))]
+LL + impl Default for NewWithCfg {
+LL + fn default() -> Self {
+LL + Self::new()
+LL + }
+LL + }
+LL | impl NewWithCfg {
+ |
+
+error: you should consider adding a `Default` implementation for `NewWith2Cfgs`
+ --> tests/ui/new_without_default.rs:283:5
+ |
+LL | / pub fn new() -> Self {
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+help: try adding this
+ |
+LL + #[cfg(not(test))]
+LL + #[cfg(panic = "unwind")]
+LL + impl Default for NewWith2Cfgs {
+LL + fn default() -> Self {
+LL + Self::new()
+LL + }
+LL + }
+LL | impl NewWith2Cfgs {
+ |
+
+error: you should consider adding a `Default` implementation for `NewWithExtraneous`
+ --> tests/ui/new_without_default.rs:292:5
+ |
+LL | / pub fn new() -> Self {
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+help: try adding this
+ |
+LL + impl Default for NewWithExtraneous {
+LL + fn default() -> Self {
+LL + Self::new()
+LL + }
+LL + }
+ |
+
+error: you should consider adding a `Default` implementation for `NewWithCfgAndExtraneous`
+ --> tests/ui/new_without_default.rs:302:5
+ |
+LL | / pub fn new() -> Self {
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+help: try adding this
+ |
+LL + #[cfg(not(test))]
+LL + impl Default for NewWithCfgAndExtraneous {
+LL + fn default() -> Self {
+LL + Self::new()
+LL + }
+LL + }
+LL | impl NewWithCfgAndExtraneous {
+ |
+
+error: aborting due to 13 previous errors
diff --git a/tests/ui/should_impl_trait/method_list_1.stderr b/tests/ui/should_impl_trait/method_list_1.edition2015.stderr
similarity index 85%
rename from tests/ui/should_impl_trait/method_list_1.stderr
rename to tests/ui/should_impl_trait/method_list_1.edition2015.stderr
index 5609d6a..0312fa8 100644
--- a/tests/ui/should_impl_trait/method_list_1.stderr
+++ b/tests/ui/should_impl_trait/method_list_1.edition2015.stderr
@@ -1,5 +1,5 @@
error: method `add` can be confused for the standard trait method `std::ops::Add::add`
- --> tests/ui/should_impl_trait/method_list_1.rs:24:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:27:5
|
LL | / pub fn add(self, other: T) -> T {
LL | |
@@ -13,7 +13,7 @@
= help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:30:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:33:5
|
LL | / pub fn as_mut(&mut self) -> &mut T {
LL | |
@@ -25,7 +25,7 @@
= help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
- --> tests/ui/should_impl_trait/method_list_1.rs:36:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:39:5
|
LL | / pub fn as_ref(&self) -> &T {
LL | |
@@ -37,7 +37,7 @@
= help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
- --> tests/ui/should_impl_trait/method_list_1.rs:42:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:45:5
|
LL | / pub fn bitand(self, rhs: T) -> T {
LL | |
@@ -49,7 +49,7 @@
= help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
- --> tests/ui/should_impl_trait/method_list_1.rs:48:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:51:5
|
LL | / pub fn bitor(self, rhs: Self) -> Self {
LL | |
@@ -61,7 +61,7 @@
= help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
- --> tests/ui/should_impl_trait/method_list_1.rs:54:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:57:5
|
LL | / pub fn bitxor(self, rhs: Self) -> Self {
LL | |
@@ -73,7 +73,7 @@
= help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
- --> tests/ui/should_impl_trait/method_list_1.rs:60:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:63:5
|
LL | / pub fn borrow(&self) -> &str {
LL | |
@@ -85,7 +85,7 @@
= help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:66:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:69:5
|
LL | / pub fn borrow_mut(&mut self) -> &mut str {
LL | |
@@ -97,7 +97,7 @@
= help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
- --> tests/ui/should_impl_trait/method_list_1.rs:72:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:75:5
|
LL | / pub fn clone(&self) -> Self {
LL | |
@@ -109,7 +109,7 @@
= help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
- --> tests/ui/should_impl_trait/method_list_1.rs:78:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:81:5
|
LL | / pub fn cmp(&self, other: &Self) -> Self {
LL | |
@@ -121,7 +121,7 @@
= help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
error: method `default` can be confused for the standard trait method `std::default::Default::default`
- --> tests/ui/should_impl_trait/method_list_1.rs:84:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:87:5
|
LL | / pub fn default() -> Self {
LL | |
@@ -133,7 +133,7 @@
= help: consider implementing the trait `std::default::Default` or choosing a less ambiguous method name
error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
- --> tests/ui/should_impl_trait/method_list_1.rs:90:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:93:5
|
LL | / pub fn deref(&self) -> &Self {
LL | |
@@ -145,7 +145,7 @@
= help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:96:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:99:5
|
LL | / pub fn deref_mut(&mut self) -> &mut Self {
LL | |
@@ -157,7 +157,7 @@
= help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
error: method `div` can be confused for the standard trait method `std::ops::Div::div`
- --> tests/ui/should_impl_trait/method_list_1.rs:102:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:105:5
|
LL | / pub fn div(self, rhs: Self) -> Self {
LL | |
@@ -169,7 +169,7 @@
= help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
- --> tests/ui/should_impl_trait/method_list_1.rs:108:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:111:5
|
LL | / pub fn drop(&mut self) {
LL | |
diff --git a/tests/ui/should_impl_trait/method_list_1.stderr b/tests/ui/should_impl_trait/method_list_1.edition2021.stderr
similarity index 85%
copy from tests/ui/should_impl_trait/method_list_1.stderr
copy to tests/ui/should_impl_trait/method_list_1.edition2021.stderr
index 5609d6a..0312fa8 100644
--- a/tests/ui/should_impl_trait/method_list_1.stderr
+++ b/tests/ui/should_impl_trait/method_list_1.edition2021.stderr
@@ -1,5 +1,5 @@
error: method `add` can be confused for the standard trait method `std::ops::Add::add`
- --> tests/ui/should_impl_trait/method_list_1.rs:24:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:27:5
|
LL | / pub fn add(self, other: T) -> T {
LL | |
@@ -13,7 +13,7 @@
= help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:30:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:33:5
|
LL | / pub fn as_mut(&mut self) -> &mut T {
LL | |
@@ -25,7 +25,7 @@
= help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
- --> tests/ui/should_impl_trait/method_list_1.rs:36:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:39:5
|
LL | / pub fn as_ref(&self) -> &T {
LL | |
@@ -37,7 +37,7 @@
= help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
- --> tests/ui/should_impl_trait/method_list_1.rs:42:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:45:5
|
LL | / pub fn bitand(self, rhs: T) -> T {
LL | |
@@ -49,7 +49,7 @@
= help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
- --> tests/ui/should_impl_trait/method_list_1.rs:48:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:51:5
|
LL | / pub fn bitor(self, rhs: Self) -> Self {
LL | |
@@ -61,7 +61,7 @@
= help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
- --> tests/ui/should_impl_trait/method_list_1.rs:54:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:57:5
|
LL | / pub fn bitxor(self, rhs: Self) -> Self {
LL | |
@@ -73,7 +73,7 @@
= help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
- --> tests/ui/should_impl_trait/method_list_1.rs:60:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:63:5
|
LL | / pub fn borrow(&self) -> &str {
LL | |
@@ -85,7 +85,7 @@
= help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:66:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:69:5
|
LL | / pub fn borrow_mut(&mut self) -> &mut str {
LL | |
@@ -97,7 +97,7 @@
= help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
- --> tests/ui/should_impl_trait/method_list_1.rs:72:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:75:5
|
LL | / pub fn clone(&self) -> Self {
LL | |
@@ -109,7 +109,7 @@
= help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
- --> tests/ui/should_impl_trait/method_list_1.rs:78:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:81:5
|
LL | / pub fn cmp(&self, other: &Self) -> Self {
LL | |
@@ -121,7 +121,7 @@
= help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
error: method `default` can be confused for the standard trait method `std::default::Default::default`
- --> tests/ui/should_impl_trait/method_list_1.rs:84:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:87:5
|
LL | / pub fn default() -> Self {
LL | |
@@ -133,7 +133,7 @@
= help: consider implementing the trait `std::default::Default` or choosing a less ambiguous method name
error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
- --> tests/ui/should_impl_trait/method_list_1.rs:90:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:93:5
|
LL | / pub fn deref(&self) -> &Self {
LL | |
@@ -145,7 +145,7 @@
= help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
- --> tests/ui/should_impl_trait/method_list_1.rs:96:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:99:5
|
LL | / pub fn deref_mut(&mut self) -> &mut Self {
LL | |
@@ -157,7 +157,7 @@
= help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
error: method `div` can be confused for the standard trait method `std::ops::Div::div`
- --> tests/ui/should_impl_trait/method_list_1.rs:102:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:105:5
|
LL | / pub fn div(self, rhs: Self) -> Self {
LL | |
@@ -169,7 +169,7 @@
= help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
- --> tests/ui/should_impl_trait/method_list_1.rs:108:5
+ --> tests/ui/should_impl_trait/method_list_1.rs:111:5
|
LL | / pub fn drop(&mut self) {
LL | |
diff --git a/tests/ui/should_impl_trait/method_list_1.rs b/tests/ui/should_impl_trait/method_list_1.rs
index e8de0e0..bbb04c0 100644
--- a/tests/ui/should_impl_trait/method_list_1.rs
+++ b/tests/ui/should_impl_trait/method_list_1.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2021
+//@[edition2015] edition:2015
+//@[edition2021] edition:2021
#![allow(
clippy::missing_errors_doc,
clippy::needless_pass_by_value,
diff --git a/tests/ui/should_impl_trait/method_list_2.edition2015.stderr b/tests/ui/should_impl_trait/method_list_2.edition2015.stderr
new file mode 100644
index 0000000..2598159
--- /dev/null
+++ b/tests/ui/should_impl_trait/method_list_2.edition2015.stderr
@@ -0,0 +1,172 @@
+error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
+ --> tests/ui/should_impl_trait/method_list_2.rs:28:5
+ |
+LL | / pub fn eq(&self, other: &Self) -> bool {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
+ = note: `-D clippy::should-implement-trait` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
+
+error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
+ --> tests/ui/should_impl_trait/method_list_2.rs:40:5
+ |
+LL | / pub fn from_str(s: &str) -> Result<Self, Self> {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
+
+error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
+ --> tests/ui/should_impl_trait/method_list_2.rs:46:5
+ |
+LL | / pub fn hash(&self, state: &mut T) {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
+
+error: method `index` can be confused for the standard trait method `std::ops::Index::index`
+ --> tests/ui/should_impl_trait/method_list_2.rs:52:5
+ |
+LL | / pub fn index(&self, index: usize) -> &Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
+
+error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
+ --> tests/ui/should_impl_trait/method_list_2.rs:58:5
+ |
+LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
+
+error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
+ --> tests/ui/should_impl_trait/method_list_2.rs:64:5
+ |
+LL | / pub fn into_iter(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
+
+error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
+ --> tests/ui/should_impl_trait/method_list_2.rs:70:5
+ |
+LL | / pub fn mul(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
+
+error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
+ --> tests/ui/should_impl_trait/method_list_2.rs:76:5
+ |
+LL | / pub fn neg(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
+
+error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
+ --> tests/ui/should_impl_trait/method_list_2.rs:82:5
+ |
+LL | / pub fn next(&mut self) -> Option<Self> {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
+
+error: method `not` can be confused for the standard trait method `std::ops::Not::not`
+ --> tests/ui/should_impl_trait/method_list_2.rs:88:5
+ |
+LL | / pub fn not(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
+
+error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
+ --> tests/ui/should_impl_trait/method_list_2.rs:94:5
+ |
+LL | / pub fn rem(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
+
+error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
+ --> tests/ui/should_impl_trait/method_list_2.rs:100:5
+ |
+LL | / pub fn shl(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
+
+error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
+ --> tests/ui/should_impl_trait/method_list_2.rs:106:5
+ |
+LL | / pub fn shr(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
+
+error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
+ --> tests/ui/should_impl_trait/method_list_2.rs:112:5
+ |
+LL | / pub fn sub(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/should_impl_trait/method_list_2.edition2021.stderr b/tests/ui/should_impl_trait/method_list_2.edition2021.stderr
new file mode 100644
index 0000000..2f90b61
--- /dev/null
+++ b/tests/ui/should_impl_trait/method_list_2.edition2021.stderr
@@ -0,0 +1,184 @@
+error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
+ --> tests/ui/should_impl_trait/method_list_2.rs:28:5
+ |
+LL | / pub fn eq(&self, other: &Self) -> bool {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
+ = note: `-D clippy::should-implement-trait` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
+
+error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
+ --> tests/ui/should_impl_trait/method_list_2.rs:34:5
+ |
+LL | / pub fn from_iter<T>(iter: T) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
+
+error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
+ --> tests/ui/should_impl_trait/method_list_2.rs:40:5
+ |
+LL | / pub fn from_str(s: &str) -> Result<Self, Self> {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
+
+error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
+ --> tests/ui/should_impl_trait/method_list_2.rs:46:5
+ |
+LL | / pub fn hash(&self, state: &mut T) {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
+
+error: method `index` can be confused for the standard trait method `std::ops::Index::index`
+ --> tests/ui/should_impl_trait/method_list_2.rs:52:5
+ |
+LL | / pub fn index(&self, index: usize) -> &Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
+
+error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
+ --> tests/ui/should_impl_trait/method_list_2.rs:58:5
+ |
+LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
+
+error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
+ --> tests/ui/should_impl_trait/method_list_2.rs:64:5
+ |
+LL | / pub fn into_iter(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
+
+error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
+ --> tests/ui/should_impl_trait/method_list_2.rs:70:5
+ |
+LL | / pub fn mul(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
+
+error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
+ --> tests/ui/should_impl_trait/method_list_2.rs:76:5
+ |
+LL | / pub fn neg(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
+
+error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
+ --> tests/ui/should_impl_trait/method_list_2.rs:82:5
+ |
+LL | / pub fn next(&mut self) -> Option<Self> {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
+
+error: method `not` can be confused for the standard trait method `std::ops::Not::not`
+ --> tests/ui/should_impl_trait/method_list_2.rs:88:5
+ |
+LL | / pub fn not(self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
+
+error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
+ --> tests/ui/should_impl_trait/method_list_2.rs:94:5
+ |
+LL | / pub fn rem(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
+
+error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
+ --> tests/ui/should_impl_trait/method_list_2.rs:100:5
+ |
+LL | / pub fn shl(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
+
+error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
+ --> tests/ui/should_impl_trait/method_list_2.rs:106:5
+ |
+LL | / pub fn shr(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
+
+error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
+ --> tests/ui/should_impl_trait/method_list_2.rs:112:5
+ |
+LL | / pub fn sub(self, rhs: Self) -> Self {
+LL | |
+LL | |
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name
+
+error: aborting due to 15 previous errors
+
diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs
index 1f25ab3..4dfbe7e 100644
--- a/tests/ui/should_impl_trait/method_list_2.rs
+++ b/tests/ui/should_impl_trait/method_list_2.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2021
+//@[edition2015] edition:2015
+//@[edition2021] edition:2021
#![allow(
clippy::missing_errors_doc,
clippy::needless_pass_by_value,
@@ -29,7 +32,7 @@
}
pub fn from_iter<T>(iter: T) -> Self {
- //~^ should_implement_trait
+ //~[edition2021]^ should_implement_trait
unimplemented!()
}