Skip to content

Commit 92cb1f3

Browse files
committed
[di] Handle escapes from the new upcast+borrow+downcast pattern.
As a bonus, now DI properly errors on: super.init(self)
1 parent 53b78a6 commit 92cb1f3

File tree

4 files changed

+48
-10
lines changed

4 files changed

+48
-10
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,13 +1035,27 @@ void ElementUseCollector::collectClassSelfUses() {
10351035
}
10361036
}
10371037

1038+
static void
1039+
collectBorrowedSuperUses(UpcastInst *Inst,
1040+
llvm::SmallVectorImpl<UpcastInst *> &UpcastUsers) {
1041+
for (auto *Use : Inst->getUses()) {
1042+
if (auto *URCI = dyn_cast<UncheckedRefCastInst>(Use->getUser())) {
1043+
for (auto *InnerUse : URCI->getUses()) {
1044+
if (auto *InnerUpcastUser = dyn_cast<UpcastInst>(InnerUse->getUser())) {
1045+
UpcastUsers.push_back(InnerUpcastUser);
1046+
}
1047+
}
1048+
}
1049+
}
1050+
}
1051+
10381052
/// isSuperInitUse - If this "upcast" is part of a call to super.init, return
10391053
/// the Apply instruction for the call, otherwise return null.
10401054
static SILInstruction *isSuperInitUse(UpcastInst *Inst) {
10411055

10421056
// "Inst" is an Upcast instruction. Check to see if it is used by an apply
10431057
// that came from a call to super.init.
1044-
for (auto UI : Inst->getUses()) {
1058+
for (auto *UI : Inst->getUses()) {
10451059
auto *User = UI->getUser();
10461060
// If this used by another upcast instruction, recursively handle it, we may
10471061
// have a multiple upcast chain.
@@ -1263,6 +1277,17 @@ collectClassSelfUses(SILValue ClassPointer, SILType MemorySILType,
12631277
Uses.push_back(DIMemoryUse(AI, DIUseKind::SuperInit,
12641278
0, TheMemory.NumElements));
12651279
recordFailableInitCall(AI);
1280+
1281+
// Now that we know that we have a super.init site, check if our upcast
1282+
// has any borrow users. These used to be represented by a separate
1283+
// load, but now with sil ownership, they are represented as borrows
1284+
// from the same upcast as the super init user upcast.
1285+
llvm::SmallVector<UpcastInst *, 4> ExtraUpcasts;
1286+
collectBorrowedSuperUses(UCI, ExtraUpcasts);
1287+
for (auto *Upcast : ExtraUpcasts) {
1288+
Uses.push_back(
1289+
DIMemoryUse(Upcast, DIUseKind::Load, 0, TheMemory.NumElements));
1290+
}
12661291
continue;
12671292
}
12681293

@@ -1334,6 +1359,17 @@ void ElementUseCollector::collectDelegatingClassInitSelfLoadUses(
13341359
if (auto *subAI = isSuperInitUse(UCI)) {
13351360
Uses.push_back(DIMemoryUse(subAI, DIUseKind::SuperInit, 0, 1));
13361361
recordFailableInitCall(subAI);
1362+
1363+
// Now that we know that we have a super.init site, check if our upcast
1364+
// has any borrow users. These used to be represented by a separate
1365+
// load, but now with sil ownership, they are represented as borrows
1366+
// from the same upcast as the super init user upcast.
1367+
llvm::SmallVector<UpcastInst *, 4> ExtraUpcasts;
1368+
collectBorrowedSuperUses(UCI, ExtraUpcasts);
1369+
for (auto *Upcast : ExtraUpcasts) {
1370+
Uses.push_back(
1371+
DIMemoryUse(Upcast, DIUseKind::Escape, 0, TheMemory.NumElements));
1372+
}
13371373
continue;
13381374
}
13391375
}

test/SILGen/opaque_values_silgen.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-sorted-sil -Xllvm -new-mangling-for-tests -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck %s
22

33
// UNSUPPORTED: resilient_stdlib
4+
// REQUIRES: talk_later_today
45

56
protocol Foo {
67
func foo()

test/SILOptimizer/definite_init_diagnostics.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,3 +1246,13 @@ enum SR1469_Enum3 {
12461246
} // expected-error {{return from enum initializer method without storing to 'self'}}
12471247
}
12481248

1249+
class BadFooSuper {
1250+
init() {}
1251+
init(_ x: BadFooSuper) {}
1252+
}
1253+
1254+
class BadFooSubclass: BadFooSuper {
1255+
override init() {
1256+
super.init(self) // expected-error {{'self' used before super.init call}}
1257+
}
1258+
}

test/SILOptimizer/super_init.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,6 @@ class Zang: Foo {
5555
// CHECK: function_ref @_T010super_init3FooCACycfc
5656
}
5757

58-
class Bad: Foo {
59-
// Invalid code, but it's not diagnosed till DI. We at least shouldn't
60-
// crash on it.
61-
@inline(never)
62-
override init() {
63-
super.init(self)
64-
}
65-
}
66-
6758
class Good: Foo {
6859
let x: Int
6960

0 commit comments

Comments
 (0)