11//! Print diagnostics to explain why values are borrowed.
22
33use rustc_errors:: { Applicability , Diagnostic } ;
4+ use rustc_hir as hir;
5+ use rustc_hir:: intravisit:: Visitor ;
46use rustc_index:: vec:: IndexVec ;
57use rustc_infer:: infer:: NllRegionVariableOrigin ;
68use rustc_middle:: mir:: {
@@ -11,6 +13,7 @@ use rustc_middle::ty::adjustment::PointerCast;
1113use rustc_middle:: ty:: { self , RegionVid , TyCtxt } ;
1214use rustc_span:: symbol:: { kw, Symbol } ;
1315use rustc_span:: { sym, DesugaringKind , Span } ;
16+ use rustc_trait_selection:: traits:: error_reporting:: FindExprBySpan ;
1417
1518use crate :: region_infer:: { BlameConstraint , ExtraConstraintInfo } ;
1619use crate :: {
@@ -63,6 +66,36 @@ impl<'tcx> BorrowExplanation<'tcx> {
6366 borrow_span : Option < Span > ,
6467 multiple_borrow_span : Option < ( Span , Span ) > ,
6568 ) {
69+ if let Some ( span) = borrow_span {
70+ let def_id = body. source . def_id ( ) ;
71+ if let Some ( node) = tcx. hir ( ) . get_if_local ( def_id)
72+ && let Some ( body_id) = node. body_id ( )
73+ {
74+ let body = tcx. hir ( ) . body ( body_id) ;
75+ let mut expr_finder = FindExprBySpan :: new ( span) ;
76+ expr_finder. visit_expr ( body. value ) ;
77+ if let Some ( mut expr) = expr_finder. result {
78+ while let hir:: ExprKind :: AddrOf ( _, _, inner)
79+ | hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , inner)
80+ | hir:: ExprKind :: Field ( inner, _)
81+ | hir:: ExprKind :: MethodCall ( _, inner, _, _)
82+ | hir:: ExprKind :: Index ( inner, _) = & expr. kind
83+ {
84+ expr = inner;
85+ }
86+ if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , p) ) = expr. kind
87+ && let [ hir:: PathSegment { ident, args : None , .. } ] = p. segments
88+ && let hir:: def:: Res :: Local ( hir_id) = p. res
89+ && let Some ( hir:: Node :: Pat ( pat) ) = tcx. hir ( ) . find ( hir_id)
90+ {
91+ err. span_label (
92+ pat. span ,
93+ & format ! ( "binding `{ident}` declared here" ) ,
94+ ) ;
95+ }
96+ }
97+ }
98+ }
6699 match * self {
67100 BorrowExplanation :: UsedLater ( later_use_kind, var_or_use_span, path_span) => {
68101 let message = match later_use_kind {
0 commit comments