Skip to content

Commit b7f7f17

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 ef6b828 commit b7f7f17

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
@@ -837,7 +837,30 @@ void LifetimeChecker::handleLoadForTypeOfSelfUse(const DIMemoryUse &Use) {
837837
break;
838838
}
839839
assert(valueMetatype);
840-
auto metatypeArgument = load->getFunction()->getSelfMetadataArgument();
840+
SILValue metatypeArgument = load->getFunction()->getSelfMetadataArgument();
841+
842+
// SILFunction parameter types never have a DynamicSelfType, since it only
843+
// makes sense in the context of a given method's body. Since the
844+
// value_metatype instruction might produce a DynamicSelfType we have to
845+
// cast the metatype argument.
846+
//
847+
// FIXME: Semantically, we're "opening" the class metatype here to produce
848+
// the "opened" DynamicSelfType. Ideally it would be modeled as an opened
849+
// archetype associated with the original metatype or class instance value,
850+
// instead of as a "global" type.
851+
auto metatypeSelfType = metatypeArgument->getType()
852+
.castTo<MetatypeType>().getInstanceType();
853+
auto valueSelfType = valueMetatype->getType()
854+
.castTo<MetatypeType>().getInstanceType();
855+
if (metatypeSelfType != valueSelfType) {
856+
assert(metatypeSelfType ==
857+
cast<DynamicSelfType>(valueSelfType).getSelfType());
858+
859+
SILBuilderWithScope B(valueMetatype);
860+
metatypeArgument = B.createUncheckedTrivialBitCast(
861+
valueMetatype->getLoc(), metatypeArgument,
862+
valueMetatype->getType());
863+
}
841864
replaceAllSimplifiedUsesAndErase(valueMetatype, metatypeArgument,
842865
[](SILInstruction*) { });
843866
}

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)