Skip to content

Commit ab81426

Browse files
committed
SIL: Fix SILType substitution bug with DynamicSelfType vs MetatypeType
Previously, SIL type lowering would assume a MetatypeType was completely lowered if it had a representation, but this is not quite right; after substitution, we can have a MetatypeType whose instance type is a DynamicSelfType. Strip these away more eagerly, since they show up in SILType::subst(), where we first substitute AST-level generic parameters, and then lower the result to get the final SIL type. Fixes <https://bugs.swift.org/browse/SR-2733>.
1 parent 9f8ccd4 commit ab81426

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,28 @@ namespace {
22092209
substObjectType));
22102210
}
22112211

2212+
/// Metatypes get DynamicSelfType stripped off the instance type.
2213+
CanType visitMetatypeType(CanMetatypeType origType) {
2214+
CanType origInstanceType = origType.getInstanceType();
2215+
CanType substInstanceType = origInstanceType.subst(
2216+
Subst, Conformances, None)->getCanonicalType();
2217+
2218+
// If the substitution didn't change anything, we know that the
2219+
// original type was a lowered type, so we're good.
2220+
if (origInstanceType == substInstanceType) {
2221+
return origType;
2222+
}
2223+
2224+
// If this is a DynamicSelf metatype, turn it into a metatype of the
2225+
// underlying self type.
2226+
if (auto dynamicSelf = dyn_cast<DynamicSelfType>(substInstanceType)) {
2227+
substInstanceType = dynamicSelf.getSelfType();
2228+
}
2229+
2230+
return CanMetatypeType::get(substInstanceType,
2231+
origType->getRepresentation());
2232+
}
2233+
22122234
/// Any other type is would be a valid type in the AST. Just
22132235
/// apply the substitution on the AST level and then lower that.
22142236
CanType visitType(CanType origType) {

lib/SIL/TypeLowering.cpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,30 +1235,6 @@ void TypeConverter::insert(TypeKey k, const TypeLowering *tl) {
12351235
Types[k.getCachingKey()] = tl;
12361236
}
12371237

1238-
#ifndef NDEBUG
1239-
/// Is this type a lowered type?
1240-
static bool isLoweredType(CanType type) {
1241-
if (isa<LValueType>(type) || isa<InOutType>(type))
1242-
return false;
1243-
if (isa<AnyFunctionType>(type))
1244-
return false;
1245-
if (auto tuple = dyn_cast<TupleType>(type)) {
1246-
for (auto elt : tuple.getElementTypes())
1247-
if (!isLoweredType(elt))
1248-
return false;
1249-
return true;
1250-
}
1251-
OptionalTypeKind optKind;
1252-
if (auto objectType = type.getAnyOptionalObjectType(optKind)) {
1253-
return (optKind == OTK_Optional && isLoweredType(objectType));
1254-
}
1255-
if (auto meta = dyn_cast<AnyMetatypeType>(type)) {
1256-
return meta->hasRepresentation();
1257-
}
1258-
return true;
1259-
}
1260-
#endif
1261-
12621238
/// Lower each of the elements of the substituted type according to
12631239
/// the abstraction pattern of the given original type.
12641240
static CanTupleType getLoweredTupleType(TypeConverter &tc,
@@ -1525,7 +1501,7 @@ const TypeLowering &TypeConverter::getTypeLowering(SILType type) {
15251501
const TypeLowering &
15261502
TypeConverter::getTypeLoweringForLoweredType(TypeKey key) {
15271503
auto type = key.SubstType;
1528-
assert(isLoweredType(type) && "type is not lowered!");
1504+
assert(type->isLegalSILType() && "type is not lowered!");
15291505
(void)type;
15301506

15311507
// Re-using uncurry level 0 is reasonable because our uncurrying
@@ -1542,7 +1518,7 @@ TypeConverter::getTypeLoweringForLoweredType(TypeKey key) {
15421518
const TypeLowering &
15431519
TypeConverter::getTypeLoweringForUncachedLoweredType(TypeKey key) {
15441520
assert(!find(key) && "re-entrant or already cached");
1545-
assert(isLoweredType(key.SubstType) && "type is not already lowered");
1521+
assert(key.SubstType->isLegalSILType() && "type is not already lowered");
15461522

15471523
#ifndef NDEBUG
15481524
// Catch reentrancy bugs.

test/SILGen/dynamic_self.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ class Z {
207207

208208
}
209209

210+
// Make sure we erase dynamic Self in a metatype instance type when
211+
// performing SIL type substitution.
212+
213+
func makeInstance<T: FactoryBase>(_ cls: T.Type) -> T {
214+
return cls.init()
215+
}
216+
217+
class FactoryBase {
218+
required init() { }
219+
func before() -> Self {
220+
return makeInstance(type(of: self))
221+
}
222+
}
223+
210224
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
211225
// CHECK: method #P.f!1: @_TTWC12dynamic_self1XS_1PS_FS1_1f
212226

0 commit comments

Comments
 (0)