@@ -18,10 +18,10 @@ use rustc_hir as hir;
18
18
use rustc_hir:: def:: DefKind ;
19
19
use rustc_hir:: def_id:: DefId ;
20
20
use rustc_macros:: HashStable ;
21
- use rustc_span:: { Span , DUMMY_SP } ;
21
+ use rustc_span:: DUMMY_SP ;
22
22
use rustc_target:: abi:: { Integer , Size , TargetDataLayout } ;
23
23
use smallvec:: SmallVec ;
24
- use std:: { cmp , fmt, iter} ;
24
+ use std:: { fmt, iter} ;
25
25
26
26
#[ derive( Copy , Clone , Debug ) ]
27
27
pub struct Discr < ' tcx > {
@@ -135,21 +135,6 @@ impl IntTypeExt for attr::IntType {
135
135
}
136
136
}
137
137
138
- /// Describes whether a type is representable. For types that are not
139
- /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
140
- /// distinguish between types that are recursive with themselves and types that
141
- /// contain a different recursive type. These cases can therefore be treated
142
- /// differently when reporting errors.
143
- ///
144
- /// The ordering of the cases is significant. They are sorted so that cmp::max
145
- /// will keep the "more erroneous" of two values.
146
- #[ derive( Clone , PartialOrd , Ord , Eq , PartialEq , Debug ) ]
147
- pub enum Representability {
148
- Representable ,
149
- ContainsRecursive ,
150
- SelfRecursive ( Vec < Span > ) ,
151
- }
152
-
153
138
impl < ' tcx > TyCtxt < ' tcx > {
154
139
/// Creates a hash of the type `Ty` which will be the same no matter what crate
155
140
/// context it's calculated within. This is used by the `type_id` intrinsic.
@@ -870,178 +855,6 @@ impl<'tcx> ty::TyS<'tcx> {
870
855
}
871
856
}
872
857
873
- /// Check whether a type is representable. This means it cannot contain unboxed
874
- /// structural recursion. This check is needed for structs and enums.
875
- pub fn is_representable ( & ' tcx self , tcx : TyCtxt < ' tcx > , sp : Span ) -> Representability {
876
- // Iterate until something non-representable is found
877
- fn fold_repr < It : Iterator < Item = Representability > > ( iter : It ) -> Representability {
878
- iter. fold ( Representability :: Representable , |r1, r2| match ( r1, r2) {
879
- ( Representability :: SelfRecursive ( v1) , Representability :: SelfRecursive ( v2) ) => {
880
- Representability :: SelfRecursive ( v1. into_iter ( ) . chain ( v2) . collect ( ) )
881
- }
882
- ( r1, r2) => cmp:: max ( r1, r2) ,
883
- } )
884
- }
885
-
886
- fn are_inner_types_recursive < ' tcx > (
887
- tcx : TyCtxt < ' tcx > ,
888
- sp : Span ,
889
- seen : & mut Vec < Ty < ' tcx > > ,
890
- representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
891
- ty : Ty < ' tcx > ,
892
- ) -> Representability {
893
- match ty. kind ( ) {
894
- Tuple ( ..) => {
895
- // Find non representable
896
- fold_repr ( ty. tuple_fields ( ) . map ( |ty| {
897
- is_type_structurally_recursive ( tcx, sp, seen, representable_cache, ty)
898
- } ) )
899
- }
900
- // Fixed-length vectors.
901
- // FIXME(#11924) Behavior undecided for zero-length vectors.
902
- Array ( ty, _) => {
903
- is_type_structurally_recursive ( tcx, sp, seen, representable_cache, ty)
904
- }
905
- Adt ( def, substs) => {
906
- // Find non representable fields with their spans
907
- fold_repr ( def. all_fields ( ) . map ( |field| {
908
- let ty = field. ty ( tcx, substs) ;
909
- let span = match field
910
- . did
911
- . as_local ( )
912
- . map ( |id| tcx. hir ( ) . local_def_id_to_hir_id ( id) )
913
- . and_then ( |id| tcx. hir ( ) . find ( id) )
914
- {
915
- Some ( hir:: Node :: Field ( field) ) => field. ty . span ,
916
- _ => sp,
917
- } ;
918
- match is_type_structurally_recursive (
919
- tcx,
920
- span,
921
- seen,
922
- representable_cache,
923
- ty,
924
- ) {
925
- Representability :: SelfRecursive ( _) => {
926
- Representability :: SelfRecursive ( vec ! [ span] )
927
- }
928
- x => x,
929
- }
930
- } ) )
931
- }
932
- Closure ( ..) => {
933
- // this check is run on type definitions, so we don't expect
934
- // to see closure types
935
- bug ! ( "requires check invoked on inapplicable type: {:?}" , ty)
936
- }
937
- _ => Representability :: Representable ,
938
- }
939
- }
940
-
941
- fn same_struct_or_enum < ' tcx > ( ty : Ty < ' tcx > , def : & ' tcx ty:: AdtDef ) -> bool {
942
- match * ty. kind ( ) {
943
- Adt ( ty_def, _) => ty_def == def,
944
- _ => false ,
945
- }
946
- }
947
-
948
- // Does the type `ty` directly (without indirection through a pointer)
949
- // contain any types on stack `seen`?
950
- fn is_type_structurally_recursive < ' tcx > (
951
- tcx : TyCtxt < ' tcx > ,
952
- sp : Span ,
953
- seen : & mut Vec < Ty < ' tcx > > ,
954
- representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
955
- ty : Ty < ' tcx > ,
956
- ) -> Representability {
957
- debug ! ( "is_type_structurally_recursive: {:?} {:?}" , ty, sp) ;
958
- if let Some ( representability) = representable_cache. get ( ty) {
959
- debug ! (
960
- "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}" ,
961
- ty, sp, representability
962
- ) ;
963
- return representability. clone ( ) ;
964
- }
965
-
966
- let representability =
967
- is_type_structurally_recursive_inner ( tcx, sp, seen, representable_cache, ty) ;
968
-
969
- representable_cache. insert ( ty, representability. clone ( ) ) ;
970
- representability
971
- }
972
-
973
- fn is_type_structurally_recursive_inner < ' tcx > (
974
- tcx : TyCtxt < ' tcx > ,
975
- sp : Span ,
976
- seen : & mut Vec < Ty < ' tcx > > ,
977
- representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
978
- ty : Ty < ' tcx > ,
979
- ) -> Representability {
980
- match ty. kind ( ) {
981
- Adt ( def, _) => {
982
- {
983
- // Iterate through stack of previously seen types.
984
- let mut iter = seen. iter ( ) ;
985
-
986
- // The first item in `seen` is the type we are actually curious about.
987
- // We want to return SelfRecursive if this type contains itself.
988
- // It is important that we DON'T take generic parameters into account
989
- // for this check, so that Bar<T> in this example counts as SelfRecursive:
990
- //
991
- // struct Foo;
992
- // struct Bar<T> { x: Bar<Foo> }
993
-
994
- if let Some ( & seen_type) = iter. next ( ) {
995
- if same_struct_or_enum ( seen_type, * def) {
996
- debug ! ( "SelfRecursive: {:?} contains {:?}" , seen_type, ty) ;
997
- return Representability :: SelfRecursive ( vec ! [ sp] ) ;
998
- }
999
- }
1000
-
1001
- // We also need to know whether the first item contains other types
1002
- // that are structurally recursive. If we don't catch this case, we
1003
- // will recurse infinitely for some inputs.
1004
- //
1005
- // It is important that we DO take generic parameters into account
1006
- // here, so that code like this is considered SelfRecursive, not
1007
- // ContainsRecursive:
1008
- //
1009
- // struct Foo { Option<Option<Foo>> }
1010
-
1011
- for & seen_type in iter {
1012
- if ty:: TyS :: same_type ( ty, seen_type) {
1013
- debug ! ( "ContainsRecursive: {:?} contains {:?}" , seen_type, ty) ;
1014
- return Representability :: ContainsRecursive ;
1015
- }
1016
- }
1017
- }
1018
-
1019
- // For structs and enums, track all previously seen types by pushing them
1020
- // onto the 'seen' stack.
1021
- seen. push ( ty) ;
1022
- let out = are_inner_types_recursive ( tcx, sp, seen, representable_cache, ty) ;
1023
- seen. pop ( ) ;
1024
- out
1025
- }
1026
- _ => {
1027
- // No need to push in other cases.
1028
- are_inner_types_recursive ( tcx, sp, seen, representable_cache, ty)
1029
- }
1030
- }
1031
- }
1032
-
1033
- debug ! ( "is_type_representable: {:?}" , self ) ;
1034
-
1035
- // To avoid a stack overflow when checking an enum variant or struct that
1036
- // contains a different, structurally recursive type, maintain a stack
1037
- // of seen types and check recursion for each of them (issues #3008, #3779).
1038
- let mut seen: Vec < Ty < ' _ > > = Vec :: new ( ) ;
1039
- let mut representable_cache = FxHashMap :: default ( ) ;
1040
- let r = is_type_structurally_recursive ( tcx, sp, & mut seen, & mut representable_cache, self ) ;
1041
- debug ! ( "is_type_representable: {:?} is {:?}" , self , r) ;
1042
- r
1043
- }
1044
-
1045
858
/// Peel off all reference types in this type until there are none left.
1046
859
///
1047
860
/// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.
0 commit comments