@@ -760,8 +760,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
760
760
if !receiver_is_valid ( fcx, span, receiver_ty, self_ty, true ) {
761
761
// report error, arbitrary_self_types was enabled
762
762
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" )
765
765
. help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
766
766
. code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
767
767
. emit ( ) ;
@@ -785,8 +785,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
785
785
} else {
786
786
// report error, would not have worked with arbitrary_self_types
787
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 ) )
788
+ span, & format ! ( "invalid method receiver type: {:?}" , receiver_ty)
789
+ ) . note ( "type must be `Self ` or a type that dereferences to it" )
790
790
. help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
791
791
. code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
792
792
. emit ( ) ;
@@ -800,9 +800,9 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
800
800
/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
801
801
/// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref<Target=self_ty>`.
802
802
///
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 ,
804
804
/// 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.
806
806
fn receiver_is_valid < ' fcx , ' tcx , ' gcx > (
807
807
fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
808
808
span : Span ,
@@ -814,6 +814,7 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
814
814
815
815
let can_eq_self = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
816
816
817
+ // `self: Self` is always valid
817
818
if can_eq_self ( receiver_ty) {
818
819
if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, receiver_ty) {
819
820
err. emit ( ) ;
@@ -823,96 +824,72 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
823
824
824
825
let mut autoderef = fcx. autoderef ( span, receiver_ty) ;
825
826
827
+ // the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`
826
828
if arbitrary_self_types_enabled {
827
829
autoderef = autoderef. include_raw_pointers ( ) ;
828
830
}
829
831
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.
831
833
autoderef. next ( ) ;
832
834
833
- let potential_self_ty = loop {
835
+ // keep dereferencing `receiver_ty` until we get to `self_ty`
836
+ loop {
834
837
if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
835
838
debug ! ( "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
836
839
potential_self_ty, self_ty) ;
837
840
838
841
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
840
851
}
841
852
} else {
842
853
debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" ,
843
854
receiver_ty, self_ty) ;
844
855
return false
845
856
}
846
- } ;
847
857
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
+ }
850
864
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 ( ) {
852
868
Some ( did) => did,
853
869
None => {
854
870
debug ! ( "receiver_is_valid: missing Receiver trait" ) ;
855
871
return false
856
872
}
857
873
} ;
858
874
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 ,
861
877
substs : fcx. tcx . mk_substs_trait ( receiver_ty, & [ ] ) ,
862
878
} ;
863
879
864
- let receiver_obligation = traits:: Obligation :: new (
880
+ let obligation = traits:: Obligation :: new (
865
881
cause. clone ( ) ,
866
882
fcx. param_env ,
867
- receiver_trait_ref . to_predicate ( )
883
+ trait_ref . to_predicate ( )
868
884
) ;
869
885
870
- if !fcx. predicate_must_hold ( & receiver_obligation ) {
886
+ if !fcx. predicate_must_hold ( & obligation ) {
871
887
debug ! ( "receiver_is_valid: type `{:?}` does not implement `Receiver` trait" ,
872
888
receiver_ty) ;
873
889
return false
874
890
}
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 ( ) ;
912
891
}
913
892
914
- autoderef. finalize ( fcx) ;
915
-
916
893
true
917
894
}
918
895
0 commit comments