@@ -83,6 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
83
83
}
84
84
85
85
self . annotate_expected_due_to_let_ty ( err, expr, error) ;
86
+
87
+ if self . is_destruct_assignment_desugaring ( expr) {
88
+ return ;
89
+ }
86
90
self . emit_type_mismatch_suggestions ( err, expr, expr_ty, expected, expected_ty_expr, error) ;
87
91
self . note_type_is_not_clone ( err, expected, expr_ty, expr) ;
88
92
self . note_internal_mutation_in_method ( err, expr, Some ( expected) , expr_ty) ;
@@ -1253,6 +1257,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1253
1257
false
1254
1258
}
1255
1259
1260
+ // Returns whether the given expression is a destruct assignment desugaring.
1261
+ // For example, `(a, b) = (1, &2);`
1262
+ // Here we try to find the pattern binding of the expression,
1263
+ // `default_binding_modes` is false only for destruct assignment desugaring.
1264
+ pub ( crate ) fn is_destruct_assignment_desugaring ( & self , expr : & hir:: Expr < ' _ > ) -> bool {
1265
+ if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
1266
+ _,
1267
+ hir:: Path { res : hir:: def:: Res :: Local ( bind_hir_id) , .. } ,
1268
+ ) ) = expr. kind
1269
+ {
1270
+ let bind = self . tcx . hir ( ) . find ( * bind_hir_id) ;
1271
+ let parent = self . tcx . hir ( ) . find ( self . tcx . hir ( ) . parent_id ( * bind_hir_id) ) ;
1272
+ if let Some ( hir:: Node :: Pat ( hir:: Pat { kind : hir:: PatKind :: Binding ( _, _hir_id, _, _) , .. } ) ) = bind &&
1273
+ let Some ( hir:: Node :: Pat ( hir:: Pat { default_binding_modes : false , .. } ) ) = parent {
1274
+ return true ;
1275
+ }
1276
+ }
1277
+ return false ;
1278
+ }
1279
+
1256
1280
/// This function is used to determine potential "simple" improvements or users' errors and
1257
1281
/// provide them useful help. For example:
1258
1282
///
@@ -1443,6 +1467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1443
1467
_,
1444
1468
& ty:: Ref ( _, checked, _) ,
1445
1469
) if self . can_sub ( self . param_env , checked, expected) => {
1470
+ let make_sugg = |start : Span , end : BytePos | {
1471
+ // skip `(` for tuples such as `(c) = (&123)`.
1472
+ // make sure we won't suggest like `(c) = 123)` which is incorrect.
1473
+ let sp = sm. span_extend_while ( start. shrink_to_lo ( ) , |c| c == '(' || c. is_whitespace ( ) )
1474
+ . map_or ( start, |s| s. shrink_to_hi ( ) ) ;
1475
+ Some ( (
1476
+ vec ! [ ( sp. with_hi( end) , String :: new( ) ) ] ,
1477
+ "consider removing the borrow" . to_string ( ) ,
1478
+ Applicability :: MachineApplicable ,
1479
+ true ,
1480
+ true ,
1481
+ ) )
1482
+ } ;
1483
+
1446
1484
// We have `&T`, check if what was expected was `T`. If so,
1447
1485
// we may want to suggest removing a `&`.
1448
1486
if sm. is_imported ( expr. span ) {
@@ -1456,24 +1494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1456
1494
. find ( |& s| sp. contains ( s) )
1457
1495
&& sm. is_span_accessible ( call_span)
1458
1496
{
1459
- return Some ( (
1460
- vec ! [ ( sp. with_hi( call_span. lo( ) ) , String :: new( ) ) ] ,
1461
- "consider removing the borrow" . to_string ( ) ,
1462
- Applicability :: MachineApplicable ,
1463
- true ,
1464
- true ,
1465
- ) ) ;
1497
+ return make_sugg ( sp, call_span. lo ( ) )
1466
1498
}
1467
1499
return None ;
1468
1500
}
1469
1501
if sp. contains ( expr. span ) && sm. is_span_accessible ( expr. span ) {
1470
- return Some ( (
1471
- vec ! [ ( sp. with_hi( expr. span. lo( ) ) , String :: new( ) ) ] ,
1472
- "consider removing the borrow" . to_string ( ) ,
1473
- Applicability :: MachineApplicable ,
1474
- true ,
1475
- true ,
1476
- ) ) ;
1502
+ return make_sugg ( sp, expr. span . lo ( ) )
1477
1503
}
1478
1504
}
1479
1505
(
0 commit comments