@@ -13,9 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
13
13
14
14
use hir:: def_id:: DefId ;
15
15
use rustc:: traits:: { self , ObligationCauseCode } ;
16
- use rustc:: ty:: { self , Lift , Ty , TyCtxt , TyKind , GenericParamDefKind , TypeFoldable } ;
16
+ use rustc:: ty:: { self , Lift , Ty , TyCtxt , TyKind , GenericParamDefKind , TypeFoldable , ToPredicate } ;
17
17
use rustc:: ty:: subst:: { Subst , Substs } ;
18
- use rustc:: ty:: util:: ExplicitSelf ;
19
18
use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
20
19
use rustc:: middle:: lang_items;
21
20
use rustc:: infer:: opaque_types:: may_define_existential_type;
@@ -749,72 +748,164 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
749
748
& ty:: Binder :: bind ( self_ty)
750
749
) ;
751
750
752
- let self_arg_ty = sig. inputs ( ) [ 0 ] ;
751
+ let receiver_ty = sig. inputs ( ) [ 0 ] ;
753
752
754
- let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
755
- let self_arg_ty = fcx. normalize_associated_types_in ( span, & self_arg_ty) ;
756
- let self_arg_ty = fcx. tcx . liberate_late_bound_regions (
753
+ let receiver_ty = fcx. normalize_associated_types_in ( span, & receiver_ty) ;
754
+ let receiver_ty = fcx. tcx . liberate_late_bound_regions (
757
755
method. def_id ,
758
- & ty:: Binder :: bind ( self_arg_ty )
756
+ & ty:: Binder :: bind ( receiver_ty )
759
757
) ;
760
758
761
- let mut autoderef = fcx. autoderef ( span, self_arg_ty) . include_raw_pointers ( ) ;
762
-
763
- loop {
764
- if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
765
- debug ! ( "check_method_receiver: potential self type `{:?}` to match `{:?}`" ,
766
- potential_self_ty, self_ty) ;
767
-
768
- if fcx. infcx . can_eq ( fcx. param_env , self_ty, potential_self_ty) . is_ok ( ) {
769
- autoderef. finalize ( fcx) ;
770
- if let Some ( mut err) = fcx. demand_eqtype_with_origin (
771
- & cause, self_ty, potential_self_ty) {
772
- err. emit ( ) ;
773
- }
774
- break
775
- }
776
- } else {
759
+ if fcx. tcx . features ( ) . arbitrary_self_types {
760
+ if !receiver_is_valid ( fcx, span, receiver_ty, self_ty, true ) {
761
+ // report error, arbitrary_self_types was enabled
777
762
fcx. tcx . sess . diagnostic ( ) . mut_span_err (
778
- span, & format ! ( "invalid `self` type: {:?}" , self_arg_ty ) )
779
- . note ( & format ! ( "type must be `{:?}` or a type that dereferences to it" , self_ty) )
763
+ span, & format ! ( "invalid `self` type: {:?}" , receiver_ty )
764
+ ) . note ( & format ! ( "type must be `{:?}` or a type that dereferences to it" , self_ty) )
780
765
. help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
781
766
. code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
782
767
. emit ( ) ;
783
- return
784
768
}
785
- }
786
-
787
- let is_self_ty = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
788
- let self_kind = ExplicitSelf :: determine ( self_arg_ty, is_self_ty) ;
789
-
790
- if !fcx. tcx . features ( ) . arbitrary_self_types {
791
- match self_kind {
792
- ExplicitSelf :: ByValue |
793
- ExplicitSelf :: ByReference ( _, _) |
794
- ExplicitSelf :: ByBox => ( ) ,
795
-
796
- ExplicitSelf :: ByRawPointer ( _) => {
769
+ } else {
770
+ if !receiver_is_valid ( fcx, span, receiver_ty, self_ty, false ) {
771
+ if receiver_is_valid ( fcx, span, receiver_ty, self_ty, true ) {
772
+ // report error, would have worked with arbitrary_self_types
797
773
feature_gate:: feature_err (
798
774
& fcx. tcx . sess . parse_sess ,
799
775
"arbitrary_self_types" ,
800
776
span,
801
777
GateIssue :: Language ,
802
- "raw pointer `self` is unstable" )
778
+ & format ! (
779
+ "`{}` cannot be used as the type of `self` without \
780
+ the `arbitrary_self_types` feature",
781
+ receiver_ty,
782
+ ) ,
783
+ ) . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
784
+ . emit ( ) ;
785
+ } else {
786
+ // report error, would not have worked with arbitrary_self_types
787
+ fcx. tcx . sess . diagnostic ( ) . mut_span_err (
788
+ span, & format ! ( "invalid `self` type: {:?}" , receiver_ty)
789
+ ) . note ( & format ! ( "type must be `{:?}` or a type that dereferences to it" , self_ty) )
803
790
. help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
791
+ . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
804
792
. emit ( ) ;
805
793
}
794
+ }
795
+ }
796
+ }
806
797
807
- ExplicitSelf :: Other => {
808
- feature_gate:: feature_err (
809
- & fcx. tcx . sess . parse_sess ,
810
- "arbitrary_self_types" ,
811
- span,
812
- GateIssue :: Language , "arbitrary `self` types are unstable" )
813
- . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
814
- . emit ( ) ;
798
+ fn receiver_is_valid < ' fcx , ' tcx , ' gcx > (
799
+ fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
800
+ span : Span ,
801
+ receiver_ty : Ty < ' tcx > ,
802
+ self_ty : Ty < ' tcx > ,
803
+ arbitrary_self_types_enabled : bool ,
804
+ ) -> bool {
805
+ let cause = fcx. cause ( span, traits:: ObligationCauseCode :: MethodReceiver ) ;
806
+
807
+ let can_eq_self = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
808
+
809
+ if can_eq_self ( receiver_ty) {
810
+ if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, receiver_ty) {
811
+ err. emit ( ) ;
812
+ }
813
+ return true
814
+ }
815
+
816
+ let mut autoderef = fcx. autoderef ( span, receiver_ty) ;
817
+
818
+ if arbitrary_self_types_enabled {
819
+ autoderef = autoderef. include_raw_pointers ( ) ;
820
+ }
821
+
822
+ // skip the first type, we know its not equal to `self_ty`
823
+ autoderef. next ( ) ;
824
+
825
+ let potential_self_ty = loop {
826
+ if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
827
+ debug ! ( "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
828
+ potential_self_ty, self_ty) ;
829
+
830
+ if can_eq_self ( potential_self_ty) {
831
+ break potential_self_ty
832
+ }
833
+ } else {
834
+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
835
+ receiver_ty, self_ty) ;
836
+ return false
837
+ }
838
+ } ;
839
+
840
+ if !arbitrary_self_types_enabled {
841
+ // check that receiver_ty: Receiver<Target=self_ty>
842
+
843
+ let receiver_trait_def_id = match fcx. tcx . lang_items ( ) . receiver_trait ( ) {
844
+ Some ( did) => did,
845
+ None => {
846
+ debug ! ( "receiver_is_valid: missing Receiver trait" ) ;
847
+ return false
815
848
}
849
+ } ;
850
+
851
+ let receiver_trait_ref = ty:: TraitRef {
852
+ def_id : receiver_trait_def_id,
853
+ substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
854
+ } ;
855
+
856
+ let receiver_obligation = traits:: Obligation :: new (
857
+ cause. clone ( ) ,
858
+ fcx. param_env ,
859
+ receiver_trait_ref. to_predicate ( )
860
+ ) ;
861
+
862
+ if !fcx. predicate_must_hold ( & receiver_obligation) {
863
+ debug ! ( "receiver_is_valid: type `{:?}` does not implement `Receiver` trait" ,
864
+ receiver_ty) ;
865
+ return false
866
+ }
867
+
868
+ let deref_trait_def_id = match fcx. tcx . lang_items ( ) . deref_trait ( ) {
869
+ Some ( did) => did,
870
+ None => {
871
+ debug ! ( "receiver_is_valid: missing Deref trait" ) ;
872
+ return false
873
+ }
874
+ } ;
875
+
876
+ let deref_trait_ref = ty:: TraitRef {
877
+ def_id : deref_trait_def_id,
878
+ substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
879
+ } ;
880
+
881
+ let projection_ty = ty:: ProjectionTy :: from_ref_and_name (
882
+ fcx. tcx , deref_trait_ref, ast:: Ident :: from_str ( "Target" )
883
+ ) ;
884
+
885
+ let projection_predicate = ty:: Binder :: dummy ( ty:: ProjectionPredicate {
886
+ projection_ty, ty : self_ty
887
+ } ) . to_predicate ( ) ;
888
+
889
+ let deref_obligation = traits:: Obligation :: new (
890
+ cause. clone ( ) ,
891
+ fcx. param_env ,
892
+ projection_predicate,
893
+ ) ;
894
+
895
+ if !fcx. predicate_must_hold ( & deref_obligation) {
896
+ debug ! ( "receiver_is_valid: type `{:?}` does not directly deref to `{:?}`" ,
897
+ receiver_ty, self_ty) ;
898
+ return false
816
899
}
817
900
}
901
+
902
+ if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, potential_self_ty) {
903
+ err. emit ( ) ;
904
+ }
905
+
906
+ autoderef. finalize ( fcx) ;
907
+
908
+ true
818
909
}
819
910
820
911
fn check_variances_for_type_defn < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
0 commit comments