diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 398b694ae6bd6..dd8fb1f7eb6c5 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -7,7 +7,7 @@ use rustc_ast::token::CommentKind;
 use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
 use rustc_ast::{
     self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
-    IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
+    IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
 };
 pub use rustc_ast::{
     BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
@@ -2064,6 +2064,18 @@ impl Expr<'_> {
         }
     }
 
+    /// Check if expression is an integer literal that can be used
+    /// where `usize` is expected.
+    pub fn is_size_lit(&self) -> bool {
+        matches!(
+            self.kind,
+            ExprKind::Lit(Lit {
+                node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
+                ..
+            })
+        )
+    }
+
     /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
     /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
     /// silent, only signaling the ownership system. By doing this, suggestions that check the
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index a93da52b2703c..0f424a39840a3 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -165,6 +165,8 @@ hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this ret
 hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it
 hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon
 
+hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr}
+
 hir_typeck_return_stmt_outside_of_fn_body =
     {$statement_kind} statement outside of function body
     .encl_body_label = the {$statement_kind} is part of this body...
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index e51323fc5c852..56f7a2c1150ae 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -30,7 +30,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if expr_ty == expected {
             return;
         }
-
         self.annotate_alternative_method_deref(err, expr, error);
         self.explain_self_literal(err, expr, expected, expr_ty);
 
@@ -39,6 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
             || self.suggest_remove_last_method_call(err, expr, expected)
             || self.suggest_associated_const(err, expr, expected)
+            || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
             || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
             || self.suggest_option_to_bool(err, expr, expr_ty, expected)
             || self.suggest_compatible_variants(err, expr, expected, expr_ty)
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ff09583cc65a6..4eed2bc12388d 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -846,3 +846,16 @@ pub(crate) struct PassFnItemToVariadicFunction {
     pub sugg_span: Span,
     pub replace: String,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    hir_typeck_replace_comma_with_semicolon,
+    applicability = "machine-applicable",
+    style = "verbose",
+    code = "; "
+)]
+pub(crate) struct ReplaceCommaWithSemicolon {
+    #[primary_span]
+    pub comma_span: Span,
+    pub descr: &'static str,
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 964ef5b2106b1..c17218b611ecb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1319,14 +1319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let span = expr.span.shrink_to_hi();
                 let subdiag = if self.type_is_copy_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Copied { span, def_path }
-                } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
-                    && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
-                        self,
-                        self.param_env,
-                        ty,
-                        clone_did,
-                    )
-                {
+                } else if self.type_is_clone_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Cloned { span, def_path }
                 } else {
                     return false;
@@ -2181,6 +2174,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Suggest replacing comma with semicolon in incorrect repeat expressions
+    /// like `["_", 10]` or `vec![String::new(), 10]`.
+    pub(crate) fn suggest_semicolon_in_repeat_expr(
+        &self,
+        err: &mut Diag<'_>,
+        expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+    ) -> bool {
+        // Check if `expr` is contained in array of two elements
+        if let hir::Node::Expr(array_expr) = self.tcx.parent_hir_node(expr.hir_id)
+            && let hir::ExprKind::Array(elements) = array_expr.kind
+            && let [first, second] = &elements[..]
+            && second.hir_id == expr.hir_id
+        {
+            // Span between the two elements of the array
+            let comma_span = first.span.between(second.span);
+
+            // Check if `expr` is a constant value of type `usize`.
+            // This can only detect const variable declarations and
+            // calls to const functions.
+
+            // Checking this here instead of rustc_hir::hir because
+            // this check needs access to `self.tcx` but rustc_hir
+            // has no access to `TyCtxt`.
+            let expr_is_const_usize = expr_ty.is_usize()
+                && match expr.kind {
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        Path { res: Res::Def(DefKind::Const, _), .. },
+                    )) => true,
+                    ExprKind::Call(
+                        Expr {
+                            kind:
+                                ExprKind::Path(QPath::Resolved(
+                                    None,
+                                    Path { res: Res::Def(DefKind::Fn, fn_def_id), .. },
+                                )),
+                            ..
+                        },
+                        _,
+                    ) => self.tcx.is_const_fn(*fn_def_id),
+                    _ => false,
+                };
+
+            // Type of the first element is guaranteed to be checked
+            // when execution reaches here because `mismatched types`
+            // error occurs only when type of second element of array
+            // is not the same as type of first element.
+            let first_ty = self.typeck_results.borrow().expr_ty(first);
+
+            // `array_expr` is from a macro `vec!["a", 10]` if
+            // 1. array expression's span is imported from a macro
+            // 2. first element of array implements `Clone` trait
+            // 3. second element is an integer literal or is an expression of `usize` like type
+            if self.tcx.sess.source_map().is_imported(array_expr.span)
+                && self.type_is_clone_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_ty.is_usize_like())
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "a vector",
+                });
+                return true;
+            }
+
+            // `array_expr` is from an array `["a", 10]` if
+            // 1. first element of array implements `Copy` trait
+            // 2. second element is an integer literal or is a const value of type `usize`
+            if self.type_is_copy_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_is_const_usize)
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "an array",
+                });
+                return true;
+            }
+        }
+        false
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     pub(crate) fn suggest_compatible_variants(
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 045c483d6a58a..c45238b1eb0e4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -27,7 +27,7 @@ use crate::infer::canonical::Canonical;
 use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
-    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
 };
 
 // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
@@ -1008,6 +1008,18 @@ impl<'tcx> Ty<'tcx> {
         }
     }
 
+    /// Check if type is an `usize`.
+    #[inline]
+    pub fn is_usize(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize))
+    }
+
+    /// Check if type is an `usize` or an integral type variable.
+    #[inline]
+    pub fn is_usize_like(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
+    }
+
     #[inline]
     pub fn is_never(self) -> bool {
         matches!(self.kind(), Never)
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index ee708564a8046..f373706b2960c 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -47,6 +47,12 @@ impl<'tcx> InferCtxt<'tcx> {
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
     }
 
+    fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+        let ty = self.resolve_vars_if_possible(ty);
+        let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, None);
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id)
+    }
+
     fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
new file mode 100644
index 0000000000000..c76e7a1d71665
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
@@ -0,0 +1,70 @@
+#[derive(Copy, Clone)]
+struct Type;
+
+struct NewType;
+
+const fn get_size() -> usize {
+    10
+}
+
+fn get_dyn_size() -> usize {
+    10
+}
+
+fn main() {
+    let a = ["a", 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    const size_b: usize = 20;
+    let b = [Type, size_b];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let size_c: usize = 13;
+    let c = [Type, size_c];
+    //~^ ERROR mismatched types
+
+    const size_d: bool = true;
+    let d = [Type, size_d];
+    //~^ ERROR mismatched types
+
+    let e = [String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP try using a conversion method
+
+    let f = ["f", get_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let m = ["m", get_dyn_size()];
+    //~^ ERROR mismatched types
+
+    // is_vec, is_clone, is_usize_like
+    let g = vec![String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let dyn_size = 10;
+    let h = vec![Type, dyn_size];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let i = vec![Type, get_dyn_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let k = vec!['c', 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let j = vec![Type, 10_u8];
+    //~^ ERROR mismatched types
+
+    let l = vec![NewType, 10];
+    //~^ ERROR mismatched types
+
+    let byte_size: u8 = 10;
+    let h = vec![Type, byte_size];
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
new file mode 100644
index 0000000000000..95eddbde9e672
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
@@ -0,0 +1,124 @@
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:15:19
+   |
+LL |     let a = ["a", 10];
+   |                   ^^ expected `&str`, found integer
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let a = ["a"; 10];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:20:20
+   |
+LL |     let b = [Type, size_b];
+   |                    ^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let b = [Type; size_b];
+   |                  ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:25:20
+   |
+LL |     let c = [Type, size_c];
+   |                    ^^^^^^ expected `Type`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:29:20
+   |
+LL |     let d = [Type, size_d];
+   |                    ^^^^^^ expected `Type`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:32:29
+   |
+LL |     let e = [String::new(), 10];
+   |                             ^^- help: try using a conversion method: `.to_string()`
+   |                             |
+   |                             expected `String`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:36:19
+   |
+LL |     let f = ["f", get_size()];
+   |                   ^^^^^^^^^^ expected `&str`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let f = ["f"; get_size()];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:40:19
+   |
+LL |     let m = ["m", get_dyn_size()];
+   |                   ^^^^^^^^^^^^^^ expected `&str`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:44:33
+   |
+LL |     let g = vec![String::new(), 10];
+   |                                 ^^ expected `String`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let g = vec![String::new(); 10];
+   |                               ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:49:24
+   |
+LL |     let h = vec![Type, dyn_size];
+   |                        ^^^^^^^^ expected `Type`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let h = vec![Type; dyn_size];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:53:24
+   |
+LL |     let i = vec![Type, get_dyn_size()];
+   |                        ^^^^^^^^^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let i = vec![Type; get_dyn_size()];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:57:23
+   |
+LL |     let k = vec!['c', 10];
+   |                       ^^ expected `char`, found `u8`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let k = vec!['c'; 10];
+   |                     ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:61:24
+   |
+LL |     let j = vec![Type, 10_u8];
+   |                        ^^^^^ expected `Type`, found `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:64:27
+   |
+LL |     let l = vec![NewType, 10];
+   |                           ^^ expected `NewType`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:68:24
+   |
+LL |     let h = vec![Type, byte_size];
+   |                        ^^^^^^^^^ expected `Type`, found `u8`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.