Skip to content

Commit d17baed

Browse files
committed
Runtime: Check superclass pack requirements in checkGenericPackRequirement()
1 parent b6b51cf commit d17baed

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,20 @@ static bool isSubclass(const Metadata *subclass, const Metadata *superclass) {
12751275
});
12761276
}
12771277

1278+
static bool isSubclassOrExistential(const Metadata *subclass,
1279+
const Metadata *superclass) {
1280+
// If the type which is constrained to a base class is an existential
1281+
// type, and if that existential type includes a superclass constraint,
1282+
// just require that the superclass by which the existential is
1283+
// constrained is a subclass of the base class.
1284+
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subclass)) {
1285+
if (auto *superclassConstraint = existential->getSuperclassConstraint())
1286+
subclass = superclassConstraint;
1287+
}
1288+
1289+
return isSubclass(subclass, superclass);
1290+
}
1291+
12781292
SWIFT_CC(swift)
12791293
SWIFT_RUNTIME_STDLIB_SPI
12801294
bool swift::_swift_class_isSubclass(const Metadata *subclass,
@@ -1367,16 +1381,7 @@ checkGenericRequirement(const GenericRequirementDescriptor &req,
13671381
return *result.getError();
13681382
auto baseType = result.getType().getMetadata();
13691383

1370-
// If the type which is constrained to a base class is an existential
1371-
// type, and if that existential type includes a superclass constraint,
1372-
// just require that the superclass by which the existential is
1373-
// constrained is a subclass of the base class.
1374-
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subjectType)) {
1375-
if (auto *superclassConstraint = existential->getSuperclassConstraint())
1376-
subjectType = superclassConstraint;
1377-
}
1378-
1379-
if (!isSubclass(subjectType, baseType))
1384+
if (!isSubclassOrExistential(subjectType, baseType))
13801385
return TYPE_LOOKUP_ERROR_FMT(
13811386
"%.*s is not subclass of %.*s", (int)req.getParam().size(),
13821387
req.getParam().data(), (int)req.getMangledTypeName().size(),
@@ -1464,7 +1469,26 @@ checkGenericPackRequirement(const GenericRequirementDescriptor &req,
14641469
}
14651470

14661471
case GenericRequirementKind::BaseClass: {
1467-
llvm_unreachable("Implement me");
1472+
// Demangle the base type under the given substitutions.
1473+
auto result = swift_getTypeByMangledName(
1474+
MetadataState::Abstract, req.getMangledTypeName(),
1475+
extraArguments.data(), substGenericParam, substWitnessTable);
1476+
if (result.getError())
1477+
return *result.getError();
1478+
auto baseType = result.getType().getMetadata();
1479+
1480+
// Check that each pack element inherits from the base class.
1481+
for (unsigned i = 0, e = subjectType.getNumElements(); i < e; ++i) {
1482+
const Metadata *elt = subjectType.getElements()[i];
1483+
1484+
if (!isSubclassOrExistential(elt, baseType))
1485+
return TYPE_LOOKUP_ERROR_FMT(
1486+
"%.*s is not subclass of %.*s", (int)req.getParam().size(),
1487+
req.getParam().data(), (int)req.getMangledTypeName().size(),
1488+
req.getMangledTypeName().data());
1489+
}
1490+
1491+
return llvm::None;
14681492
}
14691493

14701494
case GenericRequirementKind::SameConformance: {

test/Interpreter/variadic_generic_types.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,18 @@ types.test("ConformanceReq") {
7171
expectEqual("main.ConformanceReq<Pack{Swift.Int, Swift.String, Swift.Float}>", _typeName(ConformanceReq<Int, String, Float>.self))
7272
}
7373

74-
// FIXME: Test superclass, layout and same-type pack requirements once more stuff is plumbed through
74+
public class Base {}
75+
public class Derived: Base {}
76+
77+
public struct SuperclassReq<each T: Base> {}
78+
79+
types.test("SuperclassReq") {
80+
expectEqual("main.SuperclassReq<Pack{}>", _typeName(SuperclassReq< >.self))
81+
expectEqual("main.SuperclassReq<Pack{main.Base}>", _typeName(SuperclassReq<Base>.self))
82+
expectEqual("main.SuperclassReq<Pack{main.Derived, main.Base}>", _typeName(SuperclassReq<Derived, Base>.self))
83+
}
84+
85+
// FIXME: Test layout and same-type pack requirements once more stuff is plumbed through
7586

7687
//
7788
// Stored property layout tests

0 commit comments

Comments
 (0)