@@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
1313use  rustc_middle:: ty:: error:: { ExpectedFound ,  TypeError } ; 
1414use  rustc_middle:: ty:: print:: with_no_trimmed_paths; 
1515use  rustc_middle:: ty:: { self ,  AssocItem ,  Ty ,  TypeAndMut } ; 
16- use  rustc_span:: symbol:: sym; 
16+ use  rustc_span:: symbol:: { sym,   Symbol } ; 
1717use  rustc_span:: { BytePos ,  Span } ; 
1818
1919use  super :: method:: probe; 
@@ -24,7 +24,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2424    pub  fn  emit_coerce_suggestions ( 
2525        & self , 
2626        err :  & mut  DiagnosticBuilder < ' _ > , 
27-         expr :  & hir:: Expr < ' _ > , 
27+         expr :  & hir:: Expr < ' tcx > , 
2828        expr_ty :  Ty < ' tcx > , 
2929        expected :  Ty < ' tcx > , 
3030        expected_ty_expr :  Option < & ' tcx  hir:: Expr < ' tcx > > , 
@@ -109,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
109109
110110    pub  fn  demand_coerce ( 
111111        & self , 
112-         expr :  & hir:: Expr < ' _ > , 
112+         expr :  & hir:: Expr < ' tcx > , 
113113        checked_ty :  Ty < ' tcx > , 
114114        expected :  Ty < ' tcx > , 
115115        expected_ty_expr :  Option < & ' tcx  hir:: Expr < ' tcx > > , 
@@ -129,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
129129/// will be permitted if the diverges flag is currently "always". 
130130pub  fn  demand_coerce_diag ( 
131131        & self , 
132-         expr :  & hir:: Expr < ' _ > , 
132+         expr :  & hir:: Expr < ' tcx > , 
133133        checked_ty :  Ty < ' tcx > , 
134134        expected :  Ty < ' tcx > , 
135135        expected_ty_expr :  Option < & ' tcx  hir:: Expr < ' tcx > > , 
@@ -338,31 +338,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338338                } ) 
339339                . collect ( ) ; 
340340
341-             if  let  [ variant]  = & compatible_variants[ ..]  { 
342-                 // Just a single matching variant. 
343-                 err. multipart_suggestion ( 
344-                     & format ! ( "try wrapping the expression in `{}`" ,  variant) , 
345-                     vec ! [ 
346-                         ( expr. span. shrink_to_lo( ) ,  format!( "{}(" ,  variant) ) , 
347-                         ( expr. span. shrink_to_hi( ) ,  ")" . to_string( ) ) , 
348-                     ] , 
349-                     Applicability :: MaybeIncorrect , 
350-                 ) ; 
351-             }  else  if  compatible_variants. len ( )  > 1  { 
352-                 // More than one matching variant. 
353-                 err. multipart_suggestions ( 
354-                     & format ! ( 
355-                         "try wrapping the expression in a variant of `{}`" , 
356-                         self . tcx. def_path_str( expected_adt. did) 
357-                     ) , 
358-                     compatible_variants. into_iter ( ) . map ( |variant| { 
341+             let  prefix = match  self . maybe_get_struct_pattern_shorthand_field ( expr)  { 
342+                 Some ( ident)  => format ! ( "{}: " ,  ident) , 
343+                 None  => format ! ( "" ) , 
344+             } ; 
345+ 
346+             match  & compatible_variants[ ..]  { 
347+                 [ ]  => {  /* No variants to format */  } 
348+                 [ variant]  => { 
349+                     // Just a single matching variant. 
350+                     err. multipart_suggestion_verbose ( 
351+                         & format ! ( "try wrapping the expression in `{}`" ,  variant) , 
359352                        vec ! [ 
360-                             ( expr. span. shrink_to_lo( ) ,  format!( "{}("  ,  variant) ) , 
353+                             ( expr. span. shrink_to_lo( ) ,  format!( "{}{}("  ,  prefix ,  variant) ) , 
361354                            ( expr. span. shrink_to_hi( ) ,  ")" . to_string( ) ) , 
362-                         ] 
363-                     } ) , 
364-                     Applicability :: MaybeIncorrect , 
365-                 ) ; 
355+                         ] , 
356+                         Applicability :: MaybeIncorrect , 
357+                     ) ; 
358+                 } 
359+                 _ => { 
360+                     // More than one matching variant. 
361+                     err. multipart_suggestions ( 
362+                         & format ! ( 
363+                             "try wrapping the expression in a variant of `{}`" , 
364+                             self . tcx. def_path_str( expected_adt. did) 
365+                         ) , 
366+                         compatible_variants. into_iter ( ) . map ( |variant| { 
367+                             vec ! [ 
368+                                 ( expr. span. shrink_to_lo( ) ,  format!( "{}{}(" ,  prefix,  variant) ) , 
369+                                 ( expr. span. shrink_to_hi( ) ,  ")" . to_string( ) ) , 
370+                             ] 
371+                         } ) , 
372+                         Applicability :: MaybeIncorrect , 
373+                     ) ; 
374+                 } 
366375            } 
367376        } 
368377    } 
@@ -483,33 +492,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483492        } 
484493    } 
485494
486-     crate  fn  is_hir_id_from_struct_pattern_shorthand_field ( 
495+     crate  fn  maybe_get_struct_pattern_shorthand_field ( 
487496        & self , 
488-         hir_id :  hir:: HirId , 
489-         sp :  Span , 
490-     )  -> bool  { 
491-         let  sm = self . sess ( ) . source_map ( ) ; 
492-         let  parent_id = self . tcx . hir ( ) . get_parent_node ( hir_id) ; 
493-         if  let  Some ( parent)  = self . tcx . hir ( ) . find ( parent_id)  { 
494-             // Account for fields 
495-             if  let  Node :: Expr ( hir:: Expr  {  kind :  hir:: ExprKind :: Struct ( _,  fields,  ..) ,  .. } )  = parent
496-             { 
497-                 if  let  Ok ( src)  = sm. span_to_snippet ( sp)  { 
498-                     for  field in  * fields { 
499-                         if  field. ident . as_str ( )  == src && field. is_shorthand  { 
500-                             return  true ; 
501-                         } 
497+         expr :  & hir:: Expr < ' _ > , 
498+     )  -> Option < Symbol >  { 
499+         let  hir = self . tcx . hir ( ) ; 
500+         let  local = match  expr { 
501+             hir:: Expr  { 
502+                 kind : 
503+                     hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( 
504+                         None , 
505+                         hir:: Path  { 
506+                             res :  hir:: def:: Res :: Local ( _) , 
507+                             segments :  [ hir:: PathSegment  {  ident,  .. } ] , 
508+                             ..
509+                         } , 
510+                     ) ) , 
511+                 ..
512+             }  => Some ( ident) , 
513+             _ => None , 
514+         } ?; 
515+ 
516+         match  hir. find ( hir. get_parent_node ( expr. hir_id ) ) ? { 
517+             Node :: Expr ( hir:: Expr  {  kind :  hir:: ExprKind :: Struct ( _,  fields,  ..) ,  .. } )  => { 
518+                 for  field in  * fields { 
519+                     if  field. ident . name  == local. name  && field. is_shorthand  { 
520+                         return  Some ( local. name ) ; 
502521                    } 
503522                } 
504523            } 
524+             _ => { } 
505525        } 
506-         false 
526+ 
527+         None 
507528    } 
508529
509530    /// If the given `HirId` corresponds to a block with a trailing expression, return that expression 
510- crate  fn  maybe_get_block_expr ( & self ,  hir_id :   hir:: HirId )  -> Option < & ' tcx  hir:: Expr < ' tcx > >  { 
511-         match  self . tcx . hir ( ) . find ( hir_id ) ?  { 
512-             Node :: Expr ( hir:: Expr  {  kind :  hir:: ExprKind :: Block ( block,  ..) ,  .. } )  => block. expr , 
531+ crate  fn  maybe_get_block_expr ( & self ,  expr :   & hir:: Expr < ' tcx > )  -> Option < & ' tcx  hir:: Expr < ' tcx > >  { 
532+         match  expr  { 
533+             hir:: Expr  {  kind :  hir:: ExprKind :: Block ( block,  ..) ,  .. }  => block. expr , 
513534            _ => None , 
514535        } 
515536    } 
@@ -547,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
547568/// `&mut`!". 
548569pub  fn  check_ref ( 
549570        & self , 
550-         expr :  & hir:: Expr < ' _ > , 
571+         expr :  & hir:: Expr < ' tcx > , 
551572        checked_ty :  Ty < ' tcx > , 
552573        expected :  Ty < ' tcx > , 
553574    )  -> Option < ( Span ,  & ' static  str ,  String ,  Applicability ,  bool  /* verbose */ ) >  { 
@@ -565,9 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
565586            s. strip_prefix ( old) . map ( |stripped| new. to_string ( )  + stripped) 
566587        } ; 
567588
568-         let  is_struct_pat_shorthand_field =
569-             self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id ,  sp) ; 
570- 
571589        // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. 
572590        let  expr = expr. peel_drop_temps ( ) ; 
573591
@@ -661,11 +679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
661679                                false , 
662680                            ) ) ; 
663681                        } 
664-                          let  field_name =  if  is_struct_pat_shorthand_field  { 
665-                              format ! ( "{}: " ,  sugg_expr ) 
666-                         }   else   { 
667-                             String :: new ( ) 
682+ 
683+                         let  prefix =  match   self . maybe_get_struct_pattern_shorthand_field ( expr )   { 
684+                              Some ( ident )  =>  format ! ( "{}: " ,  ident ) , 
685+                             None  =>  format ! ( "" ) , 
668686                        } ; 
687+ 
669688                        if  let  Some ( hir:: Node :: Expr ( hir:: Expr  { 
670689                            kind :  hir:: ExprKind :: Assign ( left_expr,  ..) , 
671690                            ..
@@ -695,14 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
695714                            hir:: Mutability :: Mut  => ( 
696715                                sp, 
697716                                "consider mutably borrowing here" , 
698-                                 format ! ( "{}&mut {}" ,  field_name ,  sugg_expr) , 
717+                                 format ! ( "{}&mut {}" ,  prefix ,  sugg_expr) , 
699718                                Applicability :: MachineApplicable , 
700719                                false , 
701720                            ) , 
702721                            hir:: Mutability :: Not  => ( 
703722                                sp, 
704723                                "consider borrowing here" , 
705-                                 format ! ( "{}&{}" ,  field_name ,  sugg_expr) , 
724+                                 format ! ( "{}&{}" ,  prefix ,  sugg_expr) , 
706725                                Applicability :: MachineApplicable , 
707726                                false , 
708727                            ) , 
@@ -846,32 +865,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
846865                        if  self . infcx . type_is_copy_modulo_regions ( self . param_env ,  expected,  sp) 
847866                            || checked_ty. is_box ( ) 
848867                        { 
849-                             if  let  Ok ( code)  = sm. span_to_snippet ( expr. span )  { 
850-                                 let  message = if  checked_ty. is_box ( )  { 
851-                                     "consider unboxing the value" 
852-                                 }  else  if  checked_ty. is_region_ptr ( )  { 
853-                                     "consider dereferencing the borrow" 
854-                                 }  else  { 
855-                                     "consider dereferencing the type" 
856-                                 } ; 
857-                                 let  ( span,  suggestion)  = if  is_struct_pat_shorthand_field { 
858-                                     ( expr. span ,  format ! ( "{}: *{}" ,  code,  code) ) 
859-                                 }  else  if  self . is_else_if_block ( expr)  { 
860-                                     // Don't suggest nonsense like `else *if` 
861-                                     return  None ; 
862-                                 }  else  if  let  Some ( expr)  = self . maybe_get_block_expr ( expr. hir_id )  { 
863-                                     ( expr. span . shrink_to_lo ( ) ,  "*" . to_string ( ) ) 
864-                                 }  else  { 
865-                                     ( expr. span . shrink_to_lo ( ) ,  "*" . to_string ( ) ) 
866-                                 } ; 
867-                                 return  Some ( ( 
868-                                     span, 
869-                                     message, 
870-                                     suggestion, 
871-                                     Applicability :: MachineApplicable , 
872-                                     true , 
873-                                 ) ) ; 
874-                             } 
868+                             let  message = if  checked_ty. is_box ( )  { 
869+                                 "consider unboxing the value" 
870+                             }  else  if  checked_ty. is_region_ptr ( )  { 
871+                                 "consider dereferencing the borrow" 
872+                             }  else  { 
873+                                 "consider dereferencing the type" 
874+                             } ; 
875+                             let  prefix = match  self . maybe_get_struct_pattern_shorthand_field ( expr)  { 
876+                                 Some ( ident)  => format ! ( "{}: " ,  ident) , 
877+                                 None  => format ! ( "" ) , 
878+                             } ; 
879+                             let  ( span,  suggestion)  = if  self . is_else_if_block ( expr)  { 
880+                                 // Don't suggest nonsense like `else *if` 
881+                                 return  None ; 
882+                             }  else  if  let  Some ( expr)  = self . maybe_get_block_expr ( expr)  { 
883+                                 // prefix should be empty here.. 
884+                                 ( expr. span . shrink_to_lo ( ) ,  "*" . to_string ( ) ) 
885+                             }  else  { 
886+                                 ( expr. span . shrink_to_lo ( ) ,  format ! ( "{}*" ,  prefix) ) 
887+                             } ; 
888+                             return  Some ( ( 
889+                                 span, 
890+                                 message, 
891+                                 suggestion, 
892+                                 Applicability :: MachineApplicable , 
893+                                 true , 
894+                             ) ) ; 
875895                        } 
876896                    } 
877897                } 
0 commit comments