23
23
#include " swift/AST/ParameterList.h"
24
24
#include " swift/AST/ProtocolConformance.h"
25
25
#include " swift/AST/TypeVisitor.h"
26
+ #include " swift/Basic/Defer.h"
26
27
#include " swift/Basic/QuotedString.h"
27
28
#include " swift/Basic/STLExtras.h"
28
29
#include " llvm/ADT/APFloat.h"
@@ -2792,55 +2793,74 @@ void TypeRepr::dump() const {
2792
2793
llvm::errs () << ' \n ' ;
2793
2794
}
2794
2795
2795
- void ProtocolConformanceRef::dump () const {
2796
- dump (llvm::errs ());
2797
- }
2798
-
2799
- void ProtocolConformanceRef::dump (llvm::raw_ostream &out,
2800
- unsigned indent) const {
2801
- if (isConcrete ()) {
2802
- getConcrete ()->dump (out, indent);
2796
+ // Recursive helpers to avoid infinite recursion for recursive protocol
2797
+ // conformances.
2798
+ static void dumpProtocolConformanceRec (
2799
+ const ProtocolConformance *conformance, llvm::raw_ostream &out,
2800
+ unsigned indent,
2801
+ llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited);
2802
+
2803
+ static void dumpSubstitutionMapRec (
2804
+ SubstitutionMap map, llvm::raw_ostream &out,
2805
+ SubstitutionMap::DumpStyle style, unsigned indent,
2806
+ llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited);
2807
+
2808
+ static void dumpProtocolConformanceRefRec (
2809
+ const ProtocolConformanceRef conformance, llvm::raw_ostream &out,
2810
+ unsigned indent,
2811
+ llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
2812
+ if (conformance.isConcrete ()) {
2813
+ dumpProtocolConformanceRec (conformance.getConcrete (), out, indent, visited);
2803
2814
} else {
2804
2815
out.indent (indent) << " (abstract_conformance protocol="
2805
- << getAbstract ()->getName ();
2816
+ << conformance. getAbstract ()->getName ();
2806
2817
PrintWithColorRAII (out, ParenthesisColor) << ' )' ;
2807
- out << ' \n ' ;
2808
2818
}
2809
2819
}
2810
2820
2811
- void ProtocolConformance::dump () const {
2812
- auto &out = llvm::errs ();
2813
- dump (out);
2814
- out << ' \n ' ;
2815
- }
2821
+ static void dumpProtocolConformanceRec (
2822
+ const ProtocolConformance *conformance, llvm::raw_ostream &out,
2823
+ unsigned indent,
2824
+ llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
2825
+ // A recursive conformance shouldn't have its contents printed, or there's
2826
+ // infinite recursion. (This also avoids printing things that occur multiple
2827
+ // times in a conformance hierarchy.)
2828
+ auto shouldPrintDetails = visited.insert (conformance).second ;
2816
2829
2817
- void ProtocolConformance::dump (llvm::raw_ostream &out, unsigned indent) const {
2818
2830
auto printCommon = [&](StringRef kind) {
2819
2831
out.indent (indent);
2820
2832
PrintWithColorRAII (out, ParenthesisColor) << ' (' ;
2821
- out << kind << " _conformance type=" << getType ()
2822
- << " protocol=" << getProtocol ()->getName ();
2833
+ out << kind << " _conformance type=" << conformance->getType ()
2834
+ << " protocol=" << conformance->getProtocol ()->getName ();
2835
+
2836
+ if (!shouldPrintDetails)
2837
+ out << " (details printed above)" ;
2823
2838
};
2824
2839
2825
- switch (getKind ()) {
2840
+ switch (conformance-> getKind ()) {
2826
2841
case ProtocolConformanceKind::Normal: {
2827
- auto normal = cast<NormalProtocolConformance>(this );
2842
+ auto normal = cast<NormalProtocolConformance>(conformance );
2828
2843
2829
2844
printCommon (" normal" );
2845
+ if (!shouldPrintDetails)
2846
+ break ;
2847
+
2830
2848
// Maybe print information about the conforming context?
2831
2849
if (normal->isLazilyLoaded ()) {
2832
2850
out << " lazy" ;
2833
2851
} else {
2834
- forEachTypeWitness (nullptr , [&](const AssociatedTypeDecl *req,
2835
- Type ty, const TypeDecl *) -> bool {
2836
- out << ' \n ' ;
2837
- out.indent (indent + 2 );
2838
- PrintWithColorRAII (out, ParenthesisColor) << ' (' ;
2839
- out << " assoc_type req=" << req->getName () << " type=" ;
2840
- PrintWithColorRAII (out, TypeColor) << ty;
2841
- PrintWithColorRAII (out, ParenthesisColor) << ' )' ;
2842
- return false ;
2843
- });
2852
+ normal->forEachTypeWitness (
2853
+ nullptr ,
2854
+ [&](const AssociatedTypeDecl *req, Type ty,
2855
+ const TypeDecl *) -> bool {
2856
+ out << ' \n ' ;
2857
+ out.indent (indent + 2 );
2858
+ PrintWithColorRAII (out, ParenthesisColor) << ' (' ;
2859
+ out << " assoc_type req=" << req->getName () << " type=" ;
2860
+ PrintWithColorRAII (out, TypeColor) << Type (ty->getDesugaredType ());
2861
+ PrintWithColorRAII (out, ParenthesisColor) << ' )' ;
2862
+ return false ;
2863
+ });
2844
2864
normal->forEachValueWitness (nullptr , [&](const ValueDecl *req,
2845
2865
Witness witness) {
2846
2866
out << ' \n ' ;
@@ -2857,9 +2877,9 @@ void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
2857
2877
PrintWithColorRAII (out, ParenthesisColor) << ' )' ;
2858
2878
});
2859
2879
2860
- for (auto conformance : normal->getSignatureConformances ()) {
2880
+ for (auto sigConf : normal->getSignatureConformances ()) {
2861
2881
out << ' \n ' ;
2862
- conformance. dump ( out, indent + 2 );
2882
+ dumpProtocolConformanceRefRec (sigConf, out, indent + 2 , visited );
2863
2883
}
2864
2884
}
2865
2885
@@ -2872,31 +2892,137 @@ void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
2872
2892
}
2873
2893
2874
2894
case ProtocolConformanceKind::Inherited: {
2875
- auto conf = cast<InheritedProtocolConformance>(this );
2895
+ auto conf = cast<InheritedProtocolConformance>(conformance );
2876
2896
printCommon (" inherited" );
2897
+ if (!shouldPrintDetails)
2898
+ break ;
2899
+
2877
2900
out << ' \n ' ;
2878
- conf->getInheritedConformance ()->dump (out, indent + 2 );
2901
+ dumpProtocolConformanceRec (conf->getInheritedConformance (), out, indent + 2 ,
2902
+ visited);
2879
2903
break ;
2880
2904
}
2881
2905
2882
2906
case ProtocolConformanceKind::Specialized: {
2883
- auto conf = cast<SpecializedProtocolConformance>(this );
2907
+ auto conf = cast<SpecializedProtocolConformance>(conformance );
2884
2908
printCommon (" specialized" );
2909
+ if (!shouldPrintDetails)
2910
+ break ;
2911
+
2912
+ out << ' \n ' ;
2913
+ dumpSubstitutionMapRec (conf->getSubstitutionMap (), out,
2914
+ SubstitutionMap::DumpStyle::Full, indent + 2 ,
2915
+ visited);
2885
2916
out << ' \n ' ;
2886
- conf->getSubstitutionMap ().dump (out);
2887
2917
for (auto subReq : conf->getConditionalRequirements ()) {
2888
2918
out.indent (indent + 2 );
2889
2919
subReq.dump (out);
2890
2920
out << ' \n ' ;
2891
2921
}
2892
- conf->getGenericConformance ()->dump (out, indent + 2 );
2922
+ dumpProtocolConformanceRec (conf->getGenericConformance (), out, indent + 2 ,
2923
+ visited);
2893
2924
break ;
2894
2925
}
2895
2926
}
2896
2927
2897
2928
PrintWithColorRAII (out, ParenthesisColor) << ' )' ;
2898
2929
}
2899
2930
2931
+ static void dumpSubstitutionMapRec (
2932
+ SubstitutionMap map, llvm::raw_ostream &out,
2933
+ SubstitutionMap::DumpStyle style, unsigned indent,
2934
+ llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
2935
+ auto *genericSig = map.getGenericSignature ();
2936
+ out.indent (indent);
2937
+
2938
+ auto printParen = [&](char p) {
2939
+ PrintWithColorRAII (out, ParenthesisColor) << p;
2940
+ };
2941
+ printParen (' (' );
2942
+ SWIFT_DEFER { printParen (' )' ); };
2943
+ out << " substitution_map generic_signature=" ;
2944
+ if (genericSig == nullptr ) {
2945
+ out << " <nullptr>" ;
2946
+ return ;
2947
+ }
2948
+
2949
+ genericSig->print (out);
2950
+ auto genericParams = genericSig->getGenericParams ();
2951
+ auto replacementTypes =
2952
+ static_cast <const SubstitutionMap &>(map).getReplacementTypesBuffer ();
2953
+ for (unsigned i : indices (genericParams)) {
2954
+ if (style == SubstitutionMap::DumpStyle::Minimal) {
2955
+ out << " " ;
2956
+ } else {
2957
+ out << " \n " ;
2958
+ out.indent (indent + 2 );
2959
+ }
2960
+ printParen (' (' );
2961
+ out << " substitution " ;
2962
+ genericParams[i]->print (out);
2963
+ out << " -> " ;
2964
+ if (replacementTypes[i])
2965
+ replacementTypes[i]->print (out);
2966
+ else
2967
+ out << " <<unresolved concrete type>>" ;
2968
+ printParen (' )' );
2969
+ }
2970
+ // A minimal dump doesn't need the details about the conformances, a lot of
2971
+ // that info can be inferred from the signature.
2972
+ if (style == SubstitutionMap::DumpStyle::Minimal)
2973
+ return ;
2974
+
2975
+ auto conformances = map.getConformances ();
2976
+ for (const auto &req : genericSig->getRequirements ()) {
2977
+ if (req.getKind () != RequirementKind::Conformance)
2978
+ continue ;
2979
+
2980
+ out << " \n " ;
2981
+ out.indent (indent + 2 );
2982
+ printParen (' (' );
2983
+ out << " conformance type=" ;
2984
+ req.getFirstType ()->print (out);
2985
+ out << " \n " ;
2986
+ dumpProtocolConformanceRefRec (conformances.front (), out, indent + 4 ,
2987
+ visited);
2988
+
2989
+ printParen (' )' );
2990
+ conformances = conformances.slice (1 );
2991
+ }
2992
+ }
2993
+
2994
+ void ProtocolConformanceRef::dump () const {
2995
+ dump (llvm::errs ());
2996
+ llvm::errs () << ' \n ' ;
2997
+ }
2998
+
2999
+ void ProtocolConformanceRef::dump (llvm::raw_ostream &out,
3000
+ unsigned indent) const {
3001
+ llvm::SmallPtrSet<const ProtocolConformance *, 8 > visited;
3002
+ dumpProtocolConformanceRefRec (*this , out, indent, visited);
3003
+ }
3004
+ void ProtocolConformance::dump () const {
3005
+ auto &out = llvm::errs ();
3006
+ dump (out);
3007
+ out << ' \n ' ;
3008
+ }
3009
+
3010
+ void ProtocolConformance::dump (llvm::raw_ostream &out, unsigned indent) const {
3011
+ llvm::SmallPtrSet<const ProtocolConformance *, 8 > visited;
3012
+ dumpProtocolConformanceRec (this , out, indent, visited);
3013
+ }
3014
+
3015
+ void SubstitutionMap::dump (llvm::raw_ostream &out, DumpStyle style,
3016
+ unsigned indent) const {
3017
+ llvm::SmallPtrSet<const ProtocolConformance *, 8 > visited;
3018
+ dumpSubstitutionMapRec (*this , out, style, indent, visited);
3019
+ }
3020
+
3021
+ void SubstitutionMap::dump () const {
3022
+ dump (llvm::errs ());
3023
+ llvm::errs () << " \n " ;
3024
+ }
3025
+
2900
3026
// ===----------------------------------------------------------------------===//
2901
3027
// Dumping for Types.
2902
3028
// ===----------------------------------------------------------------------===//
0 commit comments