@@ -1358,26 +1358,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13581358 err : & mut Diagnostic ,
13591359 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
13601360 ) -> bool {
1361- let span = obligation. cause . span ;
1362-
1361+ let mut span = obligation. cause . span ;
1362+ while span. desugaring_kind ( ) . is_some ( ) {
1363+ // Remove all the hir desugaring contexts while maintaining the macro contexts.
1364+ span. remove_mark ( ) ;
1365+ }
13631366 let mut suggested = false ;
1364- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
1365- let refs_number =
1366- snippet. chars ( ) . filter ( |c| !c. is_whitespace ( ) ) . take_while ( |c| * c == '&' ) . count ( ) ;
1367- if let Some ( '\'' ) = snippet. chars ( ) . filter ( |c| !c. is_whitespace ( ) ) . nth ( refs_number) {
1368- // Do not suggest removal of borrow from type arguments.
1369- return false ;
1370- }
13711367
1372- // Skipping binder here, remapping below
1373- let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
1368+ let mut expr_finder = super :: FindExprBySpan { span, result : None } ;
1369+ let Some ( hir:: Node :: Expr ( body) ) = self . tcx . hir ( ) . find ( obligation. cause . body_id ) else {
1370+ return false ;
1371+ } ;
1372+ expr_finder. visit_expr ( & body) ;
1373+ let mut count = 0 ;
1374+ let mut suggestions = vec ! [ ] ;
1375+ let Some ( mut expr) = expr_finder. result else { return false ; } ;
1376+ // Skipping binder here, remapping below
1377+ let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
1378+
1379+ ' outer: loop {
1380+ while let hir:: ExprKind :: AddrOf ( _, _, borrowed) = expr. kind {
1381+ count += 1 ;
1382+ let span = if expr. span . eq_ctxt ( borrowed. span ) {
1383+ expr. span . until ( borrowed. span )
1384+ } else {
1385+ expr. span . with_hi ( expr. span . lo ( ) + BytePos ( 1 ) )
1386+ } ;
1387+ suggestions. push ( ( span, String :: new ( ) ) ) ;
13741388
1375- for refs_remaining in 0 ..refs_number {
13761389 let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
13771390 break ;
13781391 } ;
13791392 suggested_ty = * inner_ty;
13801393
1394+ expr = borrowed;
1395+
13811396 // Remapping bound vars here
13821397 let trait_pred_and_suggested_ty =
13831398 trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
@@ -1388,25 +1403,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13881403 ) ;
13891404
13901405 if self . predicate_may_hold ( & new_obligation) {
1391- let sp = self
1392- . tcx
1393- . sess
1394- . source_map ( )
1395- . span_take_while ( span, |c| c. is_whitespace ( ) || * c == '&' ) ;
1396-
1397- let remove_refs = refs_remaining + 1 ;
1398-
1399- let msg = if remove_refs == 1 {
1406+ let msg = if count == 1 {
14001407 "consider removing the leading `&`-reference" . to_string ( )
14011408 } else {
1402- format ! ( "consider removing {} leading `&`-references" , remove_refs )
1409+ format ! ( "consider removing {count } leading `&`-references" )
14031410 } ;
14041411
1405- err. span_suggestion_short ( sp, & msg, "" , Applicability :: MachineApplicable ) ;
1412+ err. multipart_suggestion_verbose (
1413+ & msg,
1414+ suggestions,
1415+ Applicability :: MachineApplicable ,
1416+ ) ;
14061417 suggested = true ;
1407- break ;
1418+ break ' outer ;
14081419 }
14091420 }
1421+ if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = expr. kind
1422+ && let hir:: def:: Res :: Local ( hir_id) = path. res
1423+ && let Some ( hir:: Node :: Pat ( binding) ) = self . tcx . hir ( ) . find ( hir_id)
1424+ && let parent_hir_id = self . tcx . hir ( ) . get_parent_node ( binding. hir_id )
1425+ && let Some ( hir:: Node :: Local ( local) ) = self . tcx . hir ( ) . find ( parent_hir_id)
1426+ && let None = local. ty
1427+ && let Some ( binding_expr) = local. init
1428+ {
1429+ expr = binding_expr;
1430+ } else {
1431+ break ' outer;
1432+ }
14101433 }
14111434 suggested
14121435 }
0 commit comments