@@ -760,8 +760,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
760760 if !receiver_is_valid ( fcx, span, receiver_ty, self_ty, true ) {
761761 // report error, arbitrary_self_types was enabled
762762 fcx. tcx . sess . diagnostic ( ) . mut_span_err (
763- span, & format ! ( "invalid `self` type: {:?}" , receiver_ty)
764- ) . note ( & format ! ( "type must be `{:?} ` or a type that dereferences to it" , self_ty ) )
763+ span, & format ! ( "invalid method receiver type: {:?}" , receiver_ty)
764+ ) . note ( "type of `self` must be `Self ` or a type that dereferences to it" )
765765 . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
766766 . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
767767 . emit ( ) ;
@@ -785,8 +785,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
785785 } else {
786786 // report error, would not have worked with arbitrary_self_types
787787 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 ) )
788+ span, & format ! ( "invalid method receiver type: {:?}" , receiver_ty)
789+ ) . note ( "type must be `Self ` or a type that dereferences to it" )
790790 . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
791791 . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
792792 . emit ( ) ;
@@ -800,9 +800,9 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
800800/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
801801/// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref<Target=self_ty>`.
802802///
803- /// NB: there are cases this function returns `true` but then causes an error to be raised later ,
803+ /// NB: there are cases this function returns `true` but causes an error to be emitted ,
804804/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
805- /// wrong lifetime.
805+ /// wrong lifetime. Be careful of this if you are calling this function speculatively.
806806fn receiver_is_valid < ' fcx , ' tcx , ' gcx > (
807807 fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
808808 span : Span ,
@@ -814,6 +814,7 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
814814
815815 let can_eq_self = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
816816
817+ // `self: Self` is always valid
817818 if can_eq_self ( receiver_ty) {
818819 if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, receiver_ty) {
819820 err. emit ( ) ;
@@ -823,96 +824,72 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
823824
824825 let mut autoderef = fcx. autoderef ( span, receiver_ty) ;
825826
827+ // the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`
826828 if arbitrary_self_types_enabled {
827829 autoderef = autoderef. include_raw_pointers ( ) ;
828830 }
829831
830- // skip the first type, we know its not equal to `self_ty`
832+ // the first type is `receiver_ty`, which we know its not equal to `self_ty`. skip it.
831833 autoderef. next ( ) ;
832834
833- let potential_self_ty = loop {
835+ // keep dereferencing `receiver_ty` until we get to `self_ty`
836+ loop {
834837 if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
835838 debug ! ( "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
836839 potential_self_ty, self_ty) ;
837840
838841 if can_eq_self ( potential_self_ty) {
839- break potential_self_ty
842+ autoderef. finalize ( fcx) ;
843+
844+ if let Some ( mut err) = fcx. demand_eqtype_with_origin (
845+ & cause, self_ty, potential_self_ty
846+ ) {
847+ err. emit ( ) ;
848+ }
849+
850+ break
840851 }
841852 } else {
842853 debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
843854 receiver_ty, self_ty) ;
844855 return false
845856 }
846- } ;
847857
848- if !arbitrary_self_types_enabled {
849- // check that receiver_ty: Receiver<Target=self_ty>
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
862+ }
863+ }
850864
851- let receiver_trait_def_id = match fcx. tcx . lang_items ( ) . receiver_trait ( ) {
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 ( ) {
852868 Some ( did) => did,
853869 None => {
854870 debug ! ( "receiver_is_valid: missing Receiver trait" ) ;
855871 return false
856872 }
857873 } ;
858874
859- let receiver_trait_ref = ty:: TraitRef {
860- def_id : receiver_trait_def_id ,
875+ let trait_ref = ty:: TraitRef {
876+ def_id : trait_def_id ,
861877 substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
862878 } ;
863879
864- let receiver_obligation = traits:: Obligation :: new (
880+ let obligation = traits:: Obligation :: new (
865881 cause. clone ( ) ,
866882 fcx. param_env ,
867- receiver_trait_ref . to_predicate ( )
883+ trait_ref . to_predicate ( )
868884 ) ;
869885
870- if !fcx. predicate_must_hold ( & receiver_obligation ) {
886+ if !fcx. predicate_must_hold ( & obligation ) {
871887 debug ! ( "receiver_is_valid: type `{:?}` does not implement `Receiver` trait" ,
872888 receiver_ty) ;
873889 return false
874890 }
875-
876- let deref_trait_def_id = match fcx. tcx . lang_items ( ) . deref_trait ( ) {
877- Some ( did) => did,
878- None => {
879- debug ! ( "receiver_is_valid: missing Deref trait" ) ;
880- return false
881- }
882- } ;
883-
884- let deref_trait_ref = ty:: TraitRef {
885- def_id : deref_trait_def_id,
886- substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
887- } ;
888-
889- let projection_ty = ty:: ProjectionTy :: from_ref_and_name (
890- fcx. tcx , deref_trait_ref, ast:: Ident :: from_str ( "Target" )
891- ) ;
892-
893- let projection_predicate = ty:: Binder :: dummy ( ty:: ProjectionPredicate {
894- projection_ty, ty : self_ty
895- } ) . to_predicate ( ) ;
896-
897- let deref_obligation = traits:: Obligation :: new (
898- cause. clone ( ) ,
899- fcx. param_env ,
900- projection_predicate,
901- ) ;
902-
903- if !fcx. predicate_must_hold ( & deref_obligation) {
904- debug ! ( "receiver_is_valid: type `{:?}` does not directly deref to `{:?}`" ,
905- receiver_ty, self_ty) ;
906- return false
907- }
908- }
909-
910- if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, potential_self_ty) {
911- err. emit ( ) ;
912891 }
913892
914- autoderef. finalize ( fcx) ;
915-
916893 true
917894}
918895
0 commit comments