@@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
13
13
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
14
14
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
15
15
use rustc_middle:: ty:: { self , AssocItem , Ty , TypeAndMut } ;
16
- use rustc_span:: symbol:: sym;
16
+ use rustc_span:: symbol:: { sym, Symbol } ;
17
17
use rustc_span:: { BytePos , Span } ;
18
18
19
19
use super :: method:: probe;
@@ -24,7 +24,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24
24
pub fn emit_coerce_suggestions (
25
25
& self ,
26
26
err : & mut DiagnosticBuilder < ' _ > ,
27
- expr : & hir:: Expr < ' _ > ,
27
+ expr : & hir:: Expr < ' tcx > ,
28
28
expr_ty : Ty < ' tcx > ,
29
29
expected : Ty < ' tcx > ,
30
30
expected_ty_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
@@ -109,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
109
109
110
110
pub fn demand_coerce (
111
111
& self ,
112
- expr : & hir:: Expr < ' _ > ,
112
+ expr : & hir:: Expr < ' tcx > ,
113
113
checked_ty : Ty < ' tcx > ,
114
114
expected : Ty < ' tcx > ,
115
115
expected_ty_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
@@ -129,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
129
129
/// will be permitted if the diverges flag is currently "always".
130
130
pub fn demand_coerce_diag (
131
131
& self ,
132
- expr : & hir:: Expr < ' _ > ,
132
+ expr : & hir:: Expr < ' tcx > ,
133
133
checked_ty : Ty < ' tcx > ,
134
134
expected : Ty < ' tcx > ,
135
135
expected_ty_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
@@ -338,67 +338,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338
338
} )
339
339
. collect ( ) ;
340
340
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
+ ) ;
371
358
}
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| {
379
367
vec ! [
380
- ( expr. span. shrink_to_lo( ) , format!( "{}(" , variant) ) ,
368
+ ( expr. span. shrink_to_lo( ) , format!( "{}{}(" , prefix , variant) ) ,
381
369
( 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
+ ) ;
402
374
}
403
375
}
404
376
}
@@ -520,33 +492,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
520
492
}
521
493
}
522
494
523
- crate fn is_hir_id_from_struct_pattern_shorthand_field (
495
+ crate fn maybe_get_struct_pattern_shorthand_field (
524
496
& 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 ) ;
539
521
}
540
522
}
541
523
}
524
+ _ => { }
542
525
}
543
- false
526
+
527
+ None
544
528
}
545
529
546
530
/// 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 ,
550
534
_ => None ,
551
535
}
552
536
}
@@ -584,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
584
568
/// `&mut`!".
585
569
pub fn check_ref (
586
570
& self ,
587
- expr : & hir:: Expr < ' _ > ,
571
+ expr : & hir:: Expr < ' tcx > ,
588
572
checked_ty : Ty < ' tcx > ,
589
573
expected : Ty < ' tcx > ,
590
574
) -> Option < ( Span , & ' static str , String , Applicability , bool /* verbose */ ) > {
@@ -602,9 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
602
586
s. strip_prefix ( old) . map ( |stripped| new. to_string ( ) + stripped)
603
587
} ;
604
588
605
- let is_struct_pat_shorthand_field =
606
- self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id , sp) ;
607
-
608
589
// `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
609
590
let expr = expr. peel_drop_temps ( ) ;
610
591
@@ -698,11 +679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
698
679
false ,
699
680
) ) ;
700
681
}
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 ! ( "" ) ,
705
686
} ;
687
+
706
688
if let Some ( hir:: Node :: Expr ( hir:: Expr {
707
689
kind : hir:: ExprKind :: Assign ( left_expr, ..) ,
708
690
..
@@ -732,14 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732
714
hir:: Mutability :: Mut => (
733
715
sp,
734
716
"consider mutably borrowing here" ,
735
- format ! ( "{}&mut {}" , field_name , sugg_expr) ,
717
+ format ! ( "{}&mut {}" , prefix , sugg_expr) ,
736
718
Applicability :: MachineApplicable ,
737
719
false ,
738
720
) ,
739
721
hir:: Mutability :: Not => (
740
722
sp,
741
723
"consider borrowing here" ,
742
- format ! ( "{}&{}" , field_name , sugg_expr) ,
724
+ format ! ( "{}&{}" , prefix , sugg_expr) ,
743
725
Applicability :: MachineApplicable ,
744
726
false ,
745
727
) ,
@@ -883,32 +865,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
883
865
if self . infcx . type_is_copy_modulo_regions ( self . param_env , expected, sp)
884
866
|| checked_ty. is_box ( )
885
867
{
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
+ ) ) ;
912
895
}
913
896
}
914
897
}
0 commit comments