@@ -1320,14 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13201320 let span = expr. span . shrink_to_hi ( ) ;
13211321 let subdiag = if self . type_is_copy_modulo_regions ( self . param_env , ty) {
13221322 errors:: OptionResultRefMismatch :: Copied { span, def_path }
1323- } else if let Some ( clone_did) = self . tcx . lang_items ( ) . clone_trait ( )
1324- && rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions (
1325- self ,
1326- self . param_env ,
1327- ty,
1328- clone_did,
1329- )
1330- {
1323+ } else if self . type_is_clone_modulo_regions ( self . param_env , ty) {
13311324 errors:: OptionResultRefMismatch :: Cloned { span, def_path }
13321325 } else {
13331326 return false ;
@@ -2182,6 +2175,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21822175 }
21832176 }
21842177
2178+ /// Suggest replacing comma with semicolon in incorrect repeat expressions
2179+ /// like `["_", 10]` or `vec![String::new(), 10]`.
2180+ pub ( crate ) fn suggest_semicolon_in_repeat_expr (
2181+ & self ,
2182+ err : & mut Diag < ' _ > ,
2183+ expr : & hir:: Expr < ' _ > ,
2184+ expr_ty : Ty < ' tcx > ,
2185+ ) -> bool {
2186+ // Check if `expr` is contained in array of two elements
2187+ if let hir:: Node :: Expr ( array_expr) = self . tcx . parent_hir_node ( expr. hir_id )
2188+ && let hir:: ExprKind :: Array ( elements) = array_expr. kind
2189+ && let [ first, second] = & elements[ ..]
2190+ && second. hir_id == expr. hir_id
2191+ {
2192+ // Span between the two elements of the array
2193+ let comma_span = first. span . between ( second. span ) ;
2194+
2195+ // Check if `expr` is a constant value of type `usize`.
2196+ // This can only detect const variable declarations and
2197+ // calls to const functions.
2198+
2199+ // Checking this here instead of rustc_hir::hir because
2200+ // this check needs access to `self.tcx` but rustc_hir
2201+ // has no access to `TyCtxt`.
2202+ let expr_is_const_usize = expr_ty. is_usize ( )
2203+ && match expr. kind {
2204+ ExprKind :: Path ( QPath :: Resolved (
2205+ None ,
2206+ Path { res : Res :: Def ( DefKind :: Const , _) , .. } ,
2207+ ) ) => true ,
2208+ ExprKind :: Call (
2209+ Expr {
2210+ kind :
2211+ ExprKind :: Path ( QPath :: Resolved (
2212+ None ,
2213+ Path { res : Res :: Def ( DefKind :: Fn , fn_def_id) , .. } ,
2214+ ) ) ,
2215+ ..
2216+ } ,
2217+ _,
2218+ ) => self . tcx . is_const_fn ( * fn_def_id) ,
2219+ _ => false ,
2220+ } ;
2221+
2222+ // Type of the first element is guaranteed to be checked
2223+ // when execution reaches here because `mismatched types`
2224+ // error occurs only when type of second element of array
2225+ // is not the same as type of first element.
2226+ let first_ty = self . typeck_results . borrow ( ) . expr_ty ( first) ;
2227+
2228+ // `array_expr` is from a macro `vec!["a", 10]` if
2229+ // 1. array expression's span is imported from a macro
2230+ // 2. first element of array implements `Clone` trait
2231+ // 3. second element is an integer literal or is an expression of `usize` like type
2232+ if self . tcx . sess . source_map ( ) . is_imported ( array_expr. span )
2233+ && self . type_is_clone_modulo_regions ( self . param_env , first_ty)
2234+ && ( expr. is_size_lit ( ) || expr_ty. is_usize_like ( ) )
2235+ {
2236+ err. subdiagnostic ( errors:: ReplaceCommaWithSemicolon {
2237+ comma_span,
2238+ descr : "a vector" ,
2239+ } ) ;
2240+ return true ;
2241+ }
2242+
2243+ // `array_expr` is from an array `["a", 10]` if
2244+ // 1. first element of array implements `Copy` trait
2245+ // 2. second element is an integer literal or is a const value of type `usize`
2246+ if self . type_is_copy_modulo_regions ( self . param_env , first_ty)
2247+ && ( expr. is_size_lit ( ) || expr_is_const_usize)
2248+ {
2249+ err. subdiagnostic ( errors:: ReplaceCommaWithSemicolon {
2250+ comma_span,
2251+ descr : "an array" ,
2252+ } ) ;
2253+ return true ;
2254+ }
2255+ }
2256+ false
2257+ }
2258+
21852259 /// If the expected type is an enum (Issue #55250) with any variants whose
21862260 /// sole field is of the found type, suggest such variants. (Issue #42764)
21872261 pub ( crate ) fn suggest_compatible_variants (
0 commit comments