@@ -6,7 +6,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
6
6
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
7
7
use rustc_middle:: {
8
8
hir:: place:: PlaceBase ,
9
- mir:: { self , ClearCrossCrate , Local , LocalDecl , LocalInfo , Location } ,
9
+ mir:: { self , ClearCrossCrate , Local , LocalDecl , LocalInfo , LocalKind , Location } ,
10
10
} ;
11
11
use rustc_span:: source_map:: DesugaringKind ;
12
12
use rustc_span:: symbol:: { kw, Symbol } ;
@@ -424,15 +424,28 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
424
424
425
425
match label {
426
426
Some ( ( true , err_help_span, suggested_code) ) => {
427
- err. span_suggestion (
428
- err_help_span,
429
- & format ! (
430
- "consider changing this to be a mutable {}" ,
431
- pointer_desc
432
- ) ,
433
- suggested_code,
434
- Applicability :: MachineApplicable ,
435
- ) ;
427
+ let ( is_trait_sig, local_trait) = self . is_error_in_trait ( local) ;
428
+ if !is_trait_sig {
429
+ err. span_suggestion (
430
+ err_help_span,
431
+ & format ! (
432
+ "consider changing this to be a mutable {}" ,
433
+ pointer_desc
434
+ ) ,
435
+ suggested_code,
436
+ Applicability :: MachineApplicable ,
437
+ ) ;
438
+ } else if let Some ( x) = local_trait {
439
+ err. span_suggestion (
440
+ x,
441
+ & format ! (
442
+ "consider changing that to be a mutable {}" ,
443
+ pointer_desc
444
+ ) ,
445
+ suggested_code,
446
+ Applicability :: MachineApplicable ,
447
+ ) ;
448
+ }
436
449
}
437
450
Some ( ( false , err_label_span, message) ) => {
438
451
err. span_label ( err_label_span, & message) ;
@@ -502,6 +515,69 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
502
515
503
516
err. buffer ( & mut self . errors_buffer ) ;
504
517
}
518
+
519
+ /// User cannot make signature of a trait mutable without changing the
520
+ /// trait. So we find if this error belongs to a trait and if so we move
521
+ /// suggestion to the trait or disable it if it is out of scope of this crate
522
+ fn is_error_in_trait ( & self , local : Local ) -> ( bool , Option < Span > ) {
523
+ if self . body . local_kind ( local) != LocalKind :: Arg {
524
+ return ( false , None ) ;
525
+ }
526
+ let hir_map = self . infcx . tcx . hir ( ) ;
527
+ let my_def = self . body . source . def_id ( ) ;
528
+ let my_hir = hir_map. local_def_id_to_hir_id ( my_def. as_local ( ) . unwrap ( ) ) ;
529
+ let td = if let Some ( a) = self . infcx . tcx . impl_of_method ( my_def) . and_then ( |x| {
530
+ self . infcx . tcx . trait_id_of_impl ( x)
531
+ } ) {
532
+ a
533
+ } else {
534
+ return ( false , None ) ;
535
+ } ;
536
+ ( true , td. as_local ( ) . and_then ( |tld| {
537
+ let h = hir_map. local_def_id_to_hir_id ( tld) ;
538
+ match hir_map. find ( h) {
539
+ Some ( Node :: Item ( hir:: Item {
540
+ kind : hir:: ItemKind :: Trait (
541
+ _, _, _, _,
542
+ items
543
+ ) ,
544
+ ..
545
+ } ) ) => {
546
+ let mut f_in_trait_opt = None ;
547
+ for hir:: TraitItemRef { id : fi, kind : k, .. } in * items {
548
+ let hi = fi. hir_id ( ) ;
549
+ if !matches ! ( k, hir:: AssocItemKind :: Fn { .. } ) {
550
+ continue ;
551
+ }
552
+ if hir_map. name ( hi) != hir_map. name ( my_hir) {
553
+ continue ;
554
+ }
555
+ f_in_trait_opt = Some ( hi) ;
556
+ break ;
557
+ }
558
+ f_in_trait_opt. and_then ( |f_in_trait| {
559
+ match hir_map. find ( f_in_trait) {
560
+ Some ( Node :: TraitItem ( hir:: TraitItem {
561
+ kind : hir:: TraitItemKind :: Fn ( hir:: FnSig {
562
+ decl : hir:: FnDecl {
563
+ inputs,
564
+ ..
565
+ } ,
566
+ ..
567
+ } , _) ,
568
+ ..
569
+ } ) ) => {
570
+ let hir:: Ty { span, .. } = inputs[ local. index ( ) - 1 ] ;
571
+ Some ( span)
572
+ } ,
573
+ _ => None ,
574
+ }
575
+ } )
576
+ }
577
+ _ => None
578
+ }
579
+ } ) )
580
+ }
505
581
506
582
// point to span of upvar making closure call require mutable borrow
507
583
fn show_mutating_upvar (
0 commit comments