@@ -376,15 +376,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
376
376
opt_assignment_rhs_span. and_then ( |span| span. desugaring_kind ( ) ) ;
377
377
match opt_desugaring_kind {
378
378
// on for loops, RHS points to the iterator part
379
- Some ( DesugaringKind :: ForLoop ( _) ) => Some ( (
380
- false ,
381
- opt_assignment_rhs_span. unwrap ( ) ,
382
- format ! (
383
- "this iterator yields `{SIGIL}` {DESC}s" ,
384
- SIGIL = pointer_sigil,
385
- DESC = pointer_desc
386
- ) ,
387
- ) ) ,
379
+ Some ( DesugaringKind :: ForLoop ( _) ) => {
380
+ self . suggest_similar_mut_method_for_for_loop ( & mut err) ;
381
+ Some ( (
382
+ false ,
383
+ opt_assignment_rhs_span. unwrap ( ) ,
384
+ format ! (
385
+ "this iterator yields `{SIGIL}` {DESC}s" ,
386
+ SIGIL = pointer_sigil,
387
+ DESC = pointer_desc
388
+ ) ,
389
+ ) )
390
+ }
388
391
// don't create labels for compiler-generated spans
389
392
Some ( _) => None ,
390
393
None => {
@@ -537,6 +540,79 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
537
540
) ;
538
541
}
539
542
543
+ // Attempt to search similar mutable assosiated items for suggestion.
544
+ // In the future, attempt in all path but initially for RHS of for_loop
545
+ fn suggest_similar_mut_method_for_for_loop ( & self , err : & mut DiagnosticBuilder < ' _ > ) {
546
+ let hir = self . infcx . tcx . hir ( ) ;
547
+ let node = hir. item ( self . mir_hir_id ( ) ) ;
548
+ use hir:: {
549
+ Expr ,
550
+ ExprKind :: { Block , Call , DropTemps , Match , MethodCall } ,
551
+ } ;
552
+ if let hir:: ItemKind :: Fn ( _, _, body_id) = node. kind {
553
+ if let Block (
554
+ hir:: Block {
555
+ expr :
556
+ Some ( Expr {
557
+ kind :
558
+ DropTemps ( Expr {
559
+ kind :
560
+ Match (
561
+ Expr {
562
+ kind :
563
+ Call (
564
+ _,
565
+ [ Expr {
566
+ kind : MethodCall ( path_segment, ..) ,
567
+ hir_id,
568
+ ..
569
+ } , ..] ,
570
+ ) ,
571
+ ..
572
+ } ,
573
+ ..,
574
+ ) ,
575
+ ..
576
+ } ) ,
577
+ ..
578
+ } ) ,
579
+ ..
580
+ } ,
581
+ _,
582
+ ) = hir. body ( body_id) . value . kind
583
+ {
584
+ let opt_suggestions = path_segment
585
+ . hir_id
586
+ . map ( |path_hir_id| self . infcx . tcx . typeck ( path_hir_id. owner ) )
587
+ . and_then ( |typeck| typeck. type_dependent_def_id ( * hir_id) )
588
+ . and_then ( |def_id| self . infcx . tcx . impl_of_method ( def_id) )
589
+ . map ( |def_id| self . infcx . tcx . associated_items ( def_id) )
590
+ . map ( |assoc_items| {
591
+ assoc_items
592
+ . in_definition_order ( )
593
+ . map ( |assoc_item_def| assoc_item_def. ident )
594
+ . filter ( |& ident| {
595
+ let original_method_ident = path_segment. ident ;
596
+ original_method_ident != ident
597
+ && ident
598
+ . as_str ( )
599
+ . starts_with ( & original_method_ident. name . to_string ( ) )
600
+ } )
601
+ . map ( |ident| format ! ( "{}()" , ident) )
602
+ } ) ;
603
+
604
+ if let Some ( suggestions) = opt_suggestions {
605
+ err. span_suggestions (
606
+ path_segment. ident . span ,
607
+ & format ! ( "use mutable method" ) ,
608
+ suggestions,
609
+ Applicability :: MaybeIncorrect ,
610
+ ) ;
611
+ }
612
+ }
613
+ } ;
614
+ }
615
+
540
616
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
541
617
fn expected_fn_found_fn_mut_call ( & self , err : & mut DiagnosticBuilder < ' _ > , sp : Span , act : & str ) {
542
618
err. span_label ( sp, format ! ( "cannot {}" , act) ) ;
0 commit comments