@@ -908,111 +908,113 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
908908 let param_env = obligation. param_env ;
909909
910910 // 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+ } ) ;
930929
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) ;
938937
939- let ref_inner_ty_result =
938+ let ( ref_inner_ty_satisfies_pred , ref_inner_ty_mut ) =
940939 if let ObligationCauseCode :: ItemObligation ( _) = obligation. cause . code ( )
941940 && let ty:: Ref ( _, ty, mutability) = old_pred. self_ty ( ) . skip_binder ( ) . kind ( )
942941 {
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+ )
944946 } else {
945- None
947+ ( false , false )
946948 } ;
947949
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) ;
995964 } 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 ) ] ;
1009967 }
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 ;
10101014 }
1011- return true ;
10121015 }
1013- }
1014- return false ;
1015- } ;
1016+ return false ;
1017+ } ;
10161018
10171019 if let ObligationCauseCode :: ImplDerivedObligation ( cause) = & * code {
10181020 try_borrowing ( cause. derived . parent_trait_pred , & [ ] )
0 commit comments