@@ -511,9 +511,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
511
511
self . expected_fn_found_fn_mut_call ( & mut err, span, act) ;
512
512
}
513
513
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;
517
516
match opt_source {
518
517
Some ( BorrowedContentSource :: OverloadedDeref ( ty) ) => {
519
518
err. help ( format ! (
@@ -528,8 +527,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
528
527
) ) ;
529
528
self . suggest_map_index_mut_alternatives ( ty, & mut err, span) ;
530
529
}
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
+ }
531
536
_ => ( ) ,
532
537
}
538
+ err. span_label ( span, format ! ( "cannot {act}" ) ) ;
533
539
}
534
540
535
541
_ => {
@@ -544,6 +550,46 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
544
550
}
545
551
}
546
552
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
+
547
593
fn suggest_map_index_mut_alternatives ( & self , ty : Ty < ' tcx > , err : & mut Diagnostic , span : Span ) {
548
594
let Some ( adt) = ty. ty_adt_def ( ) else { return } ;
549
595
let did = adt. did ( ) ;
0 commit comments