@@ -1299,14 +1299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12991299 let span = expr. span . shrink_to_hi ( ) ;
13001300 let subdiag = if self . type_is_copy_modulo_regions ( self . param_env , ty) {
13011301 errors:: OptionResultRefMismatch :: Copied { span, def_path }
1302- } else if let Some ( clone_did) = self . tcx . lang_items ( ) . clone_trait ( )
1303- && rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions (
1304- self ,
1305- self . param_env ,
1306- ty,
1307- clone_did,
1308- )
1309- {
1302+ } else if self . type_is_clone_modulo_regions ( self . param_env , ty) {
13101303 errors:: OptionResultRefMismatch :: Cloned { span, def_path }
13111304 } else {
13121305 return false ;
@@ -2159,6 +2152,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21592152 }
21602153 }
21612154
2155+ /// Suggest replacing comma with semicolon in incorrect repeat expressions
2156+ /// like `["_", 10]` or `vec![String::new(), 10]`.
2157+ pub ( crate ) fn suggest_semicolon_in_repeat_expr (
2158+ & self ,
2159+ err : & mut Diag < ' _ > ,
2160+ expr : & hir:: Expr < ' _ > ,
2161+ expr_ty : Ty < ' tcx > ,
2162+ ) -> bool {
2163+ // Check if `expr` is contained in array of two elements
2164+ if let hir:: Node :: Expr ( array_expr) = self . tcx . parent_hir_node ( expr. hir_id )
2165+ && let hir:: ExprKind :: Array ( elements) = array_expr. kind
2166+ && let [ first, second] = & elements[ ..]
2167+ && second. hir_id == expr. hir_id
2168+ {
2169+ // Span between the two elements of the array
2170+ let comma_span = first. span . between ( second. span ) ;
2171+
2172+ // Check if `expr` is a constant value of type `usize`.
2173+ // This can only detect const variable declarations and
2174+ // calls to const functions.
2175+
2176+ // Checking this here instead of rustc_hir::hir because
2177+ // this check needs access to `self.tcx` but rustc_hir
2178+ // has no access to `TyCtxt`.
2179+ let expr_is_const_usize = expr_ty. is_usize ( )
2180+ && match expr. kind {
2181+ ExprKind :: Path ( QPath :: Resolved (
2182+ None ,
2183+ Path { res : Res :: Def ( DefKind :: Const , _) , .. } ,
2184+ ) ) => true ,
2185+ ExprKind :: Call (
2186+ Expr {
2187+ kind :
2188+ ExprKind :: Path ( QPath :: Resolved (
2189+ None ,
2190+ Path { res : Res :: Def ( DefKind :: Fn , fn_def_id) , .. } ,
2191+ ) ) ,
2192+ ..
2193+ } ,
2194+ _,
2195+ ) => self . tcx . is_const_fn ( * fn_def_id) ,
2196+ _ => false ,
2197+ } ;
2198+
2199+ // `array_expr` is from a macro `vec!["a", 10]` if
2200+ // 1. array expression's span is imported from a macro
2201+ // 2. first element of array implements `Clone` trait
2202+ // 3. second element is an integer literal or is an expression of `usize` like type
2203+ if self . tcx . sess . source_map ( ) . is_imported ( array_expr. span )
2204+ && self . type_is_clone_modulo_regions ( self . param_env , self . check_expr ( first) )
2205+ && ( second. is_size_lit ( ) || expr_ty. is_usize_like ( ) )
2206+ {
2207+ err. subdiagnostic ( errors:: ReplaceCommaWithSemicolon {
2208+ comma_span,
2209+ descr : "a vector" ,
2210+ } ) ;
2211+ return true ;
2212+ } else if self . type_is_copy_modulo_regions ( self . param_env , self . check_expr ( first) )
2213+ && ( second. is_size_lit ( ) || expr_is_const_usize)
2214+ {
2215+ // `array_expr` is from an array `["a", 10]` if
2216+ // 1. first element of array implements `Copy` trait
2217+ // 2. second element is an integer literal or is a const value of type `usize`
2218+ err. subdiagnostic ( errors:: ReplaceCommaWithSemicolon {
2219+ comma_span,
2220+ descr : "an array" ,
2221+ } ) ;
2222+ return true ;
2223+ }
2224+ }
2225+ false
2226+ }
2227+
21622228 /// If the expected type is an enum (Issue #55250) with any variants whose
21632229 /// sole field is of the found type, suggest such variants. (Issue #42764)
21642230 pub ( crate ) fn suggest_compatible_variants (
0 commit comments