mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
fix: incorrect suggestions generated by manual_retain
lint
This commit is contained in:
parent
9eb2b225f8
commit
b5a2192628
4 changed files with 333 additions and 66 deletions
|
@ -11,6 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_semver::RustcVersion;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
const ACCEPTABLE_METHODS: [&[&str]; 5] = [
|
||||
&paths::BINARYHEAP_ITER,
|
||||
|
@ -28,6 +29,7 @@ const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
|
|||
(sym::Vec, None),
|
||||
(sym::VecDeque, None),
|
||||
];
|
||||
const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap];
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
@ -44,6 +46,7 @@ declare_clippy_lint! {
|
|||
/// ```no_run
|
||||
/// let mut vec = vec![0, 1, 2];
|
||||
/// vec.retain(|x| x % 2 == 0);
|
||||
/// vec.retain(|x| x % 2 == 0);
|
||||
/// ```
|
||||
#[clippy::version = "1.64.0"]
|
||||
pub MANUAL_RETAIN,
|
||||
|
@ -74,9 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain {
|
|||
&& let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
|
||||
&& cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id)
|
||||
{
|
||||
check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
|
||||
check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
|
||||
check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv);
|
||||
check_into_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
|
||||
check_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
|
||||
check_to_owned(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,9 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain {
|
|||
|
||||
fn check_into_iter(
|
||||
cx: &LateContext<'_>,
|
||||
parent_expr: &hir::Expr<'_>,
|
||||
left_expr: &hir::Expr<'_>,
|
||||
target_expr: &hir::Expr<'_>,
|
||||
parent_expr_span: Span,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
|
||||
|
@ -98,16 +101,39 @@ fn check_into_iter(
|
|||
&& Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
|
||||
&& match_acceptable_type(cx, left_expr, msrv)
|
||||
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
|
||||
&& let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = target_expr.kind
|
||||
&& let hir::ExprKind::Closure(closure) = closure_expr.kind
|
||||
&& let filter_body = cx.tcx.hir().body(closure.body)
|
||||
&& let [filter_params] = filter_body.params
|
||||
{
|
||||
suggest(cx, parent_expr, left_expr, target_expr);
|
||||
if match_map_type(cx, left_expr) {
|
||||
if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind {
|
||||
if let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body) {
|
||||
make_span_lint_and_sugg(cx, parent_expr_span, sugg);
|
||||
}
|
||||
}
|
||||
// Cannot lint other cases because `retain` requires two parameters
|
||||
} else {
|
||||
// Can always move because `retain` and `filter` have the same bound on the predicate
|
||||
// for other types
|
||||
make_span_lint_and_sugg(
|
||||
cx,
|
||||
parent_expr_span,
|
||||
format!(
|
||||
"{}.retain({})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, closure_expr.span, "..")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_iter(
|
||||
cx: &LateContext<'_>,
|
||||
parent_expr: &hir::Expr<'_>,
|
||||
left_expr: &hir::Expr<'_>,
|
||||
target_expr: &hir::Expr<'_>,
|
||||
parent_expr_span: Span,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
|
||||
|
@ -122,16 +148,50 @@ fn check_iter(
|
|||
&& match_acceptable_def_path(cx, iter_expr_def_id)
|
||||
&& match_acceptable_type(cx, left_expr, msrv)
|
||||
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
|
||||
&& let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
|
||||
&& let hir::ExprKind::Closure(closure) = closure_expr.kind
|
||||
&& let filter_body = cx.tcx.hir().body(closure.body)
|
||||
&& let [filter_params] = filter_body.params
|
||||
{
|
||||
suggest(cx, parent_expr, left_expr, filter_expr);
|
||||
match filter_params.pat.kind {
|
||||
// hir::PatKind::Binding(_, _, _, None) => {
|
||||
// // Be conservative now. Do nothing here.
|
||||
// // TODO: Ideally, we can rewrite the lambda by stripping one level of reference
|
||||
// },
|
||||
hir::PatKind::Tuple([_, _], _) => {
|
||||
// the `&&` reference for the `filter` method will be auto derefed to `ref`
|
||||
// so, we can directly use the lambda
|
||||
// https://doc.rust-lang.org/reference/patterns.html#binding-modes
|
||||
make_span_lint_and_sugg(
|
||||
cx,
|
||||
parent_expr_span,
|
||||
format!(
|
||||
"{}.retain({})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, closure_expr.span, "..")
|
||||
),
|
||||
);
|
||||
},
|
||||
hir::PatKind::Ref(pat, _) => make_span_lint_and_sugg(
|
||||
cx,
|
||||
parent_expr_span,
|
||||
format!(
|
||||
"{}.retain(|{}| {})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, pat.span, ".."),
|
||||
snippet(cx, filter_body.value.span, "..")
|
||||
),
|
||||
),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_to_owned(
|
||||
cx: &LateContext<'_>,
|
||||
parent_expr: &hir::Expr<'_>,
|
||||
left_expr: &hir::Expr<'_>,
|
||||
target_expr: &hir::Expr<'_>,
|
||||
parent_expr_span: Span,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
if msrv.meets(msrvs::STRING_RETAIN)
|
||||
|
@ -147,43 +207,25 @@ fn check_to_owned(
|
|||
&& let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
|
||||
&& is_type_lang_item(cx, ty, hir::LangItem::String)
|
||||
&& SpanlessEq::new(cx).eq_expr(left_expr, str_expr)
|
||||
{
|
||||
suggest(cx, parent_expr, left_expr, filter_expr);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) {
|
||||
if let hir::ExprKind::MethodCall(_, _, [closure], _) = filter_expr.kind
|
||||
&& let hir::ExprKind::Closure(&hir::Closure { body, .. }) = closure.kind
|
||||
&& let filter_body = cx.tcx.hir().body(body)
|
||||
&& let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
|
||||
&& let hir::ExprKind::Closure(closure) = closure_expr.kind
|
||||
&& let filter_body = cx.tcx.hir().body(closure.body)
|
||||
&& let [filter_params] = filter_body.params
|
||||
&& let Some(sugg) = match filter_params.pat.kind {
|
||||
hir::PatKind::Binding(_, _, filter_param_ident, None) => Some(format!(
|
||||
"{}.retain(|{filter_param_ident}| {})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, filter_body.value.span, "..")
|
||||
)),
|
||||
hir::PatKind::Tuple([key_pat, value_pat], _) => make_sugg(cx, key_pat, value_pat, left_expr, filter_body),
|
||||
hir::PatKind::Ref(pat, _) => match pat.kind {
|
||||
hir::PatKind::Binding(_, _, filter_param_ident, None) => Some(format!(
|
||||
"{}.retain(|{filter_param_ident}| {})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, filter_body.value.span, "..")
|
||||
)),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_RETAIN,
|
||||
parent_expr.span,
|
||||
"this expression can be written more simply using `.retain()`",
|
||||
"consider calling `.retain()` instead",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind {
|
||||
make_span_lint_and_sugg(
|
||||
cx,
|
||||
parent_expr_span,
|
||||
format!(
|
||||
"{}.retain(|{}| {})",
|
||||
snippet(cx, left_expr.span, ".."),
|
||||
snippet(cx, pat.span, ".."),
|
||||
snippet(cx, filter_body.value.span, "..")
|
||||
),
|
||||
);
|
||||
}
|
||||
// Be conservative now. Do nothing for the `Binding` case.
|
||||
// TODO: Ideally, we can rewrite the lambda by stripping one level of reference
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,3 +271,20 @@ fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv
|
|||
&& acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv))
|
||||
})
|
||||
}
|
||||
|
||||
fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty))
|
||||
}
|
||||
|
||||
fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_RETAIN,
|
||||
span,
|
||||
"this expression can be written more simply using `.retain()`",
|
||||
"consider calling `.retain()` instead",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ fn main() {
|
|||
_msrv_153();
|
||||
_msrv_126();
|
||||
_msrv_118();
|
||||
|
||||
issue_10393();
|
||||
issue_12081();
|
||||
}
|
||||
|
||||
fn binary_heap_retain() {
|
||||
|
@ -23,6 +26,11 @@ fn binary_heap_retain() {
|
|||
binary_heap.retain(|x| x % 2 == 0);
|
||||
binary_heap.retain(|x| x % 2 == 0);
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples.retain(|(ref x, ref y)| *x == 0);
|
||||
tuples.retain(|(x, y)| *x == 0);
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
binary_heap = binary_heap
|
||||
.into_iter()
|
||||
|
@ -55,6 +63,9 @@ fn btree_map_retain() {
|
|||
btree_map.retain(|_, &mut v| v % 2 == 0);
|
||||
btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0));
|
||||
|
||||
// Do not lint, because the parameters are not matched in tuple pattern
|
||||
btree_map = btree_map.into_iter().filter(|t| t.0 % 2 == 0).collect();
|
||||
|
||||
// Do not lint.
|
||||
btree_map = btree_map
|
||||
.into_iter()
|
||||
|
@ -76,6 +87,11 @@ fn btree_set_retain() {
|
|||
btree_set.retain(|x| x % 2 == 0);
|
||||
btree_set.retain(|x| x % 2 == 0);
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples.retain(|(ref x, ref y)| *x == 0);
|
||||
tuples.retain(|(x, y)| *x == 0);
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
btree_set = btree_set
|
||||
.iter()
|
||||
|
@ -108,6 +124,9 @@ fn hash_map_retain() {
|
|||
hash_map.retain(|_, &mut v| v % 2 == 0);
|
||||
hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0));
|
||||
|
||||
// Do not lint, because the parameters are not matched in tuple pattern
|
||||
hash_map = hash_map.into_iter().filter(|t| t.0 % 2 == 0).collect();
|
||||
|
||||
// Do not lint.
|
||||
hash_map = hash_map
|
||||
.into_iter()
|
||||
|
@ -128,6 +147,11 @@ fn hash_set_retain() {
|
|||
hash_set.retain(|x| x % 2 == 0);
|
||||
hash_set.retain(|x| x % 2 == 0);
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples.retain(|(ref x, ref y)| *x == 0);
|
||||
tuples.retain(|(x, y)| *x == 0);
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>();
|
||||
hash_set = hash_set
|
||||
|
@ -157,6 +181,9 @@ fn string_retain() {
|
|||
// Do lint.
|
||||
s.retain(|c| c != 'o');
|
||||
|
||||
// Do not lint, because we need to rewrite the lambda
|
||||
s = s.chars().filter(|c| *c != 'o').to_owned().collect();
|
||||
|
||||
// Do not lint, because this expression is not assign.
|
||||
let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
|
||||
|
@ -171,6 +198,11 @@ fn vec_retain() {
|
|||
vec.retain(|x| x % 2 == 0);
|
||||
vec.retain(|x| x % 2 == 0);
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = vec![(0, 1), (1, 2), (2, 3)];
|
||||
tuples.retain(|(ref x, ref y)| *x == 0);
|
||||
tuples.retain(|(x, y)| *x == 0);
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>();
|
||||
vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>();
|
||||
|
@ -246,3 +278,27 @@ fn _msrv_118() {
|
|||
let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
|
||||
hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
|
||||
}
|
||||
|
||||
fn issue_10393() {
|
||||
// Do lint
|
||||
let mut vec = vec![(0, 1), (1, 2), (2, 3)];
|
||||
vec.retain(|(x, y)| *x == 0);
|
||||
|
||||
// Do lint
|
||||
let mut tuples = vec![(true, -2), (false, 3)];
|
||||
tuples.retain(|(_, n)| *n > 0);
|
||||
}
|
||||
|
||||
fn issue_12081() {
|
||||
let mut vec = vec![0, 1, 2];
|
||||
|
||||
// Do lint
|
||||
vec.retain(|&x| x == 0);
|
||||
vec.retain(|&x| x == 0);
|
||||
vec.retain(|&x| x == 0);
|
||||
|
||||
// Do lint
|
||||
vec.retain(|x| *x == 0);
|
||||
vec.retain(|x| *x == 0);
|
||||
vec.retain(|x| *x == 0);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ fn main() {
|
|||
_msrv_153();
|
||||
_msrv_126();
|
||||
_msrv_118();
|
||||
|
||||
issue_10393();
|
||||
issue_12081();
|
||||
}
|
||||
|
||||
fn binary_heap_retain() {
|
||||
|
@ -23,6 +26,11 @@ fn binary_heap_retain() {
|
|||
binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
binary_heap = binary_heap
|
||||
.into_iter()
|
||||
|
@ -58,6 +66,9 @@ fn btree_map_retain() {
|
|||
.filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0))
|
||||
.collect();
|
||||
|
||||
// Do not lint, because the parameters are not matched in tuple pattern
|
||||
btree_map = btree_map.into_iter().filter(|t| t.0 % 2 == 0).collect();
|
||||
|
||||
// Do not lint.
|
||||
btree_map = btree_map
|
||||
.into_iter()
|
||||
|
@ -79,6 +90,11 @@ fn btree_set_retain() {
|
|||
btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
btree_set = btree_set
|
||||
.iter()
|
||||
|
@ -114,6 +130,9 @@ fn hash_map_retain() {
|
|||
.filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0))
|
||||
.collect();
|
||||
|
||||
// Do not lint, because the parameters are not matched in tuple pattern
|
||||
hash_map = hash_map.into_iter().filter(|t| t.0 % 2 == 0).collect();
|
||||
|
||||
// Do not lint.
|
||||
hash_map = hash_map
|
||||
.into_iter()
|
||||
|
@ -134,6 +153,11 @@ fn hash_set_retain() {
|
|||
hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]);
|
||||
tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>();
|
||||
hash_set = hash_set
|
||||
|
@ -163,6 +187,9 @@ fn string_retain() {
|
|||
// Do lint.
|
||||
s = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
|
||||
// Do not lint, because we need to rewrite the lambda
|
||||
s = s.chars().filter(|c| *c != 'o').to_owned().collect();
|
||||
|
||||
// Do not lint, because this expression is not assign.
|
||||
let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
|
||||
|
@ -177,6 +204,11 @@ fn vec_retain() {
|
|||
vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
|
||||
// Do lint, because we use pattern matching
|
||||
let mut tuples = vec![(0, 1), (1, 2), (2, 3)];
|
||||
tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
|
||||
// Do not lint, because type conversion is performed
|
||||
vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>();
|
||||
vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>();
|
||||
|
@ -252,3 +284,27 @@ fn _msrv_118() {
|
|||
let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
|
||||
hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
|
||||
}
|
||||
|
||||
fn issue_10393() {
|
||||
// Do lint
|
||||
let mut vec = vec![(0, 1), (1, 2), (2, 3)];
|
||||
vec = vec.into_iter().filter(|(x, y)| *x == 0).collect();
|
||||
|
||||
// Do lint
|
||||
let mut tuples = vec![(true, -2), (false, 3)];
|
||||
tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect();
|
||||
}
|
||||
|
||||
fn issue_12081() {
|
||||
let mut vec = vec![0, 1, 2];
|
||||
|
||||
// Do lint
|
||||
vec = vec.iter().filter(|&&x| x == 0).copied().collect();
|
||||
vec = vec.iter().filter(|&&x| x == 0).cloned().collect();
|
||||
vec = vec.into_iter().filter(|&x| x == 0).collect();
|
||||
|
||||
// Do lint
|
||||
vec = vec.iter().filter(|&x| *x == 0).copied().collect();
|
||||
vec = vec.iter().filter(|&x| *x == 0).cloned().collect();
|
||||
vec = vec.into_iter().filter(|x| *x == 0).collect();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:22:5
|
||||
--> $DIR/manual_retain.rs:25:5
|
||||
|
|
||||
LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
|
||||
|
@ -8,31 +8,43 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
|
|||
= help: to override `-D warnings` add `#[allow(clippy::manual_retain)]`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:23:5
|
||||
--> $DIR/manual_retain.rs:26:5
|
||||
|
|
||||
LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:24:5
|
||||
--> $DIR/manual_retain.rs:27:5
|
||||
|
|
||||
LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:54:5
|
||||
--> $DIR/manual_retain.rs:31:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:32:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:62:5
|
||||
|
|
||||
LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:55:5
|
||||
--> $DIR/manual_retain.rs:63:5
|
||||
|
|
||||
LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:56:5
|
||||
--> $DIR/manual_retain.rs:64:5
|
||||
|
|
||||
LL | / btree_map = btree_map
|
||||
LL | | .into_iter()
|
||||
|
@ -41,37 +53,49 @@ LL | | .collect();
|
|||
| |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:78:5
|
||||
--> $DIR/manual_retain.rs:89:5
|
||||
|
|
||||
LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:79:5
|
||||
--> $DIR/manual_retain.rs:90:5
|
||||
|
|
||||
LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:80:5
|
||||
--> $DIR/manual_retain.rs:91:5
|
||||
|
|
||||
LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:110:5
|
||||
--> $DIR/manual_retain.rs:95:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:96:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:126:5
|
||||
|
|
||||
LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:111:5
|
||||
--> $DIR/manual_retain.rs:127:5
|
||||
|
|
||||
LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:112:5
|
||||
--> $DIR/manual_retain.rs:128:5
|
||||
|
|
||||
LL | / hash_map = hash_map
|
||||
LL | | .into_iter()
|
||||
|
@ -80,64 +104,136 @@ LL | | .collect();
|
|||
| |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:133:5
|
||||
--> $DIR/manual_retain.rs:152:5
|
||||
|
|
||||
LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:134:5
|
||||
--> $DIR/manual_retain.rs:153:5
|
||||
|
|
||||
LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:135:5
|
||||
--> $DIR/manual_retain.rs:154:5
|
||||
|
|
||||
LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:164:5
|
||||
--> $DIR/manual_retain.rs:158:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:159:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:188:5
|
||||
|
|
||||
LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:176:5
|
||||
--> $DIR/manual_retain.rs:203:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:177:5
|
||||
--> $DIR/manual_retain.rs:204:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:178:5
|
||||
--> $DIR/manual_retain.rs:205:5
|
||||
|
|
||||
LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:200:5
|
||||
--> $DIR/manual_retain.rs:209:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:210:5
|
||||
|
|
||||
LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:232:5
|
||||
|
|
||||
LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:201:5
|
||||
--> $DIR/manual_retain.rs:233:5
|
||||
|
|
||||
LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:202:5
|
||||
--> $DIR/manual_retain.rs:234:5
|
||||
|
|
||||
LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:291:5
|
||||
|
|
||||
LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:295:5
|
||||
|
|
||||
LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:302:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:303:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:304:5
|
||||
|
|
||||
LL | vec = vec.into_iter().filter(|&x| x == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:307:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:308:5
|
||||
|
|
||||
LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
|
||||
|
||||
error: this expression can be written more simply using `.retain()`
|
||||
--> $DIR/manual_retain.rs:309:5
|
||||
|
|
||||
LL | vec = vec.into_iter().filter(|x| *x == 0).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
|
||||
|
||||
error: aborting due to 38 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue