Skip to content

Commit c1404c4

Browse files
authored
Merge pull request #29142 from slavapestov/capture-two-values-and-crash-5.2
SILGen: Fix crash when a closure captures two values with dynamic 'Self' type [5.2]
2 parents b6b943e + bc42289 commit c1404c4

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
@@ -2288,9 +2288,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
22882288
continue;
22892289

22902290
// We can always capture the storage in these cases.
2291-
Type captureType = capturedVar->getType();
2292-
if (auto *metatypeType = captureType->getAs<MetatypeType>())
2293-
captureType = metatypeType->getInstanceType();
2291+
Type captureType = capturedVar->getType()->getMetatypeInstanceType();
22942292

22952293
if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
22962294
captureType = selfType->getSelfType();
@@ -2302,11 +2300,22 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
23022300
// mutable, we're going to be capturing a box or an address.
23032301
if (captureType->getClassOrBoundGenericClass() &&
23042302
capturedVar->isLet()) {
2305-
if (selfCapture)
2303+
// If we've already captured the same value already, just merge
2304+
// flags.
2305+
if (selfCapture && selfCapture->getDecl() == capture.getDecl()) {
23062306
selfCapture = selfCapture->mergeFlags(capture);
2307-
else
2307+
continue;
2308+
2309+
// Otherwise, record the canonical self capture. It will appear
2310+
// at the end of the capture list.
2311+
} else if (!selfCapture) {
23082312
selfCapture = capture;
2309-
continue;
2313+
continue;
2314+
}
2315+
2316+
// If we end up here, we have multiple different captured values
2317+
// with a dynamic 'Self' type. Handle this and any subsequent
2318+
// captures via the normal code path below.
23102319
}
23112320
}
23122321

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)