@@ -25,6 +25,7 @@ use middle::lang_items;
25
25
use rustc_const_math:: { ConstInt , ConstIsize , ConstUsize } ;
26
26
use rustc_data_structures:: stable_hasher:: { StableHasher , StableHasherResult ,
27
27
HashStable } ;
28
+ use rustc_data_structures:: fx:: FxHashMap ;
28
29
use std:: cmp;
29
30
use std:: hash:: Hash ;
30
31
use std:: intrinsics;
@@ -835,27 +836,33 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
835
836
} )
836
837
}
837
838
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
+ {
841
846
match ty. sty {
842
847
TyTuple ( ref ts, _) => {
843
848
// Find non representable
844
849
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)
846
851
} ) )
847
852
}
848
853
// Fixed-length vectors.
849
854
// FIXME(#11924) Behavior undecided for zero-length vectors.
850
855
TyArray ( ty, _) => {
851
- is_type_structurally_recursive ( tcx, sp, seen, ty)
856
+ is_type_structurally_recursive ( tcx, sp, seen, representable_cache , ty)
852
857
}
853
858
TyAdt ( def, substs) => {
854
859
// Find non representable fields with their spans
855
860
fold_repr ( def. all_fields ( ) . map ( |field| {
856
861
let ty = field. ty ( tcx, substs) ;
857
862
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
+ {
859
866
Representability :: SelfRecursive ( _) => {
860
867
Representability :: SelfRecursive ( vec ! [ span] )
861
868
}
@@ -896,12 +903,34 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
896
903
897
904
// Does the type `ty` directly (without indirection through a pointer)
898
905
// 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
+ {
903
913
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
+ }
904
926
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
+ {
905
934
match ty. sty {
906
935
TyAdt ( def, _) => {
907
936
{
@@ -948,13 +977,13 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
948
977
// For structs and enums, track all previously seen types by pushing them
949
978
// onto the 'seen' stack.
950
979
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) ;
952
981
seen. pop ( ) ;
953
982
out
954
983
}
955
984
_ => {
956
985
// 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)
958
987
}
959
988
}
960
989
}
@@ -965,7 +994,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
965
994
// contains a different, structurally recursive type, maintain a stack
966
995
// of seen types and check recursion for each of them (issues #3008, #3779).
967
996
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 ) ;
969
1000
debug ! ( "is_type_representable: {:?} is {:?}" , self , r) ;
970
1001
r
971
1002
}
0 commit comments