@@ -628,17 +628,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
628
628
if let Some ( parent_trait_pred) = parent_trait_pred {
629
629
real_trait_pred = parent_trait_pred;
630
630
}
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 ( ) ;
634
634
635
635
if let ty:: Ref ( region, base_ty, mutbl) = * real_ty. kind ( ) {
636
636
let mut autoderef = Autoderef :: new ( self , param_env, body_id, span, base_ty, span) ;
637
637
if let Some ( steps) = autoderef. find_map ( |( ty, steps) | {
638
638
// Re-add the `&`
639
639
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) ;
642
646
Some ( steps) . filter ( |_| self . predicate_may_hold ( & obligation) )
643
647
} ) {
644
648
if steps > 0 {
@@ -659,10 +663,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
659
663
}
660
664
} else if real_trait_pred != trait_pred {
661
665
// 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) ) ;
662
670
let obligation = self . mk_trait_obligation_with_new_self_ty (
663
671
param_env,
664
- real_trait_pred,
665
- base_ty,
672
+ real_trait_pred_and_base_ty,
666
673
) ;
667
674
if self . predicate_may_hold ( & obligation) {
668
675
err. span_suggestion_verbose (
@@ -720,9 +727,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
720
727
err : & mut Diagnostic ,
721
728
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
722
729
) -> 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 ( ) ;
726
732
727
733
let ( def_id, output_ty, callable) = match * self_ty. kind ( ) {
728
734
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> {
731
737
} ;
732
738
let msg = format ! ( "use parentheses to call the {}" , callable) ;
733
739
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) ) ;
739
746
740
747
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 ) ;
742
749
743
750
match self . evaluate_obligation ( & new_obligation) {
744
751
Ok (
@@ -842,96 +849,97 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
842
849
let param_env = obligation. param_env ;
843
850
844
851
// 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
+ } ) ;
898
870
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 ) ;
918
890
} 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 ) ] ;
928
893
}
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 ;
929
939
}
930
- return true ;
931
940
}
932
- }
933
- return false ;
934
- } ;
941
+ return false ;
942
+ } ;
935
943
936
944
if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
937
945
try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
@@ -992,20 +1000,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
992
1000
return false ;
993
1001
}
994
1002
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 ( ) ;
998
1005
999
1006
for refs_remaining in 0 ..refs_number {
1000
1007
let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1001
1008
break ;
1002
1009
} ;
1003
1010
suggested_ty = * inner_ty;
1004
1011
1012
+ // Remapping bound vars here
1013
+ let trait_pred_and_suggested_ty =
1014
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1015
+
1005
1016
let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1006
1017
obligation. param_env ,
1007
- trait_pred,
1008
- suggested_ty,
1018
+ trait_pred_and_suggested_ty,
1009
1019
) ;
1010
1020
1011
1021
if self . predicate_may_hold ( & new_obligation) {
@@ -1125,26 +1135,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1125
1135
return ;
1126
1136
}
1127
1137
1138
+ // Skipping binder here, remapping below
1128
1139
if let ty:: Ref ( region, t_type, mutability) = * trait_pred. skip_binder ( ) . self_ty ( ) . kind ( )
1129
1140
{
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
-
1139
1141
let suggested_ty = match mutability {
1140
1142
hir:: Mutability :: Mut => self . tcx . mk_imm_ref ( region, t_type) ,
1141
1143
hir:: Mutability :: Not => self . tcx . mk_mut_ref ( region, t_type) ,
1142
1144
} ;
1143
1145
1146
+ // Remapping bound vars here
1147
+ let trait_pred_and_suggested_ty =
1148
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1149
+
1144
1150
let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1145
1151
obligation. param_env ,
1146
- trait_pred,
1147
- suggested_ty,
1152
+ trait_pred_and_suggested_ty,
1148
1153
) ;
1149
1154
let suggested_ty_would_satisfy_obligation = self
1150
1155
. evaluate_obligation_no_overflow ( & new_obligation)
@@ -1195,7 +1200,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1195
1200
// Only suggest this if the expression behind the semicolon implements the predicate
1196
1201
&& let Some ( typeck_results) = self . in_progress_typeck_results
1197
1202
&& 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
+ ) )
1199
1206
{
1200
1207
err. span_label (
1201
1208
expr. span ,
@@ -2727,8 +2734,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
2727
2734
) ;
2728
2735
let try_obligation = self . mk_trait_obligation_with_new_self_ty (
2729
2736
obligation. param_env ,
2730
- trait_pred,
2731
- normalized_ty. ty ( ) . unwrap ( ) ,
2737
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, normalized_ty. ty ( ) . unwrap ( ) ) ) ,
2732
2738
) ;
2733
2739
debug ! ( "suggest_await_before_try: try_trait_obligation {:?}" , try_obligation) ;
2734
2740
if self . predicate_may_hold ( & try_obligation)
0 commit comments