@@ -637,8 +637,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
637637 if let Some ( steps) = autoderef. find_map ( |( ty, steps) | {
638638 // Re-add the `&`
639639 let ty = self . tcx . mk_ref ( region, TypeAndMut { ty, mutbl } ) ;
640- let obligation =
641- self . mk_trait_obligation_with_new_self_ty ( param_env, real_trait_pred, ty) ;
640+ let real_trait_pred_and_ty =
641+ real_trait_pred. map_bound ( |inner_trait_pred| ( inner_trait_pred, ty) ) ;
642+ let obligation = self
643+ . mk_trait_obligation_with_new_self_ty ( param_env, real_trait_pred_and_ty) ;
642644 Some ( steps) . filter ( |_| self . predicate_may_hold ( & obligation) )
643645 } ) {
644646 if steps > 0 {
@@ -659,10 +661,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
659661 }
660662 } else if real_trait_pred != trait_pred {
661663 // This branch addresses #87437.
664+ let real_trait_pred_and_base_ty =
665+ real_trait_pred. map_bound ( |inner_trait_pred| ( inner_trait_pred, base_ty) ) ;
662666 let obligation = self . mk_trait_obligation_with_new_self_ty (
663667 param_env,
664- real_trait_pred,
665- base_ty,
668+ real_trait_pred_and_base_ty,
666669 ) ;
667670 if self . predicate_may_hold ( & obligation) {
668671 err. span_suggestion_verbose (
@@ -720,9 +723,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
720723 err : & mut Diagnostic ,
721724 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
722725 ) -> bool {
723- let Some ( self_ty) = trait_pred. self_ty ( ) . no_bound_vars ( ) else {
724- return false ;
725- } ;
726+ let self_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
726727
727728 let ( def_id, output_ty, callable) = match * self_ty. kind ( ) {
728729 ty:: Closure ( def_id, substs) => ( def_id, substs. as_closure ( ) . sig ( ) . output ( ) , "closure" ) ,
@@ -731,14 +732,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
731732 } ;
732733 let msg = format ! ( "use parentheses to call the {}" , callable) ;
733734
734- // `mk_trait_obligation_with_new_self_ty` only works for types with no escaping bound
735- // variables, so bail out if we have any.
736- let Some ( output_ty) = output_ty. no_bound_vars ( ) else {
737- return false ;
738- } ;
735+ let output_ty = self . tcx . liberate_late_bound_regions ( def_id, output_ty) ;
736+
737+ let trait_pred_and_self = trait_pred. map_bound ( |trait_pred| ( trait_pred, output_ty) ) ;
739738
740739 let new_obligation =
741- self . mk_trait_obligation_with_new_self_ty ( obligation. param_env , trait_pred , output_ty ) ;
740+ self . mk_trait_obligation_with_new_self_ty ( obligation. param_env , trait_pred_and_self ) ;
742741
743742 match self . evaluate_obligation ( & new_obligation) {
744743 Ok (
@@ -842,96 +841,102 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
842841 let param_env = obligation. param_env ;
843842
844843 // Try to apply the original trait binding obligation by borrowing.
845- let mut try_borrowing = |old_pred : ty:: PolyTraitPredicate < ' tcx > ,
846- blacklist : & [ DefId ] |
847- -> bool {
848- if blacklist. contains ( & old_pred. def_id ( ) ) {
849- return false ;
850- }
844+ let mut try_borrowing =
845+ |old_pred : ty:: PolyTraitPredicate < ' tcx > , blacklist : & [ DefId ] | -> bool {
846+ if blacklist. contains ( & old_pred. def_id ( ) ) {
847+ return false ;
848+ }
849+ // We map bounds to `&T` and `&mut T`
850+ let trait_pred_and_imm_ref = old_pred. map_bound ( |trait_pred| {
851+ (
852+ trait_pred,
853+ self . tcx . mk_imm_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
854+ )
855+ } ) ;
856+ let trait_pred_and_mut_ref = old_pred. map_bound ( |trait_pred| {
857+ (
858+ trait_pred,
859+ self . tcx . mk_mut_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
860+ )
861+ } ) ;
851862
852- // This is a quick fix to resolve an ICE (#96223).
853- // This change should probably be deeper.
854- // As suggested by @jackh726, `mk_trait_obligation_with_new_self_ty` could take a `Binder<(TraitRef, Ty)>
855- // instead of `Binder<Ty>` leading to some changes to its call places.
856- let Some ( orig_ty) = old_pred. self_ty ( ) . no_bound_vars ( ) else {
857- return false ;
858- } ;
859- let mk_result = |new_ty| {
860- let obligation =
861- self . mk_trait_obligation_with_new_self_ty ( param_env, old_pred, new_ty) ;
862- self . predicate_must_hold_modulo_regions ( & obligation)
863- } ;
864- let imm_result = mk_result ( self . tcx . mk_imm_ref ( self . tcx . lifetimes . re_static , orig_ty) ) ;
865- let mut_result = mk_result ( self . tcx . mk_mut_ref ( self . tcx . lifetimes . re_static , orig_ty) ) ;
866-
867- if imm_result || mut_result {
868- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
869- // We have a very specific type of error, where just borrowing this argument
870- // might solve the problem. In cases like this, the important part is the
871- // original type obligation, not the last one that failed, which is arbitrary.
872- // Because of this, we modify the error to refer to the original obligation and
873- // return early in the caller.
874-
875- let msg = format ! (
876- "the trait bound `{}: {}` is not satisfied" ,
877- orig_ty,
878- old_pred. print_modifiers_and_trait_path( ) ,
879- ) ;
880- if has_custom_message {
881- err. note ( & msg) ;
882- } else {
883- err. message =
884- vec ! [ ( rustc_errors:: DiagnosticMessage :: Str ( msg) , Style :: NoStyle ) ] ;
885- }
886- if snippet. starts_with ( '&' ) {
887- // This is already a literal borrow and the obligation is failing
888- // somewhere else in the obligation chain. Do not suggest non-sense.
889- return false ;
890- }
891- err. span_label (
892- span,
893- & format ! (
894- "expected an implementor of trait `{}`" ,
863+ let mk_result = |trait_pred_and_new_ty| {
864+ let obligation =
865+ self . mk_trait_obligation_with_new_self_ty ( param_env, trait_pred_and_new_ty) ;
866+ self . predicate_must_hold_modulo_regions ( & obligation)
867+ } ;
868+ let imm_result = mk_result ( trait_pred_and_imm_ref) ;
869+ let mut_result = mk_result ( trait_pred_and_mut_ref) ;
870+
871+ if imm_result || mut_result {
872+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
873+ // We have a very specific type of error, where just borrowing this argument
874+ // might solve the problem. In cases like this, the important part is the
875+ // original type obligation, not the last one that failed, which is arbitrary.
876+ // Because of this, we modify the error to refer to the original obligation and
877+ // return early in the caller.
878+
879+ let msg = format ! (
880+ "the trait bound `{}: {}` is not satisfied" ,
881+ // Safe to skip binder here
882+ old_pred. self_ty( ) . skip_binder( ) ,
895883 old_pred. print_modifiers_and_trait_path( ) ,
896- ) ,
897- ) ;
898-
899- // This if is to prevent a special edge-case
900- if matches ! (
901- span. ctxt( ) . outer_expn_data( ) . kind,
902- ExpnKind :: Root | ExpnKind :: Desugaring ( DesugaringKind :: ForLoop )
903- ) {
904- // We don't want a borrowing suggestion on the fields in structs,
905- // ```
906- // struct Foo {
907- // the_foos: Vec<Foo>
908- // }
909- // ```
910-
911- if imm_result && mut_result {
912- err. span_suggestions (
913- span. shrink_to_lo ( ) ,
914- "consider borrowing here" ,
915- [ "&" . to_string ( ) , "&mut " . to_string ( ) ] . into_iter ( ) ,
916- Applicability :: MaybeIncorrect ,
917- ) ;
884+ ) ;
885+ if has_custom_message {
886+ err. note ( & msg) ;
918887 } else {
919- err. span_suggestion_verbose (
920- span. shrink_to_lo ( ) ,
921- & format ! (
922- "consider{} borrowing here" ,
923- if mut_result { " mutably" } else { "" }
924- ) ,
925- format ! ( "&{}" , if mut_result { "mut " } else { "" } ) ,
926- Applicability :: MaybeIncorrect ,
927- ) ;
888+ err. message =
889+ vec ! [ ( rustc_errors:: DiagnosticMessage :: Str ( msg) , Style :: NoStyle ) ] ;
928890 }
891+ if snippet. starts_with ( '&' ) {
892+ // This is already a literal borrow and the obligation is failing
893+ // somewhere else in the obligation chain. Do not suggest non-sense.
894+ return false ;
895+ }
896+ err. span_label (
897+ span,
898+ & format ! (
899+ "expected an implementor of trait `{}`" ,
900+ old_pred. print_modifiers_and_trait_path( ) ,
901+ ) ,
902+ ) ;
903+
904+ // This if is to prevent a special edge-case
905+ if matches ! (
906+ span. ctxt( ) . outer_expn_data( ) . kind,
907+ ExpnKind :: Root | ExpnKind :: Desugaring ( DesugaringKind :: ForLoop )
908+ ) {
909+ // We don't want a borrowing suggestion on the fields in structs,
910+ // ```
911+ // struct Foo {
912+ // the_foos: Vec<Foo>
913+ // }
914+ // ```
915+
916+ if imm_result && mut_result {
917+ err. span_suggestions (
918+ span. shrink_to_lo ( ) ,
919+ "consider borrowing here" ,
920+ [ "&" . to_string ( ) , "&mut " . to_string ( ) ] . into_iter ( ) ,
921+ Applicability :: MaybeIncorrect ,
922+ ) ;
923+ } else {
924+ err. span_suggestion_verbose (
925+ span. shrink_to_lo ( ) ,
926+ & format ! (
927+ "consider{} borrowing here" ,
928+ if mut_result { " mutably" } else { "" }
929+ ) ,
930+ format ! ( "&{}" , if mut_result { "mut " } else { "" } ) ,
931+ Applicability :: MaybeIncorrect ,
932+ ) ;
933+ }
934+ }
935+ return true ;
929936 }
930- return true ;
931937 }
932- }
933- return false ;
934- } ;
938+ return false ;
939+ } ;
935940
936941 if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
937942 try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
@@ -992,20 +997,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
992997 return false ;
993998 }
994999
995- let Some ( mut suggested_ty) = trait_pred. self_ty ( ) . no_bound_vars ( ) else {
996- return false ;
997- } ;
1000+ // We skip binder here
1001+ let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
9981002
9991003 for refs_remaining in 0 ..refs_number {
10001004 let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
10011005 break ;
10021006 } ;
10031007 suggested_ty = * inner_ty;
10041008
1009+ // We remap bounds here
1010+ let trait_pred_and_suggested_ty =
1011+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1012+
10051013 let new_obligation = self . mk_trait_obligation_with_new_self_ty (
10061014 obligation. param_env ,
1007- trait_pred,
1008- suggested_ty,
1015+ trait_pred_and_suggested_ty,
10091016 ) ;
10101017
10111018 if self . predicate_may_hold ( & new_obligation) {
@@ -1141,10 +1148,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
11411148 hir:: Mutability :: Not => self . tcx . mk_mut_ref ( region, t_type) ,
11421149 } ;
11431150
1151+ let trait_pred_and_suggested_ty =
1152+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1153+
11441154 let new_obligation = self . mk_trait_obligation_with_new_self_ty (
11451155 obligation. param_env ,
1146- trait_pred,
1147- suggested_ty,
1156+ trait_pred_and_suggested_ty,
11481157 ) ;
11491158 let suggested_ty_would_satisfy_obligation = self
11501159 . evaluate_obligation_no_overflow ( & new_obligation)
@@ -1195,7 +1204,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
11951204 // Only suggest this if the expression behind the semicolon implements the predicate
11961205 && let Some ( typeck_results) = self . in_progress_typeck_results
11971206 && let Some ( ty) = typeck_results. borrow ( ) . expr_ty_opt ( expr)
1198- && self . predicate_may_hold ( & self . mk_trait_obligation_with_new_self_ty ( obligation. param_env , trait_pred, ty) )
1207+ && self . predicate_may_hold ( & self . mk_trait_obligation_with_new_self_ty (
1208+ obligation. param_env , trait_pred. map_bound ( |trait_pred| ( trait_pred, ty) )
1209+ ) )
11991210 {
12001211 err. span_label (
12011212 expr. span ,
@@ -2727,8 +2738,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
27272738 ) ;
27282739 let try_obligation = self . mk_trait_obligation_with_new_self_ty (
27292740 obligation. param_env ,
2730- trait_pred,
2731- normalized_ty. ty ( ) . unwrap ( ) ,
2741+ trait_pred. map_bound ( |trait_pred| ( trait_pred, normalized_ty. ty ( ) . unwrap ( ) ) ) ,
27322742 ) ;
27332743 debug ! ( "suggest_await_before_try: try_trait_obligation {:?}" , try_obligation) ;
27342744 if self . predicate_may_hold ( & try_obligation)
0 commit comments