@@ -18,10 +18,10 @@ use rustc_hir as hir;
1818use rustc_hir:: def:: DefKind ;
1919use rustc_hir:: def_id:: DefId ;
2020use rustc_macros:: HashStable ;
21- use rustc_span:: { Span , DUMMY_SP } ;
21+ use rustc_span:: DUMMY_SP ;
2222use rustc_target:: abi:: { Integer , Size , TargetDataLayout } ;
2323use smallvec:: SmallVec ;
24- use std:: { cmp , fmt, iter} ;
24+ use std:: { fmt, iter} ;
2525
2626#[ derive( Copy , Clone , Debug ) ]
2727pub struct Discr < ' tcx > {
@@ -135,21 +135,6 @@ impl IntTypeExt for attr::IntType {
135135 }
136136}
137137
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-
153138impl < ' tcx > TyCtxt < ' tcx > {
154139 /// Creates a hash of the type `Ty` which will be the same no matter what crate
155140 /// context it's calculated within. This is used by the `type_id` intrinsic.
@@ -870,178 +855,6 @@ impl<'tcx> ty::TyS<'tcx> {
870855 }
871856 }
872857
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-
1045858 /// Peel off all reference types in this type until there are none left.
1046859 ///
1047860 /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.
0 commit comments