fix: iter_cloned_collect FP with custom From/IntoIterator impl
This commit is contained in:
parent
f74d7ce813
commit
ee36124011
4 changed files with 69 additions and 3 deletions
|
|
@ -1,16 +1,22 @@
|
|||
use crate::methods::utils::derefs_to_slice;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::ty::{get_iterator_item_ty, is_type_diagnostic_item};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::ITER_CLONED_COLLECT;
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) {
|
||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec)
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr);
|
||||
if is_type_diagnostic_item(cx, expr_ty, sym::Vec)
|
||||
&& let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv))
|
||||
&& let ty::Adt(_, args) = expr_ty.kind()
|
||||
&& let Some(iter_item_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv))
|
||||
&& let ty::Ref(_, iter_item_ty, _) = iter_item_ty.kind()
|
||||
&& *iter_item_ty == args.type_at(0)
|
||||
&& let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite())
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
|
|
|
|||
|
|
@ -29,3 +29,30 @@ fn main() {
|
|||
let _: Vec<isize> = v.to_vec();
|
||||
//~^ iter_cloned_collect
|
||||
}
|
||||
|
||||
mod issue9119 {
|
||||
|
||||
use std::iter;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Example(u16);
|
||||
|
||||
impl iter::FromIterator<Example> for Vec<u8> {
|
||||
fn from_iter<T>(iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = Example>,
|
||||
{
|
||||
iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let examples = [Example(1), Example(0x1234)];
|
||||
let encoded: Vec<u8> = examples.iter().cloned().collect();
|
||||
assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
|
||||
|
||||
let a = [&&String::new()];
|
||||
let v: Vec<&&String> = a.to_vec();
|
||||
//~^ iter_cloned_collect
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,3 +33,30 @@ fn main() {
|
|||
let _: Vec<isize> = v.iter().copied().collect();
|
||||
//~^ iter_cloned_collect
|
||||
}
|
||||
|
||||
mod issue9119 {
|
||||
|
||||
use std::iter;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Example(u16);
|
||||
|
||||
impl iter::FromIterator<Example> for Vec<u8> {
|
||||
fn from_iter<T>(iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = Example>,
|
||||
{
|
||||
iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let examples = [Example(1), Example(0x1234)];
|
||||
let encoded: Vec<u8> = examples.iter().cloned().collect();
|
||||
assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
|
||||
|
||||
let a = [&&String::new()];
|
||||
let v: Vec<&&String> = a.iter().cloned().collect();
|
||||
//~^ iter_cloned_collect
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,5 +36,11 @@ error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling
|
|||
LL | let _: Vec<isize> = v.iter().copied().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
|
||||
--> tests/ui/iter_cloned_collect.rs:59:33
|
||||
|
|
||||
LL | let v: Vec<&&String> = a.iter().cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue