Skip to content

Commit 84ed245

Browse files
committed
DI: Fix transformation of value_metatype inside convenience init in Swift 5 mode
In Swift 5 mode, 'self' in a convenience init has a DynamicSelfType, so the value_metatype instruction returns a DynamicSelfType metatype. However, the metatype argument to the constructor is a plain class metatype because it's an interface type, so we have to "open" it by bitcasting it to a DynamicSelfType. Fixes <https://bugs.swift.org/browse/SR-9430>, <rdar://problem/46982573>.
1 parent ae6cea7 commit 84ed245

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,30 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(const DIMemoryUse &Use) {
834834
break;
835835
}
836836
assert(valueMetatype);
837-
auto metatypeArgument = load->getFunction()->getSelfMetadataArgument();
837+
SILValue metatypeArgument = load->getFunction()->getSelfMetadataArgument();
838+
839+
// SILFunction parameter types never have a DynamicSelfType, since it only
840+
// makes sense in the context of a given method's body. Since the
841+
// value_metatype instruction might produce a DynamicSelfType we have to
842+
// cast the metatype argument.
843+
//
844+
// FIXME: Semantically, we're "opening" the class metatype here to produce
845+
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
846+
// archetype associated with the original metatype or class instance value,
847+
// instead of as a "global" type.
848+
auto metatypeSelfType = metatypeArgument->getType()
849+
.castTo<MetatypeType>().getInstanceType();
850+
auto valueSelfType = valueMetatype->getType()
851+
.castTo<MetatypeType>().getInstanceType();
852+
if (metatypeSelfType != valueSelfType) {
853+
assert(metatypeSelfType ==
854+
cast<DynamicSelfType>(valueSelfType).getSelfType());
855+
856+
SILBuilderWithScope B(valueMetatype);
857+
metatypeArgument = B.createUncheckedTrivialBitCast(
858+
valueMetatype->getLoc(), metatypeArgument,
859+
valueMetatype->getType());
860+
}
838861
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument,
839862
[](SILInstruction*) { });
840863
}

test/SILOptimizer/definite_init_type_of_self_in_convenience_init.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
// RUN: %target-swift-emit-sil -verify %s
1+
// RUN: %target-swift-emit-sil -swift-version 4 -verify %s
2+
// RUN: %target-swift-emit-sil -swift-version 5 -verify %s
23

34
// Integration test to ensure that `type(of: self)` keeps working in
45
// class convenience initializers, even though they are now implemented as
56
// allocating entry points.
67

78
class C {
8-
init() { }
9-
init(throwingDesignated: ()) throws {}
9+
required init() { }
10+
required init(throwingDesignated: ()) throws {}
1011

1112
convenience init(normal: ()) {
1213
_ = (type(of: self), type(of: self))
@@ -37,4 +38,11 @@ class C {
3738
}
3839
_ = (type(of: self), type(of: self))
3940
}
41+
42+
convenience init(closureCapture: ()) {
43+
let t = type(of: self)
44+
let fn = { t.init() }
45+
_ = fn()
46+
self.init()
47+
}
4048
}

0 commit comments

Comments
 (0)