@@ -2,7 +2,7 @@ use crate::check::{Inherited, FnCtxt};
22use crate :: constrained_generic_params:: { identify_constrained_generic_params, Parameter } ;
33
44use crate :: hir:: def_id:: DefId ;
5- use rustc:: traits:: { self , ObligationCauseCode } ;
5+ use rustc:: traits:: { self , ObligationCause , ObligationCauseCode } ;
66use rustc:: ty:: { self , Ty , TyCtxt , GenericParamDefKind , TypeFoldable , ToPredicate } ;
77use rustc:: ty:: subst:: { Subst , InternalSubsts } ;
88use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
@@ -895,6 +895,11 @@ fn receiver_is_valid<'fcx, 'tcx>(
895895 // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
896896 autoderef. next ( ) ;
897897
898+ let receiver_trait_def_id = fcx. tcx . require_lang_item (
899+ lang_items:: ReceiverTraitLangItem ,
900+ None ,
901+ ) ;
902+
898903 // Keep dereferencing `receiver_ty` until we get to `self_ty`.
899904 loop {
900905 if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
@@ -911,6 +916,19 @@ fn receiver_is_valid<'fcx, 'tcx>(
911916 }
912917
913918 break
919+ } else {
920+ // Without `feature(arbitrary_self_types)`, we require that each step in the
921+ // deref chain implement `receiver`
922+ if !arbitrary_self_types_enabled
923+ && !receiver_is_implemented (
924+ fcx,
925+ receiver_trait_def_id,
926+ cause. clone ( ) ,
927+ potential_self_ty,
928+ )
929+ {
930+ return false
931+ }
914932 }
915933 } else {
916934 debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
@@ -919,43 +937,42 @@ fn receiver_is_valid<'fcx, 'tcx>(
919937 // unecessary errors (#58712).
920938 return receiver_ty. references_error ( ) ;
921939 }
922-
923- // Without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
924- // `self_ty`. Enforce this by only doing one iteration of the loop.
925- if !arbitrary_self_types_enabled {
926- return false
927- }
928940 }
929941
930942 // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
931- if !arbitrary_self_types_enabled {
932- let trait_def_id = match fcx. tcx . lang_items ( ) . receiver_trait ( ) {
933- Some ( did) => did,
934- None => {
935- debug ! ( "receiver_is_valid: missing Receiver trait" ) ;
936- return false
937- }
938- } ;
943+ if !arbitrary_self_types_enabled
944+ && !receiver_is_implemented ( fcx, receiver_trait_def_id, cause. clone ( ) , receiver_ty)
945+ {
946+ return false
947+ }
939948
940- let trait_ref = ty:: TraitRef {
941- def_id : trait_def_id,
942- substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
943- } ;
949+ true
950+ }
951+
952+ fn receiver_is_implemented (
953+ fcx : & FnCtxt < ' _ , ' tcx > ,
954+ receiver_trait_def_id : DefId ,
955+ cause : ObligationCause < ' tcx > ,
956+ receiver_ty : Ty < ' tcx > ,
957+ ) -> bool {
958+ let trait_ref = ty:: TraitRef {
959+ def_id : receiver_trait_def_id,
960+ substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
961+ } ;
944962
945- let obligation = traits:: Obligation :: new (
946- cause,
947- fcx. param_env ,
948- trait_ref. to_predicate ( )
949- ) ;
963+ let obligation = traits:: Obligation :: new (
964+ cause,
965+ fcx. param_env ,
966+ trait_ref. to_predicate ( )
967+ ) ;
950968
951- if !fcx. predicate_must_hold_modulo_regions ( & obligation) {
952- debug ! ( "receiver_is_valid: type `{:?}` does not implement `Receiver` trait" ,
953- receiver_ty) ;
954- return false
955- }
969+ if fcx. predicate_must_hold_modulo_regions ( & obligation) {
970+ true
971+ } else {
972+ debug ! ( "receiver_is_implemented: type `{:?}` does not implement `Receiver` trait" ,
973+ receiver_ty) ;
974+ false
956975 }
957-
958- true
959976}
960977
961978fn check_variances_for_type_defn < ' tcx > (
0 commit comments