@@ -908,111 +908,113 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
908
908
let param_env = obligation. param_env ;
909
909
910
910
// Try to apply the original trait binding obligation by borrowing.
911
- let mut try_borrowing = |old_pred : ty:: PolyTraitPredicate < ' tcx > ,
912
- blacklist : & [ DefId ] |
913
- -> bool {
914
- if blacklist. contains ( & old_pred. def_id ( ) ) {
915
- return false ;
916
- }
917
- // We map bounds to `&T` and `&mut T`
918
- let trait_pred_and_imm_ref = old_pred. map_bound ( |trait_pred| {
919
- (
920
- trait_pred,
921
- self . tcx . mk_imm_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
922
- )
923
- } ) ;
924
- let trait_pred_and_mut_ref = old_pred. map_bound ( |trait_pred| {
925
- (
926
- trait_pred,
927
- self . tcx . mk_mut_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
928
- )
929
- } ) ;
911
+ let mut try_borrowing =
912
+ |old_pred : ty:: PolyTraitPredicate < ' tcx > , blacklist : & [ DefId ] | -> bool {
913
+ if blacklist. contains ( & old_pred. def_id ( ) ) {
914
+ return false ;
915
+ }
916
+ // We map bounds to `&T` and `&mut T`
917
+ let trait_pred_and_imm_ref = old_pred. map_bound ( |trait_pred| {
918
+ (
919
+ trait_pred,
920
+ self . tcx . mk_imm_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
921
+ )
922
+ } ) ;
923
+ let trait_pred_and_mut_ref = old_pred. map_bound ( |trait_pred| {
924
+ (
925
+ trait_pred,
926
+ self . tcx . mk_mut_ref ( self . tcx . lifetimes . re_static , trait_pred. self_ty ( ) ) ,
927
+ )
928
+ } ) ;
930
929
931
- let mk_result = |trait_pred_and_new_ty| {
932
- let obligation =
933
- self . mk_trait_obligation_with_new_self_ty ( param_env, trait_pred_and_new_ty) ;
934
- self . predicate_must_hold_modulo_regions ( & obligation)
935
- } ;
936
- let imm_result = mk_result ( trait_pred_and_imm_ref) ;
937
- let mut_result = mk_result ( trait_pred_and_mut_ref) ;
930
+ let mk_result = |trait_pred_and_new_ty| {
931
+ let obligation =
932
+ self . mk_trait_obligation_with_new_self_ty ( param_env, trait_pred_and_new_ty) ;
933
+ self . predicate_must_hold_modulo_regions ( & obligation)
934
+ } ;
935
+ let imm_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_imm_ref) ;
936
+ let mut_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_mut_ref) ;
938
937
939
- let ref_inner_ty_result =
938
+ let ( ref_inner_ty_satisfies_pred , ref_inner_ty_mut ) =
940
939
if let ObligationCauseCode :: ItemObligation ( _) = obligation. cause . code ( )
941
940
&& let ty:: Ref ( _, ty, mutability) = old_pred. self_ty ( ) . skip_binder ( ) . kind ( )
942
941
{
943
- Some ( ( mk_result ( old_pred. map_bound ( |trait_pred| ( trait_pred, * ty) ) ) , mutability) )
942
+ (
943
+ mk_result ( old_pred. map_bound ( |trait_pred| ( trait_pred, * ty) ) ) ,
944
+ matches ! ( mutability, hir:: Mutability :: Mut ) ,
945
+ )
944
946
} else {
945
- None
947
+ ( false , false )
946
948
} ;
947
949
948
- if imm_result || mut_result || ref_inner_ty_result. map_or ( false , |( result, _) | result) {
949
- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
950
- // We have a very specific type of error, where just borrowing this argument
951
- // might solve the problem. In cases like this, the important part is the
952
- // original type obligation, not the last one that failed, which is arbitrary.
953
- // Because of this, we modify the error to refer to the original obligation and
954
- // return early in the caller.
955
-
956
- let msg = format ! ( "the trait bound `{}` is not satisfied" , old_pred) ;
957
- if has_custom_message {
958
- err. note ( & msg) ;
959
- } else {
960
- err. message =
961
- vec ! [ ( rustc_errors:: DiagnosticMessage :: Str ( msg) , Style :: NoStyle ) ] ;
962
- }
963
- if snippet. starts_with ( '&' ) {
964
- // This is already a literal borrow and the obligation is failing
965
- // somewhere else in the obligation chain. Do not suggest non-sense.
966
- return false ;
967
- }
968
- err. span_label (
969
- span,
970
- & format ! (
971
- "expected an implementor of trait `{}`" ,
972
- old_pred. print_modifiers_and_trait_path( ) ,
973
- ) ,
974
- ) ;
975
-
976
- // This if is to prevent a special edge-case
977
- if matches ! (
978
- span. ctxt( ) . outer_expn_data( ) . kind,
979
- ExpnKind :: Root | ExpnKind :: Desugaring ( DesugaringKind :: ForLoop )
980
- ) {
981
- // We don't want a borrowing suggestion on the fields in structs,
982
- // ```
983
- // struct Foo {
984
- // the_foos: Vec<Foo>
985
- // }
986
- // ```
987
-
988
- if imm_result && mut_result {
989
- err. span_suggestions (
990
- span. shrink_to_lo ( ) ,
991
- "consider borrowing here" ,
992
- [ "&" . to_string ( ) , "&mut " . to_string ( ) ] . into_iter ( ) ,
993
- Applicability :: MaybeIncorrect ,
994
- ) ;
950
+ if imm_ref_self_ty_satisfies_pred
951
+ || mut_ref_self_ty_satisfies_pred
952
+ || ref_inner_ty_satisfies_pred
953
+ {
954
+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
955
+ // We have a very specific type of error, where just borrowing this argument
956
+ // might solve the problem. In cases like this, the important part is the
957
+ // original type obligation, not the last one that failed, which is arbitrary.
958
+ // Because of this, we modify the error to refer to the original obligation and
959
+ // return early in the caller.
960
+
961
+ let msg = format ! ( "the trait bound `{}` is not satisfied" , old_pred) ;
962
+ if has_custom_message {
963
+ err. note ( & msg) ;
995
964
} else {
996
- let is_mut = mut_result
997
- || ref_inner_ty_result. map_or ( false , |( _, mutabl) | {
998
- matches ! ( mutabl, hir:: Mutability :: Mut )
999
- } ) ;
1000
- err. span_suggestion_verbose (
1001
- span. shrink_to_lo ( ) ,
1002
- & format ! (
1003
- "consider{} borrowing here" ,
1004
- if is_mut { " mutably" } else { "" }
1005
- ) ,
1006
- format ! ( "&{}" , if is_mut { "mut " } else { "" } ) ,
1007
- Applicability :: MaybeIncorrect ,
1008
- ) ;
965
+ err. message =
966
+ vec ! [ ( rustc_errors:: DiagnosticMessage :: Str ( msg) , Style :: NoStyle ) ] ;
1009
967
}
968
+ if snippet. starts_with ( '&' ) {
969
+ // This is already a literal borrow and the obligation is failing
970
+ // somewhere else in the obligation chain. Do not suggest non-sense.
971
+ return false ;
972
+ }
973
+ err. span_label (
974
+ span,
975
+ & format ! (
976
+ "expected an implementor of trait `{}`" ,
977
+ old_pred. print_modifiers_and_trait_path( ) ,
978
+ ) ,
979
+ ) ;
980
+
981
+ // This if is to prevent a special edge-case
982
+ if matches ! (
983
+ span. ctxt( ) . outer_expn_data( ) . kind,
984
+ ExpnKind :: Root | ExpnKind :: Desugaring ( DesugaringKind :: ForLoop )
985
+ ) {
986
+ // We don't want a borrowing suggestion on the fields in structs,
987
+ // ```
988
+ // struct Foo {
989
+ // the_foos: Vec<Foo>
990
+ // }
991
+ // ```
992
+
993
+ if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
994
+ err. span_suggestions (
995
+ span. shrink_to_lo ( ) ,
996
+ "consider borrowing here" ,
997
+ [ "&" . to_string ( ) , "&mut " . to_string ( ) ] . into_iter ( ) ,
998
+ Applicability :: MaybeIncorrect ,
999
+ ) ;
1000
+ } else {
1001
+ let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
1002
+ err. span_suggestion_verbose (
1003
+ span. shrink_to_lo ( ) ,
1004
+ & format ! (
1005
+ "consider{} borrowing here" ,
1006
+ if is_mut { " mutably" } else { "" }
1007
+ ) ,
1008
+ format ! ( "&{}" , if is_mut { "mut " } else { "" } ) ,
1009
+ Applicability :: MaybeIncorrect ,
1010
+ ) ;
1011
+ }
1012
+ }
1013
+ return true ;
1010
1014
}
1011
- return true ;
1012
1015
}
1013
- }
1014
- return false ;
1015
- } ;
1016
+ return false ;
1017
+ } ;
1016
1018
1017
1019
if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
1018
1020
try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
0 commit comments