@@ -511,9 +511,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
511511 self . expected_fn_found_fn_mut_call ( & mut err, span, act) ;
512512 }
513513
514- PlaceRef { local : _, projection : [ .., ProjectionElem :: Deref ] } => {
515- err. span_label ( span, format ! ( "cannot {act}" ) ) ;
516-
514+ PlaceRef { local : _, projection : [ proj_base @ .., ProjectionElem :: Deref ] } => {
515+ let mut span = span;
517516 match opt_source {
518517 Some ( BorrowedContentSource :: OverloadedDeref ( ty) ) => {
519518 err. help ( format ! (
@@ -528,8 +527,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
528527 ) ) ;
529528 self . suggest_map_index_mut_alternatives ( ty, & mut err, span) ;
530529 }
530+ Some ( BorrowedContentSource :: DerefSharedRef ) => {
531+ let place_ref =
532+ PlaceRef { local : the_place_err. local , projection : proj_base } ;
533+ let ty = place_ref. ty ( self . body , self . infcx . tcx ) . ty ;
534+ self . suggest_detailed_hint_for_ref ( ty, & mut err, & mut span) ;
535+ }
531536 _ => ( ) ,
532537 }
538+ err. span_label ( span, format ! ( "cannot {act}" ) ) ;
533539 }
534540
535541 _ => {
@@ -544,6 +550,46 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
544550 }
545551 }
546552
553+ fn suggest_detailed_hint_for_ref ( & self , ty : Ty < ' _ > , err : & mut Diagnostic , span : & mut Span ) {
554+ struct ExprFinder {
555+ span : Span ,
556+ hir_id : Option < hir:: HirId > ,
557+ }
558+
559+ impl < ' tcx > Visitor < ' tcx > for ExprFinder {
560+ fn visit_expr ( & mut self , s : & ' tcx hir:: Expr < ' tcx > ) {
561+ if s. span . contains ( self . span ) {
562+ self . hir_id = Some ( s. hir_id ) ;
563+ }
564+ hir:: intravisit:: walk_expr ( self , s) ;
565+ }
566+ }
567+ let hir_map = self . infcx . tcx . hir ( ) ;
568+ let def_id = self . body . source . def_id ( ) ;
569+ let hir_id = if let Some ( local_def_id) = def_id. as_local ( )
570+ && let Some ( body_id) = hir_map. maybe_body_owned_by ( local_def_id) {
571+ let body = hir_map. body ( body_id) ;
572+ let mut v = ExprFinder {
573+ span : * span,
574+ hir_id : None ,
575+ } ;
576+ v. visit_body ( body) ;
577+ v. hir_id
578+ } else {
579+ None
580+ } ;
581+ let expr = if let Some ( hir_id) = hir_id {
582+ hir_map. expect_expr ( hir_id)
583+ } else {
584+ return ;
585+ } ;
586+ if let hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , Mutability :: Mut , ex) = expr. kind
587+ && !matches ! ( ex. kind, hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , _) | hir:: ExprKind :: Field ( _, _) | hir:: ExprKind :: Lit ( _) ) {
588+ * span = ex. span ;
589+ err. span_help ( ex. span , format ! ( "this expression is of type `{:?}`, which is an immutable reference" , ty) ) ;
590+ }
591+ }
592+
547593 fn suggest_map_index_mut_alternatives ( & self , ty : Ty < ' tcx > , err : & mut Diagnostic , span : Span ) {
548594 let Some ( adt) = ty. ty_adt_def ( ) else { return } ;
549595 let did = adt. did ( ) ;
0 commit comments