Skip to content

Commit c50e8bb

Browse files
committed
Runtime: Check same-type pack requirements in checkGenericPackRequirement()
1 parent f12be70 commit c50e8bb

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,7 +1438,7 @@ checkGenericPackRequirement(const GenericRequirementDescriptor &req,
14381438
llvm::SmallVector<const WitnessTable *, 4> witnessTables;
14391439

14401440
// Look up the conformance of each pack element to the protocol.
1441-
for (unsigned i = 0, e = subjectType.getNumElements(); i < e; ++i) {
1441+
for (size_t i = 0, e = subjectType.getNumElements(); i < e; ++i) {
14421442
const Metadata *elt = subjectType.getElements()[i];
14431443

14441444
const WitnessTable *witnessTable = nullptr;
@@ -1447,8 +1447,8 @@ checkGenericPackRequirement(const GenericRequirementDescriptor &req,
14471447
const char *protoName =
14481448
req.getProtocol() ? req.getProtocol().getName() : "<null>";
14491449
return TYPE_LOOKUP_ERROR_FMT(
1450-
"subject type %.*s does not conform to protocol %s",
1451-
(int)req.getParam().size(), req.getParam().data(), protoName);
1450+
"subject type %.*s does not conform to protocol %s at pack index %lu",
1451+
(int)req.getParam().size(), req.getParam().data(), protoName, i);
14521452
}
14531453

14541454
if (req.getProtocol().needsWitnessTable())
@@ -1467,11 +1467,40 @@ checkGenericPackRequirement(const GenericRequirementDescriptor &req,
14671467
}
14681468

14691469
case GenericRequirementKind::SameType: {
1470-
llvm_unreachable("Implement me");
1470+
// Resolve the constraint generic parameter.
1471+
auto result = swift::getTypePackByMangledName(
1472+
req.getMangledTypeName(), extraArguments.data(),
1473+
substGenericParam, substWitnessTable);
1474+
if (result.getError())
1475+
return *result.getError();
1476+
MetadataPackPointer constraintType = result.getType();
1477+
assert(constraintType.getLifetime() == PackLifetime::OnHeap);
1478+
1479+
if (subjectType.getNumElements() != constraintType.getNumElements()) {
1480+
return TYPE_LOOKUP_ERROR_FMT(
1481+
"mismatched pack lengths in same-type pack requirement %.*s: %lu vs %lu",
1482+
(int)req.getParam().size(), req.getParam().data(),
1483+
subjectType.getNumElements(), constraintType.getNumElements());
1484+
}
1485+
1486+
for (size_t i = 0, e = subjectType.getNumElements(); i < e; ++i) {
1487+
auto *subjectElt = subjectType.getElements()[i];
1488+
auto *constraintElt = constraintType.getElements()[i];
1489+
1490+
if (subjectElt != constraintElt) {
1491+
return TYPE_LOOKUP_ERROR_FMT(
1492+
"subject type %.*s does not match %.*s at pack index %lu",
1493+
(int)req.getParam().size(),
1494+
req.getParam().data(), (int)req.getMangledTypeName().size(),
1495+
req.getMangledTypeName().data(), i);
1496+
}
1497+
}
1498+
1499+
return llvm::None;
14711500
}
14721501

14731502
case GenericRequirementKind::Layout: {
1474-
for (unsigned i = 0, e = subjectType.getNumElements(); i < e; ++i) {
1503+
for (size_t i = 0, e = subjectType.getNumElements(); i < e; ++i) {
14751504
const Metadata *elt = subjectType.getElements()[i];
14761505
if (auto result = satisfiesLayoutConstraint(req, elt))
14771506
return result;
@@ -1490,14 +1519,15 @@ checkGenericPackRequirement(const GenericRequirementDescriptor &req,
14901519
auto baseType = result.getType().getMetadata();
14911520

14921521
// Check that each pack element inherits from the base class.
1493-
for (unsigned i = 0, e = subjectType.getNumElements(); i < e; ++i) {
1522+
for (size_t i = 0, e = subjectType.getNumElements(); i < e; ++i) {
14941523
const Metadata *elt = subjectType.getElements()[i];
14951524

14961525
if (!isSubclassOrExistential(elt, baseType))
14971526
return TYPE_LOOKUP_ERROR_FMT(
1498-
"%.*s is not subclass of %.*s", (int)req.getParam().size(),
1527+
"%.*s is not subclass of %.*s at pack index %lu",
1528+
(int)req.getParam().size(),
14991529
req.getParam().data(), (int)req.getMangledTypeName().size(),
1500-
req.getMangledTypeName().data());
1530+
req.getMangledTypeName().data(), i);
15011531
}
15021532

15031533
return llvm::None;

test/Interpreter/variadic_generic_types.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ types.test("LayoutReq") {
9090
expectEqual("main.LayoutReq<Pack{Swift.AnyObject, main.Base}>", _typeName(LayoutReq<AnyObject, Base>.self))
9191
}
9292

93-
// FIXME: Test same-type pack requirements once more stuff is plumbed through
93+
public struct OuterSeq<each T: Sequence> {
94+
public struct InnerSeq<each U: Sequence> where each T.Element == each U.Element {}
95+
}
96+
97+
types.test("SameTypeReq") {
98+
expectEqual("main.OuterSeq<Pack{}>.InnerSeq<Pack{}>", _typeName(OuterSeq< >.InnerSeq< >.self))
99+
expectEqual("main.OuterSeq<Pack{Swift.Array<Swift.Int>}>.InnerSeq<Pack{Swift.Set<Swift.Int>}>", _typeName(OuterSeq<Array<Int>>.InnerSeq<Set<Int>>.self))
100+
expectEqual("main.OuterSeq<Pack{Swift.Array<Swift.Int>, Swift.Set<Swift.String>}>.InnerSeq<Pack{Swift.Set<Swift.Int>, Swift.Array<Swift.String>}>", _typeName(OuterSeq<Array<Int>, Set<String>>.InnerSeq<Set<Int>, Array<String>>.self))
101+
}
102+
94103

95104
//
96105
// Stored property layout tests

0 commit comments

Comments
 (0)