@@ -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".
130130 pub 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,67 +338,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338338 } )
339339 . collect ( ) ;
340340
341- if self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id , expr. span ) {
342- if let Ok ( code) = self . tcx . sess . source_map ( ) . span_to_snippet ( expr. span ) {
343- match & compatible_variants[ ..] {
344- [ ] => { /* No variants to format */ }
345- [ variant] => {
346- // Just a single matching variant.
347- err. span_suggestion_verbose (
348- expr. span ,
349- & format ! ( "try wrapping the expression in `{}`" , variant) ,
350- format ! ( "{}: {}({})" , code, variant, code) ,
351- Applicability :: MaybeIncorrect ,
352- ) ;
353- }
354- _ => {
355- // More than one matching variant.
356- err. span_suggestions (
357- expr. span ,
358- & format ! (
359- "try wrapping the expression in a variant of `{}`" ,
360- self . tcx. def_path_str( expected_adt. did)
361- ) ,
362- compatible_variants
363- . into_iter ( )
364- . map ( |variant| format ! ( "{}: {}({})" , code, variant, code) ) ,
365- Applicability :: MaybeIncorrect ,
366- ) ;
367- }
368- }
369- } else {
370- /* Can't format this without a snippet */
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) ,
352+ vec ! [
353+ ( expr. span. shrink_to_lo( ) , format!( "{}{}(" , prefix, variant) ) ,
354+ ( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
355+ ] ,
356+ Applicability :: MaybeIncorrect ,
357+ ) ;
371358 }
372- } else {
373- match & compatible_variants[ ..] {
374- [ ] => { /* No variants to format */ }
375- [ variant] => {
376- // Just a single matching variant.
377- err. multipart_suggestion_verbose (
378- & format ! ( "try wrapping the expression in `{}`" , variant) ,
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| {
379367 vec ! [
380- ( expr. span. shrink_to_lo( ) , format!( "{}(" , variant) ) ,
368+ ( expr. span. shrink_to_lo( ) , format!( "{}{}(" , prefix , variant) ) ,
381369 ( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
382- ] ,
383- Applicability :: MaybeIncorrect ,
384- ) ;
385- }
386- _ => {
387- // More than one matching variant.
388- err. multipart_suggestions (
389- & format ! (
390- "try wrapping the expression in a variant of `{}`" ,
391- self . tcx. def_path_str( expected_adt. did)
392- ) ,
393- compatible_variants. into_iter ( ) . map ( |variant| {
394- vec ! [
395- ( expr. span. shrink_to_lo( ) , format!( "{}(" , variant) ) ,
396- ( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
397- ]
398- } ) ,
399- Applicability :: MaybeIncorrect ,
400- ) ;
401- }
370+ ]
371+ } ) ,
372+ Applicability :: MaybeIncorrect ,
373+ ) ;
402374 }
403375 }
404376 }
@@ -520,33 +492,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
520492 }
521493 }
522494
523- crate fn is_hir_id_from_struct_pattern_shorthand_field (
495+ crate fn maybe_get_struct_pattern_shorthand_field (
524496 & self ,
525- hir_id : hir:: HirId ,
526- sp : Span ,
527- ) -> bool {
528- let sm = self . sess ( ) . source_map ( ) ;
529- let parent_id = self . tcx . hir ( ) . get_parent_node ( hir_id) ;
530- if let Some ( parent) = self . tcx . hir ( ) . find ( parent_id) {
531- // Account for fields
532- if let Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Struct ( _, fields, ..) , .. } ) = parent
533- {
534- if let Ok ( src) = sm. span_to_snippet ( sp) {
535- for field in * fields {
536- if field. ident . as_str ( ) == src && field. is_shorthand {
537- return true ;
538- }
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 ) ;
539521 }
540522 }
541523 }
524+ _ => { }
542525 }
543- false
526+
527+ None
544528 }
545529
546530 /// If the given `HirId` corresponds to a block with a trailing expression, return that expression
547- crate fn maybe_get_block_expr ( & self , hir_id : hir:: HirId ) -> Option < & ' tcx hir:: Expr < ' tcx > > {
548- match self . tcx . hir ( ) . find ( hir_id ) ? {
549- 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 ,
550534 _ => None ,
551535 }
552536 }
@@ -584,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
584568 /// `&mut`!".
585569 pub fn check_ref (
586570 & self ,
587- expr : & hir:: Expr < ' _ > ,
571+ expr : & hir:: Expr < ' tcx > ,
588572 checked_ty : Ty < ' tcx > ,
589573 expected : Ty < ' tcx > ,
590574 ) -> Option < ( Span , & ' static str , String , Applicability , bool /* verbose */ ) > {
@@ -602,9 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
602586 s. strip_prefix ( old) . map ( |stripped| new. to_string ( ) + stripped)
603587 } ;
604588
605- let is_struct_pat_shorthand_field =
606- self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id , sp) ;
607-
608589 // `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
609590 let expr = expr. peel_drop_temps ( ) ;
610591
@@ -698,11 +679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
698679 false ,
699680 ) ) ;
700681 }
701- let field_name = if is_struct_pat_shorthand_field {
702- format ! ( "{}: " , sugg_expr )
703- } else {
704- String :: new ( )
682+
683+ let prefix = match self . maybe_get_struct_pattern_shorthand_field ( expr ) {
684+ Some ( ident ) => format ! ( "{}: " , ident ) ,
685+ None => format ! ( "" ) ,
705686 } ;
687+
706688 if let Some ( hir:: Node :: Expr ( hir:: Expr {
707689 kind : hir:: ExprKind :: Assign ( left_expr, ..) ,
708690 ..
@@ -732,14 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732714 hir:: Mutability :: Mut => (
733715 sp,
734716 "consider mutably borrowing here" ,
735- format ! ( "{}&mut {}" , field_name , sugg_expr) ,
717+ format ! ( "{}&mut {}" , prefix , sugg_expr) ,
736718 Applicability :: MachineApplicable ,
737719 false ,
738720 ) ,
739721 hir:: Mutability :: Not => (
740722 sp,
741723 "consider borrowing here" ,
742- format ! ( "{}&{}" , field_name , sugg_expr) ,
724+ format ! ( "{}&{}" , prefix , sugg_expr) ,
743725 Applicability :: MachineApplicable ,
744726 false ,
745727 ) ,
@@ -883,32 +865,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
883865 if self . infcx . type_is_copy_modulo_regions ( self . param_env , expected, sp)
884866 || checked_ty. is_box ( )
885867 {
886- if let Ok ( code) = sm. span_to_snippet ( expr. span ) {
887- let message = if checked_ty. is_box ( ) {
888- "consider unboxing the value"
889- } else if checked_ty. is_region_ptr ( ) {
890- "consider dereferencing the borrow"
891- } else {
892- "consider dereferencing the type"
893- } ;
894- let ( span, suggestion) = if is_struct_pat_shorthand_field {
895- ( expr. span , format ! ( "{}: *{}" , code, code) )
896- } else if self . is_else_if_block ( expr) {
897- // Don't suggest nonsense like `else *if`
898- return None ;
899- } else if let Some ( expr) = self . maybe_get_block_expr ( expr. hir_id ) {
900- ( expr. span . shrink_to_lo ( ) , "*" . to_string ( ) )
901- } else {
902- ( expr. span . shrink_to_lo ( ) , "*" . to_string ( ) )
903- } ;
904- return Some ( (
905- span,
906- message,
907- suggestion,
908- Applicability :: MachineApplicable ,
909- true ,
910- ) ) ;
911- }
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+ ) ) ;
912895 }
913896 }
914897 }
0 commit comments