@@ -2,7 +2,7 @@ use crate::check::{Inherited, FnCtxt};
2
2
use crate :: constrained_generic_params:: { identify_constrained_generic_params, Parameter } ;
3
3
4
4
use crate :: hir:: def_id:: DefId ;
5
- use rustc:: traits:: { self , ObligationCauseCode } ;
5
+ use rustc:: traits:: { self , ObligationCause , ObligationCauseCode } ;
6
6
use rustc:: ty:: { self , Ty , TyCtxt , GenericParamDefKind , TypeFoldable , ToPredicate } ;
7
7
use rustc:: ty:: subst:: { Subst , InternalSubsts } ;
8
8
use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
@@ -895,6 +895,11 @@ fn receiver_is_valid<'fcx, 'tcx>(
895
895
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
896
896
autoderef. next ( ) ;
897
897
898
+ let receiver_trait_def_id = fcx. tcx . require_lang_item (
899
+ lang_items:: ReceiverTraitLangItem ,
900
+ None ,
901
+ ) ;
902
+
898
903
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
899
904
loop {
900
905
if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
@@ -911,6 +916,19 @@ fn receiver_is_valid<'fcx, 'tcx>(
911
916
}
912
917
913
918
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
+ }
914
932
}
915
933
} else {
916
934
debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
@@ -919,43 +937,42 @@ fn receiver_is_valid<'fcx, 'tcx>(
919
937
// unecessary errors (#58712).
920
938
return receiver_ty. references_error ( ) ;
921
939
}
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
- }
928
940
}
929
941
930
942
// 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
+ }
939
948
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
+ } ;
944
962
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
+ ) ;
950
968
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
956
975
}
957
-
958
- true
959
976
}
960
977
961
978
fn check_variances_for_type_defn < ' tcx > (
0 commit comments