about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-12 16:25:59 +0000
committerbors <bors@rust-lang.org>2023-06-12 16:25:59 +0000
commitda56c3502ace00cfdef77af38cead0b9802e97fb (patch)
treee44a890859ffa11803edf74a2739d4c995c1d49c
parentb095247ab637194fbf6d271fc6a55552572dea2d (diff)
parent50ba459987a9b73a2db99e19b774531070a9f5fa (diff)
downloadrust-da56c3502ace00cfdef77af38cead0b9802e97fb.tar.gz
rust-da56c3502ace00cfdef77af38cead0b9802e97fb.zip
Auto merge of #10933 - y21:issue2262-followup, r=Centri3
[`useless_vec`]: lint on `vec![_]` invocations that adjust to a slice

Fixes #2262 (well, actually my PR over at #10901 did do most of the stuff, but this PR implements the one last other case mentioned in the comments that my PR didn't fix)

Before this change, it would lint `(&vec![1]).iter().sum::<i32>()`, but not `vec![1].iter().sum::<i32>()`. This PR handles this case.
This also refactors a few things that I wanted to do in my other PR but forgot about.

changelog: [`useless_vec`]: lint on `vec![_]` invocations that adjust to a slice
-rw-r--r--clippy_lints/src/vec.rs97
-rw-r--r--tests/ui/cloned_instead_of_copied.fixed1
-rw-r--r--tests/ui/cloned_instead_of_copied.rs1
-rw-r--r--tests/ui/cloned_instead_of_copied.stderr16
-rw-r--r--tests/ui/eta.fixed3
-rw-r--r--tests/ui/eta.rs3
-rw-r--r--tests/ui/eta.stderr52
-rw-r--r--tests/ui/from_iter_instead_of_collect.fixed1
-rw-r--r--tests/ui/from_iter_instead_of_collect.rs1
-rw-r--r--tests/ui/from_iter_instead_of_collect.stderr30
-rw-r--r--tests/ui/iter_cloned_collect.fixed1
-rw-r--r--tests/ui/iter_cloned_collect.rs1
-rw-r--r--tests/ui/iter_cloned_collect.stderr10
-rw-r--r--tests/ui/vec.fixed3
-rw-r--r--tests/ui/vec.rs3
-rw-r--r--tests/ui/vec.stderr18
16 files changed, 124 insertions, 117 deletions
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 25b6f40762d..2a594e750b9 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -8,7 +8,6 @@ use clippy_utils::ty::is_copy;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{get_parent_expr, higher, is_trait_method};
 use if_chain::if_chain;
-use rustc_ast::BindingAnnotation;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -54,11 +53,7 @@ declare_clippy_lint! {
 impl_lint_pass!(UselessVec => [USELESS_VEC]);
 
 fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(e).kind() {
-        ty.is_slice()
-    } else {
-        false
-    }
+    matches!(cx.typeck_results().expr_ty_adjusted(e).kind(), ty::Ref(_, ty, _) if ty.is_slice())
 }
 
 /// Checks if the given expression is a method call to a `Vec` method
@@ -76,13 +71,21 @@ fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 
 impl<'tcx> LateLintPass<'tcx> for UselessVec {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        // search for `&vec![_]` expressions where the adjusted type is `&[_]`
+        // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
         if_chain! {
             if adjusts_to_slice(cx, expr);
-            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
-            if let Some(vec_args) = higher::VecArgs::hir(cx, addressee);
+            if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows());
             then {
-                self.check_vec_macro(cx, &vec_args, mutability, expr.span, SuggestSlice::Yes);
+                let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind {
+                    // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
+                    (SuggestedType::SliceRef(mutability), expr.span)
+                } else {
+                    // `expr` is the `vec![_]` expansion, so suggest `[_]`
+                    // and also use the span of the actual `vec![_]` expression
+                    (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site)
+                };
+
+                self.check_vec_macro(cx, &vec_args, span, suggest_slice);
             }
         }
 
@@ -93,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
             // for now ignore locals with type annotations.
             // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
             && local.ty.is_none()
-            && let PatKind::Binding(BindingAnnotation(_, mutbl), id, ..) = local.pat.kind
+            && let PatKind::Binding(_, id, ..) = local.pat.kind
             && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr)))
         {
             let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| {
@@ -113,9 +116,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
                 self.check_vec_macro(
                     cx,
                     &vec_args,
-                    mutbl,
                     expr.span.ctxt().outer_expn_data().call_site,
-                    SuggestSlice::No
+                    SuggestedType::Array
                 );
             }
         }
@@ -128,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
             then {
                 // report the error around the `vec!` not inside `<std macros>:`
                 let span = arg.span.ctxt().outer_expn_data().call_site;
-                self.check_vec_macro(cx, &vec_args, Mutability::Not, span, SuggestSlice::No);
+                self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array);
             }
         }
     }
@@ -137,11 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
 }
 
 #[derive(Copy, Clone)]
-enum SuggestSlice {
+enum SuggestedType {
     /// Suggest using a slice `&[..]` / `&mut [..]`
-    Yes,
+    SliceRef(Mutability),
     /// Suggest using an array: `[..]`
-    No,
+    Array,
 }
 
 impl UselessVec {
@@ -149,17 +151,11 @@ impl UselessVec {
         &mut self,
         cx: &LateContext<'tcx>,
         vec_args: &higher::VecArgs<'tcx>,
-        mutability: Mutability,
         span: Span,
-        suggest_slice: SuggestSlice,
+        suggest_slice: SuggestedType,
     ) {
         let mut applicability = Applicability::MachineApplicable;
 
-        let (borrow_prefix_mut, borrow_prefix) = match suggest_slice {
-            SuggestSlice::Yes => ("&mut ", "&"),
-            SuggestSlice::No => ("", ""),
-        };
-
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
                 if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
@@ -168,21 +164,13 @@ impl UselessVec {
                         return;
                     }
 
-                    match mutability {
-                        Mutability::Mut => {
-                            format!(
-                                "{borrow_prefix_mut}[{}; {}]",
-                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
-                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
-                            )
-                        },
-                        Mutability::Not => {
-                            format!(
-                                "{borrow_prefix}[{}; {}]",
-                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
-                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
-                            )
-                        },
+                    let elem = snippet_with_applicability(cx, elem.span, "elem", &mut applicability);
+                    let len = snippet_with_applicability(cx, len.span, "len", &mut applicability);
+
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => format!("&mut [{elem}; {len}]"),
+                        SuggestedType::SliceRef(Mutability::Not) => format!("&[{elem}; {len}]"),
+                        SuggestedType::Array => format!("[{elem}; {len}]"),
                     }
                 } else {
                     return;
@@ -194,25 +182,24 @@ impl UselessVec {
                         return;
                     }
                     let span = args[0].span.to(last.span);
+                    let args = snippet_with_applicability(cx, span, "..", &mut applicability);
 
-                    match mutability {
-                        Mutability::Mut => {
-                            format!(
-                                "{borrow_prefix_mut}[{}]",
-                                snippet_with_applicability(cx, span, "..", &mut applicability)
-                            )
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => {
+                            format!("&mut [{args}]")
+                        },
+                        SuggestedType::SliceRef(Mutability::Not) => {
+                            format!("&[{args}]")
                         },
-                        Mutability::Not => {
-                            format!(
-                                "{borrow_prefix}[{}]",
-                                snippet_with_applicability(cx, span, "..", &mut applicability)
-                            )
+                        SuggestedType::Array => {
+                            format!("[{args}]")
                         },
                     }
                 } else {
-                    match mutability {
-                        Mutability::Mut => format!("{borrow_prefix_mut}[]"),
-                        Mutability::Not => format!("{borrow_prefix}[]"),
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => "&mut []".to_owned(),
+                        SuggestedType::SliceRef(Mutability::Not) => "&[]".to_owned(),
+                        SuggestedType::Array => "[]".to_owned(),
                     }
                 }
             },
@@ -226,8 +213,8 @@ impl UselessVec {
             &format!(
                 "you can use {} directly",
                 match suggest_slice {
-                    SuggestSlice::Yes => "a slice",
-                    SuggestSlice::No => "an array",
+                    SuggestedType::SliceRef(_) => "a slice",
+                    SuggestedType::Array => "an array",
                 }
             ),
             snippet,
diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed
index b6e09ab3190..34bd2233440 100644
--- a/tests/ui/cloned_instead_of_copied.fixed
+++ b/tests/ui/cloned_instead_of_copied.fixed
@@ -2,6 +2,7 @@
 
 #![warn(clippy::cloned_instead_of_copied)]
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // yay
diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs
index fa9e1a99613..fa8444937b6 100644
--- a/tests/ui/cloned_instead_of_copied.rs
+++ b/tests/ui/cloned_instead_of_copied.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::cloned_instead_of_copied)]
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // yay
diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr
index e0361acd956..3ce482006e9 100644
--- a/tests/ui/cloned_instead_of_copied.stderr
+++ b/tests/ui/cloned_instead_of_copied.stderr
@@ -1,5 +1,5 @@
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:8:24
+  --> $DIR/cloned_instead_of_copied.rs:9:24
    |
 LL |     let _ = [1].iter().cloned();
    |                        ^^^^^^ help: try: `copied`
@@ -7,43 +7,43 @@ LL |     let _ = [1].iter().cloned();
    = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:9:31
+  --> $DIR/cloned_instead_of_copied.rs:10:31
    |
 LL |     let _ = vec!["hi"].iter().cloned();
    |                               ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:10:22
+  --> $DIR/cloned_instead_of_copied.rs:11:22
    |
 LL |     let _ = Some(&1).cloned();
    |                      ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:11:34
+  --> $DIR/cloned_instead_of_copied.rs:12:34
    |
 LL |     let _ = Box::new([1].iter()).cloned();
    |                                  ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:12:32
+  --> $DIR/cloned_instead_of_copied.rs:13:32
    |
 LL |     let _ = Box::new(Some(&1)).cloned();
    |                                ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:28:22
+  --> $DIR/cloned_instead_of_copied.rs:29:22
    |
 LL |     let _ = Some(&1).cloned(); // Option::copied needs 1.35
    |                      ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:33:24
+  --> $DIR/cloned_instead_of_copied.rs:34:24
    |
 LL |     let _ = [1].iter().cloned(); // Iterator::copied needs 1.36
    |                        ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:34:22
+  --> $DIR/cloned_instead_of_copied.rs:35:22
    |
 LL |     let _ = Some(&1).cloned();
    |                      ^^^^^^ help: try: `copied`
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index 31a94cb10e8..bf44bcb564e 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::option_map_unit_fn,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 use std::path::{Path, PathBuf};
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 978aecd24b3..b2af4bf0953 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::option_map_unit_fn,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 use std::path::{Path, PathBuf};
diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr
index 19be5fc7389..0ac0b901df4 100644
--- a/tests/ui/eta.stderr
+++ b/tests/ui/eta.stderr
@@ -1,5 +1,5 @@
 error: redundant closure
-  --> $DIR/eta.rs:28:27
+  --> $DIR/eta.rs:29:27
    |
 LL |     let a = Some(1u8).map(|a| foo(a));
    |                           ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@@ -7,31 +7,31 @@ LL |     let a = Some(1u8).map(|a| foo(a));
    = note: `-D clippy::redundant-closure` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:32:40
+  --> $DIR/eta.rs:33: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
-  --> $DIR/eta.rs:33:35
+  --> $DIR/eta.rs:34: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
-  --> $DIR/eta.rs:34:26
+  --> $DIR/eta.rs:35: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
-  --> $DIR/eta.rs:41:27
+  --> $DIR/eta.rs:42:27
    |
 LL |     let e = Some(1u8).map(|a| generic(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
 
 error: redundant closure
-  --> $DIR/eta.rs:93:51
+  --> $DIR/eta.rs:94:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    |                                                   ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -39,121 +39,121 @@ LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:94:51
+  --> $DIR/eta.rs:95: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
-  --> $DIR/eta.rs:96:42
+  --> $DIR/eta.rs:97: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
-  --> $DIR/eta.rs:100:29
+  --> $DIR/eta.rs:101: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
-  --> $DIR/eta.rs:101:27
+  --> $DIR/eta.rs:102: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
-  --> $DIR/eta.rs:103:65
+  --> $DIR/eta.rs:104: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
-  --> $DIR/eta.rs:166:22
+  --> $DIR/eta.rs:167:22
    |
 LL |     requires_fn_once(|| x());
    |                      ^^^^^^ help: replace the closure with the function itself: `x`
 
 error: redundant closure
-  --> $DIR/eta.rs:173:27
+  --> $DIR/eta.rs:174:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> $DIR/eta.rs:178:27
+  --> $DIR/eta.rs:179:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:210:28
+  --> $DIR/eta.rs:211: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
-  --> $DIR/eta.rs:211:28
+  --> $DIR/eta.rs:212: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
-  --> $DIR/eta.rs:212:28
+  --> $DIR/eta.rs:213: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
-  --> $DIR/eta.rs:219:21
+  --> $DIR/eta.rs:220:21
    |
 LL |         Some(1).map(|n| closure(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:223:21
+  --> $DIR/eta.rs:224:21
    |
 LL |         Some(1).map(|n| in_loop(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
 
 error: redundant closure
-  --> $DIR/eta.rs:316:18
+  --> $DIR/eta.rs:317:18
    |
 LL |     takes_fn_mut(|| f());
    |                  ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> $DIR/eta.rs:319:19
+  --> $DIR/eta.rs:320:19
    |
 LL |     takes_fn_once(|| f());
    |                   ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> $DIR/eta.rs:323:26
+  --> $DIR/eta.rs:324:26
    |
 LL |     move || takes_fn_mut(|| f_used_once())
    |                          ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
 
 error: redundant closure
-  --> $DIR/eta.rs:335:19
+  --> $DIR/eta.rs:336:19
    |
 LL |     array_opt.map(|a| a.as_slice());
    |                   ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
 
 error: redundant closure
-  --> $DIR/eta.rs:338:19
+  --> $DIR/eta.rs:339:19
    |
 LL |     slice_opt.map(|s| s.len());
    |                   ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
 
 error: redundant closure
-  --> $DIR/eta.rs:341:17
+  --> $DIR/eta.rs:342:17
    |
 LL |     ptr_opt.map(|p| p.is_null());
    |                 ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
 
 error: redundant closure
-  --> $DIR/eta.rs:345:17
+  --> $DIR/eta.rs:346:17
    |
 LL |     dyn_opt.map(|d| d.method_on_dyn());
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
diff --git a/tests/ui/from_iter_instead_of_collect.fixed b/tests/ui/from_iter_instead_of_collect.fixed
index 915ff4fb079..1671987cb67 100644
--- a/tests/ui/from_iter_instead_of_collect.fixed
+++ b/tests/ui/from_iter_instead_of_collect.fixed
@@ -2,6 +2,7 @@
 
 #![warn(clippy::from_iter_instead_of_collect)]
 #![allow(unused_imports, unused_tuple_struct_fields)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/tests/ui/from_iter_instead_of_collect.rs b/tests/ui/from_iter_instead_of_collect.rs
index e926f8c529d..48509b32f10 100644
--- a/tests/ui/from_iter_instead_of_collect.rs
+++ b/tests/ui/from_iter_instead_of_collect.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::from_iter_instead_of_collect)]
 #![allow(unused_imports, unused_tuple_struct_fields)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/tests/ui/from_iter_instead_of_collect.stderr b/tests/ui/from_iter_instead_of_collect.stderr
index 8aa3c3c01f8..8f08ac8c3ff 100644
--- a/tests/ui/from_iter_instead_of_collect.stderr
+++ b/tests/ui/from_iter_instead_of_collect.stderr
@@ -1,5 +1,5 @@
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:18:9
+  --> $DIR/from_iter_instead_of_collect.rs:19:9
    |
 LL |         <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::<Self>()`
@@ -7,85 +7,85 @@ LL |         <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
    = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:24:13
+  --> $DIR/from_iter_instead_of_collect.rs:25:13
    |
 LL |     let _ = Vec::from_iter(iter_expr);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:26:13
+  --> $DIR/from_iter_instead_of_collect.rs:27:13
    |
 LL |     let _ = HashMap::<usize, &i8>::from_iter(vec![5, 5, 5, 5].iter().enumerate());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::<HashMap<usize, &i8>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:31:19
+  --> $DIR/from_iter_instead_of_collect.rs:32:19
    |
 LL |     assert_eq!(a, Vec::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:32:19
+  --> $DIR/from_iter_instead_of_collect.rs:33:19
    |
 LL |     assert_eq!(a, Vec::<i32>::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:34:17
+  --> $DIR/from_iter_instead_of_collect.rs:35:17
    |
 LL |     let mut b = VecDeque::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:37:17
+  --> $DIR/from_iter_instead_of_collect.rs:38:17
    |
 LL |     let mut b = VecDeque::<i32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:42:21
+  --> $DIR/from_iter_instead_of_collect.rs:43:21
    |
 LL |         let mut b = collections::VecDeque::<i32>::from_iter(0..3);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:47:14
+  --> $DIR/from_iter_instead_of_collect.rs:48:14
    |
 LL |     let bm = BTreeMap::from_iter(values.iter().cloned());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:48:19
+  --> $DIR/from_iter_instead_of_collect.rs:49:19
    |
 LL |     let mut bar = BTreeMap::from_iter(bm.range(0..2));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:51:19
+  --> $DIR/from_iter_instead_of_collect.rs:52:19
    |
 LL |     let mut bts = BTreeSet::from_iter(0..3);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:55:17
+  --> $DIR/from_iter_instead_of_collect.rs:56:17
    |
 LL |         let _ = collections::BTreeSet::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:56:17
+  --> $DIR/from_iter_instead_of_collect.rs:57:17
    |
 LL |         let _ = collections::BTreeSet::<u32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<u32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:59:15
+  --> $DIR/from_iter_instead_of_collect.rs:60:15
    |
 LL |     for _i in Vec::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:60:15
+  --> $DIR/from_iter_instead_of_collect.rs:61:15
    |
 LL |     for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<&i32>>()`
diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed
index 88f08bb991b..2baea06f84b 100644
--- a/tests/ui/iter_cloned_collect.fixed
+++ b/tests/ui/iter_cloned_collect.fixed
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::HashSet;
 use std::collections::VecDeque;
diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs
index d3438b7f51a..9eac94eb8d9 100644
--- a/tests/ui/iter_cloned_collect.rs
+++ b/tests/ui/iter_cloned_collect.rs
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::HashSet;
 use std::collections::VecDeque;
diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr
index b2cc497bf43..b38cf547dc5 100644
--- a/tests/ui/iter_cloned_collect.stderr
+++ b/tests/ui/iter_cloned_collect.stderr
@@ -1,5 +1,5 @@
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:10:27
+  --> $DIR/iter_cloned_collect.rs:11:27
    |
 LL |     let v2: Vec<isize> = v.iter().cloned().collect();
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
@@ -7,13 +7,13 @@ LL |     let v2: Vec<isize> = v.iter().cloned().collect();
    = note: `-D clippy::iter-cloned-collect` implied by `-D warnings`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:15:38
+  --> $DIR/iter_cloned_collect.rs:16:38
    |
 LL |     let _: Vec<isize> = vec![1, 2, 3].iter().cloned().collect();
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:20:24
+  --> $DIR/iter_cloned_collect.rs:21:24
    |
 LL |               .to_bytes()
    |  ________________________^
@@ -23,13 +23,13 @@ LL | |             .collect();
    | |______________________^ help: try: `.to_vec()`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:28:24
+  --> $DIR/iter_cloned_collect.rs:29:24
    |
 LL |     let _: Vec<_> = arr.iter().cloned().collect();
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
 
 error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:31:26
+  --> $DIR/iter_cloned_collect.rs:32:26
    |
 LL |     let _: Vec<isize> = v.iter().copied().collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed
index 55329ee843d..fcdc917c1b1 100644
--- a/tests/ui/vec.fixed
+++ b/tests/ui/vec.fixed
@@ -71,6 +71,9 @@ fn main() {
         println!("{:?}", a);
     }
 
+    // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
+    let _x: i32 = [1, 2, 3].iter().sum();
+
     // Do lint
     let mut x = [1, 2, 3];
     x.fill(123);
diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs
index bab316fa620..0404d8cdb84 100644
--- a/tests/ui/vec.rs
+++ b/tests/ui/vec.rs
@@ -71,6 +71,9 @@ fn main() {
         println!("{:?}", a);
     }
 
+    // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
+    let _x: i32 = vec![1, 2, 3].iter().sum();
+
     // Do lint
     let mut x = vec![1, 2, 3];
     x.fill(123);
diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr
index f3a4bf925dd..33d565b2d52 100644
--- a/tests/ui/vec.stderr
+++ b/tests/ui/vec.stderr
@@ -61,34 +61,40 @@ LL |     on_mut_slice(&mut vec![1; 2]);
    |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:75:17
+  --> $DIR/vec.rs:75:19
+   |
+LL |     let _x: i32 = vec![1, 2, 3].iter().sum();
+   |                   ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:78:17
    |
 LL |     let mut x = vec![1, 2, 3];
    |                 ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:81:22
+  --> $DIR/vec.rs:84:22
    |
 LL |     let _x: &[i32] = &vec![1, 2, 3];
    |                      ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:83:14
+  --> $DIR/vec.rs:86:14
    |
 LL |     for _ in vec![1, 2, 3] {}
    |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:117:14
+  --> $DIR/vec.rs:120:14
    |
 LL |     for a in vec![1, 2, 3] {
    |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:121:14
+  --> $DIR/vec.rs:124:14
    |
 LL |     for a in vec![String::new(), String::new()] {
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]`
 
-error: aborting due to 15 previous errors
+error: aborting due to 16 previous errors