@@ -8,11 +8,10 @@ use rustc_index::vec::Idx;
8
8
use rustc_middle:: mir:: {
9
9
self , AggregateKind , BindingForm , BorrowKind , ClearCrossCrate , ConstraintCategory ,
10
10
FakeReadCause , Local , LocalDecl , LocalInfo , LocalKind , Location , Operand , Place , PlaceRef ,
11
- ProjectionElem , Rvalue , Statement , StatementKind , TerminatorKind , VarBindingForm ,
11
+ ProjectionElem , Rvalue , Statement , StatementKind , Terminator , TerminatorKind , VarBindingForm ,
12
12
} ;
13
- use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty } ;
14
- use rustc_span:: source_map:: DesugaringKind ;
15
- use rustc_span:: Span ;
13
+ use rustc_middle:: ty:: { self , suggest_constraining_type_param, Instance , Ty } ;
14
+ use rustc_span:: { source_map:: DesugaringKind , symbol:: sym, Span } ;
16
15
17
16
use crate :: dataflow:: drop_flag_effects;
18
17
use crate :: dataflow:: indexes:: { MoveOutIndex , MovePathIndex } ;
@@ -1543,9 +1542,43 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1543
1542
None ,
1544
1543
) ;
1545
1544
1545
+ self . explain_deref_coercion ( loan, & mut err) ;
1546
+
1546
1547
err. buffer ( & mut self . errors_buffer ) ;
1547
1548
}
1548
1549
1550
+ fn explain_deref_coercion ( & mut self , loan : & BorrowData < ' tcx > , err : & mut DiagnosticBuilder < ' _ > ) {
1551
+ let tcx = self . infcx . tcx ;
1552
+ if let (
1553
+ Some ( Terminator { kind : TerminatorKind :: Call { from_hir_call : false , .. } , .. } ) ,
1554
+ Some ( ( method_did, method_substs) ) ,
1555
+ ) = (
1556
+ & self . body [ loan. reserve_location . block ] . terminator ,
1557
+ crate :: util:: find_self_call (
1558
+ tcx,
1559
+ self . body ,
1560
+ loan. assigned_place . local ,
1561
+ loan. reserve_location . block ,
1562
+ ) ,
1563
+ ) {
1564
+ if tcx. is_diagnostic_item ( sym:: deref_method, method_did) {
1565
+ let deref_target =
1566
+ tcx. get_diagnostic_item ( sym:: deref_target) . and_then ( |deref_target| {
1567
+ Instance :: resolve ( tcx, self . param_env , deref_target, method_substs)
1568
+ . transpose ( )
1569
+ } ) ;
1570
+ if let Some ( Ok ( instance) ) = deref_target {
1571
+ let deref_target_ty = instance. ty ( tcx, self . param_env ) ;
1572
+ err. note ( & format ! (
1573
+ "borrow occurs due to deref coercion to `{}`" ,
1574
+ deref_target_ty
1575
+ ) ) ;
1576
+ err. span_note ( tcx. def_span ( instance. def_id ( ) ) , "deref defined here" ) ;
1577
+ }
1578
+ }
1579
+ }
1580
+ }
1581
+
1549
1582
/// Reports an illegal reassignment; for example, an assignment to
1550
1583
/// (part of) a non-`mut` local that occurs potentially after that
1551
1584
/// local has already been initialized. `place` is the path being
0 commit comments