@@ -637,8 +637,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
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
+ 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) ;
642
644
Some ( steps) . filter ( |_| self . predicate_may_hold ( & obligation) )
643
645
} ) {
644
646
if steps > 0 {
@@ -659,10 +661,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
659
661
}
660
662
} else if real_trait_pred != trait_pred {
661
663
// 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) ) ;
662
666
let obligation = self . mk_trait_obligation_with_new_self_ty (
663
667
param_env,
664
- real_trait_pred,
665
- base_ty,
668
+ real_trait_pred_and_base_ty,
666
669
) ;
667
670
if self . predicate_may_hold ( & obligation) {
668
671
err. span_suggestion_verbose (
@@ -720,9 +723,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
720
723
err : & mut Diagnostic ,
721
724
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
722
725
) -> 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 ( ) ;
726
727
727
728
let ( def_id, output_ty, callable) = match * self_ty. kind ( ) {
728
729
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> {
731
732
} ;
732
733
let msg = format ! ( "use parentheses to call the {}" , callable) ;
733
734
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) ) ;
739
738
740
739
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 ) ;
742
741
743
742
match self . evaluate_obligation ( & new_obligation) {
744
743
Ok (
@@ -842,96 +841,102 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
842
841
let param_env = obligation. param_env ;
843
842
844
843
// 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
+ } ) ;
851
862
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( ) ,
895
883
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) ;
918
887
} 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 ) ] ;
928
890
}
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 ;
929
936
}
930
- return true ;
931
937
}
932
- }
933
- return false ;
934
- } ;
938
+ return false ;
939
+ } ;
935
940
936
941
if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
937
942
try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
@@ -992,20 +997,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
992
997
return false ;
993
998
}
994
999
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 ( ) ;
998
1002
999
1003
for refs_remaining in 0 ..refs_number {
1000
1004
let ty:: Ref ( _, inner_ty, _) = suggested_ty. kind ( ) else {
1001
1005
break ;
1002
1006
} ;
1003
1007
suggested_ty = * inner_ty;
1004
1008
1009
+ // We remap bounds here
1010
+ let trait_pred_and_suggested_ty =
1011
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1012
+
1005
1013
let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1006
1014
obligation. param_env ,
1007
- trait_pred,
1008
- suggested_ty,
1015
+ trait_pred_and_suggested_ty,
1009
1016
) ;
1010
1017
1011
1018
if self . predicate_may_hold ( & new_obligation) {
@@ -1141,10 +1148,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1141
1148
hir:: Mutability :: Not => self . tcx . mk_mut_ref ( region, t_type) ,
1142
1149
} ;
1143
1150
1151
+ let trait_pred_and_suggested_ty =
1152
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, suggested_ty) ) ;
1153
+
1144
1154
let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1145
1155
obligation. param_env ,
1146
- trait_pred,
1147
- suggested_ty,
1156
+ trait_pred_and_suggested_ty,
1148
1157
) ;
1149
1158
let suggested_ty_would_satisfy_obligation = self
1150
1159
. evaluate_obligation_no_overflow ( & new_obligation)
@@ -1195,7 +1204,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1195
1204
// Only suggest this if the expression behind the semicolon implements the predicate
1196
1205
&& let Some ( typeck_results) = self . in_progress_typeck_results
1197
1206
&& 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
+ ) )
1199
1210
{
1200
1211
err. span_label (
1201
1212
expr. span ,
@@ -2727,8 +2738,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
2727
2738
) ;
2728
2739
let try_obligation = self . mk_trait_obligation_with_new_self_ty (
2729
2740
obligation. param_env ,
2730
- trait_pred,
2731
- normalized_ty. ty ( ) . unwrap ( ) ,
2741
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, normalized_ty. ty ( ) . unwrap ( ) ) ) ,
2732
2742
) ;
2733
2743
debug ! ( "suggest_await_before_try: try_trait_obligation {:?}" , try_obligation) ;
2734
2744
if self . predicate_may_hold ( & try_obligation)
0 commit comments