@@ -506,9 +506,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
506506 self . expected_fn_found_fn_mut_call ( & mut err, span, act) ;
507507 }
508508
509- PlaceRef { local : _, projection : [ .., ProjectionElem :: Deref ] } => {
510- err. span_label ( span, format ! ( "cannot {act}" ) ) ;
511-
509+ PlaceRef { local : _, projection : [ proj_base @ .., ProjectionElem :: Deref ] } => {
510+ let mut span = span;
512511 match opt_source {
513512 Some ( BorrowedContentSource :: OverloadedDeref ( ty) ) => {
514513 err. help ( format ! (
@@ -523,8 +522,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
523522 ) ) ;
524523 self . suggest_map_index_mut_alternatives ( ty, & mut err, span) ;
525524 }
525+ Some ( BorrowedContentSource :: DerefSharedRef ) => {
526+ let place_ref =
527+ PlaceRef { local : the_place_err. local , projection : proj_base } ;
528+ let ty = place_ref. ty ( self . body , self . infcx . tcx ) . ty ;
529+ self . suggest_detailed_hint_for_ref ( ty, & mut err, & mut span) ;
530+ }
526531 _ => ( ) ,
527532 }
533+ err. span_label ( span, format ! ( "cannot {act}" ) ) ;
528534 }
529535
530536 _ => {
@@ -539,6 +545,46 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
539545 }
540546 }
541547
548+ fn suggest_detailed_hint_for_ref ( & self , ty : Ty < ' _ > , err : & mut Diagnostic , span : & mut Span ) {
549+ struct ExprFinder {
550+ span : Span ,
551+ hir_id : Option < hir:: HirId > ,
552+ }
553+
554+ impl < ' tcx > Visitor < ' tcx > for ExprFinder {
555+ fn visit_expr ( & mut self , s : & ' tcx hir:: Expr < ' tcx > ) {
556+ if s. span . contains ( self . span ) {
557+ self . hir_id = Some ( s. hir_id ) ;
558+ }
559+ hir:: intravisit:: walk_expr ( self , s) ;
560+ }
561+ }
562+ let hir_map = self . infcx . tcx . hir ( ) ;
563+ let def_id = self . body . source . def_id ( ) ;
564+ let hir_id = if let Some ( local_def_id) = def_id. as_local ( )
565+ && let Some ( body_id) = hir_map. maybe_body_owned_by ( local_def_id) {
566+ let body = hir_map. body ( body_id) ;
567+ let mut v = ExprFinder {
568+ span : * span,
569+ hir_id : None ,
570+ } ;
571+ v. visit_body ( body) ;
572+ v. hir_id
573+ } else {
574+ None
575+ } ;
576+ let expr = if let Some ( hir_id) = hir_id {
577+ hir_map. expect_expr ( hir_id)
578+ } else {
579+ return ;
580+ } ;
581+ if let hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , Mutability :: Mut , ex) = expr. kind
582+ && !matches ! ( ex. kind, hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , _) | hir:: ExprKind :: Field ( _, _) | hir:: ExprKind :: Lit ( _) ) {
583+ * span = ex. span ;
584+ err. span_help ( ex. span , format ! ( "this expression is of type `{}`, which is an immutable reference" , ty) ) ;
585+ }
586+ }
587+
542588 fn suggest_map_index_mut_alternatives ( & self , ty : Ty < ' tcx > , err : & mut Diagnostic , span : Span ) {
543589 let Some ( adt) = ty. ty_adt_def ( ) else { return } ;
544590 let did = adt. did ( ) ;
0 commit comments