@@ -13,9 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
1313
1414use hir:: def_id:: DefId ;
1515use 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 } ;
1717use rustc:: ty:: subst:: { Subst , Substs } ;
18- use rustc:: ty:: util:: ExplicitSelf ;
1918use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
2019use rustc:: middle:: lang_items;
2120use rustc:: infer:: opaque_types:: may_define_existential_type;
@@ -749,72 +748,149 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
749748 & ty:: Binder :: bind ( self_ty)
750749 ) ;
751750
752- let self_arg_ty = sig. inputs ( ) [ 0 ] ;
751+ let receiver_ty = sig. inputs ( ) [ 0 ] ;
753752
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 (
757755 method. def_id ,
758- & ty:: Binder :: bind ( self_arg_ty )
756+ & ty:: Binder :: bind ( receiver_ty )
759757 ) ;
760758
761- let mut autoderef = fcx. autoderef ( span, self_arg_ty) . include_raw_pointers ( ) ;
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
762+ fcx. tcx . sess . diagnostic ( ) . mut_span_err (
763+ span, & format ! ( "invalid method receiver type: {:?}" , receiver_ty)
764+ ) . note ( "type of `self` must be `Self` or a type that dereferences to it" )
765+ . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
766+ . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
767+ . emit ( ) ;
768+ }
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
773+ feature_gate:: feature_err (
774+ & fcx. tcx . sess . parse_sess ,
775+ "arbitrary_self_types" ,
776+ span,
777+ GateIssue :: Language ,
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 method receiver type: {:?}" , receiver_ty)
789+ ) . note ( "type must be `Self` or a type that dereferences to it" )
790+ . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
791+ . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
792+ . emit ( ) ;
793+ }
794+ }
795+ }
796+ }
797+
798+ /// returns true if `receiver_ty` would be considered a valid receiver type for `self_ty`. If
799+ /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
800+ /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
801+ /// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref<Target=self_ty>`.
802+ ///
803+ /// NB: there are cases this function returns `true` but causes an error to be emitted,
804+ /// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
805+ /// wrong lifetime. Be careful of this if you are calling this function speculatively.
806+ fn receiver_is_valid < ' fcx , ' tcx , ' gcx > (
807+ fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
808+ span : Span ,
809+ receiver_ty : Ty < ' tcx > ,
810+ self_ty : Ty < ' tcx > ,
811+ arbitrary_self_types_enabled : bool ,
812+ ) -> bool {
813+ let cause = fcx. cause ( span, traits:: ObligationCauseCode :: MethodReceiver ) ;
814+
815+ let can_eq_self = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
816+
817+ // `self: Self` is always valid
818+ if can_eq_self ( receiver_ty) {
819+ if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, receiver_ty) {
820+ err. emit ( ) ;
821+ }
822+ return true
823+ }
824+
825+ let mut autoderef = fcx. autoderef ( span, receiver_ty) ;
826+
827+ // the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`
828+ if arbitrary_self_types_enabled {
829+ autoderef = autoderef. include_raw_pointers ( ) ;
830+ }
831+
832+ // the first type is `receiver_ty`, which we know its not equal to `self_ty`. skip it.
833+ autoderef. next ( ) ;
762834
835+ // keep dereferencing `receiver_ty` until we get to `self_ty`
763836 loop {
764837 if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
765- debug ! ( "check_method_receiver : potential self type `{:?}` to match `{:?}`" ,
838+ debug ! ( "receiver_is_valid : potential self type `{:?}` to match `{:?}`" ,
766839 potential_self_ty, self_ty) ;
767840
768- if fcx . infcx . can_eq ( fcx . param_env , self_ty , potential_self_ty) . is_ok ( ) {
841+ if can_eq_self ( potential_self_ty) {
769842 autoderef. finalize ( fcx) ;
843+
770844 if let Some ( mut err) = fcx. demand_eqtype_with_origin (
771- & cause, self_ty, potential_self_ty) {
845+ & cause, self_ty, potential_self_ty
846+ ) {
772847 err. emit ( ) ;
773848 }
849+
774850 break
775851 }
776852 } else {
777- 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) )
780- . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
781- . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
782- . emit ( ) ;
783- return
853+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
854+ receiver_ty, self_ty) ;
855+ return false
856+ }
857+
858+ // without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
859+ // `self_ty`. Enforce this by only doing one iteration of the loop
860+ if !arbitrary_self_types_enabled {
861+ return false
784862 }
785863 }
786864
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) ;
865+ // without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`
866+ if !arbitrary_self_types_enabled {
867+ let trait_def_id = match fcx. tcx . lang_items ( ) . receiver_trait ( ) {
868+ Some ( did) => did,
869+ None => {
870+ debug ! ( "receiver_is_valid: missing Receiver trait" ) ;
871+ return false
872+ }
873+ } ;
789874
790- if !fcx. tcx . features ( ) . arbitrary_self_types {
791- match self_kind {
792- ExplicitSelf :: ByValue |
793- ExplicitSelf :: ByReference ( _, _) |
794- ExplicitSelf :: ByBox => ( ) ,
875+ let trait_ref = ty:: TraitRef {
876+ def_id : trait_def_id,
877+ substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
878+ } ;
795879
796- ExplicitSelf :: ByRawPointer ( _) => {
797- feature_gate:: feature_err (
798- & fcx. tcx . sess . parse_sess ,
799- "arbitrary_self_types" ,
800- span,
801- GateIssue :: Language ,
802- "raw pointer `self` is unstable" )
803- . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
804- . emit ( ) ;
805- }
880+ let obligation = traits:: Obligation :: new (
881+ cause. clone ( ) ,
882+ fcx. param_env ,
883+ trait_ref. to_predicate ( )
884+ ) ;
806885
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 ( ) ;
815- }
886+ if !fcx. predicate_must_hold ( & obligation) {
887+ debug ! ( "receiver_is_valid: type `{:?}` does not implement `Receiver` trait" ,
888+ receiver_ty) ;
889+ return false
816890 }
817891 }
892+
893+ true
818894}
819895
820896fn check_variances_for_type_defn < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
0 commit comments