Auto merge of #13286 - smoelius:elidable-impl-lifetimes, r=Alexendoo

Extend `needless_lifetimes` to suggest eliding `impl` lifetimes

Example:
```
error: the following explicit lifetimes could be elided: 'a
  --> tests/ui/needless_lifetimes.rs:332:10
   |
LL |     impl<'a> Foo for Baz<'a> {}
   |          ^^              ^^
   |
help: elide the lifetimes
   |
LL -     impl<'a> Foo for Baz<'a> {}
LL +     impl Foo for Baz<'_> {}
```
The main change is in how `impl` lifetime uses are tracked. Previously, a hashmap was created, and lifetimes were removed from the hashmap as their uses were discovered. However, the uses are needed to generate elision suggestions. So, now, uses are added to the hashmap as they are discovered.

The PR is currently organized as six commits, which I think are self-explanatory:
- Extend `needless_lifetimes` to suggest eliding `impl` lifetimes
- Reorder functions _[not strictly necessary, but IMHO, the code is better structured as a result]_
- Fix lifetime tests
- Fix non-lifetime tests
- Fix `clippy_lints` and `clippy_utils`
- Fix typo in `needless_lifetimes` test

r? `@Alexendoo` (I think you are `needless_lifetimes`' primary author? Sorry if I have this wrong.)

---

changelog: Extend `needless_lifetimes` to suggest eliding `impl` lifetimes
This commit is contained in:
bors 2024-10-01 00:41:21 +00:00
commit db1bda3df1
115 changed files with 796 additions and 618 deletions

View File

@ -205,7 +205,7 @@ struct Hir2Qmm<'a, 'tcx, 'v> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
impl<'v> Hir2Qmm<'_, '_, 'v> {
fn extract(&mut self, op: BinOpKind, a: &[&'v Expr<'_>], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
for a in a {
if let ExprKind::Binary(binop, lhs, rhs) = &a.kind {
@ -292,7 +292,7 @@ struct SuggestContext<'a, 'tcx, 'v> {
output: String,
}
impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
impl SuggestContext<'_, '_, '_> {
fn recurse(&mut self, suggestion: &Bool) -> Option<()> {
use quine_mc_cluskey::Bool::{And, False, Not, Or, Term, True};
match suggestion {
@ -475,7 +475,7 @@ fn terminal_stats(b: &Bool) -> Stats {
stats
}
impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> {
fn bool_expr(&self, e: &'tcx Expr<'_>) {
let mut h2q = Hir2Qmm {
terminals: Vec::new(),
@ -582,7 +582,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'_, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
if !e.span.from_expansion() {
match &e.kind {

View File

@ -91,7 +91,7 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>)
#[derive(Default)]
struct InferVisitor(bool);
impl<'tcx> Visitor<'tcx> for InferVisitor {
impl Visitor<'_> for InferVisitor {
fn visit_ty(&mut self, t: &Ty<'_>) {
self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
if !self.0 {

View File

@ -48,7 +48,7 @@ impl CheckedConversions {
impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]);
impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
impl LateLintPass<'_> for CheckedConversions {
fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
if let ExprKind::Binary(op, lhs, rhs) = item.kind
&& let (lt1, gt1, op2) = match op.node {

View File

@ -119,7 +119,7 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
match &expr.kind {
ExprKind::Block(

View File

@ -970,7 +970,7 @@ impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {

View File

@ -60,7 +60,7 @@ declare_clippy_lint! {
declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]);
impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
impl LateLintPass<'_> for EmptyEnum {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Enum(..) = item.kind
// Only suggest the `never_type` if the feature is enabled

View File

@ -141,7 +141,7 @@ fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool {
matches!(tcx.parent_hir_node(id), Node::Param(_))
}
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
if cmt.place.projections.is_empty() {
if let PlaceBase::Local(lid) = cmt.place.base {
@ -188,7 +188,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
impl<'tcx> EscapeDelegate<'_, 'tcx> {
fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
// Large types need to be boxed to avoid stack overflows.
if let Some(boxed_ty) = ty.boxed_ty() {

View File

@ -135,7 +135,7 @@ impl NestingVisitor<'_, '_> {
}
}
impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> {
impl Visitor<'_> for NestingVisitor<'_, '_> {
fn visit_block(&mut self, block: &Block) {
if block.span.from_expansion() {
return;

View File

@ -193,7 +193,7 @@ fn bound_to_trait_def_id(bound: &GenericBound<'_>) -> Option<LocalDefId> {
bound.trait_ref()?.trait_def_id()?.as_local()
}
impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {

View File

@ -73,7 +73,7 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
result: Vec<Span>,
}
impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr) {
if is_panic(self.lcx, macro_call.def_id) {

View File

@ -219,7 +219,7 @@ struct FormatArgsExpr<'a, 'tcx> {
ignore_mixed: bool,
}
impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
impl FormatArgsExpr<'_, '_> {
fn check_templates(&self) {
for piece in &self.format_args.template {
if let FormatArgsPiece::Placeholder(placeholder) = piece

View File

@ -148,7 +148,7 @@ struct FormatImplExpr<'a, 'tcx> {
format_trait_impl: FormatTraitNames,
}
impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
impl FormatImplExpr<'_, '_> {
fn check_to_string_in_display(&self) {
if self.format_trait_impl.name == sym::Display
&& let ExprKind::MethodCall(path, self_arg, ..) = self.expr.kind

View File

@ -126,7 +126,7 @@ struct SelfFinder<'a, 'tcx> {
invalid: bool,
}
impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for SelfFinder<'_, 'tcx> {
type NestedFilter = OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {

View File

@ -281,7 +281,7 @@ impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'_, 'tcx> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
if let Some(target) = ImplicitHasherType::new(self.cx, t) {
self.found.push(target);
@ -318,7 +318,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
}
}
impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_body(&mut self, body: &Body<'tcx>) {

View File

@ -226,7 +226,7 @@ struct SliceIndexLintingVisitor<'a, 'tcx> {
max_suggested_slice: u64,
}
impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {

View File

@ -6,12 +6,12 @@ use rustc_errors::Applicability;
use rustc_hir::FnRetTy::Return;
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
use rustc_hir::intravisit::{
Visitor, walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
walk_poly_trait_ref, walk_trait_ref, walk_ty,
Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_where_predicate,
};
use rustc_hir::{
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl,
ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -21,7 +21,7 @@ use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol, kw};
use rustc_span::symbol::{Ident, kw};
use std::ops::ControlFlow;
declare_clippy_lint! {
@ -191,45 +191,10 @@ fn check_fn_inner<'tcx>(
if usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span)) {
return;
}
let lts = elidable_lts
.iter()
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
// `Node::GenericParam`.
.filter_map(|&def_id| cx.tcx.hir_node_by_def_id(def_id).ident())
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ");
span_lint_and_then(
cx,
NEEDLESS_LIFETIMES,
elidable_lts
.iter()
.map(|&lt| cx.tcx.def_span(lt))
.chain(usages.iter().filter_map(|usage| {
if let LifetimeName::Param(def_id) = usage.res
&& elidable_lts.contains(&def_id)
{
return Some(usage.ident.span);
}
None
}))
.collect_vec(),
format!("the following explicit lifetimes could be elided: {lts}"),
|diag| {
if sig.header.is_async() {
// async functions have usages whose spans point at the lifetime declaration which messes up
// suggestions
return;
};
if let Some(suggestions) = elision_suggestions(cx, generics, &elidable_lts, &usages) {
diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
}
},
);
// async functions have usages whose spans point at the lifetime declaration which messes up
// suggestions
let include_suggestions = !sig.header.is_async();
report_elidable_lifetimes(cx, generics, &elidable_lts, &usages, include_suggestions);
}
if report_extra_lifetimes {
@ -237,97 +202,6 @@ fn check_fn_inner<'tcx>(
}
}
fn elision_suggestions(
cx: &LateContext<'_>,
generics: &Generics<'_>,
elidable_lts: &[LocalDefId],
usages: &[Lifetime],
) -> Option<Vec<(Span, String)>> {
let explicit_params = generics
.params
.iter()
.filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
.collect::<Vec<_>>();
let mut suggestions = if elidable_lts.len() == explicit_params.len() {
// if all the params are elided remove the whole generic block
//
// fn x<'a>() {}
// ^^^^
vec![(generics.span, String::new())]
} else {
elidable_lts
.iter()
.map(|&id| {
let pos = explicit_params.iter().position(|param| param.def_id == id)?;
let param = explicit_params.get(pos)?;
let span = if let Some(next) = explicit_params.get(pos + 1) {
// fn x<'prev, 'a, 'next>() {}
// ^^^^
param.span.until(next.span)
} else {
// `pos` should be at least 1 here, because the param in position 0 would either have a `next`
// param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
let prev = explicit_params.get(pos - 1)?;
// fn x<'prev, 'a>() {}
// ^^^^
param.span.with_lo(prev.span.hi())
};
Some((span, String::new()))
})
.collect::<Option<Vec<_>>>()?
};
suggestions.extend(
usages
.iter()
.filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
.map(|usage| {
match cx.tcx.parent_hir_node(usage.hir_id) {
Node::Ty(Ty {
kind: TyKind::Ref(..), ..
}) => {
// expand `&'a T` to `&'a T`
// ^^ ^^^
let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span);
(span, String::new())
},
// `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
_ => (usage.ident.span, String::from("'_")),
}
}),
);
Some(suggestions)
}
// elision doesn't work for explicit self types, see rust-lang/rust#69064
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
if let Some(ident) = ident
&& ident.name == kw::SelfLower
&& !func.implicit_self.has_implicit_self()
&& let Some(self_ty) = func.inputs.first()
{
let mut visitor = RefVisitor::new(cx);
visitor.visit_ty(self_ty);
!visitor.all_lts().is_empty()
} else {
false
}
}
fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
match lt.res {
LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
_ => None,
}
}
fn could_use_elision<'tcx>(
cx: &LateContext<'tcx>,
func: &'tcx FnDecl<'_>,
@ -450,6 +324,22 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<LocalDefId
.collect()
}
// elision doesn't work for explicit self types, see rust-lang/rust#69064
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
if let Some(ident) = ident
&& ident.name == kw::SelfLower
&& !func.implicit_self.has_implicit_self()
&& let Some(self_ty) = func.inputs.first()
{
let mut visitor = RefVisitor::new(cx);
visitor.visit_ty(self_ty);
!visitor.all_lts().is_empty()
} else {
false
}
}
/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
/// relative order.
#[must_use]
@ -470,6 +360,13 @@ fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> {
occurrences
}
fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
match lt.res {
LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
_ => None,
}
}
struct RefVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
lts: Vec<Lifetime>,
@ -500,7 +397,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.lts.push(*lifetime);
@ -594,23 +491,43 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
false
}
struct Usage {
lifetime: Lifetime,
in_where_predicate: bool,
in_generics_arg: bool,
}
struct LifetimeChecker<'cx, 'tcx, F> {
cx: &'cx LateContext<'tcx>,
map: FxHashMap<Symbol, Span>,
map: FxHashMap<LocalDefId, Vec<Usage>>,
where_predicate_depth: usize,
generic_args_depth: usize,
phantom: std::marker::PhantomData<F>,
}
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
fn new(cx: &'cx LateContext<'tcx>, map: FxHashMap<Symbol, Span>) -> LifetimeChecker<'cx, 'tcx, F> {
fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> {
let map = generics
.params
.iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.def_id, Vec::new())),
_ => None,
})
.collect();
Self {
cx,
map,
where_predicate_depth: 0,
generic_args_depth: 0,
phantom: std::marker::PhantomData,
}
}
}
impl<'cx, 'tcx, F> Visitor<'tcx> for LifetimeChecker<'cx, 'tcx, F>
impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
where
F: NestedFilter<'tcx>,
{
@ -619,18 +536,27 @@ where
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.map.remove(&lifetime.ident.name);
if let LifetimeName::Param(def_id) = lifetime.res
&& let Some(usages) = self.map.get_mut(&def_id)
{
usages.push(Usage {
lifetime: *lifetime,
in_where_predicate: self.where_predicate_depth != 0,
in_generics_arg: self.generic_args_depth != 0,
});
}
}
fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
// don't actually visit `<'a>` or `<'a: 'b>`
// we've already visited the `'a` declarations and
// don't want to spuriously remove them
// `'b` in `'a: 'b` is useless unless used elsewhere in
// a non-lifetime bound
if let GenericParamKind::Type { .. } = param.kind {
walk_generic_param(self, param);
}
fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
self.where_predicate_depth += 1;
walk_where_predicate(self, predicate);
self.where_predicate_depth -= 1;
}
fn visit_generic_args(&mut self, generic_args: &'tcx GenericArgs<'tcx>) -> Self::Result {
self.generic_args_depth += 1;
walk_generic_args(self, generic_args);
self.generic_args_depth -= 1;
}
fn nested_visit_map(&mut self) -> Self::Map {
@ -639,44 +565,28 @@ where
}
fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) {
let hs = generics
.params
.iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None,
})
.collect();
let mut checker = LifetimeChecker::<hir_nested_filter::None>::new(cx, hs);
let mut checker = LifetimeChecker::<hir_nested_filter::None>::new(cx, generics);
walk_generics(&mut checker, generics);
walk_fn_decl(&mut checker, func);
for &v in checker.map.values() {
span_lint(
cx,
EXTRA_UNUSED_LIFETIMES,
v,
"this lifetime isn't used in the function definition",
);
for (def_id, usages) in checker.map {
if usages
.iter()
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
{
span_lint(
cx,
EXTRA_UNUSED_LIFETIMES,
cx.tcx.def_span(def_id),
"this lifetime isn't used in the function definition",
);
}
}
}
fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>) {
let hs = impl_
.generics
.params
.iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None,
})
.collect();
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, hs);
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, impl_.generics);
walk_generics(&mut checker, impl_.generics);
if let Some(ref trait_ref) = impl_.of_trait {
@ -687,9 +597,176 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
walk_impl_item_ref(&mut checker, item);
}
for &v in checker.map.values() {
span_lint(cx, EXTRA_UNUSED_LIFETIMES, v, "this lifetime isn't used in the impl");
for (&def_id, usages) in &checker.map {
if usages
.iter()
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
{
span_lint(
cx,
EXTRA_UNUSED_LIFETIMES,
cx.tcx.def_span(def_id),
"this lifetime isn't used in the impl",
);
}
}
report_elidable_impl_lifetimes(cx, impl_, &checker.map);
}
// An `impl` lifetime is elidable if it satisfies the following conditions:
// - It is used exactly once.
// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
// different from `GenericParam`s.)
fn report_elidable_impl_lifetimes<'tcx>(
cx: &LateContext<'tcx>,
impl_: &'tcx Impl<'_>,
map: &FxHashMap<LocalDefId, Vec<Usage>>,
) {
let single_usages = map
.iter()
.filter_map(|(def_id, usages)| {
if let [
Usage {
lifetime,
in_where_predicate: false,
..
}
| Usage {
lifetime,
in_generics_arg: false,
..
},
] = usages.as_slice()
{
Some((def_id, lifetime))
} else {
None
}
})
.collect::<Vec<_>>();
if single_usages.is_empty() {
return;
}
let (elidable_lts, usages): (Vec<_>, Vec<_>) = single_usages.into_iter().unzip();
report_elidable_lifetimes(cx, impl_.generics, &elidable_lts, &usages, true);
}
/// Generate diagnostic messages for elidable lifetimes.
fn report_elidable_lifetimes(
cx: &LateContext<'_>,
generics: &Generics<'_>,
elidable_lts: &[LocalDefId],
usages: &[Lifetime],
include_suggestions: bool,
) {
let lts = elidable_lts
.iter()
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
// `Node::GenericParam`.
.filter_map(|&def_id| cx.tcx.hir_node_by_def_id(def_id).ident())
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ");
span_lint_and_then(
cx,
NEEDLESS_LIFETIMES,
elidable_lts
.iter()
.map(|&lt| cx.tcx.def_span(lt))
.chain(usages.iter().filter_map(|usage| {
if let LifetimeName::Param(def_id) = usage.res
&& elidable_lts.contains(&def_id)
{
return Some(usage.ident.span);
}
None
}))
.collect_vec(),
format!("the following explicit lifetimes could be elided: {lts}"),
|diag| {
if !include_suggestions {
return;
};
if let Some(suggestions) = elision_suggestions(cx, generics, elidable_lts, usages) {
diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
}
},
);
}
fn elision_suggestions(
cx: &LateContext<'_>,
generics: &Generics<'_>,
elidable_lts: &[LocalDefId],
usages: &[Lifetime],
) -> Option<Vec<(Span, String)>> {
let explicit_params = generics
.params
.iter()
.filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
.collect::<Vec<_>>();
let mut suggestions = if elidable_lts.len() == explicit_params.len() {
// if all the params are elided remove the whole generic block
//
// fn x<'a>() {}
// ^^^^
vec![(generics.span, String::new())]
} else {
elidable_lts
.iter()
.map(|&id| {
let pos = explicit_params.iter().position(|param| param.def_id == id)?;
let param = explicit_params.get(pos)?;
let span = if let Some(next) = explicit_params.get(pos + 1) {
// fn x<'prev, 'a, 'next>() {}
// ^^^^
param.span.until(next.span)
} else {
// `pos` should be at least 1 here, because the param in position 0 would either have a `next`
// param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
let prev = explicit_params.get(pos - 1)?;
// fn x<'prev, 'a>() {}
// ^^^^
param.span.with_lo(prev.span.hi())
};
Some((span, String::new()))
})
.collect::<Option<Vec<_>>>()?
};
suggestions.extend(
usages
.iter()
.filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
.map(|usage| {
match cx.tcx.parent_hir_node(usage.hir_id) {
Node::Ty(Ty {
kind: TyKind::Ref(..), ..
}) => {
// expand `&'a T` to `&'a T`
// ^^ ^^^
let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span);
(span, String::new())
},
// `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
_ => (usage.ident.span, String::from("'_")),
}
}),
);
Some(suggestions)
}
struct BodyLifetimeChecker;

View File

@ -209,7 +209,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
#[derive(Clone)]
struct MinifyingSugg<'a>(Sugg<'a>);
impl<'a> Display for MinifyingSugg<'a> {
impl Display for MinifyingSugg<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}

View File

@ -241,7 +241,7 @@ struct VarVisitor<'a, 'tcx> {
prefer_mutable: bool,
}
impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
impl<'tcx> VarVisitor<'_, 'tcx> {
fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) -> bool {
if let ExprKind::Path(ref seqpath) = seqexpr.kind
// the indexed container is referenced by a name
@ -292,7 +292,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind
// a range index op

View File

@ -123,7 +123,7 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for SameItemPushVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
match &expr.kind {
// Non-determinism may occur ... don't give a lint

View File

@ -44,7 +44,7 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for IncrementVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
// If node is a variable
if let Some(def_id) = path_to_local(expr) {
@ -138,7 +138,7 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for InitializeVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_local(&mut self, l: &'tcx LetStmt<'_>) {

View File

@ -84,7 +84,7 @@ struct VarCollectorVisitor<'a, 'tcx> {
skip: bool,
}
impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
impl<'tcx> VarCollectorVisitor<'_, 'tcx> {
fn insert_def_id(&mut self, ex: &'tcx Expr<'_>) {
if let ExprKind::Path(ref qpath) = ex.kind
&& let QPath::Resolved(None, _) = *qpath
@ -103,7 +103,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for VarCollectorVisitor<'_, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
match ex.kind {
ExprKind::Path(_) => self.insert_def_id(ex),

View File

@ -283,7 +283,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
found_local: bool,
used_after: bool,
}
impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedLoopVisitor<'a, 'b, 'tcx> {
impl<'tcx> Visitor<'tcx> for NestedLoopVisitor<'_, '_, 'tcx> {
type NestedFilter = OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
self.cx.tcx.hir()

View File

@ -149,7 +149,7 @@ fn is_public_macro(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
&& !cx.tcx.is_doc_hidden(def_id)
}
impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for BodyVisitor<'_, 'tcx> {
fn visit_stmt(&mut self, s: &'tcx Stmt<'tcx>) {
let from_expn = s.span.from_expansion();
if from_expn {

View File

@ -81,7 +81,7 @@ impl MacroUseImports {
}
}
impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
impl LateLintPass<'_> for MacroUseImports {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if cx.sess().opts.edition >= Edition::Edition2018
&& let hir::ItemKind::Use(path, _kind) = &item.kind

View File

@ -741,7 +741,7 @@ enum MaybeBorrowedStmtKind<'a> {
Owned(StmtKind<'a>),
}
impl<'a> Clone for MaybeBorrowedStmtKind<'a> {
impl Clone for MaybeBorrowedStmtKind<'_> {
fn clone(&self) -> Self {
match self {
Self::Borrowed(t) => Self::Borrowed(t),

View File

@ -203,7 +203,7 @@ fn find_stripping<'tcx>(
results: Vec<Span>,
}
impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for StrippingFinder<'_, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
if is_ref_str(self.cx, ex)
&& let unref = peel_ref(ex)

View File

@ -251,7 +251,7 @@ fn lint_map_unit_fn(
}
}
impl<'tcx> LateLintPass<'tcx> for MapUnit {
impl LateLintPass<'_> for MapUnit {
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &hir::Stmt<'_>) {
if let hir::StmtKind::Semi(expr) = stmt.kind
&& !stmt.span.from_expansion()

View File

@ -40,7 +40,7 @@ struct MatchExprVisitor<'a, 'tcx> {
case_method: Option<CaseMethod>,
}
impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for MatchExprVisitor<'_, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
match ex.kind {
ExprKind::MethodCall(segment, receiver, [], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
@ -49,7 +49,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> MatchExprVisitor<'a, 'tcx> {
impl MatchExprVisitor<'_, '_> {
fn case_altered(&mut self, segment_ident: &str, receiver: &Expr<'_>) -> bool {
if let Some(case_method) = get_case_method(segment_ident) {
let ty = self.cx.typeck_results().expr_ty(receiver).peel_refs();

View File

@ -96,13 +96,13 @@ where
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct RangeBound<'a, T>(T, BoundKind, &'a SpannedRange<T>);
impl<'a, T: Copy + Ord> PartialOrd for RangeBound<'a, T> {
impl<T: Copy + Ord> PartialOrd for RangeBound<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'a, T: Copy + Ord> Ord for RangeBound<'a, T> {
impl<T: Copy + Ord> Ord for RangeBound<'_, T> {
fn cmp(&self, RangeBound(other_value, other_kind, _): &Self) -> Ordering {
let RangeBound(self_value, self_kind, _) = *self;
(self_value, self_kind).cmp(&(*other_value, *other_kind))

View File

@ -424,7 +424,7 @@ fn ty_has_erased_regions(ty: Ty<'_>) -> bool {
ty.visit_with(&mut V).is_break()
}
impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for SigDropHelper<'_, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
// We've emitted a lint on some neighborhood expression. That lint will suggest to move out the
// _parent_ expression (not the expression itself). Since we decide to move out the parent
@ -495,7 +495,7 @@ fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &[&'tcx Expr
helper.found_sig_drop_spans
}
impl<'a, 'tcx> Visitor<'tcx> for ArmSigDropHelper<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ArmSigDropHelper<'_, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
if self.sig_drop_checker.is_sig_drop_expr(ex) {
self.found_sig_drop_spans.insert(ex.span);

View File

@ -441,7 +441,7 @@ struct UsedCountVisitor<'a, 'tcx> {
count: usize,
}
impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for UsedCountVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {

View File

@ -130,7 +130,7 @@ struct UnwrapVisitor<'a, 'tcx> {
identifiers: FxHashSet<HirId>,
}
impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::All;
fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) {
@ -154,7 +154,7 @@ struct ReferenceVisitor<'a, 'tcx> {
unwrap_or_span: Span,
}
impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::All;
type Result = ControlFlow<()>;
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> {

View File

@ -86,7 +86,7 @@ struct CloneOrCopyVisitor<'cx, 'tcx> {
references_to_binding: Vec<(Span, String)>,
}
impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
impl<'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
@ -123,7 +123,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
}
}
impl<'cx, 'tcx> CloneOrCopyVisitor<'cx, 'tcx> {
impl<'tcx> CloneOrCopyVisitor<'_, 'tcx> {
fn is_binding(&self, expr: &Expr<'tcx>) -> bool {
self.binding_hir_ids
.iter()

View File

@ -116,7 +116,7 @@ struct DivergenceVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
impl<'tcx> DivergenceVisitor<'_, 'tcx> {
fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) {
match e.kind {
ExprKind::Closure(..) | ExprKind::If(..) | ExprKind::Loop(..) => {},
@ -148,7 +148,7 @@ fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
!matches!(stmt.kind, StmtKind::Item(..))
}
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for DivergenceVisitor<'_, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
match e.kind {
// fix #10776
@ -321,7 +321,7 @@ struct ReadVisitor<'a, 'tcx> {
last_expr: &'tcx Expr<'tcx>,
}
impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if expr.hir_id == self.last_expr.hir_id {
return;

View File

@ -55,7 +55,7 @@ pub struct MutVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
if in_external_macro(self.cx.sess(), expr.span) {
return;

View File

@ -87,7 +87,7 @@ impl<'a, 'tcx> MutArgVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for MutArgVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {

View File

@ -133,7 +133,7 @@ struct RetCollector {
loop_depth: u16,
}
impl<'tcx> Visitor<'tcx> for RetCollector {
impl Visitor<'_> for RetCollector {
fn visit_expr(&mut self, expr: &Expr<'_>) {
match expr.kind {
ExprKind::Ret(..) => {

View File

@ -311,7 +311,7 @@ struct MutablyUsedVariablesCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutablyUsedVariablesCtxt<'tcx> {
impl MutablyUsedVariablesCtxt<'_> {
fn add_mutably_used_var(&mut self, used_id: HirId) {
self.mutably_used_vars.insert(used_id);
}

View File

@ -104,7 +104,7 @@ struct SimilarNamesLocalVisitor<'a, 'tcx> {
single_char_names: Vec<Vec<Ident>>,
}
impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
impl SimilarNamesLocalVisitor<'_, '_> {
fn check_single_char_names(&self) {
if self.single_char_names.last().map(Vec::len) == Some(0) {
return;
@ -152,7 +152,7 @@ fn chars_are_similar(a: char, b: char) -> bool {
struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> {
impl<'tcx> Visitor<'tcx> for SimilarNamesNameVisitor<'_, 'tcx, '_> {
fn visit_pat(&mut self, pat: &'tcx Pat) {
match pat.kind {
PatKind::Ident(_, ident, _) => {
@ -189,7 +189,7 @@ fn allowed_to_be_similar(interned_name: &str, list: &[&str]) -> bool {
.any(|&name| interned_name.starts_with(name) || interned_name.ends_with(name))
}
impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
impl SimilarNamesNameVisitor<'_, '_, '_> {
fn check_short_ident(&mut self, ident: Ident) {
// Ignore shadowing
if self
@ -329,7 +329,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
}
}
impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> {
impl SimilarNamesLocalVisitor<'_, '_> {
/// ensure scoping rules work
fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
let n = self.names.len();
@ -340,7 +340,7 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'_, 'tcx> {
fn visit_local(&mut self, local: &'tcx Local) {
if let Some((init, els)) = &local.kind.init_else_opt() {
self.apply(|this| walk_expr(this, init));

View File

@ -159,7 +159,7 @@ struct NonSendField<'tcx> {
generic_params: Vec<Ty<'tcx>>,
}
impl<'tcx> NonSendField<'tcx> {
impl NonSendField<'_> {
fn generic_params_string(&self) -> String {
self.generic_params
.iter()

View File

@ -110,7 +110,7 @@ pub struct PassByRefOrValue {
avoid_breaking_exported_api: bool,
}
impl<'tcx> PassByRefOrValue {
impl PassByRefOrValue {
pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
let ref_min_size = conf.trivial_copy_size_limit.unwrap_or_else(|| {
let bit_width = u64::from(tcx.sess.target.pointer_width);
@ -130,7 +130,7 @@ impl<'tcx> PassByRefOrValue {
}
}
fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &FnDecl<'_>, span: Option<Span>) {
fn check_poly_fn(&mut self, cx: &LateContext<'_>, def_id: LocalDefId, decl: &FnDecl<'_>, span: Option<Span>) {
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}

View File

@ -60,7 +60,7 @@ struct PathbufPushSearcher<'tcx> {
err_span: Span,
}
impl<'tcx> PathbufPushSearcher<'tcx> {
impl PathbufPushSearcher<'_> {
/// Try to generate a suggestion with `PathBuf::from`.
/// Returns `None` if the suggestion would be invalid.
fn gen_pathbuf_from(&self, cx: &LateContext<'_>) -> Option<String> {

View File

@ -228,7 +228,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
path: &'tcx hir::Path<'tcx>,
count: usize,
}
impl<'a, 'tcx> Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ClosureUsageCount<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {

View File

@ -140,7 +140,7 @@ enum RetReplacement<'tcx> {
Expr(Cow<'tcx, str>, Applicability),
}
impl<'tcx> RetReplacement<'tcx> {
impl RetReplacement<'_> {
fn sugg_help(&self) -> &'static str {
match self {
Self::Empty | Self::Expr(..) => "remove `return`",
@ -158,7 +158,7 @@ impl<'tcx> RetReplacement<'tcx> {
}
}
impl<'tcx> Display for RetReplacement<'tcx> {
impl Display for RetReplacement<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Empty => write!(f, ""),

View File

@ -249,7 +249,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx
}
}
impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
self.ap.curr_block_hir_id = block.hir_id;
self.ap.curr_block_span = block.span;

View File

@ -102,7 +102,7 @@ struct ImportUsageVisitor {
imports_referenced_with_self: Vec<Symbol>,
}
impl<'tcx> Visitor<'tcx> for ImportUsageVisitor {
impl Visitor<'_> for ImportUsageVisitor {
fn visit_expr(&mut self, expr: &Expr) {
if let ExprKind::Path(_, path) = &expr.kind
&& path.segments.len() > 1

View File

@ -229,7 +229,7 @@ struct VectorInitializationVisitor<'a, 'tcx> {
initialization_found: bool,
}
impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
impl<'tcx> VectorInitializationVisitor<'_, 'tcx> {
/// Checks if the given expression is extending a vector with `repeat(0).take(..)`
fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
if self.initialization_found
@ -299,7 +299,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for VectorInitializationVisitor<'_, 'tcx> {
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
if self.initialization_found {
match stmt.kind {

View File

@ -332,7 +332,7 @@ struct IndexBinding<'a, 'tcx> {
applicability: &'a mut Applicability,
}
impl<'a, 'tcx> IndexBinding<'a, 'tcx> {
impl<'tcx> IndexBinding<'_, 'tcx> {
fn snippet_index_bindings(&mut self, exprs: &[&'tcx Expr<'tcx>]) -> String {
let mut bindings = FxHashSet::default();
for expr in exprs {

View File

@ -67,7 +67,7 @@ struct AsyncFnVisitor<'a, 'tcx> {
async_depth: usize,
}
impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for AsyncFnVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {

View File

@ -235,7 +235,7 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
impl<'tcx> UnwrappableVariablesVisitor<'_, 'tcx> {
fn visit_branch(
&mut self,
if_expr: &'tcx Expr<'_>,
@ -288,7 +288,7 @@ fn consume_option_as_ref<'tcx>(expr: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, Opt
}
}
impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {

View File

@ -280,7 +280,7 @@ struct SkipTyCollector {
types_to_skip: Vec<HirId>,
}
impl<'tcx> Visitor<'tcx> for SkipTyCollector {
impl Visitor<'_> for SkipTyCollector {
fn visit_infer(&mut self, inf: &hir::InferArg) {
self.types_to_skip.push(inf.hir_id);

View File

@ -270,7 +270,7 @@ struct LintCollector<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for LintCollector<'_, 'tcx> {
type NestedFilter = nested_filter::All;
fn visit_path(&mut self, path: &Path<'_>, _: HirId) {

View File

@ -118,7 +118,7 @@ enum WaitFinder<'a, 'tcx> {
Found(&'a LateContext<'tcx>, HirId),
}
impl<'a, 'tcx> Visitor<'tcx> for WaitFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> {
type Result = ControlFlow<BreakReason>;
fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) -> Self::Result {
@ -300,7 +300,7 @@ struct ExitPointFinder<'a, 'tcx> {
struct ExitCallFound;
impl<'a, 'tcx> Visitor<'tcx> for ExitPointFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ExitPointFinder<'_, 'tcx> {
type Result = ControlFlow<ExitCallFound>;
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {

View File

@ -118,7 +118,7 @@ impl IntTypeBounds for IntTy {
}
}
impl<'tcx> PartialEq for Constant<'tcx> {
impl PartialEq for Constant<'_> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Str(ls), Self::Str(rs)) => ls == rs,
@ -147,7 +147,7 @@ impl<'tcx> PartialEq for Constant<'tcx> {
}
}
impl<'tcx> Hash for Constant<'tcx> {
impl Hash for Constant<'_> {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
@ -203,7 +203,7 @@ impl<'tcx> Hash for Constant<'tcx> {
}
}
impl<'tcx> Constant<'tcx> {
impl Constant<'_> {
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
match (left, right) {
(Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),

View File

@ -118,7 +118,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
eagerness: EagernessSuggestion,
}
impl<'cx, 'tcx> Visitor<'tcx> for V<'cx, 'tcx> {
impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
use EagernessSuggestion::{ForceNoChange, Lazy, NoChange};
if self.eagerness == ForceNoChange {

View File

@ -1345,7 +1345,7 @@ pub struct ContainsName<'a, 'tcx> {
pub result: bool,
}
impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ContainsName<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_name(&mut self, name: Symbol) {
@ -3115,7 +3115,7 @@ pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<
is_never: bool,
}
impl<'tcx> V<'_, 'tcx> {
impl V<'_, '_> {
fn push_break_target(&mut self, id: HirId) {
self.break_targets.push(BreakTarget { id, unused: true });
self.break_targets_for_result_ty += u32::from(self.in_final_expr);

View File

@ -58,7 +58,7 @@ struct V<'a> {
results: Vec<LocalUsage>,
}
impl<'a, 'tcx> Visitor<'tcx> for V<'a> {
impl<'tcx> Visitor<'tcx> for V<'_> {
fn visit_place(&mut self, place: &Place<'tcx>, ctx: PlaceContext, loc: Location) {
if loc.block == self.location.block && loc.statement_index <= self.location.statement_index {
return;

View File

@ -65,7 +65,7 @@ impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
}
}
impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> {
impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> {
fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
let lhs = place.local;
match rvalue {
@ -177,8 +177,8 @@ pub struct PossibleBorrowerMap<'b, 'tcx> {
pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
}
impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
let possible_origin = {
let mut vis = PossibleOriginVisitor::new(mir);
vis.visit_body(mir);

View File

@ -39,7 +39,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
impl<'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'_, 'tcx> {
fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
let lhs = place.local;
match rvalue {

View File

@ -108,7 +108,7 @@ impl<'cx, 'tcx> CertaintyVisitor<'cx, 'tcx> {
}
}
impl<'cx, 'tcx> Visitor<'cx> for CertaintyVisitor<'cx, 'tcx> {
impl<'cx> Visitor<'cx> for CertaintyVisitor<'cx, '_> {
fn visit_qpath(&mut self, qpath: &'cx QPath<'_>, hir_id: HirId, _: Span) {
self.certainty = self.certainty.meet(qpath_certainty(self.cx, qpath, true));
if self.certainty != Certainty::Uncertain {

View File

@ -46,8 +46,8 @@ struct MutVarsDelegate {
skip: bool,
}
impl<'tcx> MutVarsDelegate {
fn update(&mut self, cat: &PlaceWithHirId<'tcx>) {
impl MutVarsDelegate {
fn update(&mut self, cat: &PlaceWithHirId<'_>) {
match cat.place.base {
PlaceBase::Local(id) => {
self.used_mutably.insert(id);
@ -122,7 +122,7 @@ impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> {
finder.usage_found
}
}
impl<'a, 'tcx> Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {

View File

@ -552,7 +552,7 @@ pub fn for_each_local_use_after_expr<'tcx, B>(
res: ControlFlow<B>,
f: F,
}
impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> {
impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'_, 'tcx, F, B> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
self.cx.tcx.hir()
@ -734,7 +734,7 @@ pub fn for_each_local_assignment<'tcx, B>(
res: ControlFlow<B>,
f: F,
}
impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> {
impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'_, 'tcx, F, B> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
self.cx.tcx.hir()

View File

@ -7,7 +7,8 @@
clippy::no_effect,
clippy::unnecessary_operation,
clippy::useless_vec,
clippy::out_of_bounds_indexing
clippy::out_of_bounds_indexing,
clippy::needless_lifetimes
)]
const ARR: [i32; 2] = [1, 2];

View File

@ -1,5 +1,5 @@
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:26:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:27:5
|
LL | x[index];
| ^^^^^^^^
@ -9,7 +9,7 @@ LL | x[index];
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:41:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:42:5
|
LL | v[0];
| ^^^^
@ -17,7 +17,7 @@ LL | v[0];
= help: consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:42:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:43:5
|
LL | v[10];
| ^^^^^
@ -25,7 +25,7 @@ LL | v[10];
= help: consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:43:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:44:5
|
LL | v[1 << 3];
| ^^^^^^^^^
@ -33,7 +33,7 @@ LL | v[1 << 3];
= help: consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:49:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:50:5
|
LL | v[N];
| ^^^^
@ -41,7 +41,7 @@ LL | v[N];
= help: consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic
--> tests/ui-toml/suppress_lint_in_const/test.rs:50:5
--> tests/ui-toml/suppress_lint_in_const/test.rs:51:5
|
LL | v[M];
| ^^^^

View File

@ -3,7 +3,8 @@
#![allow(
clippy::uninlined_format_args,
clippy::disallowed_names,
clippy::needless_pass_by_ref_mut
clippy::needless_pass_by_ref_mut,
clippy::needless_lifetimes
)]
use std::fmt::Display;

View File

@ -3,7 +3,8 @@
#![allow(
clippy::uninlined_format_args,
clippy::disallowed_names,
clippy::needless_pass_by_ref_mut
clippy::needless_pass_by_ref_mut,
clippy::needless_lifetimes
)]
use std::fmt::Display;

View File

@ -1,5 +1,5 @@
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:24:14
--> tests/ui/borrow_box.rs:25:14
|
LL | let foo: &Box<bool>;
| ^^^^^^^^^^ help: try: `&bool`
@ -11,55 +11,55 @@ LL | #![deny(clippy::borrowed_box)]
| ^^^^^^^^^^^^^^^^^^^^
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:29:10
--> tests/ui/borrow_box.rs:30:10
|
LL | foo: &'a Box<bool>,
| ^^^^^^^^^^^^^ help: try: `&'a bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:34:17
--> tests/ui/borrow_box.rs:35:17
|
LL | fn test4(a: &Box<bool>);
| ^^^^^^^^^^ help: try: `&bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:95:25
--> tests/ui/borrow_box.rs:96:25
|
LL | pub fn test14(_display: &Box<dyn Display>) {}
| ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:97:25
--> tests/ui/borrow_box.rs:98:25
|
LL | pub fn test15(_display: &Box<dyn Display + Send>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:99:29
--> tests/ui/borrow_box.rs:100:29
|
LL | pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:102:25
--> tests/ui/borrow_box.rs:103:25
|
LL | pub fn test17(_display: &Box<impl Display>) {}
| ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:104:25
--> tests/ui/borrow_box.rs:105:25
|
LL | pub fn test18(_display: &Box<impl Display + Send>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:106:29
--> tests/ui/borrow_box.rs:107:29
|
LL | pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> tests/ui/borrow_box.rs:112:25
--> tests/ui/borrow_box.rs:113:25
|
LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`

View File

@ -3,7 +3,8 @@
clippy::needless_pass_by_value,
clippy::unused_unit,
clippy::redundant_clone,
clippy::match_single_binding
clippy::match_single_binding,
clippy::needless_lifetimes
)]
#![warn(clippy::boxed_local)]

View File

@ -1,5 +1,5 @@
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:39:13
--> tests/ui/boxed_local.rs:40:13
|
LL | fn warn_arg(x: Box<A>) {
| ^
@ -8,19 +8,19 @@ LL | fn warn_arg(x: Box<A>) {
= help: to override `-D warnings` add `#[allow(clippy::boxed_local)]`
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:122:12
--> tests/ui/boxed_local.rs:123:12
|
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
| ^^^^^^^^^^^
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:187:44
--> tests/ui/boxed_local.rs:188:44
|
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
| ^
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:195:16
--> tests/ui/boxed_local.rs:196:16
|
LL | fn foo(x: Box<u32>) {}
| ^

View File

@ -9,7 +9,7 @@ struct Baz<'a> {
bar: &'a Bar,
}
impl<'a> Foo for Baz<'a> {}
impl Foo for Baz<'_> {}
impl Bar {
fn baz(&self) -> impl Foo + '_ {

View File

@ -1,8 +1,8 @@
error: the following explicit lifetimes could be elided: 'a
--> tests/ui/crashes/needless_lifetimes_impl_trait.rs:15:12
--> tests/ui/crashes/needless_lifetimes_impl_trait.rs:12:6
|
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
| ^^ ^^ ^^
LL | impl<'a> Foo for Baz<'a> {}
| ^^ ^^
|
note: the lint level is defined here
--> tests/ui/crashes/needless_lifetimes_impl_trait.rs:1:9
@ -11,9 +11,21 @@ LL | #![deny(clippy::needless_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: elide the lifetimes
|
LL - impl<'a> Foo for Baz<'a> {}
LL + impl Foo for Baz<'_> {}
|
error: the following explicit lifetimes could be elided: 'a
--> tests/ui/crashes/needless_lifetimes_impl_trait.rs:15:12
|
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
| ^^ ^^ ^^
|
help: elide the lifetimes
|
LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
LL + fn baz(&self) -> impl Foo + '_ {
|
error: aborting due to 1 previous error
error: aborting due to 2 previous errors

View File

@ -1,4 +1,9 @@
#![allow(clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, dead_code)]
#![allow(
clippy::non_canonical_clone_impl,
clippy::non_canonical_partial_ord_impl,
clippy::needless_lifetimes,
dead_code
)]
#![warn(clippy::expl_impl_clone_on_copy)]
#[derive(Copy)]

View File

@ -1,5 +1,5 @@
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:7:1
--> tests/ui/derive.rs:12:1
|
LL | / impl Clone for Qux {
LL | |
@ -10,7 +10,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:7:1
--> tests/ui/derive.rs:12:1
|
LL | / impl Clone for Qux {
LL | |
@ -23,7 +23,7 @@ LL | | }
= help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]`
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:32:1
--> tests/ui/derive.rs:37:1
|
LL | / impl<'a> Clone for Lt<'a> {
LL | |
@ -34,7 +34,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:32:1
--> tests/ui/derive.rs:37:1
|
LL | / impl<'a> Clone for Lt<'a> {
LL | |
@ -45,7 +45,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:44:1
--> tests/ui/derive.rs:49:1
|
LL | / impl Clone for BigArray {
LL | |
@ -56,7 +56,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:44:1
--> tests/ui/derive.rs:49:1
|
LL | / impl Clone for BigArray {
LL | |
@ -67,7 +67,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:56:1
--> tests/ui/derive.rs:61:1
|
LL | / impl Clone for FnPtr {
LL | |
@ -78,7 +78,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:56:1
--> tests/ui/derive.rs:61:1
|
LL | / impl Clone for FnPtr {
LL | |
@ -89,7 +89,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:77:1
--> tests/ui/derive.rs:82:1
|
LL | / impl<T: Clone> Clone for Generic2<T> {
LL | |
@ -100,7 +100,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:77:1
--> tests/ui/derive.rs:82:1
|
LL | / impl<T: Clone> Clone for Generic2<T> {
LL | |

View File

@ -9,7 +9,8 @@
clippy::redundant_closure_call,
clippy::uninlined_format_args,
clippy::useless_vec,
clippy::unnecessary_map_on_constructor
clippy::unnecessary_map_on_constructor,
clippy::needless_lifetimes
)]
use std::path::{Path, PathBuf};

View File

@ -9,7 +9,8 @@
clippy::redundant_closure_call,
clippy::uninlined_format_args,
clippy::useless_vec,
clippy::unnecessary_map_on_constructor
clippy::unnecessary_map_on_constructor,
clippy::needless_lifetimes
)]
use std::path::{Path, PathBuf};

View File

@ -1,5 +1,5 @@
error: redundant closure
--> tests/ui/eta.rs:30:27
--> tests/ui/eta.rs:31:27
|
LL | let a = Some(1u8).map(|a| foo(a));
| ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@ -8,31 +8,31 @@ LL | let a = Some(1u8).map(|a| foo(a));
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
error: redundant closure
--> tests/ui/eta.rs:34:40
--> tests/ui/eta.rs:35:40
|
LL | let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec!
| ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new`
error: redundant closure
--> tests/ui/eta.rs:35:35
--> tests/ui/eta.rs:36:35
|
LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted?
| ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2`
error: redundant closure
--> tests/ui/eta.rs:36:26
--> tests/ui/eta.rs:37:26
|
LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
| ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
error: redundant closure
--> tests/ui/eta.rs:43:27
--> tests/ui/eta.rs:44:27
|
LL | let e = Some(1u8).map(|a| generic(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
error: redundant closure
--> tests/ui/eta.rs:95:51
--> tests/ui/eta.rs:96:51
|
LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
| ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@ -41,169 +41,169 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]`
error: redundant closure
--> tests/ui/eta.rs:96:51
--> tests/ui/eta.rs:97:51
|
LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
error: redundant closure
--> tests/ui/eta.rs:98:42
--> tests/ui/eta.rs:99:42
|
LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
| ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
error: redundant closure
--> tests/ui/eta.rs:102:29
--> tests/ui/eta.rs:103:29
|
LL | let e = Some("str").map(|s| s.to_string());
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
error: redundant closure
--> tests/ui/eta.rs:103:27
--> tests/ui/eta.rs:104:27
|
LL | let e = Some('a').map(|s| s.to_uppercase());
| ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
error: redundant closure
--> tests/ui/eta.rs:105:65
--> tests/ui/eta.rs:106:65
|
LL | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
error: redundant closure
--> tests/ui/eta.rs:168:22
--> tests/ui/eta.rs:169:22
|
LL | requires_fn_once(|| x());
| ^^^^^^ help: replace the closure with the function itself: `x`
error: redundant closure
--> tests/ui/eta.rs:175:27
--> tests/ui/eta.rs:176:27
|
LL | let a = Some(1u8).map(|a| foo_ptr(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
error: redundant closure
--> tests/ui/eta.rs:180:27
--> tests/ui/eta.rs:181:27
|
LL | let a = Some(1u8).map(|a| closure(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
error: redundant closure
--> tests/ui/eta.rs:212:28
--> tests/ui/eta.rs:213:28
|
LL | x.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
error: redundant closure
--> tests/ui/eta.rs:213:28
--> tests/ui/eta.rs:214:28
|
LL | y.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
error: redundant closure
--> tests/ui/eta.rs:214:28
--> tests/ui/eta.rs:215:28
|
LL | z.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
error: redundant closure
--> tests/ui/eta.rs:221:21
--> tests/ui/eta.rs:222:21
|
LL | Some(1).map(|n| closure(n));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
error: redundant closure
--> tests/ui/eta.rs:225:21
--> tests/ui/eta.rs:226:21
|
LL | Some(1).map(|n| in_loop(n));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
error: redundant closure
--> tests/ui/eta.rs:318:18
--> tests/ui/eta.rs:319:18
|
LL | takes_fn_mut(|| f());
| ^^^^^^ help: replace the closure with the function itself: `&mut f`
error: redundant closure
--> tests/ui/eta.rs:321:19
--> tests/ui/eta.rs:322:19
|
LL | takes_fn_once(|| f());
| ^^^^^^ help: replace the closure with the function itself: `&mut f`
error: redundant closure
--> tests/ui/eta.rs:325:26
--> tests/ui/eta.rs:326:26
|
LL | move || takes_fn_mut(|| f_used_once())
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
error: redundant closure
--> tests/ui/eta.rs:337:19
--> tests/ui/eta.rs:338:19
|
LL | array_opt.map(|a| a.as_slice());
| ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
error: redundant closure
--> tests/ui/eta.rs:340:19
--> tests/ui/eta.rs:341:19
|
LL | slice_opt.map(|s| s.len());
| ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
error: redundant closure
--> tests/ui/eta.rs:343:17
--> tests/ui/eta.rs:344:17
|
LL | ptr_opt.map(|p| p.is_null());
| ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
error: redundant closure
--> tests/ui/eta.rs:347:17
--> tests/ui/eta.rs:348:17
|
LL | dyn_opt.map(|d| d.method_on_dyn());
| ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
error: redundant closure
--> tests/ui/eta.rs:407:19
--> tests/ui/eta.rs:408:19
|
LL | let _ = f(&0, |x, y| f2(x, y));
| ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2`
error: redundant closure
--> tests/ui/eta.rs:435:22
--> tests/ui/eta.rs:436:22
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method`
error: redundant closure
--> tests/ui/eta.rs:439:22
--> tests/ui/eta.rs:440:22
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method`
error: redundant closure
--> tests/ui/eta.rs:452:18
--> tests/ui/eta.rs:453:18
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method`
error: redundant closure
--> tests/ui/eta.rs:459:30
--> tests/ui/eta.rs:460:30
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
error: redundant closure
--> tests/ui/eta.rs:478:38
--> tests/ui/eta.rs:479:38
|
LL | let x = Box::new(|| None.map(|x| f(x)));
| ^^^^^^^^ help: replace the closure with the function itself: `&f`
error: redundant closure
--> tests/ui/eta.rs:482:38
--> tests/ui/eta.rs:483:38
|
LL | let x = Box::new(|| None.map(|x| f(x)));
| ^^^^^^^^ help: replace the closure with the function itself: `f`
error: redundant closure
--> tests/ui/eta.rs:499:35
--> tests/ui/eta.rs:500:35
|
LL | let _field = bind.or_else(|| get_default()).unwrap();
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`

View File

@ -10,7 +10,8 @@
clippy::redundant_field_names,
clippy::too_many_arguments,
clippy::borrow_deref_ref,
clippy::let_unit_value
clippy::let_unit_value,
clippy::needless_lifetimes
)]
trait CallableStr {

View File

@ -10,7 +10,8 @@
clippy::redundant_field_names,
clippy::too_many_arguments,
clippy::borrow_deref_ref,
clippy::let_unit_value
clippy::let_unit_value,
clippy::needless_lifetimes
)]
trait CallableStr {

View File

@ -1,5 +1,5 @@
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:68:19
--> tests/ui/explicit_auto_deref.rs:69:19
|
LL | let _: &str = &*s;
| ^^^ help: try: `&s`
@ -8,271 +8,271 @@ LL | let _: &str = &*s;
= help: to override `-D warnings` add `#[allow(clippy::explicit_auto_deref)]`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:69:19
--> tests/ui/explicit_auto_deref.rs:70:19
|
LL | let _: &str = &*{ String::new() };
| ^^^^^^^^^^^^^^^^^^^ help: try: `&{ String::new() }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:70:19
--> tests/ui/explicit_auto_deref.rs:71:19
|
LL | let _: &str = &mut *{ String::new() };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut { String::new() }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:74:11
--> tests/ui/explicit_auto_deref.rs:75:11
|
LL | f_str(&*s);
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:78:13
--> tests/ui/explicit_auto_deref.rs:79:13
|
LL | f_str_t(&*s, &*s); // Don't lint second param.
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:81:24
--> tests/ui/explicit_auto_deref.rs:82:24
|
LL | let _: &Box<i32> = &**b;
| ^^^^ help: try: `&b`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:87:7
--> tests/ui/explicit_auto_deref.rs:88:7
|
LL | c(&*s);
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:93:9
--> tests/ui/explicit_auto_deref.rs:94:9
|
LL | &**x
| ^^^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:97:11
--> tests/ui/explicit_auto_deref.rs:98:11
|
LL | { &**x }
| ^^^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:101:9
--> tests/ui/explicit_auto_deref.rs:102:9
|
LL | &**{ x }
| ^^^^^^^^ help: try: `{ x }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:105:9
--> tests/ui/explicit_auto_deref.rs:106:9
|
LL | &***x
| ^^^^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:122:12
--> tests/ui/explicit_auto_deref.rs:123:12
|
LL | f1(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:123:12
--> tests/ui/explicit_auto_deref.rs:124:12
|
LL | f2(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:124:12
--> tests/ui/explicit_auto_deref.rs:125:12
|
LL | f3(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:125:27
--> tests/ui/explicit_auto_deref.rs:126:27
|
LL | f4.callable_str()(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:126:12
--> tests/ui/explicit_auto_deref.rs:127:12
|
LL | f5(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:127:12
--> tests/ui/explicit_auto_deref.rs:128:12
|
LL | f6(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:128:27
--> tests/ui/explicit_auto_deref.rs:129:27
|
LL | f7.callable_str()(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:129:25
--> tests/ui/explicit_auto_deref.rs:130:25
|
LL | f8.callable_t()(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:130:12
--> tests/ui/explicit_auto_deref.rs:131:12
|
LL | f9(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:131:13
--> tests/ui/explicit_auto_deref.rs:132:13
|
LL | f10(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:132:26
--> tests/ui/explicit_auto_deref.rs:133:26
|
LL | f11.callable_t()(&*x);
| ^^^ help: try: `&x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:136:16
--> tests/ui/explicit_auto_deref.rs:137:16
|
LL | let _ = S1(&*s);
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:141:21
--> tests/ui/explicit_auto_deref.rs:142:21
|
LL | let _ = S2 { s: &*s };
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:157:30
--> tests/ui/explicit_auto_deref.rs:158:30
|
LL | let _ = Self::S1(&**s);
| ^^^^ help: try: `s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:158:35
--> tests/ui/explicit_auto_deref.rs:159:35
|
LL | let _ = Self::S2 { s: &**s };
| ^^^^ help: try: `s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:161:20
--> tests/ui/explicit_auto_deref.rs:162:20
|
LL | let _ = E1::S1(&*s);
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:162:25
--> tests/ui/explicit_auto_deref.rs:163:25
|
LL | let _ = E1::S2 { s: &*s };
| ^^^ help: try: `&s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:180:13
--> tests/ui/explicit_auto_deref.rs:181:13
|
LL | let _ = (*b).foo;
| ^^^^ help: try: `b`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:181:13
--> tests/ui/explicit_auto_deref.rs:182:13
|
LL | let _ = (**b).foo;
| ^^^^^ help: try: `b`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:196:19
--> tests/ui/explicit_auto_deref.rs:197:19
|
LL | let _ = f_str(*ref_str);
| ^^^^^^^^ help: try: `ref_str`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:198:19
--> tests/ui/explicit_auto_deref.rs:199:19
|
LL | let _ = f_str(**ref_ref_str);
| ^^^^^^^^^^^^^ help: try: `ref_ref_str`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:208:12
--> tests/ui/explicit_auto_deref.rs:209:12
|
LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references
| ^^^^^^^^^ help: try: `ref_str`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:209:12
--> tests/ui/explicit_auto_deref.rs:210:12
|
LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
| ^^^^^^^^^^ help: try: `ref_str`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:218:41
--> tests/ui/explicit_auto_deref.rs:219:41
|
LL | let _ = || -> &'static str { return *s };
| ^^ help: try: `s`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:237:9
--> tests/ui/explicit_auto_deref.rs:238:9
|
LL | &**x
| ^^^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:260:8
--> tests/ui/explicit_auto_deref.rs:261:8
|
LL | c1(*x);
| ^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:263:20
--> tests/ui/explicit_auto_deref.rs:264:20
|
LL | return *x;
| ^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:265:9
--> tests/ui/explicit_auto_deref.rs:266:9
|
LL | *x
| ^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:299:20
--> tests/ui/explicit_auto_deref.rs:300:20
|
LL | Some(x) => &mut *x,
| ^^^^^^^ help: try: `x`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:332:22
--> tests/ui/explicit_auto_deref.rs:333:22
|
LL | let _ = &mut (*{ x.u }).x;
| ^^^^^^^^^^ help: try: `{ x.u }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:338:22
--> tests/ui/explicit_auto_deref.rs:339:22
|
LL | let _ = &mut (**x.u).x;
| ^^^^^^^ help: try: `(*x.u)`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:339:22
--> tests/ui/explicit_auto_deref.rs:340:22
|
LL | let _ = &mut (**{ x.u }).x;
| ^^^^^^^^^^^ help: try: `{ x.u }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:343:22
--> tests/ui/explicit_auto_deref.rs:344:22
|
LL | let _ = &mut (*x.u).x;
| ^^^^^^ help: try: `x.u`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:344:22
--> tests/ui/explicit_auto_deref.rs:345:22
|
LL | let _ = &mut (*{ x.u }).x;
| ^^^^^^^^^^ help: try: `{ x.u }`
error: deref which would be done by auto-deref
--> tests/ui/explicit_auto_deref.rs:367:13
--> tests/ui/explicit_auto_deref.rs:368:13
|
LL | foo(&*wrapped_bar);
| ^^^^^^^^^^^^^ help: try: `&wrapped_bar`

View File

@ -114,9 +114,17 @@ mod second_case {
fn hey();
}
// Should lint. The response to the above comment incorrectly called this a false positive. The
// lifetime `'a` can be removed, as demonstrated below.
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
fn hey() {}
}
struct OtherBox<T: ?Sized>(Box<T>);
impl<T: Source + ?Sized> Source for OtherBox<T> {
fn hey() {}
}
}
// Should not lint

View File

@ -37,5 +37,11 @@ error: this lifetime isn't used in the function definition
LL | pub fn something<'c>() -> Self {
| ^^
error: aborting due to 6 previous errors
error: this lifetime isn't used in the impl
--> tests/ui/extra_unused_lifetimes.rs:119:10
|
LL | impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
| ^^
error: aborting due to 7 previous errors

View File

@ -1,5 +1,5 @@
#![deny(clippy::index_refutable_slice)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::uninlined_format_args, clippy::needless_lifetimes)]
//@no-rustfix: need to change the suggestion to a multipart suggestion

View File

@ -1,6 +1,7 @@
//@no-rustfix
//@aux-build:proc_macros.rs
#![warn(clippy::iter_without_into_iter)]
#![allow(clippy::needless_lifetimes)]
extern crate proc_macros;
pub struct S1;

View File

@ -1,5 +1,5 @@
error: `iter` method without an `IntoIterator` impl for `&S1`
--> tests/ui/iter_without_into_iter.rs:8:5
--> tests/ui/iter_without_into_iter.rs:9:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | |
@ -22,7 +22,7 @@ LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S1`
--> tests/ui/iter_without_into_iter.rs:12:5
--> tests/ui/iter_without_into_iter.rs:13:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | |
@ -43,7 +43,7 @@ LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S3<'a>`
--> tests/ui/iter_without_into_iter.rs:28:5
--> tests/ui/iter_without_into_iter.rs:29:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | |
@ -64,7 +64,7 @@ LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S3<'a>`
--> tests/ui/iter_without_into_iter.rs:32:5
--> tests/ui/iter_without_into_iter.rs:33:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | |
@ -85,7 +85,7 @@ LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S8<T>`
--> tests/ui/iter_without_into_iter.rs:69:5
--> tests/ui/iter_without_into_iter.rs:70:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> {
LL | | todo!()
@ -105,7 +105,7 @@ LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S9<T>`
--> tests/ui/iter_without_into_iter.rs:77:5
--> tests/ui/iter_without_into_iter.rs:78:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> {
LL | |
@ -126,7 +126,7 @@ LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S9<T>`
--> tests/ui/iter_without_into_iter.rs:81:5
--> tests/ui/iter_without_into_iter.rs:82:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
LL | |
@ -147,7 +147,7 @@ LL + }
|
error: `iter` method without an `IntoIterator` impl for `&Issue12037`
--> tests/ui/iter_without_into_iter.rs:130:13
--> tests/ui/iter_without_into_iter.rs:131:13
|
LL | / fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | | todo!()

View File

@ -1,6 +1,5 @@
#![allow(unused)]
#![allow(unused, clippy::needless_lifetimes)]
#![warn(
clippy::all,
clippy::style,
clippy::mem_replace_option_with_none,
clippy::mem_replace_with_default

View File

@ -1,6 +1,5 @@
#![allow(unused)]
#![allow(unused, clippy::needless_lifetimes)]
#![warn(
clippy::all,
clippy::style,
clippy::mem_replace_option_with_none,
clippy::mem_replace_with_default

View File

@ -1,5 +1,5 @@
error: replacing an `Option` with `None`
--> tests/ui/mem_replace.rs:14:13
--> tests/ui/mem_replace.rs:13:13
|
LL | let _ = mem::replace(&mut an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
@ -8,13 +8,13 @@ LL | let _ = mem::replace(&mut an_option, None);
= help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace.rs:16:13
--> tests/ui/mem_replace.rs:15:13
|
LL | let _ = mem::replace(an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:21:13
--> tests/ui/mem_replace.rs:20:13
|
LL | let _ = std::mem::replace(&mut s, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
@ -23,127 +23,127 @@ LL | let _ = std::mem::replace(&mut s, String::default());
= help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:24:13
--> tests/ui/mem_replace.rs:23:13
|
LL | let _ = std::mem::replace(s, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:25:13
--> tests/ui/mem_replace.rs:24:13
|
LL | let _ = std::mem::replace(s, Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:28:13
--> tests/ui/mem_replace.rs:27:13
|
LL | let _ = std::mem::replace(&mut v, Vec::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:29:13
--> tests/ui/mem_replace.rs:28:13
|
LL | let _ = std::mem::replace(&mut v, Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:30:13
--> tests/ui/mem_replace.rs:29:13
|
LL | let _ = std::mem::replace(&mut v, Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:31:13
--> tests/ui/mem_replace.rs:30:13
|
LL | let _ = std::mem::replace(&mut v, vec![]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:34:13
--> tests/ui/mem_replace.rs:33:13
|
LL | let _ = std::mem::replace(&mut hash_map, HashMap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:37:13
--> tests/ui/mem_replace.rs:36:13
|
LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:40:13
--> tests/ui/mem_replace.rs:39:13
|
LL | let _ = std::mem::replace(&mut vd, VecDeque::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:43:13
--> tests/ui/mem_replace.rs:42:13
|
LL | let _ = std::mem::replace(&mut hash_set, HashSet::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:46:13
--> tests/ui/mem_replace.rs:45:13
|
LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:49:13
--> tests/ui/mem_replace.rs:48:13
|
LL | let _ = std::mem::replace(&mut list, LinkedList::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:52:13
--> tests/ui/mem_replace.rs:51:13
|
LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:55:13
--> tests/ui/mem_replace.rs:54:13
|
LL | let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:58:13
--> tests/ui/mem_replace.rs:57:13
|
LL | let _ = std::mem::replace(&mut refstr, "");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:61:13
--> tests/ui/mem_replace.rs:60:13
|
LL | let _ = std::mem::replace(&mut slice, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:97:13
--> tests/ui/mem_replace.rs:96:13
|
LL | let _ = std::mem::replace(&mut s, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace.rs:127:13
--> tests/ui/mem_replace.rs:126:13
|
LL | let _ = std::mem::replace(&mut f.0, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace.rs:128:13
--> tests/ui/mem_replace.rs:127:13
|
LL | let _ = std::mem::replace(&mut *f, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace.rs:129:13
--> tests/ui/mem_replace.rs:128:13
|
LL | let _ = std::mem::replace(&mut b.opt, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
--> tests/ui/mem_replace.rs:131:13
--> tests/ui/mem_replace.rs:130:13
|
LL | let _ = std::mem::replace(&mut b.val, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut b.val)`

View File

@ -1,6 +1,5 @@
#![allow(unused)]
#![allow(unused, clippy::needless_lifetimes)]
#![warn(
clippy::all,
clippy::style,
clippy::mem_replace_option_with_none,
clippy::mem_replace_with_default

View File

@ -1,6 +1,5 @@
#![allow(unused)]
#![allow(unused, clippy::needless_lifetimes)]
#![warn(
clippy::all,
clippy::style,
clippy::mem_replace_option_with_none,
clippy::mem_replace_with_default

View File

@ -1,5 +1,5 @@
error: replacing an `Option` with `None`
--> tests/ui/mem_replace_no_std.rs:24:13
--> tests/ui/mem_replace_no_std.rs:23:13
|
LL | let _ = mem::replace(&mut an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
@ -8,13 +8,13 @@ LL | let _ = mem::replace(&mut an_option, None);
= help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace_no_std.rs:26:13
--> tests/ui/mem_replace_no_std.rs:25:13
|
LL | let _ = mem::replace(an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take`
--> tests/ui/mem_replace_no_std.rs:31:13
--> tests/ui/mem_replace_no_std.rs:30:13
|
LL | let _ = mem::replace(&mut refstr, "");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut refstr)`
@ -23,25 +23,25 @@ LL | let _ = mem::replace(&mut refstr, "");
= help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]`
error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take`
--> tests/ui/mem_replace_no_std.rs:34:13
--> tests/ui/mem_replace_no_std.rs:33:13
|
LL | let _ = mem::replace(&mut slice, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut slice)`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace_no_std.rs:77:13
--> tests/ui/mem_replace_no_std.rs:76:13
|
LL | let _ = mem::replace(&mut f.0, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace_no_std.rs:78:13
--> tests/ui/mem_replace_no_std.rs:77:13
|
LL | let _ = mem::replace(&mut *f, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()`
error: replacing an `Option` with `None`
--> tests/ui/mem_replace_no_std.rs:79:13
--> tests/ui/mem_replace_no_std.rs:78:13
|
LL | let _ = mem::replace(&mut b.opt, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()`

View File

@ -1,5 +1,5 @@
#![warn(clippy::mismatching_type_param_order)]
#![allow(clippy::disallowed_names)]
#![allow(clippy::disallowed_names, clippy::needless_lifetimes)]
fn main() {
struct Foo<A, B> {

View File

@ -4,7 +4,8 @@
clippy::uninlined_format_args,
clippy::unnecessary_mut_passed,
clippy::unnecessary_to_owned,
clippy::unnecessary_literal_unwrap
clippy::unnecessary_literal_unwrap,
clippy::needless_lifetimes
)]
#![warn(clippy::needless_borrow)]

View File

@ -4,7 +4,8 @@
clippy::uninlined_format_args,
clippy::unnecessary_mut_passed,
clippy::unnecessary_to_owned,
clippy::unnecessary_literal_unwrap
clippy::unnecessary_literal_unwrap,
clippy::needless_lifetimes
)]
#![warn(clippy::needless_borrow)]

View File

@ -1,5 +1,5 @@
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:15:15
--> tests/ui/needless_borrow.rs:16:15
|
LL | let _ = x(&&a); // warn
| ^^^ help: change this to: `&a`
@ -8,163 +8,163 @@ LL | let _ = x(&&a); // warn
= help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:19:13
--> tests/ui/needless_borrow.rs:20:13
|
LL | mut_ref(&mut &mut b); // warn
| ^^^^^^^^^^^ help: change this to: `&mut b`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:31:13
--> tests/ui/needless_borrow.rs:32:13
|
LL | &&a
| ^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:33:15
--> tests/ui/needless_borrow.rs:34:15
|
LL | 46 => &&a,
| ^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:39:27
--> tests/ui/needless_borrow.rs:40:27
|
LL | break &ref_a;
| ^^^^^^ help: change this to: `ref_a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:46:15
--> tests/ui/needless_borrow.rs:47:15
|
LL | let _ = x(&&&a);
| ^^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:47:15
--> tests/ui/needless_borrow.rs:48:15
|
LL | let _ = x(&mut &&a);
| ^^^^^^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:48:15
--> tests/ui/needless_borrow.rs:49:15
|
LL | let _ = x(&&&mut b);
| ^^^^^^^^ help: change this to: `&mut b`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:49:15
--> tests/ui/needless_borrow.rs:50:15
|
LL | let _ = x(&&ref_a);
| ^^^^^^^ help: change this to: `ref_a`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:52:11
--> tests/ui/needless_borrow.rs:53:11
|
LL | x(&b);
| ^^ help: change this to: `b`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:59:13
--> tests/ui/needless_borrow.rs:60:13
|
LL | mut_ref(&mut x);
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:60:13
--> tests/ui/needless_borrow.rs:61:13
|
LL | mut_ref(&mut &mut x);
| ^^^^^^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:61:23
--> tests/ui/needless_borrow.rs:62:23
|
LL | let y: &mut i32 = &mut x;
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:62:23
--> tests/ui/needless_borrow.rs:63:23
|
LL | let y: &mut i32 = &mut &mut x;
| ^^^^^^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:71:14
--> tests/ui/needless_borrow.rs:72:14
|
LL | 0 => &mut x,
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:77:14
--> tests/ui/needless_borrow.rs:78:14
|
LL | 0 => &mut x,
| ^^^^^^ help: change this to: `x`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:89:13
--> tests/ui/needless_borrow.rs:90:13
|
LL | let _ = (&x).0;
| ^^^^ help: change this to: `x`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:91:22
--> tests/ui/needless_borrow.rs:92:22
|
LL | let _ = unsafe { (&*x).0 };
| ^^^^^ help: change this to: `(*x)`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:101:5
--> tests/ui/needless_borrow.rs:102:5
|
LL | (&&()).foo();
| ^^^^^^ help: change this to: `(&())`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:110:5
--> tests/ui/needless_borrow.rs:111:5
|
LL | (&&5).foo();
| ^^^^^ help: change this to: `(&5)`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:136:23
--> tests/ui/needless_borrow.rs:137:23
|
LL | let x: (&str,) = (&"",);
| ^^^ help: change this to: `""`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:178:13
--> tests/ui/needless_borrow.rs:179:13
|
LL | (&self.f)()
| ^^^^^^^^^ help: change this to: `(self.f)`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:187:13
--> tests/ui/needless_borrow.rs:188:13
|
LL | (&mut self.f)()
| ^^^^^^^^^^^^^ help: change this to: `(self.f)`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:224:22
--> tests/ui/needless_borrow.rs:225:22
|
LL | let _ = &mut (&mut { x.u }).x;
| ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:231:22
--> tests/ui/needless_borrow.rs:232:22
|
LL | let _ = &mut (&mut { x.u }).x;
| ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:235:22
--> tests/ui/needless_borrow.rs:236:22
|
LL | let _ = &mut (&mut x.u).x;
| ^^^^^^^^^^ help: change this to: `x.u`
error: this expression borrows a value the compiler would automatically borrow
--> tests/ui/needless_borrow.rs:236:22
--> tests/ui/needless_borrow.rs:237:22
|
LL | let _ = &mut (&mut { x.u }).x;
| ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
error: this expression creates a reference which is immediately dereferenced by the compiler
--> tests/ui/needless_borrow.rs:257:23
--> tests/ui/needless_borrow.rs:258:23
|
LL | option.unwrap_or((&x.0,));
| ^^^^ help: change this to: `x.0`

View File

@ -329,7 +329,7 @@ mod issue2944 {
bar: &'a Bar,
}
impl<'a> Foo for Baz<'a> {}
impl Foo for Baz<'_> {}
impl Bar {
fn baz(&self) -> impl Foo + '_ {
Baz { bar: self }
@ -384,7 +384,7 @@ mod nested_elision_sites {
f()
}
// lint
fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
fn where_clause_elidable<T>(i: &i32, f: T) -> &i32
where
T: Fn(&i32) -> &i32,
{
@ -543,4 +543,23 @@ mod issue5787 {
}
}
// https://github.com/rust-lang/rust-clippy/pull/13286#issuecomment-2374245772
mod rayon {
trait ParallelIterator {
type Item;
}
struct Copied<I: ParallelIterator> {
base: I,
}
impl<'a, T, I> ParallelIterator for Copied<I>
where
I: ParallelIterator<Item = &'a T>,
T: 'a + Copy + Send + Sync,
{
type Item = T;
}
}
fn main() {}

View File

@ -384,7 +384,7 @@ mod nested_elision_sites {
f()
}
// lint
fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32
where
T: Fn(&i32) -> &i32,
{
@ -543,4 +543,23 @@ mod issue5787 {
}
}
// https://github.com/rust-lang/rust-clippy/pull/13286#issuecomment-2374245772
mod rayon {
trait ParallelIterator {
type Item;
}
struct Copied<I: ParallelIterator> {
base: I,
}
impl<'a, T, I> ParallelIterator for Copied<I>
where
I: ParallelIterator<Item = &'a T>,
T: 'a + Copy + Send + Sync,
{
type Item = T;
}
}
fn main() {}

View File

@ -335,6 +335,18 @@ LL - fn needless_lt<'a>(_x: &'a u8) {}
LL + fn needless_lt(_x: &u8) {}
|
error: the following explicit lifetimes could be elided: 'a
--> tests/ui/needless_lifetimes.rs:332:10
|
LL | impl<'a> Foo for Baz<'a> {}
| ^^ ^^
|
help: elide the lifetimes
|
LL - impl<'a> Foo for Baz<'a> {}
LL + impl Foo for Baz<'_> {}
|
error: the following explicit lifetimes could be elided: 'a
--> tests/ui/needless_lifetimes.rs:334:16
|
@ -372,15 +384,15 @@ LL + fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
|
error: the following explicit lifetimes could be elided: 'a
--> tests/ui/needless_lifetimes.rs:387:32
--> tests/ui/needless_lifetimes.rs:387:30
|
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
| ^^ ^^ ^^
LL | fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32
| ^^ ^^ ^^
|
help: elide the lifetimes
|
LL - fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
LL + fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
LL - fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32
LL + fn where_clause_elidable<T>(i: &i32, f: T) -> &i32
|
error: the following explicit lifetimes could be elided: 'a
@ -564,5 +576,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
LL + fn one_input(x: &u8) -> &u8 {
|
error: aborting due to 47 previous errors
error: aborting due to 48 previous errors

View File

@ -5,7 +5,8 @@
clippy::redundant_clone,
clippy::redundant_pattern_matching,
clippy::single_match,
clippy::uninlined_format_args
clippy::uninlined_format_args,
clippy::needless_lifetimes
)]
//@no-rustfix
use std::borrow::Borrow;

View File

@ -1,5 +1,5 @@
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:18:23
--> tests/ui/needless_pass_by_value.rs:19:23
|
LL | fn foo<T: Default>(v: Vec<T>, w: Vec<T>, mut x: Vec<T>, y: Vec<T>) -> Vec<T> {
| ^^^^^^ help: consider changing the type to: `&[T]`
@ -8,55 +8,55 @@ LL | fn foo<T: Default>(v: Vec<T>, w: Vec<T>, mut x: Vec<T>, y: Vec<T>) -> Vec<T
= help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_value)]`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:34:11
--> tests/ui/needless_pass_by_value.rs:35:11
|
LL | fn bar(x: String, y: Wrapper) {
| ^^^^^^ help: consider changing the type to: `&str`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:34:22
--> tests/ui/needless_pass_by_value.rs:35:22
|
LL | fn bar(x: String, y: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:42:71
--> tests/ui/needless_pass_by_value.rs:43:71
|
LL | fn test_borrow_trait<T: Borrow<str>, U: AsRef<str>, V>(t: T, u: U, v: V) {
| ^ help: consider taking a reference instead: `&V`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:55:18
--> tests/ui/needless_pass_by_value.rs:56:18
|
LL | fn test_match(x: Option<Option<String>>, y: Option<Option<String>>) {
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option<Option<String>>`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:69:24
--> tests/ui/needless_pass_by_value.rs:70:24
|
LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:69:36
--> tests/ui/needless_pass_by_value.rs:70:36
|
LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:87:49
--> tests/ui/needless_pass_by_value.rs:88:49
|
LL | fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {}
| ^ help: consider taking a reference instead: `&T`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:90:18
--> tests/ui/needless_pass_by_value.rs:91:18
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^ help: consider taking a reference instead: `&String`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:90:29
--> tests/ui/needless_pass_by_value.rs:91:29
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^
@ -71,13 +71,13 @@ LL | let _ = t.to_string();
| ~~~~~~~~~~~~~
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:90:40
--> tests/ui/needless_pass_by_value.rs:91:40
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^^^ help: consider taking a reference instead: `&Vec<i32>`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:90:53
--> tests/ui/needless_pass_by_value.rs:91:53
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^^^
@ -92,85 +92,85 @@ LL | let _ = v.to_owned();
| ~~~~~~~~~~~~
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:107:12
--> tests/ui/needless_pass_by_value.rs:108:12
|
LL | s: String,
| ^^^^^^ help: consider changing the type to: `&str`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:109:12
--> tests/ui/needless_pass_by_value.rs:110:12
|
LL | t: String,
| ^^^^^^ help: consider taking a reference instead: `&String`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:119:23
--> tests/ui/needless_pass_by_value.rs:120:23
|
LL | fn baz(&self, uu: U, ss: Self) {}
| ^ help: consider taking a reference instead: `&U`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:119:30
--> tests/ui/needless_pass_by_value.rs:120:30
|
LL | fn baz(&self, uu: U, ss: Self) {}
| ^^^^ help: consider taking a reference instead: `&Self`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:143:24
--> tests/ui/needless_pass_by_value.rs:144:24
|
LL | fn bar_copy(x: u32, y: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
--> tests/ui/needless_pass_by_value.rs:142:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:150:29
--> tests/ui/needless_pass_by_value.rs:151:29
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
--> tests/ui/needless_pass_by_value.rs:142:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:150:45
--> tests/ui/needless_pass_by_value.rs:151:45
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
--> tests/ui/needless_pass_by_value.rs:142:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:150:61
--> tests/ui/needless_pass_by_value.rs:151:61
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
--> tests/ui/needless_pass_by_value.rs:142:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:165:40
--> tests/ui/needless_pass_by_value.rs:166:40
|
LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {}
| ^ help: consider taking a reference instead: `&S`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:171:20
--> tests/ui/needless_pass_by_value.rs:172:20
|
LL | fn more_fun(items: impl Club<'static, i32>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>`

View File

@ -2,7 +2,8 @@
dead_code,
clippy::missing_safety_doc,
clippy::extra_unused_lifetimes,
clippy::extra_unused_type_parameters
clippy::extra_unused_type_parameters,
clippy::needless_lifetimes
)]
#![warn(clippy::new_without_default)]

Some files were not shown because too many files have changed in this diff Show More