@@ -1358,26 +1358,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1358
1358
err : & mut Diagnostic ,
1359
1359
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1360
1360
) -> 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
+ }
1363
1366
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
- }
1371
1367
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 ( ) ) ) ;
1374
1388
1375
- for refs_remaining in 0 ..refs_number {
1376
1389
let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1377
1390
break ;
1378
1391
} ;
1379
1392
suggested_ty = * inner_ty;
1380
1393
1394
+ expr = borrowed;
1395
+
1381
1396
// Remapping bound vars here
1382
1397
let trait_pred_and_suggested_ty =
1383
1398
trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
@@ -1388,25 +1403,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1388
1403
) ;
1389
1404
1390
1405
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 {
1400
1407
"consider removing the leading `&`-reference" . to_string ( )
1401
1408
} else {
1402
- format ! ( "consider removing {} leading `&`-references" , remove_refs )
1409
+ format ! ( "consider removing {count } leading `&`-references" )
1403
1410
} ;
1404
1411
1405
- err. span_suggestion_short ( sp, & msg, "" , Applicability :: MachineApplicable ) ;
1412
+ err. multipart_suggestion_verbose (
1413
+ & msg,
1414
+ suggestions,
1415
+ Applicability :: MachineApplicable ,
1416
+ ) ;
1406
1417
suggested = true ;
1407
- break ;
1418
+ break ' outer ;
1408
1419
}
1409
1420
}
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
+ }
1410
1433
}
1411
1434
suggested
1412
1435
}
0 commit comments