Skip to content

Commit 999836b

Browse files
authored
Merge pull request swiftlang#29141 from slavapestov/capture-two-values-and-crash
SILGen: Fix crash when a closure captures two values with dynamic 'Self' type
2 parents d43dc84 + 0e801c6 commit 999836b

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

lib/SIL/TypeLowering.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,9 +2300,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
23002300
continue;
23012301

23022302
// We can always capture the storage in these cases.
2303-
Type captureType = capturedVar->getType();
2304-
if (auto *metatypeType = captureType->getAs<MetatypeType>())
2305-
captureType = metatypeType->getInstanceType();
2303+
Type captureType = capturedVar->getType()->getMetatypeInstanceType();
23062304

23072305
if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
23082306
captureType = selfType->getSelfType();
@@ -2314,11 +2312,22 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
23142312
// mutable, we're going to be capturing a box or an address.
23152313
if (captureType->getClassOrBoundGenericClass() &&
23162314
capturedVar->isLet()) {
2317-
if (selfCapture)
2315+
// If we've already captured the same value already, just merge
2316+
// flags.
2317+
if (selfCapture && selfCapture->getDecl() == capture.getDecl()) {
23182318
selfCapture = selfCapture->mergeFlags(capture);
2319-
else
2319+
continue;
2320+
2321+
// Otherwise, record the canonical self capture. It will appear
2322+
// at the end of the capture list.
2323+
} else if (!selfCapture) {
23202324
selfCapture = capture;
2321-
continue;
2325+
continue;
2326+
}
2327+
2328+
// If we end up here, we have multiple different captured values
2329+
// with a dynamic 'Self' type. Handle this and any subsequent
2330+
// captures via the normal code path below.
23222331
}
23232332
}
23242333

test/SILGen/dynamic_self.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,25 @@ public class FunctionConversionTest : EmptyProtocol {
442442
}
443443
}
444444

445+
public class CaptureTwoValuesTest {
446+
public required init() {}
447+
448+
// CHECK-LABEL: sil [ossa] @$s12dynamic_self20CaptureTwoValuesTestC08capturesdE0yyFZ : $@convention(method) (@thick CaptureTwoValuesTest.Type) -> () {
449+
public static func capturesTwoValues() {
450+
let a = Self()
451+
let b = Self()
452+
453+
// CHECK: function_ref @$s12dynamic_self20CaptureTwoValuesTestC08capturesdE0yyFZyycfU_ : $@convention(thin) (@guaranteed CaptureTwoValuesTest, @guaranteed CaptureTwoValuesTest) -> ()
454+
_ = {
455+
_ = a
456+
_ = b
457+
_ = Self.self
458+
}
459+
460+
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self20CaptureTwoValuesTestC08capturesdE0yyFZyycfU_ : $@convention(thin) (@guaranteed CaptureTwoValuesTest, @guaranteed CaptureTwoValuesTest) -> () {
461+
}
462+
}
463+
445464
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
446465
// CHECK: method #P.f!1: {{.*}} : @$s12dynamic_self1XCAA1PA2aDP1f{{[_0-9a-zA-Z]*}}FTW
447466

0 commit comments

Comments
 (0)