Skip to content

Commit 2cf1241

Browse files
committed
Runtime: Extract checkGenericRequirement() from checkGenericRequirements()
1 parent 1708696 commit 2cf1241

File tree

1 file changed

+111
-98
lines changed

1 file changed

+111
-98
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 111 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,122 +1281,135 @@ bool swift::_swift_class_isSubclass(const Metadata *subclass,
12811281
return isSubclass(subclass, superclass);
12821282
}
12831283

1284-
llvm::Optional<TypeLookupError> swift::_checkGenericRequirements(
1285-
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
1286-
llvm::SmallVectorImpl<const void *> &extraArguments,
1287-
SubstGenericParameterFn substGenericParam,
1288-
SubstDependentWitnessTableFn substWitnessTable) {
1289-
for (const auto &req : requirements) {
1290-
// Make sure we understand the requirement we're dealing with.
1291-
if (!req.hasKnownKind())
1292-
return TypeLookupError("unknown kind");
1284+
static llvm::Optional<TypeLookupError>
1285+
checkGenericRequirement(const GenericRequirementDescriptor &req,
1286+
llvm::SmallVectorImpl<const void *> &extraArguments,
1287+
SubstGenericParameterFn substGenericParam,
1288+
SubstDependentWitnessTableFn substWitnessTable) {
1289+
assert(!req.getFlags().isPackRequirement());
1290+
1291+
// Make sure we understand the requirement we're dealing with.
1292+
if (!req.hasKnownKind())
1293+
return TypeLookupError("unknown kind");
1294+
1295+
// Resolve the subject generic parameter.
1296+
auto result = swift_getTypeByMangledName(
1297+
MetadataState::Abstract, req.getParam(), extraArguments.data(),
1298+
substGenericParam, substWitnessTable);
1299+
if (result.getError())
1300+
return *result.getError();
1301+
const Metadata *subjectType = result.getType().getMetadata();
1302+
1303+
// Check the requirement.
1304+
switch (req.getKind()) {
1305+
case GenericRequirementKind::Protocol: {
1306+
const WitnessTable *witnessTable = nullptr;
1307+
if (!_conformsToProtocol(nullptr, subjectType, req.getProtocol(),
1308+
&witnessTable)) {
1309+
const char *protoName =
1310+
req.getProtocol() ? req.getProtocol().getName() : "<null>";
1311+
return TYPE_LOOKUP_ERROR_FMT(
1312+
"subject type %.*s does not conform to protocol %s",
1313+
(int)req.getParam().size(), req.getParam().data(), protoName);
1314+
}
12931315

1294-
if (req.getFlags().isPackRequirement())
1295-
return TypeLookupError("Packs not supported here yet");
1316+
// If we need a witness table, add it.
1317+
if (req.getProtocol().needsWitnessTable()) {
1318+
assert(witnessTable);
1319+
extraArguments.push_back(witnessTable);
1320+
}
12961321

1297-
// Resolve the subject generic parameter.
1322+
return llvm::None;
1323+
}
1324+
1325+
case GenericRequirementKind::SameType: {
1326+
// Demangle the second type under the given substitutions.
12981327
auto result = swift_getTypeByMangledName(
1299-
MetadataState::Abstract, req.getParam(), extraArguments.data(),
1300-
substGenericParam, substWitnessTable);
1328+
MetadataState::Abstract, req.getMangledTypeName(),
1329+
extraArguments.data(), substGenericParam, substWitnessTable);
13011330
if (result.getError())
13021331
return *result.getError();
1303-
const Metadata *subjectType = result.getType().getMetadata();
1304-
1305-
// Check the requirement.
1306-
switch (req.getKind()) {
1307-
case GenericRequirementKind::Protocol: {
1308-
const WitnessTable *witnessTable = nullptr;
1309-
if (!_conformsToProtocol(nullptr, subjectType, req.getProtocol(),
1310-
&witnessTable)) {
1311-
const char *protoName =
1312-
req.getProtocol() ? req.getProtocol().getName() : "<null>";
1313-
return TYPE_LOOKUP_ERROR_FMT(
1314-
"subject type %.*s does not conform to protocol %s",
1315-
(int)req.getParam().size(), req.getParam().data(), protoName);
1316-
}
1317-
1318-
// If we need a witness table, add it.
1319-
if (req.getProtocol().needsWitnessTable()) {
1320-
assert(witnessTable);
1321-
extraArguments.push_back(witnessTable);
1322-
}
1323-
1324-
continue;
1332+
auto otherType = result.getType().getMetadata();
1333+
1334+
// Check that the types are equivalent.
1335+
if (subjectType != otherType) {
1336+
return TYPE_LOOKUP_ERROR_FMT(
1337+
"subject type %.*s does not match %.*s", (int)req.getParam().size(),
1338+
req.getParam().data(), (int)req.getMangledTypeName().size(),
1339+
req.getMangledTypeName().data());
13251340
}
13261341

1327-
case GenericRequirementKind::SameType: {
1328-
// Demangle the second type under the given substitutions.
1329-
auto result = swift_getTypeByMangledName(
1330-
MetadataState::Abstract, req.getMangledTypeName(),
1331-
extraArguments.data(), substGenericParam, substWitnessTable);
1332-
if (result.getError())
1333-
return *result.getError();
1334-
auto otherType = result.getType().getMetadata();
1335-
1336-
// Check that the types are equivalent.
1337-
if (subjectType != otherType)
1338-
return TYPE_LOOKUP_ERROR_FMT(
1339-
"subject type %.*s does not match %.*s", (int)req.getParam().size(),
1340-
req.getParam().data(), (int)req.getMangledTypeName().size(),
1341-
req.getMangledTypeName().data());
1342+
return llvm::None;
1343+
}
13421344

1343-
continue;
1345+
case GenericRequirementKind::Layout: {
1346+
switch (req.getLayout()) {
1347+
case GenericRequirementLayoutKind::Class:
1348+
if (!subjectType->satisfiesClassConstraint()) {
1349+
return TYPE_LOOKUP_ERROR_FMT(
1350+
"subject type %.*s does not satisfy class constraint",
1351+
(int)req.getParam().size(), req.getParam().data());
1352+
}
1353+
return llvm::None;
13441354
}
13451355

1346-
case GenericRequirementKind::Layout: {
1347-
switch (req.getLayout()) {
1348-
case GenericRequirementLayoutKind::Class:
1349-
if (!subjectType->satisfiesClassConstraint())
1350-
return TYPE_LOOKUP_ERROR_FMT(
1351-
"subject type %.*s does not satisfy class constraint",
1352-
(int)req.getParam().size(), req.getParam().data());
1353-
continue;
1354-
}
1356+
// Unknown layout.
1357+
return TYPE_LOOKUP_ERROR_FMT("unknown layout kind %u", req.getLayout());
1358+
}
13551359

1356-
// Unknown layout.
1357-
return TYPE_LOOKUP_ERROR_FMT("unknown layout kind %u", req.getLayout());
1360+
case GenericRequirementKind::BaseClass: {
1361+
// Demangle the base type under the given substitutions.
1362+
auto result = swift_getTypeByMangledName(
1363+
MetadataState::Abstract, req.getMangledTypeName(),
1364+
extraArguments.data(), substGenericParam, substWitnessTable);
1365+
if (result.getError())
1366+
return *result.getError();
1367+
auto baseType = result.getType().getMetadata();
1368+
1369+
// If the type which is constrained to a base class is an existential
1370+
// type, and if that existential type includes a superclass constraint,
1371+
// just require that the superclass by which the existential is
1372+
// constrained is a subclass of the base class.
1373+
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subjectType)) {
1374+
if (auto *superclassConstraint = existential->getSuperclassConstraint())
1375+
subjectType = superclassConstraint;
13581376
}
13591377

1360-
case GenericRequirementKind::BaseClass: {
1361-
// Demangle the base type under the given substitutions.
1362-
auto result = swift_getTypeByMangledName(
1363-
MetadataState::Abstract, req.getMangledTypeName(),
1364-
extraArguments.data(), substGenericParam, substWitnessTable);
1365-
if (result.getError())
1366-
return *result.getError();
1367-
auto baseType = result.getType().getMetadata();
1368-
1369-
// If the type which is constrained to a base class is an existential
1370-
// type, and if that existential type includes a superclass constraint,
1371-
// just require that the superclass by which the existential is
1372-
// constrained is a subclass of the base class.
1373-
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subjectType)) {
1374-
if (auto *superclassConstraint = existential->getSuperclassConstraint())
1375-
subjectType = superclassConstraint;
1376-
}
1378+
if (!isSubclass(subjectType, baseType))
1379+
return TYPE_LOOKUP_ERROR_FMT(
1380+
"%.*s is not subclass of %.*s", (int)req.getParam().size(),
1381+
req.getParam().data(), (int)req.getMangledTypeName().size(),
1382+
req.getMangledTypeName().data());
13771383

1378-
if (!isSubclass(subjectType, baseType))
1379-
return TYPE_LOOKUP_ERROR_FMT(
1380-
"%.*s is not subclass of %.*s", (int)req.getParam().size(),
1381-
req.getParam().data(), (int)req.getMangledTypeName().size(),
1382-
req.getMangledTypeName().data());
1384+
return llvm::None;
1385+
}
13831386

1384-
continue;
1385-
}
1387+
case GenericRequirementKind::SameConformance: {
1388+
// FIXME: Implement this check.
1389+
return llvm::None;
1390+
}
13861391

1387-
case GenericRequirementKind::SameConformance: {
1388-
// FIXME: Implement this check.
1389-
continue;
1390-
}
1392+
case GenericRequirementKind::SameShape: {
1393+
return TYPE_LOOKUP_ERROR_FMT("can't have same-shape requirement where "
1394+
"subject type is not a pack");
1395+
}
1396+
}
13911397

1392-
case GenericRequirementKind::SameShape: {
1393-
llvm_unreachable("Implement me");
1394-
}
1395-
}
1398+
// Unknown generic requirement kind.
1399+
return TYPE_LOOKUP_ERROR_FMT("unknown generic requirement kind %u",
1400+
(unsigned)req.getKind());
1401+
}
13961402

1397-
// Unknown generic requirement kind.
1398-
return TYPE_LOOKUP_ERROR_FMT("unknown generic requirement kind %u",
1399-
(unsigned)req.getKind());
1403+
llvm::Optional<TypeLookupError> swift::_checkGenericRequirements(
1404+
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
1405+
llvm::SmallVectorImpl<const void *> &extraArguments,
1406+
SubstGenericParameterFn substGenericParam,
1407+
SubstDependentWitnessTableFn substWitnessTable) {
1408+
for (const auto &req : requirements) {
1409+
auto error = checkGenericRequirement(req, extraArguments,
1410+
substGenericParam, substWitnessTable);
1411+
if (error)
1412+
return error;
14001413
}
14011414

14021415
// Success!

0 commit comments

Comments
 (0)