mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-15 20:45:45 +03:00
Fix false positive of useless_conversion when using .into_iter().any() (#14800)
Fixes: rust-lang/rust-clippy#14656 changelog: Fix [`useless_conversion`] false positive when using `.into_iter().any()`.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
|
||||
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, PatKind};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
@@ -298,6 +298,33 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
// implements Copy, in which case .into_iter() returns a copy of the receiver and
|
||||
// cannot be safely omitted.
|
||||
if same_type_and_consts(a, b) && !is_copy(cx, b) {
|
||||
// Below we check if the parent method call meets the following conditions:
|
||||
// 1. First parameter is `&mut self` (requires mutable reference)
|
||||
// 2. Second parameter implements the `FnMut` trait (e.g., Iterator::any)
|
||||
// For methods satisfying these conditions (like any), .into_iter() must be preserved.
|
||||
if let Some(parent) = get_parent_expr(cx, e)
|
||||
&& let ExprKind::MethodCall(_, recv, _, _) = parent.kind
|
||||
&& recv.hir_id == e.hir_id
|
||||
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
|
||||
&& let sig = cx.tcx.fn_sig(def_id).skip_binder().skip_binder()
|
||||
&& let inputs = sig.inputs()
|
||||
&& inputs.len() >= 2
|
||||
&& let Some(self_ty) = inputs.first()
|
||||
&& let ty::Ref(_, _, Mutability::Mut) = self_ty.kind()
|
||||
&& let Some(second_ty) = inputs.get(1)
|
||||
&& let predicates = cx.tcx.param_env(def_id).caller_bounds()
|
||||
&& predicates.iter().any(|pred| {
|
||||
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder() {
|
||||
trait_pred.self_ty() == *second_ty
|
||||
&& cx.tcx.lang_items().fn_mut_trait() == Some(trait_pred.def_id())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let sugg = snippet(cx, recv.span, "<expr>").into_owned();
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
||||
@@ -427,3 +427,18 @@ mod issue11819 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn issue14739() {
|
||||
use std::ops::Range;
|
||||
|
||||
const R: Range<u32> = 2..7;
|
||||
|
||||
R.into_iter().all(|_x| true); // no lint
|
||||
|
||||
R.into_iter().any(|_x| true); // no lint
|
||||
|
||||
R.for_each(|_x| {});
|
||||
//~^ useless_conversion
|
||||
let _ = R.map(|_x| 0);
|
||||
//~^ useless_conversion
|
||||
}
|
||||
|
||||
@@ -427,3 +427,18 @@ pub fn with_reborrow_mut<'a, Y: 'a>(&'a mut self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn issue14739() {
|
||||
use std::ops::Range;
|
||||
|
||||
const R: Range<u32> = 2..7;
|
||||
|
||||
R.into_iter().all(|_x| true); // no lint
|
||||
|
||||
R.into_iter().any(|_x| true); // no lint
|
||||
|
||||
R.into_iter().for_each(|_x| {});
|
||||
//~^ useless_conversion
|
||||
let _ = R.into_iter().map(|_x| 0);
|
||||
//~^ useless_conversion
|
||||
}
|
||||
|
||||
@@ -377,5 +377,17 @@ LL - takes_into_iter(self.my_field.into_iter());
|
||||
LL + takes_into_iter(&mut *self.my_field);
|
||||
|
|
||||
|
||||
error: aborting due to 41 previous errors
|
||||
error: useless conversion to the same type: `std::ops::Range<u32>`
|
||||
--> tests/ui/useless_conversion.rs:440:5
|
||||
|
|
||||
LL | R.into_iter().for_each(|_x| {});
|
||||
| ^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `R`
|
||||
|
||||
error: useless conversion to the same type: `std::ops::Range<u32>`
|
||||
--> tests/ui/useless_conversion.rs:442:13
|
||||
|
|
||||
LL | let _ = R.into_iter().map(|_x| 0);
|
||||
| ^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `R`
|
||||
|
||||
error: aborting due to 43 previous errors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user