@@ -1363,19 +1363,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1363
1363
// Remove all the hir desugaring contexts while maintaining the macro contexts.
1364
1364
span. remove_mark ( ) ;
1365
1365
}
1366
- let mut suggested = false ;
1367
-
1368
- let mut expr_finder = super :: FindExprBySpan { span, result : None } ;
1366
+ let mut expr_finder = super :: FindExprBySpan :: new ( span) ;
1369
1367
let Some ( hir:: Node :: Expr ( body) ) = self . tcx . hir ( ) . find ( obligation. cause . body_id ) else {
1370
1368
return false ;
1371
1369
} ;
1372
1370
expr_finder. visit_expr ( & body) ;
1371
+ let mut maybe_suggest = |suggested_ty, count, suggestions| {
1372
+ // Remapping bound vars here
1373
+ let trait_pred_and_suggested_ty =
1374
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1375
+
1376
+ let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1377
+ obligation. param_env ,
1378
+ trait_pred_and_suggested_ty,
1379
+ ) ;
1380
+
1381
+ if self . predicate_may_hold ( & new_obligation) {
1382
+ let msg = if count == 1 {
1383
+ "consider removing the leading `&`-reference" . to_string ( )
1384
+ } else {
1385
+ format ! ( "consider removing {count} leading `&`-references" )
1386
+ } ;
1387
+
1388
+ err. multipart_suggestion_verbose (
1389
+ & msg,
1390
+ suggestions,
1391
+ Applicability :: MachineApplicable ,
1392
+ ) ;
1393
+ true
1394
+ } else {
1395
+ false
1396
+ }
1397
+ } ;
1398
+
1399
+ // Maybe suggest removal of borrows from types in type parameters, like in
1400
+ // `src/test/ui/not-panic/not-panic-safe.rs`.
1373
1401
let mut count = 0 ;
1374
1402
let mut suggestions = vec ! [ ] ;
1375
- let Some ( mut expr) = expr_finder. result else { return false ; } ;
1376
1403
// Skipping binder here, remapping below
1377
1404
let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
1405
+ if let Some ( mut hir_ty) = expr_finder. ty_result {
1406
+ while let hir:: TyKind :: Ref ( _, mut_ty) = & hir_ty. kind {
1407
+ count += 1 ;
1408
+ let span = hir_ty. span . until ( mut_ty. ty . span ) ;
1409
+ suggestions. push ( ( span, String :: new ( ) ) ) ;
1410
+
1411
+ let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1412
+ break ;
1413
+ } ;
1414
+ suggested_ty = * inner_ty;
1415
+
1416
+ hir_ty = mut_ty. ty ;
1417
+
1418
+ if maybe_suggest ( suggested_ty, count, suggestions. clone ( ) ) {
1419
+ return true ;
1420
+ }
1421
+ }
1422
+ }
1378
1423
1424
+ // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
1425
+ let Some ( mut expr) = expr_finder. result else { return false ; } ;
1426
+ let mut count = 0 ;
1427
+ let mut suggestions = vec ! [ ] ;
1428
+ // Skipping binder here, remapping below
1429
+ let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
1379
1430
' outer: loop {
1380
1431
while let hir:: ExprKind :: AddrOf ( _, _, borrowed) = expr. kind {
1381
1432
count += 1 ;
@@ -1387,35 +1438,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1387
1438
suggestions. push ( ( span, String :: new ( ) ) ) ;
1388
1439
1389
1440
let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1390
- break ;
1441
+ break ' outer ;
1391
1442
} ;
1392
1443
suggested_ty = * inner_ty;
1393
1444
1394
1445
expr = borrowed;
1395
1446
1396
- // Remapping bound vars here
1397
- let trait_pred_and_suggested_ty =
1398
- trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1399
-
1400
- let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1401
- obligation. param_env ,
1402
- trait_pred_and_suggested_ty,
1403
- ) ;
1404
-
1405
- if self . predicate_may_hold ( & new_obligation) {
1406
- let msg = if count == 1 {
1407
- "consider removing the leading `&`-reference" . to_string ( )
1408
- } else {
1409
- format ! ( "consider removing {count} leading `&`-references" )
1410
- } ;
1411
-
1412
- err. multipart_suggestion_verbose (
1413
- & msg,
1414
- suggestions,
1415
- Applicability :: MachineApplicable ,
1416
- ) ;
1417
- suggested = true ;
1418
- break ' outer;
1447
+ if maybe_suggest ( suggested_ty, count, suggestions. clone ( ) ) {
1448
+ return true ;
1419
1449
}
1420
1450
}
1421
1451
if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = expr. kind
@@ -1431,7 +1461,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1431
1461
break ' outer;
1432
1462
}
1433
1463
}
1434
- suggested
1464
+ false
1435
1465
}
1436
1466
1437
1467
fn suggest_remove_await ( & self , obligation : & PredicateObligation < ' tcx > , err : & mut Diagnostic ) {
0 commit comments