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