@@ -506,9 +506,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
506
506
self . expected_fn_found_fn_mut_call ( & mut err, span, act) ;
507
507
}
508
508
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;
512
511
match opt_source {
513
512
Some ( BorrowedContentSource :: OverloadedDeref ( ty) ) => {
514
513
err. help ( format ! (
@@ -523,8 +522,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
523
522
) ) ;
524
523
self . suggest_map_index_mut_alternatives ( ty, & mut err, span) ;
525
524
}
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
+ }
526
531
_ => ( ) ,
527
532
}
533
+ err. span_label ( span, format ! ( "cannot {act}" ) ) ;
528
534
}
529
535
530
536
_ => {
@@ -539,6 +545,46 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
539
545
}
540
546
}
541
547
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
+
542
588
fn suggest_map_index_mut_alternatives ( & self , ty : Ty < ' tcx > , err : & mut Diagnostic , span : Span ) {
543
589
let Some ( adt) = ty. ty_adt_def ( ) else { return } ;
544
590
let did = adt. did ( ) ;
0 commit comments