@@ -6,7 +6,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
66use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
77use rustc_middle:: {
88 hir:: place:: PlaceBase ,
9- mir:: { self , ClearCrossCrate , Local , LocalDecl , LocalInfo , Location } ,
9+ mir:: { self , ClearCrossCrate , Local , LocalDecl , LocalInfo , LocalKind , Location } ,
1010} ;
1111use rustc_span:: source_map:: DesugaringKind ;
1212use rustc_span:: symbol:: { kw, Symbol } ;
@@ -424,15 +424,108 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
424424
425425 match label {
426426 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+ /// User cannot make signature of a trait mutable
428+ /// without changing the trait. So we find if this
429+ /// error belongs to a trait and if so we move
430+ /// suggestion to the trait or disable it if it is
431+ /// out of scope of this crate
432+ let ( is_trait_sig, local_trait) = {
433+ if self . body . local_kind ( local) != LocalKind :: Arg {
434+ ( false , None )
435+ } else {
436+ let hir_map = self . infcx . tcx . hir ( ) ;
437+ let my_hir = hir_map. local_def_id_to_hir_id (
438+ self . body . source . def_id ( ) . as_local ( ) . unwrap ( ) ,
439+ ) ;
440+ match hir_map. find ( hir_map. get_parent_node ( my_hir) ) {
441+ Some ( Node :: Item ( hir:: Item {
442+ kind :
443+ hir:: ItemKind :: Impl ( hir:: Impl {
444+ of_trait :
445+ Some ( hir:: TraitRef {
446+ path :
447+ hir:: Path {
448+ res :
449+ hir:: def:: Res :: Def ( _, td) ,
450+ ..
451+ } ,
452+ ..
453+ } ) ,
454+ ..
455+ } ) ,
456+ ..
457+ } ) ) => {
458+ ( true , td. as_local ( ) . and_then ( |tld| {
459+ let h = hir_map. local_def_id_to_hir_id ( tld) ;
460+ match hir_map. find ( h) {
461+ Some ( Node :: Item ( hir:: Item {
462+ kind : hir:: ItemKind :: Trait (
463+ _, _, _, _,
464+ items
465+ ) ,
466+ ..
467+ } ) ) => {
468+ let mut f_in_trait_opt = None ;
469+ for hir:: TraitItemRef { id : fi, kind : k, .. } in * items {
470+ let hi = fi. hir_id ( ) ;
471+ if !matches ! ( k, hir:: AssocItemKind :: Fn { .. } ) {
472+ continue ;
473+ }
474+ if hir_map. name ( hi) != hir_map. name ( my_hir) {
475+ continue ;
476+ }
477+ f_in_trait_opt = Some ( hi) ;
478+ break ;
479+ }
480+ f_in_trait_opt. and_then ( |f_in_trait| {
481+ match hir_map. find ( f_in_trait) {
482+ Some ( Node :: TraitItem ( hir:: TraitItem {
483+ kind : hir:: TraitItemKind :: Fn ( hir:: FnSig {
484+ decl : hir:: FnDecl {
485+ inputs,
486+ ..
487+ } ,
488+ ..
489+ } , _) ,
490+ ..
491+ } ) ) => {
492+ let hir:: Ty { span, .. } = inputs[ local. index ( ) - 1 ] ;
493+ Some ( span)
494+ } ,
495+ _ => None ,
496+ }
497+ } )
498+ //Some(hir_map.span(h))
499+ }
500+ _ => None
501+ }
502+ } ) )
503+ }
504+ _ => ( false , None ) ,
505+ }
506+ }
507+ } ;
508+ if !is_trait_sig {
509+ err. span_suggestion (
510+ err_help_span,
511+ & format ! (
512+ "consider changing this to be a mutable {}" ,
513+ pointer_desc
514+ ) ,
515+ suggested_code,
516+ Applicability :: MachineApplicable ,
517+ ) ;
518+ } else if let Some ( x) = local_trait {
519+ err. span_suggestion (
520+ x,
521+ & format ! (
522+ "consider changing that to be a mutable {}" ,
523+ pointer_desc
524+ ) ,
525+ suggested_code,
526+ Applicability :: MachineApplicable ,
527+ ) ;
528+ }
436529 }
437530 Some ( ( false , err_label_span, message) ) => {
438531 err. span_label ( err_label_span, & message) ;
0 commit comments