@@ -83,6 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8383 }
8484
8585 self . annotate_expected_due_to_let_ty ( err, expr, error) ;
86+
87+ if self . is_destruct_assignment_desugaring ( expr) {
88+ return ;
89+ }
8690 self . emit_type_mismatch_suggestions ( err, expr, expr_ty, expected, expected_ty_expr, error) ;
8791 self . note_type_is_not_clone ( err, expected, expr_ty, expr) ;
8892 self . note_internal_mutation_in_method ( err, expr, Some ( expected) , expr_ty) ;
@@ -1253,6 +1257,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12531257 false
12541258 }
12551259
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+
12561280 /// This function is used to determine potential "simple" improvements or users' errors and
12571281 /// provide them useful help. For example:
12581282 ///
@@ -1443,6 +1467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14431467 _,
14441468 & ty:: Ref ( _, checked, _) ,
14451469 ) 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+
14461484 // We have `&T`, check if what was expected was `T`. If so,
14471485 // we may want to suggest removing a `&`.
14481486 if sm. is_imported ( expr. span ) {
@@ -1456,24 +1494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14561494 . find ( |& s| sp. contains ( s) )
14571495 && sm. is_span_accessible ( call_span)
14581496 {
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 ( ) )
14661498 }
14671499 return None ;
14681500 }
14691501 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 ( ) )
14771503 }
14781504 }
14791505 (
0 commit comments