@@ -466,6 +466,15 @@ ManagedValue Transform::transform(ManagedValue v,
466
466
467
467
// Subtype conversions:
468
468
469
+ // A base class method returning Self can be used in place of a derived
470
+ // class method returning Self.
471
+ if (auto outputSelfType = dyn_cast<DynamicSelfType>(outputSubstType)) {
472
+ if (auto inputSelfType = dyn_cast<DynamicSelfType>(inputSubstType)) {
473
+ inputSubstType = inputSelfType.getSelfType ();
474
+ outputSubstType = outputSelfType.getSelfType ();
475
+ }
476
+ }
477
+
469
478
// - upcasts for classes
470
479
if (outputSubstType->getClassOrBoundGenericClass () &&
471
480
inputSubstType->getClassOrBoundGenericClass ()) {
@@ -482,7 +491,9 @@ ManagedValue Transform::transform(ManagedValue v,
482
491
// Upcast to a superclass.
483
492
return SGF.B .createUpcast (Loc, v, loweredResultTy);
484
493
} else {
485
- // Unchecked-downcast to a covariant return type.
494
+ // FIXME: Should only happen with the DynamicSelfType case above,
495
+ // except that convenience inits return the static self and not
496
+ // DynamicSelfType.
486
497
assert (inputSubstType->isExactSuperclassOf (outputSubstType)
487
498
&& " should be inheritance relationship between input and output" );
488
499
return SGF.B .createUncheckedRefCast (Loc, v, loweredResultTy);
@@ -2807,11 +2818,14 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
2807
2818
// / \param inputSubstType Formal AST type of function value being thunked
2808
2819
// / \param outputOrigType Abstraction pattern of the thunk
2809
2820
// / \param outputSubstType Formal AST type of the thunk
2821
+ // / \param dynamicSelfType If true, the last parameter is a dummy used to pass
2822
+ // / DynamicSelfType metadata
2810
2823
static void buildThunkBody (SILGenFunction &SGF, SILLocation loc,
2811
2824
AbstractionPattern inputOrigType,
2812
2825
CanAnyFunctionType inputSubstType,
2813
2826
AbstractionPattern outputOrigType,
2814
- CanAnyFunctionType outputSubstType) {
2827
+ CanAnyFunctionType outputSubstType,
2828
+ CanType dynamicSelfType) {
2815
2829
PrettyStackTraceSILFunction stackTrace (" emitting reabstraction thunk in" ,
2816
2830
&SGF.F );
2817
2831
auto thunkType = SGF.F .getLoweredFunctionType ();
@@ -2821,6 +2835,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
2821
2835
SmallVector<ManagedValue, 8 > params;
2822
2836
SGF.collectThunkParams (loc, params);
2823
2837
2838
+ // Ignore the self parameter at the SIL level. IRGen will use it to
2839
+ // recover type metadata.
2840
+ if (dynamicSelfType)
2841
+ params.pop_back ();
2842
+
2824
2843
ManagedValue fnValue = params.pop_back_val ();
2825
2844
auto fnType = fnValue.getType ().castTo <SILFunctionType>();
2826
2845
assert (!fnType->isPolymorphic ());
@@ -2970,6 +2989,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
2970
2989
CanType &outputSubstType,
2971
2990
GenericEnvironment *&genericEnv,
2972
2991
SubstitutionMap &interfaceSubs,
2992
+ CanType &dynamicSelfType,
2973
2993
bool withoutActuallyEscaping) {
2974
2994
assert (!expectedType->isPolymorphic ());
2975
2995
assert (!sourceType->isPolymorphic ());
@@ -3069,6 +3089,18 @@ CanSILFunctionType SILGenFunction::buildThunkType(
3069
3089
? contextConvention
3070
3090
: ParameterConvention::Direct_Unowned});
3071
3091
3092
+ // If this thunk involves DynamicSelfType in any way, add a capture for it
3093
+ // in case we need to recover metadata.
3094
+ if (sourceType->hasDynamicSelfType () ||
3095
+ expectedType->hasDynamicSelfType ()) {
3096
+ dynamicSelfType = F.getSelfMetadataArgument ()->getType ().getASTType ();
3097
+ if (!isa<MetatypeType>(dynamicSelfType)) {
3098
+ dynamicSelfType = CanMetatypeType::get (dynamicSelfType,
3099
+ MetatypeRepresentation::Thick);
3100
+ }
3101
+ params.push_back ({dynamicSelfType, ParameterConvention::Direct_Unowned});
3102
+ }
3103
+
3072
3104
// Map the parameter and expected types out of context to get the interface
3073
3105
// type of the thunk.
3074
3106
SmallVector<SILParameterInfo, 4 > interfaceParams;
@@ -3136,11 +3168,13 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3136
3168
GenericEnvironment *genericEnv = nullptr ;
3137
3169
auto toType = expectedType->getWithExtInfo (
3138
3170
expectedType->getExtInfo ().withNoEscape (false ));
3171
+ CanType dynamicSelfType;
3139
3172
auto thunkType = SGF.buildThunkType (sourceType, toType,
3140
3173
inputSubstType,
3141
3174
outputSubstType,
3142
3175
genericEnv,
3143
- interfaceSubs);
3176
+ interfaceSubs,
3177
+ dynamicSelfType);
3144
3178
auto thunk = SGF.SGM .getOrCreateReabstractionThunk (
3145
3179
thunkType,
3146
3180
sourceType,
@@ -3156,7 +3190,8 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3156
3190
inputOrigType,
3157
3191
inputSubstType,
3158
3192
outputOrigType,
3159
- outputSubstType);
3193
+ outputSubstType,
3194
+ dynamicSelfType);
3160
3195
}
3161
3196
3162
3197
CanSILFunctionType substFnType = thunkType;
@@ -3168,10 +3203,18 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3168
3203
3169
3204
// Create it in our current function.
3170
3205
auto thunkValue = SGF.B .createFunctionRefFor (loc, thunk);
3206
+ SmallVector<ManagedValue, 2 > thunkArgs;
3207
+ thunkArgs.push_back (fn.ensurePlusOne (SGF, loc));
3208
+ if (dynamicSelfType) {
3209
+ SILType dynamicSILType = SGF.getLoweredType (dynamicSelfType);
3210
+ SILValue value = SGF.B .createMetatype (loc, dynamicSILType);
3211
+ thunkArgs.push_back (ManagedValue::forUnmanaged (value));
3212
+ }
3213
+
3171
3214
ManagedValue thunkedFn =
3172
3215
SGF.B .createPartialApply (loc, thunkValue,
3173
3216
SILType::getPrimitiveObjectType (substFnType),
3174
- interfaceSubs, fn. ensurePlusOne (SGF, loc) ,
3217
+ interfaceSubs, thunkArgs ,
3175
3218
SILType::getPrimitiveObjectType (toType));
3176
3219
3177
3220
if (!expectedType->isNoEscape ()) {
@@ -3193,10 +3236,14 @@ static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
3193
3236
noEscapingType->getExtInfo ().withNoEscape (false ));
3194
3237
3195
3238
CanType inputSubstType, outputSubstType;
3196
- return SGF.buildThunkType (noEscapingType, escapingType,
3197
- inputSubstType, outputSubstType,
3198
- genericEnv, interfaceSubs,
3199
- /* withoutActuallyEscaping=*/ true );
3239
+ CanType dynamicSelfType;
3240
+ auto type = SGF.buildThunkType (noEscapingType, escapingType,
3241
+ inputSubstType, outputSubstType,
3242
+ genericEnv, interfaceSubs,
3243
+ dynamicSelfType,
3244
+ /* withoutActuallyEscaping=*/ true );
3245
+ assert (!dynamicSelfType && " not implemented" );
3246
+ return type;
3200
3247
}
3201
3248
3202
3249
static void buildWithoutActuallyEscapingThunkBody (SILGenFunction &SGF) {
@@ -3973,8 +4020,11 @@ SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
3973
4020
// type
3974
4021
CanType inputSubstType;
3975
4022
CanType outputSubstType;
4023
+ CanType dynamicSelfType;
3976
4024
auto thunkTy = buildThunkType (nonCanonicalTy, canonicalTy, inputSubstType,
3977
- outputSubstType, genericEnv, interfaceSubs);
4025
+ outputSubstType, genericEnv, interfaceSubs,
4026
+ dynamicSelfType);
4027
+ assert (!dynamicSelfType && " not implemented" );
3978
4028
auto thunk = SGM.getOrCreateReabstractionThunk (thunkTy, nonCanonicalTy,
3979
4029
canonicalTy, F.isSerialized ());
3980
4030
if (thunk->empty ()) {
0 commit comments