@@ -12,17 +12,16 @@ use super::elaborate;
12
12
13
13
use crate :: infer:: TyCtxtInferExt ;
14
14
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
15
- use crate :: traits:: { Obligation , ObligationCause } ;
15
+ use crate :: traits:: { util , Obligation , ObligationCause } ;
16
16
use rustc_errors:: FatalError ;
17
17
use rustc_hir as hir;
18
18
use rustc_hir:: def_id:: DefId ;
19
19
use rustc_middle:: query:: Providers ;
20
- use rustc_middle:: ty:: GenericArgs ;
21
20
use rustc_middle:: ty:: {
22
- self , EarlyBinder , ExistentialPredicateStableCmpExt as _, Ty , TyCtxt , TypeSuperVisitable ,
23
- TypeVisitable , TypeVisitor ,
21
+ self , EarlyBinder , ExistentialPredicateStableCmpExt as _, GenericArgs , Ty , TyCtxt ,
22
+ TypeFoldable , TypeFolder , TypeSuperFoldable , TypeSuperVisitable , TypeVisitable ,
23
+ TypeVisitableExt , TypeVisitor , Upcast ,
24
24
} ;
25
- use rustc_middle:: ty:: { TypeVisitableExt , Upcast } ;
26
25
use rustc_span:: symbol:: Symbol ;
27
26
use rustc_span:: Span ;
28
27
use rustc_target:: abi:: Abi ;
@@ -738,129 +737,174 @@ enum AllowSelfProjections {
738
737
No ,
739
738
}
740
739
740
+ /// This is somewhat subtle. In general, we want to forbid
741
+ /// references to `Self` in the argument and return types,
742
+ /// since the value of `Self` is erased. However, there is one
743
+ /// exception: it is ok to reference `Self` in order to access
744
+ /// an associated type of the current trait, since we retain
745
+ /// the value of those associated types in the object type
746
+ /// itself.
747
+ ///
748
+ /// ```rust,ignore (example)
749
+ /// trait SuperTrait {
750
+ /// type X;
751
+ /// }
752
+ ///
753
+ /// trait Trait : SuperTrait {
754
+ /// type Y;
755
+ /// fn foo(&self, x: Self) // bad
756
+ /// fn foo(&self) -> Self // bad
757
+ /// fn foo(&self) -> Option<Self> // bad
758
+ /// fn foo(&self) -> Self::Y // OK, desugars to next example
759
+ /// fn foo(&self) -> <Self as Trait>::Y // OK
760
+ /// fn foo(&self) -> Self::X // OK, desugars to next example
761
+ /// fn foo(&self) -> <Self as SuperTrait>::X // OK
762
+ /// }
763
+ /// ```
764
+ ///
765
+ /// However, it is not as simple as allowing `Self` in a projected
766
+ /// type, because there are illegal ways to use `Self` as well:
767
+ ///
768
+ /// ```rust,ignore (example)
769
+ /// trait Trait : SuperTrait {
770
+ /// ...
771
+ /// fn foo(&self) -> <Self as SomeOtherTrait>::X;
772
+ /// }
773
+ /// ```
774
+ ///
775
+ /// Here we will not have the type of `X` recorded in the
776
+ /// object type, and we cannot resolve `Self as SomeOtherTrait`
777
+ /// without knowing what `Self` is.
741
778
fn contains_illegal_self_type_reference < ' tcx , T : TypeVisitable < TyCtxt < ' tcx > > > (
742
779
tcx : TyCtxt < ' tcx > ,
743
780
trait_def_id : DefId ,
744
781
value : T ,
745
782
allow_self_projections : AllowSelfProjections ,
746
783
) -> bool {
747
- // This is somewhat subtle. In general, we want to forbid
748
- // references to `Self` in the argument and return types,
749
- // since the value of `Self` is erased. However, there is one
750
- // exception: it is ok to reference `Self` in order to access
751
- // an associated type of the current trait, since we retain
752
- // the value of those associated types in the object type
753
- // itself.
754
- //
755
- // ```rust
756
- // trait SuperTrait {
757
- // type X;
758
- // }
759
- //
760
- // trait Trait : SuperTrait {
761
- // type Y;
762
- // fn foo(&self, x: Self) // bad
763
- // fn foo(&self) -> Self // bad
764
- // fn foo(&self) -> Option<Self> // bad
765
- // fn foo(&self) -> Self::Y // OK, desugars to next example
766
- // fn foo(&self) -> <Self as Trait>::Y // OK
767
- // fn foo(&self) -> Self::X // OK, desugars to next example
768
- // fn foo(&self) -> <Self as SuperTrait>::X // OK
769
- // }
770
- // ```
771
- //
772
- // However, it is not as simple as allowing `Self` in a projected
773
- // type, because there are illegal ways to use `Self` as well:
774
- //
775
- // ```rust
776
- // trait Trait : SuperTrait {
777
- // ...
778
- // fn foo(&self) -> <Self as SomeOtherTrait>::X;
779
- // }
780
- // ```
781
- //
782
- // Here we will not have the type of `X` recorded in the
783
- // object type, and we cannot resolve `Self as SomeOtherTrait`
784
- // without knowing what `Self` is.
785
-
786
- struct IllegalSelfTypeVisitor < ' tcx > {
787
- tcx : TyCtxt < ' tcx > ,
788
- trait_def_id : DefId ,
789
- supertraits : Option < Vec < DefId > > ,
790
- allow_self_projections : AllowSelfProjections ,
791
- }
784
+ value
785
+ . visit_with ( & mut IllegalSelfTypeVisitor {
786
+ tcx,
787
+ trait_def_id,
788
+ supertraits : None ,
789
+ allow_self_projections,
790
+ } )
791
+ . is_break ( )
792
+ }
792
793
793
- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for IllegalSelfTypeVisitor < ' tcx > {
794
- type Result = ControlFlow < ( ) > ;
794
+ struct IllegalSelfTypeVisitor < ' tcx > {
795
+ tcx : TyCtxt < ' tcx > ,
796
+ trait_def_id : DefId ,
797
+ supertraits : Option < Vec < ty:: TraitRef < ' tcx > > > ,
798
+ allow_self_projections : AllowSelfProjections ,
799
+ }
795
800
796
- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> Self :: Result {
797
- match t. kind ( ) {
798
- ty:: Param ( _) => {
799
- if t == self . tcx . types . self_param {
800
- ControlFlow :: Break ( ( ) )
801
- } else {
802
- ControlFlow :: Continue ( ( ) )
803
- }
804
- }
805
- ty:: Alias ( ty:: Projection , ref data)
806
- if self . tcx . is_impl_trait_in_trait ( data. def_id ) =>
807
- {
808
- // We'll deny these later in their own pass
801
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for IllegalSelfTypeVisitor < ' tcx > {
802
+ type Result = ControlFlow < ( ) > ;
803
+
804
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> Self :: Result {
805
+ match t. kind ( ) {
806
+ ty:: Param ( _) => {
807
+ if t == self . tcx . types . self_param {
808
+ ControlFlow :: Break ( ( ) )
809
+ } else {
809
810
ControlFlow :: Continue ( ( ) )
810
811
}
811
- ty:: Alias ( ty:: Projection , ref data) => {
812
- match self . allow_self_projections {
813
- AllowSelfProjections :: Yes => {
814
- // This is a projected type `<Foo as SomeTrait>::X`.
815
-
816
- // Compute supertraits of current trait lazily.
817
- if self . supertraits . is_none ( ) {
818
- self . supertraits =
819
- Some ( self . tcx . supertrait_def_ids ( self . trait_def_id ) . collect ( ) ) ;
820
- }
812
+ }
813
+ ty:: Alias ( ty:: Projection , ref data) if self . tcx . is_impl_trait_in_trait ( data. def_id ) => {
814
+ // We'll deny these later in their own pass
815
+ ControlFlow :: Continue ( ( ) )
816
+ }
817
+ ty:: Alias ( ty:: Projection , ref data) => {
818
+ match self . allow_self_projections {
819
+ AllowSelfProjections :: Yes => {
820
+ // This is a projected type `<Foo as SomeTrait>::X`.
821
+
822
+ // Compute supertraits of current trait lazily.
823
+ if self . supertraits . is_none ( ) {
824
+ self . supertraits = Some (
825
+ util:: supertraits (
826
+ self . tcx ,
827
+ ty:: Binder :: dummy ( ty:: TraitRef :: identity (
828
+ self . tcx ,
829
+ self . trait_def_id ,
830
+ ) ) ,
831
+ )
832
+ . map ( |trait_ref| {
833
+ self . tcx . erase_regions (
834
+ self . tcx . instantiate_bound_regions_with_erased ( trait_ref) ,
835
+ )
836
+ } )
837
+ . collect ( ) ,
838
+ ) ;
839
+ }
821
840
822
- // Determine whether the trait reference `Foo as
823
- // SomeTrait` is in fact a supertrait of the
824
- // current trait. In that case, this type is
825
- // legal, because the type `X` will be specified
826
- // in the object type. Note that we can just use
827
- // direct equality here because all of these types
828
- // are part of the formal parameter listing, and
829
- // hence there should be no inference variables.
830
- let is_supertrait_of_current_trait = self
831
- . supertraits
832
- . as_ref ( )
833
- . unwrap ( )
834
- . contains ( & data. trait_ref ( self . tcx ) . def_id ) ;
835
-
836
- if is_supertrait_of_current_trait {
837
- ControlFlow :: Continue ( ( ) )
838
- } else {
839
- t. super_visit_with ( self )
840
- }
841
+ // Determine whether the trait reference `Foo as
842
+ // SomeTrait` is in fact a supertrait of the
843
+ // current trait. In that case, this type is
844
+ // legal, because the type `X` will be specified
845
+ // in the object type. Note that we can just use
846
+ // direct equality here because all of these types
847
+ // are part of the formal parameter listing, and
848
+ // hence there should be no inference variables.
849
+ let is_supertrait_of_current_trait =
850
+ self . supertraits . as_ref ( ) . unwrap ( ) . contains (
851
+ & data. trait_ref ( self . tcx ) . fold_with (
852
+ & mut EraseEscapingBoundRegions {
853
+ tcx : self . tcx ,
854
+ binder : ty:: INNERMOST ,
855
+ } ,
856
+ ) ,
857
+ ) ;
858
+
859
+ if is_supertrait_of_current_trait {
860
+ ControlFlow :: Continue ( ( ) )
861
+ } else {
862
+ t. super_visit_with ( self )
841
863
}
842
- AllowSelfProjections :: No => t. super_visit_with ( self ) ,
843
864
}
865
+ AllowSelfProjections :: No => t. super_visit_with ( self ) ,
844
866
}
845
- _ => t. super_visit_with ( self ) ,
846
867
}
868
+ _ => t. super_visit_with ( self ) ,
847
869
}
870
+ }
848
871
849
- fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> Self :: Result {
850
- // Constants can only influence object safety if they are generic and reference `Self`.
851
- // This is only possible for unevaluated constants, so we walk these here.
852
- self . tcx . expand_abstract_consts ( ct) . super_visit_with ( self )
853
- }
872
+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> Self :: Result {
873
+ // Constants can only influence object safety if they are generic and reference `Self`.
874
+ // This is only possible for unevaluated constants, so we walk these here.
875
+ self . tcx . expand_abstract_consts ( ct) . super_visit_with ( self )
854
876
}
877
+ }
855
878
856
- value
857
- . visit_with ( & mut IllegalSelfTypeVisitor {
858
- tcx,
859
- trait_def_id,
860
- supertraits : None ,
861
- allow_self_projections,
862
- } )
863
- . is_break ( )
879
+ struct EraseEscapingBoundRegions < ' tcx > {
880
+ tcx : TyCtxt < ' tcx > ,
881
+ binder : ty:: DebruijnIndex ,
882
+ }
883
+
884
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for EraseEscapingBoundRegions < ' tcx > {
885
+ fn interner ( & self ) -> TyCtxt < ' tcx > {
886
+ self . tcx
887
+ }
888
+
889
+ fn fold_binder < T > ( & mut self , t : ty:: Binder < ' tcx , T > ) -> ty:: Binder < ' tcx , T >
890
+ where
891
+ T : TypeFoldable < TyCtxt < ' tcx > > ,
892
+ {
893
+ self . binder . shift_in ( 1 ) ;
894
+ let result = t. super_fold_with ( self ) ;
895
+ self . binder . shift_out ( 1 ) ;
896
+ result
897
+ }
898
+
899
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
900
+ if let ty:: ReBound ( debruijn, _) = * r
901
+ && debruijn < self . binder
902
+ {
903
+ r
904
+ } else {
905
+ self . tcx . lifetimes . re_erased
906
+ }
907
+ }
864
908
}
865
909
866
910
pub fn contains_illegal_impl_trait_in_trait < ' tcx > (
0 commit comments