Skip to content

Commit c7fe50d

Browse files
committed
SILGen: Fix function conversions involving DynamicSelfType
This was partially implemented but the check looked at the lowered types and not the AST types, and DynamicSelfType is erased at the top level of a lowered type. Also use the new mangling for reabstraction thunks with self, to ensure we don't emit the same symbol with two different lowered types. Fixes <https://bugs.swift.org/browse/SR-10309>, <rdar://problem/49703441>.
1 parent c3f7e85 commit c7fe50d

File tree

8 files changed

+78
-34
lines changed

8 files changed

+78
-34
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class ASTMangler : public Mangler {
143143

144144
std::string mangleReabstractionThunkHelper(CanSILFunctionType ThunkType,
145145
Type FromType, Type ToType,
146+
Type SelfType,
146147
ModuleDecl *Module);
147148

148149
std::string mangleKeyPathGetterThunkHelper(const AbstractStorageDecl *property,

lib/AST/ASTMangler.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ std::string ASTMangler::mangleReabstractionThunkHelper(
344344
CanSILFunctionType ThunkType,
345345
Type FromType,
346346
Type ToType,
347+
Type SelfType,
347348
ModuleDecl *Module) {
348349
Mod = Module;
349350
GenericSignature *GenSig = ThunkType->getGenericSignature();
@@ -353,10 +354,17 @@ std::string ASTMangler::mangleReabstractionThunkHelper(
353354
beginMangling();
354355
appendType(FromType);
355356
appendType(ToType);
357+
if (SelfType)
358+
appendType(SelfType);
359+
356360
if (GenSig)
357361
appendGenericSignature(GenSig);
358-
// TODO: mangle ThunkType->isPseudogeneric()
359-
appendOperator("TR");
362+
363+
if (SelfType)
364+
appendOperator("Ty");
365+
else
366+
appendOperator("TR");
367+
360368
return finalize();
361369
}
362370

lib/SILGen/SILGen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
173173
CanSILFunctionType thunkType,
174174
CanSILFunctionType fromType,
175175
CanSILFunctionType toType,
176-
IsSerialized_t Serialized);
176+
CanType dynamicSelfType);
177177

178178
/// Determine whether the given class has any instance variables that
179179
/// need to be destroyed.

lib/SILGen/SILGenBridging.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc,
577577
auto thunk = SGM.getOrCreateReabstractionThunk(invokeTy,
578578
loweredFuncTy,
579579
loweredBlockTy,
580-
F.isSerialized());
580+
/*dynamicSelfType=*/CanType());
581581

582582
// Build it if necessary.
583583
if (thunk->empty()) {
@@ -937,7 +937,7 @@ SILGenFunction::emitBlockToFunc(SILLocation loc,
937937
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy,
938938
loweredBlockTy,
939939
loweredFuncTyWithoutNoEscape,
940-
F.isSerialized());
940+
/*dynamicSelfType=*/CanType());
941941

942942
// Build it if necessary.
943943
if (thunk->empty()) {

lib/SILGen/SILGenPoly.cpp

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,16 +3041,23 @@ CanSILFunctionType SILGenFunction::buildThunkType(
30413041
expectedType = cast<SILFunctionType>(
30423042
substIntoThunkContext(expectedType));
30433043

3044+
bool hasDynamicSelf = false;
3045+
30443046
if (inputSubstType) {
30453047
inputSubstType = cast<AnyFunctionType>(
30463048
substIntoThunkContext(inputSubstType));
3049+
hasDynamicSelf |= inputSubstType->hasDynamicSelfType();
30473050
}
30483051

30493052
if (outputSubstType) {
30503053
outputSubstType = cast<AnyFunctionType>(
30513054
substIntoThunkContext(outputSubstType));
3055+
hasDynamicSelf |= outputSubstType->hasDynamicSelfType();
30523056
}
30533057

3058+
hasDynamicSelf |= sourceType->hasDynamicSelfType();
3059+
hasDynamicSelf |= expectedType->hasDynamicSelfType();
3060+
30543061
// If our parent function was pseudogeneric, this thunk must also be
30553062
// pseudogeneric, since we have no way to pass generic parameters.
30563063
if (genericSig)
@@ -3072,8 +3079,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
30723079

30733080
// If this thunk involves DynamicSelfType in any way, add a capture for it
30743081
// in case we need to recover metadata.
3075-
if (sourceType->hasDynamicSelfType() ||
3076-
expectedType->hasDynamicSelfType()) {
3082+
if (hasDynamicSelf) {
30773083
dynamicSelfType = F.getSelfMetadataArgument()->getType().getASTType();
30783084
if (!isa<MetatypeType>(dynamicSelfType)) {
30793085
dynamicSelfType = CanMetatypeType::get(dynamicSelfType,
@@ -3127,6 +3133,36 @@ CanSILFunctionType SILGenFunction::buildThunkType(
31273133
getASTContext());
31283134
}
31293135

3136+
static ManagedValue createPartialApplyOfThunk(SILGenFunction &SGF,
3137+
SILLocation loc,
3138+
SILFunction *thunk,
3139+
SubstitutionMap interfaceSubs,
3140+
CanType dynamicSelfType,
3141+
CanSILFunctionType toType,
3142+
ManagedValue fn) {
3143+
CanSILFunctionType substFnType = thunk->getLoweredFunctionType();
3144+
3145+
if (substFnType->getGenericSignature()) {
3146+
substFnType = substFnType->substGenericArgs(SGF.F.getModule(),
3147+
interfaceSubs);
3148+
}
3149+
3150+
auto thunkValue = SGF.B.createFunctionRefFor(loc, thunk);
3151+
SmallVector<ManagedValue, 2> thunkArgs;
3152+
thunkArgs.push_back(fn);
3153+
if (dynamicSelfType) {
3154+
SILType dynamicSILType = SGF.getLoweredType(dynamicSelfType);
3155+
SILValue value = SGF.B.createMetatype(loc, dynamicSILType);
3156+
thunkArgs.push_back(ManagedValue::forUnmanaged(value));
3157+
}
3158+
3159+
return
3160+
SGF.B.createPartialApply(loc, thunkValue,
3161+
SILType::getPrimitiveObjectType(substFnType),
3162+
interfaceSubs, thunkArgs,
3163+
SILType::getPrimitiveObjectType(toType));
3164+
}
3165+
31303166
/// Create a reabstraction thunk.
31313167
static ManagedValue createThunk(SILGenFunction &SGF,
31323168
SILLocation loc,
@@ -3160,7 +3196,7 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31603196
thunkType,
31613197
sourceType,
31623198
toType,
3163-
SGF.F.isSerialized());
3199+
dynamicSelfType);
31643200

31653201
// Build it if necessary.
31663202
if (thunk->empty()) {
@@ -3175,28 +3211,9 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31753211
dynamicSelfType);
31763212
}
31773213

3178-
CanSILFunctionType substFnType = thunkType;
3179-
3180-
if (thunkType->getGenericSignature()) {
3181-
substFnType = thunkType->substGenericArgs(SGF.F.getModule(),
3182-
interfaceSubs);
3183-
}
3184-
3185-
// Create it in our current function.
3186-
auto thunkValue = SGF.B.createFunctionRefFor(loc, thunk);
3187-
SmallVector<ManagedValue, 2> thunkArgs;
3188-
thunkArgs.push_back(fn.ensurePlusOne(SGF, loc));
3189-
if (dynamicSelfType) {
3190-
SILType dynamicSILType = SGF.getLoweredType(dynamicSelfType);
3191-
SILValue value = SGF.B.createMetatype(loc, dynamicSILType);
3192-
thunkArgs.push_back(ManagedValue::forUnmanaged(value));
3193-
}
3194-
3195-
ManagedValue thunkedFn =
3196-
SGF.B.createPartialApply(loc, thunkValue,
3197-
SILType::getPrimitiveObjectType(substFnType),
3198-
interfaceSubs, thunkArgs,
3199-
SILType::getPrimitiveObjectType(toType));
3214+
auto thunkedFn =
3215+
createPartialApplyOfThunk(SGF, loc, thunk, interfaceSubs, dynamicSelfType,
3216+
toType, fn.ensurePlusOne(SGF, loc));
32003217

32013218
if (!expectedType->isNoEscape()) {
32023219
return thunkedFn;
@@ -3284,7 +3301,8 @@ SILGenFunction::createWithoutActuallyEscapingClosure(
32843301
*this, noEscapingFnTy, escapingFnTy, genericEnv, interfaceSubs);
32853302

32863303
auto *thunk = SGM.getOrCreateReabstractionThunk(
3287-
thunkType, noEscapingFnTy, escapingFnTy, F.isSerialized());
3304+
thunkType, noEscapingFnTy, escapingFnTy,
3305+
/*dynamicSelfType=*/CanType());
32883306

32893307
if (thunk->empty()) {
32903308
thunk->setWithoutActuallyEscapingThunk();

lib/SILGen/SILGenThunk.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ SILFunction *SILGenModule::
300300
getOrCreateReabstractionThunk(CanSILFunctionType thunkType,
301301
CanSILFunctionType fromType,
302302
CanSILFunctionType toType,
303-
IsSerialized_t Serialized) {
303+
CanType dynamicSelfType) {
304304
// The reference to the thunk is likely @noescape, but declarations are always
305305
// escaping.
306306
auto thunkDeclType =
@@ -315,7 +315,8 @@ getOrCreateReabstractionThunk(CanSILFunctionType thunkType,
315315

316316
Mangle::ASTMangler NewMangler;
317317
std::string name = NewMangler.mangleReabstractionThunkHelper(thunkType,
318-
fromInterfaceType, toInterfaceType, M.getSwiftModule());
318+
fromInterfaceType, toInterfaceType, dynamicSelfType,
319+
M.getSwiftModule());
319320

320321
auto loc = RegularLocation::getAutoGeneratedLocation();
321322

test/SILGen/dynamic_self.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,22 @@ class SelfReplaceClass : SelfReplaceable {
414414
}
415415
}
416416

417+
public protocol EmptyProtocol { }
418+
419+
public extension EmptyProtocol {
420+
func run(_: (Self) -> ()) { }
421+
}
422+
423+
public class FunctionConversionTest : EmptyProtocol {
424+
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self22FunctionConversionTestC07convertC0yACXDyypXEF : $@convention(method) (@noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed FunctionConversionTest) -> @owned FunctionConversionTest {
425+
func convertFunction(_ fn: (Any) -> ()) -> Self {
426+
// The reabstraction thunk captures a self metatype here:
427+
// CHECK: function_ref @$s12dynamic_self22FunctionConversionTestCIgg_ACIegn_ACXMTTy : $@convention(thin) (@in_guaranteed FunctionConversionTest, @noescape @callee_guaranteed (@guaranteed FunctionConversionTest) -> (), @thick FunctionConversionTest.Type) -> ()
428+
run(fn)
429+
return self
430+
}
431+
}
432+
417433
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
418434
// CHECK: method #P.f!1: {{.*}} : @$s12dynamic_self1XCAA1PA2aDP1f{{[_0-9a-zA-Z]*}}FTW
419435

test/SILGen/function_conversion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ func convFuncExistential(_ f1: @escaping (Any) -> (Int) -> Int) {
338338

339339
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$sypS2iIegyd_Iegno_S2iIegyd_ypIeggr_TR : $@convention(thin) (@guaranteed @callee_guaranteed (Int) -> Int, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> @owned @callee_guaranteed (Int) -> Int) -> @out Any {
340340
// CHECK: alloc_stack $Any
341+
// CHECK: [[COPIED_VAL:%.*]] = copy_value
341342
// CHECK: function_ref @$sS2iIegyd_S2iIegnr_TR
342-
// CHECK-NEXT: [[COPIED_VAL:%.*]] = copy_value
343343
// CHECK-NEXT: partial_apply [callee_guaranteed] {{%.*}}([[COPIED_VAL]])
344344
// CHECK-NEXT: init_existential_addr %3 : $*Any, $(Int) -> Int
345345
// CHECK-NEXT: store

0 commit comments

Comments
 (0)