@@ -8,11 +8,10 @@ use rustc_index::vec::Idx;
88use rustc_middle:: mir:: {
99 self , AggregateKind , BindingForm , BorrowKind , ClearCrossCrate , ConstraintCategory ,
1010 FakeReadCause , Local , LocalDecl , LocalInfo , LocalKind , Location , Operand , Place , PlaceRef ,
11- ProjectionElem , Rvalue , Statement , StatementKind , TerminatorKind , VarBindingForm ,
11+ ProjectionElem , Rvalue , Statement , StatementKind , Terminator , TerminatorKind , VarBindingForm ,
1212} ;
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 } ;
1615
1716use crate :: dataflow:: drop_flag_effects;
1817use crate :: dataflow:: indexes:: { MoveOutIndex , MovePathIndex } ;
@@ -1543,9 +1542,43 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15431542 None ,
15441543 ) ;
15451544
1545+ self . explain_deref_coercion ( loan, & mut err) ;
1546+
15461547 err. buffer ( & mut self . errors_buffer ) ;
15471548 }
15481549
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+
15491582 /// Reports an illegal reassignment; for example, an assignment to
15501583 /// (part of) a non-`mut` local that occurs potentially after that
15511584 /// local has already been initialized. `place` is the path being
0 commit comments