@@ -628,17 +628,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
628628 if let Some ( parent_trait_pred) = parent_trait_pred {
629629 real_trait_pred = parent_trait_pred;
630630 }
631- let Some ( real_ty ) = real_trait_pred . self_ty ( ) . no_bound_vars ( ) else {
632- continue ;
633- } ;
631+
632+ // Skipping binder here, remapping below
633+ let real_ty = real_trait_pred . self_ty ( ) . skip_binder ( ) ;
634634
635635 if let ty:: Ref ( region, base_ty, mutbl) = * real_ty. kind ( ) {
636636 let mut autoderef = Autoderef :: new ( self , param_env, body_id, span, base_ty, span) ;
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+
641+ // Remapping bound vars here
642+ let real_trait_pred_and_ty =
643+ real_trait_pred. map_bound ( |inner_trait_pred| ( inner_trait_pred, ty) ) ;
644+ let obligation = self
645+ . mk_trait_obligation_with_new_self_ty ( param_env, real_trait_pred_and_ty) ;
642646 Some ( steps) . filter ( |_| self . predicate_may_hold ( & obligation) )
643647 } ) {
644648 if steps > 0 {
@@ -659,10 +663,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
659663 }
660664 } else if real_trait_pred != trait_pred {
661665 // This branch addresses #87437.
666+
667+ // Remapping bound vars here
668+ let real_trait_pred_and_base_ty =
669+ real_trait_pred. map_bound ( |inner_trait_pred| ( inner_trait_pred, base_ty) ) ;
662670 let obligation = self . mk_trait_obligation_with_new_self_ty (
663671 param_env,
664- real_trait_pred,
665- base_ty,
672+ real_trait_pred_and_base_ty,
666673 ) ;
667674 if self . predicate_may_hold ( & obligation) {
668675 err. span_suggestion_verbose (
@@ -720,9 +727,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
720727 err : & mut Diagnostic ,
721728 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
722729 ) -> bool {
723- let Some ( self_ty) = trait_pred. self_ty ( ) . no_bound_vars ( ) else {
724- return false ;
725- } ;
730+ // Skipping binder here, remapping below
731+ let self_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
726732
727733 let ( def_id, output_ty, callable) = match * self_ty. kind ( ) {
728734 ty:: Closure ( def_id, substs) => ( def_id, substs. as_closure ( ) . sig ( ) . output ( ) , "closure" ) ,
@@ -731,14 +737,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
731737 } ;
732738 let msg = format ! ( "use parentheses to call the {}" , callable) ;
733739
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- } ;
740+ // "We should really create a single list of bound vars from the combined vars
741+ // from the predicate and function, but instead we just liberate the function bound vars"
742+ let output_ty = self . tcx . liberate_late_bound_regions ( def_id, output_ty) ;
743+
744+ // Remapping bound vars here
745+ let trait_pred_and_self = trait_pred. map_bound ( |trait_pred| ( trait_pred, output_ty) ) ;
739746
740747 let new_obligation =
741- self . mk_trait_obligation_with_new_self_ty ( obligation. param_env , trait_pred , output_ty ) ;
748+ self . mk_trait_obligation_with_new_self_ty ( obligation. param_env , trait_pred_and_self ) ;
742749
743750 match self . evaluate_obligation ( & new_obligation) {
744751 Ok (
@@ -842,96 +849,97 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
842849 let param_env = obligation. param_env ;
843850
844851 // 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- }
851-
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 `{}`" ,
895- old_pred. print_modifiers_and_trait_path( ) ,
896- ) ,
897- ) ;
852+ let mut try_borrowing =
853+ |old_pred : ty:: PolyTraitPredicate < ' tcx > , blacklist : & [ DefId ] | -> bool {
854+ if blacklist. contains ( & old_pred. def_id ( ) ) {
855+ return false ;
856+ }
857+ // We map bounds to `&T` and `&mut T`
858+ let trait_pred_and_imm_ref = old_pred. map_bound ( |trait_pred| {
859+ (
860+ trait_pred,
861+ self . tcx . mk_imm_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
862+ )
863+ } ) ;
864+ let trait_pred_and_mut_ref = old_pred. map_bound ( |trait_pred| {
865+ (
866+ trait_pred,
867+ self . tcx . mk_mut_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
868+ )
869+ } ) ;
898870
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- ) ;
871+ let mk_result = |trait_pred_and_new_ty| {
872+ let obligation =
873+ self . mk_trait_obligation_with_new_self_ty ( param_env , trait_pred_and_new_ty ) ;
874+ self . predicate_must_hold_modulo_regions ( & obligation )
875+ } ;
876+ let imm_result = mk_result ( trait_pred_and_imm_ref ) ;
877+ let mut_result = mk_result ( trait_pred_and_mut_ref ) ;
878+
879+ if imm_result || mut_result {
880+ if let Ok ( snippet ) = self . tcx . sess . source_map ( ) . span_to_snippet ( span ) {
881+ // We have a very specific type of error, where just borrowing this argument
882+ // might solve the problem. In cases like this, the important part is the
883+ // original type obligation, not the last one that failed, which is arbitrary.
884+ // Because of this, we modify the error to refer to the original obligation and
885+ // return early in the caller.
886+
887+ let msg = format ! ( "the trait bound `{}` is not satisfied" , old_pred ) ;
888+ if has_custom_message {
889+ err . note ( & msg ) ;
918890 } 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- ) ;
891+ err. message =
892+ vec ! [ ( rustc_errors:: DiagnosticMessage :: Str ( msg) , Style :: NoStyle ) ] ;
928893 }
894+ if snippet. starts_with ( '&' ) {
895+ // This is already a literal borrow and the obligation is failing
896+ // somewhere else in the obligation chain. Do not suggest non-sense.
897+ return false ;
898+ }
899+ err. span_label (
900+ span,
901+ & format ! (
902+ "expected an implementor of trait `{}`" ,
903+ old_pred. print_modifiers_and_trait_path( ) ,
904+ ) ,
905+ ) ;
906+
907+ // This if is to prevent a special edge-case
908+ if matches ! (
909+ span. ctxt( ) . outer_expn_data( ) . kind,
910+ ExpnKind :: Root | ExpnKind :: Desugaring ( DesugaringKind :: ForLoop )
911+ ) {
912+ // We don't want a borrowing suggestion on the fields in structs,
913+ // ```
914+ // struct Foo {
915+ // the_foos: Vec<Foo>
916+ // }
917+ // ```
918+
919+ if imm_result && mut_result {
920+ err. span_suggestions (
921+ span. shrink_to_lo ( ) ,
922+ "consider borrowing here" ,
923+ [ "&" . to_string ( ) , "&mut " . to_string ( ) ] . into_iter ( ) ,
924+ Applicability :: MaybeIncorrect ,
925+ ) ;
926+ } else {
927+ err. span_suggestion_verbose (
928+ span. shrink_to_lo ( ) ,
929+ & format ! (
930+ "consider{} borrowing here" ,
931+ if mut_result { " mutably" } else { "" }
932+ ) ,
933+ format ! ( "&{}" , if mut_result { "mut " } else { "" } ) ,
934+ Applicability :: MaybeIncorrect ,
935+ ) ;
936+ }
937+ }
938+ return true ;
929939 }
930- return true ;
931940 }
932- }
933- return false ;
934- } ;
941+ return false ;
942+ } ;
935943
936944 if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
937945 try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
@@ -992,20 +1000,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
9921000 return false ;
9931001 }
9941002
995- let Some ( mut suggested_ty) = trait_pred. self_ty ( ) . no_bound_vars ( ) else {
996- return false ;
997- } ;
1003+ // Skipping binder here, remapping below
1004+ let mut suggested_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
9981005
9991006 for refs_remaining in 0 ..refs_number {
10001007 let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
10011008 break ;
10021009 } ;
10031010 suggested_ty = * inner_ty;
10041011
1012+ // Remapping bound vars here
1013+ let trait_pred_and_suggested_ty =
1014+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1015+
10051016 let new_obligation = self . mk_trait_obligation_with_new_self_ty (
10061017 obligation. param_env ,
1007- trait_pred,
1008- suggested_ty,
1018+ trait_pred_and_suggested_ty,
10091019 ) ;
10101020
10111021 if self . predicate_may_hold ( & new_obligation) {
@@ -1125,26 +1135,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
11251135 return ;
11261136 }
11271137
1138+ // Skipping binder here, remapping below
11281139 if let ty:: Ref ( region, t_type, mutability) = * trait_pred. skip_binder ( ) . self_ty ( ) . kind ( )
11291140 {
1130- if region. is_late_bound ( ) || t_type. has_escaping_bound_vars ( ) {
1131- // Avoid debug assertion in `mk_obligation_for_def_id`.
1132- //
1133- // If the self type has escaping bound vars then it's not
1134- // going to be the type of an expression, so the suggestion
1135- // probably won't apply anyway.
1136- return ;
1137- }
1138-
11391141 let suggested_ty = match mutability {
11401142 hir:: Mutability :: Mut => self . tcx . mk_imm_ref ( region, t_type) ,
11411143 hir:: Mutability :: Not => self . tcx . mk_mut_ref ( region, t_type) ,
11421144 } ;
11431145
1146+ // Remapping bound vars here
1147+ let trait_pred_and_suggested_ty =
1148+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1149+
11441150 let new_obligation = self . mk_trait_obligation_with_new_self_ty (
11451151 obligation. param_env ,
1146- trait_pred,
1147- suggested_ty,
1152+ trait_pred_and_suggested_ty,
11481153 ) ;
11491154 let suggested_ty_would_satisfy_obligation = self
11501155 . evaluate_obligation_no_overflow ( & new_obligation)
@@ -1195,7 +1200,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
11951200 // Only suggest this if the expression behind the semicolon implements the predicate
11961201 && let Some ( typeck_results) = self . in_progress_typeck_results
11971202 && 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) )
1203+ && self . predicate_may_hold ( & self . mk_trait_obligation_with_new_self_ty (
1204+ obligation. param_env , trait_pred. map_bound ( |trait_pred| ( trait_pred, ty) )
1205+ ) )
11991206 {
12001207 err. span_label (
12011208 expr. span ,
@@ -2727,8 +2734,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
27272734 ) ;
27282735 let try_obligation = self . mk_trait_obligation_with_new_self_ty (
27292736 obligation. param_env ,
2730- trait_pred,
2731- normalized_ty. ty ( ) . unwrap ( ) ,
2737+ trait_pred. map_bound ( |trait_pred| ( trait_pred, normalized_ty. ty ( ) . unwrap ( ) ) ) ,
27322738 ) ;
27332739 debug ! ( "suggest_await_before_try: try_trait_obligation {:?}" , try_obligation) ;
27342740 if self . predicate_may_hold ( & try_obligation)
0 commit comments