Skip to content

Commit 121a56e

Browse files
authored
Merge pull request #16900 from slavapestov/fix-non-required-base-class-convenience-init-witness-4.2
SILGen: Fix invalid SIL emitted when protocol requirement witnessed by base class convenience init [4.2]
2 parents a1ec630 + e8a4f48 commit 121a56e

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

lib/SILGen/SILGenPoly.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3346,11 +3346,20 @@ static WitnessDispatchKind getWitnessDispatchKind(SILDeclRef witness) {
33463346
// A natively ObjC method witness referenced this way will end up going
33473347
// through its native thunk, which will redispatch the method after doing
33483348
// bridging just like we want.
3349-
if (isFinal || isExtension || witness.isForeignToNativeThunk()
3350-
// Hack--We emit a static thunk for ObjC allocating constructors.
3351-
|| (decl->hasClangNode() && witness.kind == SILDeclRef::Kind::Allocator))
3349+
if (isFinal || isExtension || witness.isForeignToNativeThunk())
33523350
return WitnessDispatchKind::Static;
33533351

3352+
if (witness.kind == SILDeclRef::Kind::Allocator) {
3353+
// Non-required initializers can witness a protocol requirement if the class
3354+
// is final, so we can statically dispatch to them.
3355+
if (!cast<ConstructorDecl>(decl)->isRequired())
3356+
return WitnessDispatchKind::Static;
3357+
3358+
// We emit a static thunk for ObjC allocating constructors.
3359+
if (decl->hasClangNode())
3360+
return WitnessDispatchKind::Static;
3361+
}
3362+
33543363
// Otherwise emit a class method.
33553364
return WitnessDispatchKind::Class;
33563365
}

test/SILGen/witness-init-requirement-with-base-class-init.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,32 @@ class Dog: Animal, BestFriend {}
2020
// CHECK-LABEL: sil private [transparent] [thunk] @$S4main3DogCAA10BestFriendA2aDP6createxyFZTW
2121
// CHECK: [[SELF:%.*]] = apply
2222
// CHECK: unchecked_ref_cast [[SELF]] : $Animal to $Dog
23+
24+
class Base {
25+
init() {}
26+
27+
convenience init(x: Int) {
28+
self.init()
29+
}
30+
}
31+
32+
protocol Initable {
33+
init(x: Int)
34+
}
35+
36+
final class Derived : Base, Initable {}
37+
38+
// CHECK-LABEL: sil hidden @$S4main4BaseC1xACSi_tcfC : $@convention(method) (Int, @thick Base.Type) -> @owned Base
39+
// CHECK: [[SELF:%.*]] = alloc_ref_dynamic %1 : $@thick Base.Type, $Base
40+
// CHECK: [[METHOD:%.*]] = function_ref @$S4main4BaseC1xACSi_tcfc
41+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]](%0, [[SELF]])
42+
// CHECK-NEXT: return [[RESULT]]
43+
44+
// CHECK-LABEL: sil private [transparent] [thunk] @$S4main7DerivedCAA8InitableA2aDP1xxSi_tcfCTW : $@convention(witness_method: Initable) (Int, @thick Derived.Type) -> @out Derived
45+
// CHECK: [[SELF:%.*]] = upcast %2 : $@thick Derived.Type to $@thick Base.Type
46+
// CHECK: [[METHOD:%.*]] = function_ref @$S4main4BaseC1xACSi_tcfC
47+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]](%1, [[SELF]])
48+
// CHECK-NEXT: [[NEW_SELF:%.*]] = unchecked_ref_cast [[RESULT]] : $Base to $Derived
49+
// CHECK-NEXT: store [[NEW_SELF]] to [init] %0 : $*Derived
50+
// CHECK-NEXT: [[TUPLE:%.*]] = tuple ()
51+
// CHECK-NEXT: return [[TUPLE]]

0 commit comments

Comments
 (0)