@@ -1363,19 +1363,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13631363 // Remove all the hir desugaring contexts while maintaining the macro contexts.
13641364 span. remove_mark ( ) ;
13651365 }
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) ;
13691367 let Some ( hir:: Node :: Expr ( body) ) = self . tcx . hir ( ) . find ( obligation. cause . body_id ) else {
13701368 return false ;
13711369 } ;
13721370 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`.
13731401 let mut count = 0 ;
13741402 let mut suggestions = vec ! [ ] ;
1375- let Some ( mut expr) = expr_finder. result else { return false ; } ;
13761403 // Skipping binder here, remapping below
13771404 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+ }
13781423
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 ( ) ;
13791430 ' outer: loop {
13801431 while let hir:: ExprKind :: AddrOf ( _, _, borrowed) = expr. kind {
13811432 count += 1 ;
@@ -1387,35 +1438,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13871438 suggestions. push ( ( span, String :: new ( ) ) ) ;
13881439
13891440 let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1390- break ;
1441+ break ' outer ;
13911442 } ;
13921443 suggested_ty = * inner_ty;
13931444
13941445 expr = borrowed;
13951446
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 ;
14191449 }
14201450 }
14211451 if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = expr. kind
@@ -1431,7 +1461,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
14311461 break ' outer;
14321462 }
14331463 }
1434- suggested
1464+ false
14351465 }
14361466
14371467 fn suggest_remove_await ( & self , obligation : & PredicateObligation < ' tcx > , err : & mut Diagnostic ) {
0 commit comments