Skip to content

Commit 5af0266

Browse files
authored
Merge pull request #10193 from slavapestov/self-init-might-have-an-upcast
DI: Fix 'self.init' delegation to an imported factory initializer inherited from a base class
2 parents 337b4cc + 2192470 commit 5af0266

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,28 @@ static SILInstruction *isSuperInitUse(UpcastInst *Inst) {
11661166
return nullptr;
11671167
}
11681168

1169+
static bool isUninitializedMetatypeInst(SILInstruction *I) {
1170+
// A simple reference to "type(of:)" is always fine,
1171+
// even if self is uninitialized.
1172+
if (isa<ValueMetatypeInst>(I))
1173+
return true;
1174+
1175+
// Sometimes we get an upcast whose sole usage is a value_metatype_inst,
1176+
// for example when calling a convenience initializer from a superclass.
1177+
if (auto *UCI = dyn_cast<UpcastInst>(I)) {
1178+
for (auto *UI : UCI->getUses()) {
1179+
auto *User = UI->getUser();
1180+
if (isa<ValueMetatypeInst>(User))
1181+
continue;
1182+
return false;
1183+
}
1184+
1185+
return true;
1186+
}
1187+
1188+
return false;
1189+
}
1190+
11691191
/// isSelfInitUse - Return true if this apply_inst is a call to self.init.
11701192
static bool isSelfInitUse(SILInstruction *I) {
11711193
// If we're reading a .sil file, treat a call to "selfinit" as a
@@ -1354,11 +1376,8 @@ void ElementUseCollector::collectClassSelfUses(
13541376
Kind = DIUseKind::SelfInit;
13551377
UseInfo.trackFailableInitCall(TheMemory, User);
13561378
}
1357-
1358-
// If this is a ValueMetatypeInst, this is a simple reference
1359-
// to "type(of:)", which is always fine, even if self is
1360-
// uninitialized.
1361-
if (isa<ValueMetatypeInst>(User))
1379+
1380+
if (isUninitializedMetatypeInst(User))
13621381
continue;
13631382

13641383
// If this is a partial application of self, then this is an escape point
@@ -1630,11 +1649,8 @@ void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses(
16301649
}
16311650
}
16321651

1633-
// A simple reference to "type(of:)" is always fine,
1634-
// even if self is uninitialized.
1635-
if (isa<ValueMetatypeInst>(User)) {
1652+
if (isUninitializedMetatypeInst(User))
16361653
continue;
1637-
}
16381654

16391655
UseInfo.trackUse(DIMemoryUse(User, Kind, 0, 1));
16401656
}

test/SILOptimizer/definite_init_objc_factory_init.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,20 @@ extension SomeClass {
5252
self.init(value: double)
5353
}
5454
}
55+
56+
class SubHive : Hive {
57+
// CHECK-LABEL: sil hidden @_T0027definite_init_objc_factory_B07SubHiveCACyt20delegatesToInherited_tcfc : $@convention(method) (@owned SubHive) -> @owned SubHive
58+
convenience init(delegatesToInherited: ()) {
59+
// CHECK: [[UPCAST:%.*]] = upcast %0 : $SubHive to $Hive
60+
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST]] : $Hive
61+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
62+
// CHECK: [[OBJC:%.*]] = thick_to_objc_metatype [[METATYPE]] : $@thick Hive.Type to $@objc_metatype Hive.Type
63+
// CHECK: apply [[METHOD]]({{.*}}, [[OBJC]])
64+
65+
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick SubHive.Type, %0 : $SubHive
66+
// CHECK-NEXT: dealloc_partial_ref %0 : $SubHive, [[METATYPE]] : $@thick SubHive.Type
67+
68+
// CHECK: return {{%.*}} : $SubHive
69+
self.init(queen: Bee())
70+
}
71+
}

0 commit comments

Comments
 (0)