about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2023-12-16 14:02:50 +0100
committerSamuel Tardieu <sam@rfc1149.net>2023-12-17 11:32:15 +0100
commit4cea5a8f33715bfe38824c798a5d75218cbfec04 (patch)
treeb9dcab2c9d3f844145fc0b984fee7652da9025a0
parent29bdc8b2bc58247e3a2bdd0052a18ea46b8b5c24 (diff)
downloadrust-4cea5a8f33715bfe38824c798a5d75218cbfec04.tar.gz
rust-4cea5a8f33715bfe38824c798a5d75218cbfec04.zip
Do not suggest `[T; n]` instead of `vec![T; n]` if `T` is not `Copy`
-rw-r--r--clippy_lints/src/vec.rs17
-rw-r--r--tests/ui/vec.fixed7
-rw-r--r--tests/ui/vec.rs7
3 files changed, 20 insertions, 11 deletions
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 5e13c73f035..2c33c93412a 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -11,8 +11,8 @@ use clippy_utils::{get_parent_expr, higher, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::{sym, DesugaringKind, Span};
 
@@ -79,7 +79,6 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
                 // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
                 && local.ty.is_none()
                 && let PatKind::Binding(_, id, ..) = local.pat.kind
-                && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr.peel_borrows())))
             {
                 let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| {
                     // allow indexing into a vec and some set of allowed method calls that exist on slices, too
@@ -185,6 +184,11 @@ impl UselessVec {
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
                 if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
+                    // vec![ty; N] works when ty is Clone, [ty; N] requires it to be Copy also
+                    if !is_copy(cx, cx.typeck_results().expr_ty(elem)) {
+                        return;
+                    }
+
                     #[expect(clippy::cast_possible_truncation)]
                     if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
                         return;
@@ -241,12 +245,3 @@ fn size_of(cx: &LateContext<'_>, expr: &Expr<'_>) -> u64 {
     let ty = cx.typeck_results().expr_ty_adjusted(expr);
     cx.layout_of(ty).map_or(0, |l| l.size.bytes())
 }
-
-/// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
-fn vec_type(ty: Ty<'_>) -> Ty<'_> {
-    if let ty::Adt(_, args) = ty.kind() {
-        args.type_at(0)
-    } else {
-        panic!("The type of `vec!` is a not a struct?");
-    }
-}
diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed
index 81b8bd7da77..b318fd42f7c 100644
--- a/tests/ui/vec.fixed
+++ b/tests/ui/vec.fixed
@@ -210,3 +210,10 @@ fn issue11861() {
     // should not lint
     m!(vec![1]);
 }
+
+fn issue_11958() {
+    fn f(_s: &[String]) {}
+
+    // should not lint, `String` is not `Copy`
+    f(&vec!["test".to_owned(); 2]);
+}
diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs
index 5aca9b2925c..08ad6efa37f 100644
--- a/tests/ui/vec.rs
+++ b/tests/ui/vec.rs
@@ -210,3 +210,10 @@ fn issue11861() {
     // should not lint
     m!(vec![1]);
 }
+
+fn issue_11958() {
+    fn f(_s: &[String]) {}
+
+    // should not lint, `String` is not `Copy`
+    f(&vec!["test".to_owned(); 2]);
+}