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
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
index 49ef519..59b2953 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
@@ -1166,6 +1166,28 @@
return nullptr;
}
+static bool isUninitializedMetatypeInst(SILInstruction *I) {
+ // A simple reference to "type(of:)" is always fine,
+ // even if self is uninitialized.
+ if (isa<ValueMetatypeInst>(I))
+ return true;
+
+ // Sometimes we get an upcast whose sole usage is a value_metatype_inst,
+ // for example when calling a convenience initializer from a superclass.
+ if (auto *UCI = dyn_cast<UpcastInst>(I)) {
+ for (auto *UI : UCI->getUses()) {
+ auto *User = UI->getUser();
+ if (isa<ValueMetatypeInst>(User))
+ continue;
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
/// isSelfInitUse - Return true if this apply_inst is a call to self.init.
static bool isSelfInitUse(SILInstruction *I) {
// If we're reading a .sil file, treat a call to "selfinit" as a
@@ -1354,11 +1376,8 @@
Kind = DIUseKind::SelfInit;
UseInfo.trackFailableInitCall(TheMemory, User);
}
-
- // If this is a ValueMetatypeInst, this is a simple reference
- // to "type(of:)", which is always fine, even if self is
- // uninitialized.
- if (isa<ValueMetatypeInst>(User))
+
+ if (isUninitializedMetatypeInst(User))
continue;
// If this is a partial application of self, then this is an escape point
@@ -1630,11 +1649,8 @@
}
}
- // A simple reference to "type(of:)" is always fine,
- // even if self is uninitialized.
- if (isa<ValueMetatypeInst>(User)) {
+ if (isUninitializedMetatypeInst(User))
continue;
- }
UseInfo.trackUse(DIMemoryUse(User, Kind, 0, 1));
}
diff --git a/test/SILOptimizer/definite_init_objc_factory_init.swift b/test/SILOptimizer/definite_init_objc_factory_init.swift
index 30e6524c..855a990 100644
--- a/test/SILOptimizer/definite_init_objc_factory_init.swift
+++ b/test/SILOptimizer/definite_init_objc_factory_init.swift
@@ -52,3 +52,20 @@
self.init(value: double)
}
}
+
+class SubHive : Hive {
+ // CHECK-LABEL: sil hidden @_T0027definite_init_objc_factory_B07SubHiveCACyt20delegatesToInherited_tcfc : $@convention(method) (@owned SubHive) -> @owned SubHive
+ convenience init(delegatesToInherited: ()) {
+ // CHECK: [[UPCAST:%.*]] = upcast %0 : $SubHive to $Hive
+ // CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST]] : $Hive
+ // CHECK: [[METHOD:%.*]] = class_method [volatile] [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
+ // CHECK: [[OBJC:%.*]] = thick_to_objc_metatype [[METATYPE]] : $@thick Hive.Type to $@objc_metatype Hive.Type
+ // CHECK: apply [[METHOD]]({{.*}}, [[OBJC]])
+
+ // CHECK: [[METATYPE:%.*]] = value_metatype $@thick SubHive.Type, %0 : $SubHive
+ // CHECK-NEXT: dealloc_partial_ref %0 : $SubHive, [[METATYPE]] : $@thick SubHive.Type
+
+ // CHECK: return {{%.*}} : $SubHive
+ self.init(queen: Bee())
+ }
+}