30
30
#include " swift/Runtime/HeapObject.h"
31
31
#include " swift/Basic/Unreachable.h"
32
32
33
+ #include < type_traits>
33
34
#include < vector>
34
35
#include < unordered_map>
35
36
36
37
#include < inttypes.h>
37
38
38
39
namespace swift {
40
+ namespace reflection {
41
+ class TypeRefBuilder ;
42
+ }
39
43
namespace remote {
40
44
41
45
template <typename BuiltType>
@@ -2905,25 +2909,50 @@ class MetadataReader {
2905
2909
return builtSubsts;
2906
2910
}
2907
2911
2908
- BuiltType readNominalTypeFromMetadata (MetadataRef origMetadata,
2909
- bool skipArtificialSubclasses = false ) {
2910
- auto metadata = origMetadata;
2911
- auto descriptorAddress =
2912
- readAddressOfNominalTypeDescriptor (metadata,
2913
- skipArtificialSubclasses);
2914
- if (!descriptorAddress)
2912
+ // / "Generic" version of readNominalTypeFromDescriptor when BuilderType !=
2913
+ // / TypeRefBuilder.
2914
+ template <
2915
+ typename T = BuilderType,
2916
+ std::enable_if_t <!std::is_same<T, reflection::TypeRefBuilder>::value,
2917
+ bool > = true >
2918
+ BuiltType readNominalTypeFromDescriptor (MetadataRef metadata,
2919
+ ContextDescriptorRef descriptor) {
2920
+ if (!descriptor)
2915
2921
return BuiltType ();
2916
2922
2917
- // If we've skipped an artificial subclasses, check the cache at
2918
- // the superclass. (This also protects against recursion.)
2919
- if (skipArtificialSubclasses && metadata != origMetadata) {
2920
- auto it = TypeCache.find (getAddress (metadata));
2921
- if (it != TypeCache.end ())
2922
- return it->second ;
2923
+ // From that, attempt to resolve a nominal type.
2924
+ BuiltTypeDecl typeDecl = buildNominalTypeDecl (descriptor);
2925
+ if (!typeDecl)
2926
+ return BuiltType ();
2927
+
2928
+ // Build the nominal type.
2929
+ BuiltType nominal;
2930
+ if (descriptor->isGeneric ()) {
2931
+ // Resolve the generic arguments.
2932
+ auto builtGenerics = getGenericSubst (metadata, descriptor);
2933
+ if (builtGenerics.empty ())
2934
+ return BuiltType ();
2935
+ nominal = Builder.createBoundGenericType (typeDecl, builtGenerics);
2936
+ } else {
2937
+ nominal = Builder.createNominalType (typeDecl);
2923
2938
}
2924
2939
2925
- // Read the nominal type descriptor.
2926
- ContextDescriptorRef descriptor = readContextDescriptor (descriptorAddress);
2940
+ return nominal;
2941
+ }
2942
+
2943
+ // / Specialized version of readNominalTypeFromDescriptor where BuilderType ==
2944
+ // / TypeRefBuilder. There are two main differences in this specialization:
2945
+ // / 1 - We attempt to rebuild the parent typeref and pass that along
2946
+ // / when creating our own typeref.
2947
+ // / 2 - We remove the generic parameters that belong to our typeref's parents
2948
+ // / from the flat array of generic parameters we read from the context
2949
+ // / descriptor, as typerefs store generic parameters per level instead of as a
2950
+ // / single flat array.
2951
+ template <typename T = BuilderType,
2952
+ std::enable_if_t <std::is_same<T, reflection::TypeRefBuilder>::value,
2953
+ bool > = true >
2954
+ BuiltType readNominalTypeFromDescriptor (MetadataRef metadata,
2955
+ ContextDescriptorRef descriptor) {
2927
2956
if (!descriptor)
2928
2957
return BuiltType ();
2929
2958
@@ -2932,21 +2961,81 @@ class MetadataReader {
2932
2961
if (!typeDecl)
2933
2962
return BuiltType ();
2934
2963
2964
+ BuiltType parent;
2965
+ size_t numGenericParamsInParent = 0 ;
2966
+ if (auto parentContextRef = readParentContextDescriptor (descriptor)) {
2967
+ if (parentContextRef->isResolved ()) {
2968
+ if (auto parentContext = parentContextRef->getResolved ()) {
2969
+ // Attempt to rebuild the parent as typerefs uses a "nested"
2970
+ // representation to represent the type hierarchy.
2971
+ parent = readNominalTypeFromDescriptor (metadata, parentContext);
2972
+ // Context descriptors use a flat array to store all the generic
2973
+ // parameters, instead of storing them by level, which is what
2974
+ // typerefs do. Store the number of generic parameters in the parent
2975
+ // so we can adjust the number of generic parameters when building our
2976
+ // own typeref. Note that we only need to go one level up the
2977
+ // hierarchy, since the parent will have a flat array of generic
2978
+ // paramaters including all of it's parents parameters.
2979
+ if (auto genericContext = parentContext->getGenericContext ()) {
2980
+ auto contextHeader = genericContext->getGenericContextHeader ();
2981
+ numGenericParamsInParent = contextHeader.NumParams ;
2982
+ }
2983
+ }
2984
+ }
2985
+ }
2986
+
2935
2987
// Build the nominal type.
2936
2988
BuiltType nominal;
2937
2989
if (descriptor->isGeneric ()) {
2938
2990
// Resolve the generic arguments.
2939
2991
auto builtGenerics = getGenericSubst (metadata, descriptor);
2940
2992
if (builtGenerics.empty ())
2941
2993
return BuiltType ();
2942
- nominal = Builder.createBoundGenericType (typeDecl, builtGenerics);
2994
+
2995
+ // Erase the generic parameters that belong to the parents.
2996
+ if (numGenericParamsInParent > 0 )
2997
+ builtGenerics.erase (
2998
+ builtGenerics.begin (),
2999
+ builtGenerics.begin () +
3000
+ std::min (numGenericParamsInParent, builtGenerics.size ()));
3001
+
3002
+ if (parent)
3003
+ nominal =
3004
+ Builder.createBoundGenericType (typeDecl, builtGenerics, parent);
3005
+ else
3006
+ nominal = Builder.createBoundGenericType (typeDecl, builtGenerics);
3007
+ } else if (parent) {
3008
+ nominal = Builder.createNominalType (typeDecl, parent);
2943
3009
} else {
2944
3010
nominal = Builder.createNominalType (typeDecl);
2945
3011
}
2946
3012
3013
+ return nominal;
3014
+ }
3015
+
3016
+ BuiltType readNominalTypeFromMetadata (MetadataRef origMetadata,
3017
+ bool skipArtificialSubclasses = false ) {
3018
+ auto metadata = origMetadata;
3019
+ auto descriptorAddress =
3020
+ readAddressOfNominalTypeDescriptor (metadata, skipArtificialSubclasses);
3021
+ if (!descriptorAddress)
3022
+ return BuiltType ();
3023
+
3024
+ // If we've skipped an artificial subclasses, check the cache at
3025
+ // the superclass. (This also protects against recursion.)
3026
+ if (skipArtificialSubclasses && metadata != origMetadata) {
3027
+ auto it = TypeCache.find (getAddress (metadata));
3028
+ if (it != TypeCache.end ())
3029
+ return it->second ;
3030
+ }
3031
+
3032
+ // Read the nominal type descriptor.
3033
+ ContextDescriptorRef descriptor = readContextDescriptor (descriptorAddress);
3034
+ auto nominal = readNominalTypeFromDescriptor (origMetadata, descriptor);
3035
+
2947
3036
if (!nominal)
2948
3037
return BuiltType ();
2949
-
3038
+
2950
3039
TypeCache[getAddress (metadata)] = nominal;
2951
3040
2952
3041
// If we've skipped an artificial subclass, remove the
@@ -2958,8 +3047,9 @@ class MetadataReader {
2958
3047
return nominal;
2959
3048
}
2960
3049
2961
- BuiltType readNominalTypeFromClassMetadata (MetadataRef origMetadata,
2962
- bool skipArtificialSubclasses = false ) {
3050
+ BuiltType
3051
+ readNominalTypeFromClassMetadata (MetadataRef origMetadata,
3052
+ bool skipArtificialSubclasses = false ) {
2963
3053
auto classMeta = cast<TargetClassMetadata>(origMetadata);
2964
3054
if (classMeta->isTypeMetadata ())
2965
3055
return readNominalTypeFromMetadata (origMetadata, skipArtificialSubclasses);
0 commit comments