Skip to content

Commit 7f2b01c

Browse files
committed
DI: Fix crash when value_metatype was used with a non-class 'self' type
In a constructor, SILGen lowers type(of: self) to a value_metatype instruction, but 'self' might not have been initialized yet if this is a convenience initializer, so we replace it with a use of the 'self' metatype argument. However getDynamicSelfMetadata() asserts if 'self' is a non-class type. Since we know we're inside of a proper method here and not a closure that captured 'self', we can use getSelfArgument() instead. Fixes https://bugs.swift.org/browse/SR-12665 / rdar://problem/62481587.
1 parent 360e406 commit 7f2b01c

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(DIMemoryUse &Use) {
850850
break;
851851
}
852852
assert(valueMetatype);
853-
SILValue metatypeArgument = load->getFunction()->getDynamicSelfMetadata();
853+
SILValue metatypeArgument = load->getFunction()->getSelfArgument();
854854

855855
// SILFunction parameter types never have a DynamicSelfType, since it only
856856
// makes sense in the context of a given method's body. Since the

test/SILOptimizer/definite_init_type_of_self_in_convenience_init.swift

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-swift-emit-sil -swift-version 4 -verify %s
2-
// RUN: %target-swift-emit-sil -swift-version 5 -verify %s
1+
// RUN: %target-swift-emit-sil -swift-version 4 -verify %s | %FileCheck %s
2+
// RUN: %target-swift-emit-sil -swift-version 5 -verify %s | %FileCheck %s
33

44
// Integration test to ensure that `type(of: self)` keeps working in
55
// class convenience initializers, even though they are now implemented as
@@ -46,3 +46,63 @@ class C {
4646
self.init()
4747
}
4848
}
49+
50+
protocol P {
51+
static var n: Int { get }
52+
init(_: Int)
53+
}
54+
55+
extension P {
56+
// FIXME: SILGen inserts an unnecessary copy when 'self' is
57+
// address-only.
58+
/* init(selfInit: ()) {
59+
self.init(type(of: self).n)
60+
}
61+
62+
init(selfAssign: ()) {
63+
self = type(of: self).init(0)
64+
} */
65+
}
66+
67+
protocol PA : AnyObject {
68+
static var n: Int { get }
69+
init(_: Int)
70+
}
71+
72+
extension PA {
73+
init(selfInit: ()) {
74+
// This is OK; we can get the type of 'self' from the self metatype
75+
// argument.
76+
self.init(type(of: self).n)
77+
}
78+
79+
// FIXME: Not yet supported, but should be
80+
/* init(selfAssign: ()) {
81+
self = type(of: self).init(0)
82+
} */
83+
}
84+
85+
class CC {
86+
class var n: Int { 0 }
87+
required init(_: Int) {}
88+
}
89+
90+
protocol PC : CC {}
91+
92+
extension PC {
93+
// CHECK-LABEL: sil hidden @$s042definite_init_type_of_self_in_convenience_B02PCPAAE0E4Initxyt_tcfC : $@convention(method) <Self where Self : PC> (@thick Self.Type) -> @owned Self {
94+
init(selfInit: ()) {
95+
// This is OK; we can get the type of 'self' from the self metatype
96+
// argument.
97+
self.init(type(of: self).n)
98+
99+
// CHECK: [[SELF:%.*]] = upcast %0 : $@thick Self.Type to $@thick CC.Type
100+
// CHECK: [[INIT:%.*]] = class_method [[SELF]] : $@thick CC.Type, #CC.init!allocator : (CC.Type) -> (Int) -> CC, $@convention(method) (Int, @thick CC.Type) -> @owned CC
101+
// CHECK: apply [[INIT]]({{.*}}, [[SELF]]) : $@convention(method) (Int, @thick CC.Type) -> @owned CC
102+
}
103+
104+
// FIXME: Not yet supported, but should be
105+
/* init(selfAssign: ()) {
106+
self = type(of: self).init(0)
107+
} */
108+
}

0 commit comments

Comments
 (0)