@@ -570,11 +570,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
570
570
} = move_spans
571
571
&& can_suggest_clone
572
572
{
573
- self . suggest_cloning ( err, ty, expr, None , Some ( move_spans) ) ;
573
+ self . suggest_cloning ( err, ty, expr, Some ( move_spans) ) ;
574
574
} else if self . suggest_hoisting_call_outside_loop ( err, expr) && can_suggest_clone {
575
575
// The place where the type moves would be misleading to suggest clone.
576
576
// #121466
577
- self . suggest_cloning ( err, ty, expr, None , Some ( move_spans) ) ;
577
+ self . suggest_cloning ( err, ty, expr, Some ( move_spans) ) ;
578
578
}
579
579
}
580
580
@@ -1236,8 +1236,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
1236
1236
& self ,
1237
1237
err : & mut Diag < ' _ > ,
1238
1238
ty : Ty < ' tcx > ,
1239
- mut expr : & ' tcx hir:: Expr < ' tcx > ,
1240
- mut other_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
1239
+ expr : & ' tcx hir:: Expr < ' tcx > ,
1241
1240
use_spans : Option < UseSpans < ' tcx > > ,
1242
1241
) {
1243
1242
if let hir:: ExprKind :: Struct ( _, _, Some ( _) ) = expr. kind {
@@ -1249,97 +1248,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
1249
1248
return ;
1250
1249
}
1251
1250
1252
- if let Some ( some_other_expr) = other_expr
1253
- && let Some ( parent_binop) =
1254
- self . infcx . tcx . hir ( ) . parent_iter ( expr. hir_id ) . find_map ( |n| {
1255
- if let ( hir_id, hir:: Node :: Expr ( e) ) = n
1256
- && let hir:: ExprKind :: AssignOp ( _binop, target, _arg) = e. kind
1257
- && target. hir_id == expr. hir_id
1258
- {
1259
- Some ( hir_id)
1260
- } else {
1261
- None
1262
- }
1263
- } )
1264
- && let Some ( other_parent_binop) =
1265
- self . infcx . tcx . hir ( ) . parent_iter ( some_other_expr. hir_id ) . find_map ( |n| {
1266
- if let ( hir_id, hir:: Node :: Expr ( expr) ) = n
1267
- && let hir:: ExprKind :: AssignOp ( ..) = expr. kind
1268
- {
1269
- Some ( hir_id)
1270
- } else {
1271
- None
1272
- }
1273
- } )
1274
- && parent_binop == other_parent_binop
1275
- {
1276
- // Explicitly look for `expr += other_expr;` and avoid suggesting
1277
- // `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
1278
- other_expr = Some ( expr) ;
1279
- expr = some_other_expr;
1280
- }
1281
- ' outer: {
1282
- if let ty:: Ref ( ..) = ty. kind ( ) {
1283
- // We check for either `let binding = foo(expr, other_expr);` or
1284
- // `foo(expr, other_expr);` and if so we don't suggest an incorrect
1285
- // `foo(expr, other_expr).clone()`
1286
- if let Some ( other_expr) = other_expr
1287
- && let Some ( parent_let) =
1288
- self . infcx . tcx . hir ( ) . parent_iter ( expr. hir_id ) . find_map ( |n| {
1289
- if let ( hir_id, hir:: Node :: LetStmt ( _) | hir:: Node :: Stmt ( _) ) = n {
1290
- Some ( hir_id)
1291
- } else {
1292
- None
1293
- }
1294
- } )
1295
- && let Some ( other_parent_let) =
1296
- self . infcx . tcx . hir ( ) . parent_iter ( other_expr. hir_id ) . find_map ( |n| {
1297
- if let ( hir_id, hir:: Node :: LetStmt ( _) | hir:: Node :: Stmt ( _) ) = n {
1298
- Some ( hir_id)
1299
- } else {
1300
- None
1301
- }
1302
- } )
1303
- && parent_let == other_parent_let
1304
- {
1305
- // Explicitly check that we don't have `foo(&*expr, other_expr)`, as cloning the
1306
- // result of `foo(...)` won't help.
1307
- break ' outer;
1308
- }
1309
-
1310
- // We're suggesting `.clone()` on an borrowed value. See if the expression we have
1311
- // is an argument to a function or method call, and try to suggest cloning the
1312
- // *result* of the call, instead of the argument. This is closest to what people
1313
- // would actually be looking for in most cases, with maybe the exception of things
1314
- // like `fn(T) -> T`, but even then it is reasonable.
1315
- let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
1316
- let mut prev = expr;
1317
- while let hir:: Node :: Expr ( parent) = self . infcx . tcx . parent_hir_node ( prev. hir_id ) {
1318
- if let hir:: ExprKind :: Call ( ..) | hir:: ExprKind :: MethodCall ( ..) = parent. kind
1319
- && let Some ( call_ty) = typeck_results. node_type_opt ( parent. hir_id )
1320
- && let call_ty = call_ty. peel_refs ( )
1321
- && ( !call_ty
1322
- . walk ( )
1323
- . any ( |t| matches ! ( t. unpack( ) , ty:: GenericArgKind :: Lifetime ( _) ) )
1324
- || if let ty:: Alias ( ty:: Projection , _) = call_ty. kind ( ) {
1325
- // FIXME: this isn't quite right with lifetimes on assoc types,
1326
- // but ignore for now. We will only suggest cloning if
1327
- // `<Ty as Trait>::Assoc: Clone`, which should keep false positives
1328
- // down to a managable ammount.
1329
- true
1330
- } else {
1331
- false
1332
- } )
1333
- && self . implements_clone ( call_ty)
1334
- && self . suggest_cloning_inner ( err, call_ty, parent)
1335
- {
1336
- return ;
1337
- }
1338
- prev = parent;
1339
- }
1340
- }
1341
- }
1342
- let ty = ty. peel_refs ( ) ;
1343
1251
if self . implements_clone ( ty) {
1344
1252
self . suggest_cloning_inner ( err, ty, expr) ;
1345
1253
} else if let ty:: Adt ( def, args) = ty. kind ( )
@@ -1606,10 +1514,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
1606
1514
) ;
1607
1515
self . suggest_copy_for_type_in_cloned_ref ( & mut err, place) ;
1608
1516
let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
1609
- if let Some ( expr) = self . find_expr ( borrow_span)
1610
- && let Some ( ty) = typeck_results. node_type_opt ( expr. hir_id )
1611
- {
1612
- self . suggest_cloning ( & mut err, ty, expr, self . find_expr ( span) , Some ( move_spans) ) ;
1517
+ if let Some ( expr) = self . find_expr ( borrow_span) {
1518
+ // This is a borrow span, so we want to suggest cloning the referent.
1519
+ if let hir:: ExprKind :: AddrOf ( _, _, borrowed_expr) = expr. kind
1520
+ && let Some ( ty) = typeck_results. expr_ty_opt ( borrowed_expr)
1521
+ {
1522
+ self . suggest_cloning ( & mut err, ty, borrowed_expr, Some ( move_spans) ) ;
1523
+ } else if typeck_results. expr_adjustments ( expr) . first ( ) . is_some_and ( |adj| {
1524
+ matches ! (
1525
+ adj. kind,
1526
+ ty:: adjustment:: Adjust :: Borrow ( ty:: adjustment:: AutoBorrow :: Ref (
1527
+ _,
1528
+ ty:: adjustment:: AutoBorrowMutability :: Not
1529
+ | ty:: adjustment:: AutoBorrowMutability :: Mut {
1530
+ allow_two_phase_borrow: ty:: adjustment:: AllowTwoPhase :: No
1531
+ }
1532
+ ) )
1533
+ )
1534
+ } ) && let Some ( ty) = typeck_results. expr_ty_opt ( expr)
1535
+ {
1536
+ self . suggest_cloning ( & mut err, ty, expr, Some ( move_spans) ) ;
1537
+ }
1613
1538
}
1614
1539
self . buffer_error ( err) ;
1615
1540
}
0 commit comments