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