@@ -25,6 +25,7 @@ use middle::lang_items;
2525use rustc_const_math:: { ConstInt , ConstIsize , ConstUsize } ;
2626use rustc_data_structures:: stable_hasher:: { StableHasher , StableHasherResult ,
2727 HashStable } ;
28+ use rustc_data_structures:: fx:: FxHashMap ;
2829use std:: cmp;
2930use std:: hash:: Hash ;
3031use std:: intrinsics;
@@ -835,27 +836,33 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
835836 } )
836837 }
837838
838- fn are_inner_types_recursive < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , sp : Span ,
839- seen : & mut Vec < Ty < ' tcx > > , ty : Ty < ' tcx > )
840- -> Representability {
839+ fn are_inner_types_recursive < ' a , ' tcx > (
840+ tcx : TyCtxt < ' a , ' tcx , ' tcx > , sp : Span ,
841+ seen : & mut Vec < Ty < ' tcx > > ,
842+ representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
843+ ty : Ty < ' tcx > )
844+ -> Representability
845+ {
841846 match ty. sty {
842847 TyTuple ( ref ts, _) => {
843848 // Find non representable
844849 fold_repr ( ts. iter ( ) . map ( |ty| {
845- is_type_structurally_recursive ( tcx, sp, seen, ty)
850+ is_type_structurally_recursive ( tcx, sp, seen, representable_cache , ty)
846851 } ) )
847852 }
848853 // Fixed-length vectors.
849854 // FIXME(#11924) Behavior undecided for zero-length vectors.
850855 TyArray ( ty, _) => {
851- is_type_structurally_recursive ( tcx, sp, seen, ty)
856+ is_type_structurally_recursive ( tcx, sp, seen, representable_cache , ty)
852857 }
853858 TyAdt ( def, substs) => {
854859 // Find non representable fields with their spans
855860 fold_repr ( def. all_fields ( ) . map ( |field| {
856861 let ty = field. ty ( tcx, substs) ;
857862 let span = tcx. hir . span_if_local ( field. did ) . unwrap_or ( sp) ;
858- match is_type_structurally_recursive ( tcx, span, seen, ty) {
863+ match is_type_structurally_recursive ( tcx, span, seen,
864+ representable_cache, ty)
865+ {
859866 Representability :: SelfRecursive ( _) => {
860867 Representability :: SelfRecursive ( vec ! [ span] )
861868 }
@@ -896,12 +903,34 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
896903
897904 // Does the type `ty` directly (without indirection through a pointer)
898905 // contain any types on stack `seen`?
899- fn is_type_structurally_recursive < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
900- sp : Span ,
901- seen : & mut Vec < Ty < ' tcx > > ,
902- ty : Ty < ' tcx > ) -> Representability {
906+ fn is_type_structurally_recursive < ' a , ' tcx > (
907+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
908+ sp : Span ,
909+ seen : & mut Vec < Ty < ' tcx > > ,
910+ representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
911+ ty : Ty < ' tcx > ) -> Representability
912+ {
903913 debug ! ( "is_type_structurally_recursive: {:?} {:?}" , ty, sp) ;
914+ if let Some ( representability) = representable_cache. get ( ty) {
915+ debug ! ( "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}" ,
916+ ty, sp, representability) ;
917+ return representability. clone ( ) ;
918+ }
919+
920+ let representability = is_type_structurally_recursive_inner (
921+ tcx, sp, seen, representable_cache, ty) ;
922+
923+ representable_cache. insert ( ty, representability. clone ( ) ) ;
924+ representability
925+ }
904926
927+ fn is_type_structurally_recursive_inner < ' a , ' tcx > (
928+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
929+ sp : Span ,
930+ seen : & mut Vec < Ty < ' tcx > > ,
931+ representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
932+ ty : Ty < ' tcx > ) -> Representability
933+ {
905934 match ty. sty {
906935 TyAdt ( def, _) => {
907936 {
@@ -948,13 +977,13 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
948977 // For structs and enums, track all previously seen types by pushing them
949978 // onto the 'seen' stack.
950979 seen. push ( ty) ;
951- let out = are_inner_types_recursive ( tcx, sp, seen, ty) ;
980+ let out = are_inner_types_recursive ( tcx, sp, seen, representable_cache , ty) ;
952981 seen. pop ( ) ;
953982 out
954983 }
955984 _ => {
956985 // No need to push in other cases.
957- are_inner_types_recursive ( tcx, sp, seen, ty)
986+ are_inner_types_recursive ( tcx, sp, seen, representable_cache , ty)
958987 }
959988 }
960989 }
@@ -965,7 +994,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
965994 // contains a different, structurally recursive type, maintain a stack
966995 // of seen types and check recursion for each of them (issues #3008, #3779).
967996 let mut seen: Vec < Ty > = Vec :: new ( ) ;
968- let r = is_type_structurally_recursive ( tcx, sp, & mut seen, self ) ;
997+ let mut representable_cache = FxHashMap ( ) ;
998+ let r = is_type_structurally_recursive (
999+ tcx, sp, & mut seen, & mut representable_cache, self ) ;
9691000 debug ! ( "is_type_representable: {:?} is {:?}" , self , r) ;
9701001 r
9711002 }
0 commit comments