GSB: Assert that a minimal signature doesn't have protocols refined by other protocols

I'm looking at a bug where we end with a signature like

    protocol B { ... }
    protocol BB : B { }

    <Self where Self : B, Self : BB>

While this one be a one-off bug, it's easy enough to check for this
condition with an assert here.
This commit is contained in:
Slava Pestov
2021-07-21 15:30:33 -04:00
parent 8817de589a
commit 65ad5ea1cb

View File

@@ -7997,6 +7997,9 @@ static void checkGenericSignature(CanGenericSignature canSig,
auto canonicalRequirements = canSig.getRequirements();
// We collect conformance requirements to check that they're minimal.
llvm::SmallDenseMap<CanType, SmallVector<ProtocolDecl *, 2>, 2> conformances;
// Check that the signature is canonical.
for (unsigned idx : indices(canonicalRequirements)) {
debugStack.setRequirement(idx);
@@ -8047,6 +8050,10 @@ static void checkGenericSignature(CanGenericSignature canSig,
"Left-hand side must be a type parameter");
assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
"Right-hand side of conformance isn't a protocol type");
// Collect all conformance requirements on each type parameter.
conformances[CanType(reqt.getFirstType())].push_back(
reqt.getProtocolDecl());
break;
}
@@ -8089,6 +8096,22 @@ static void checkGenericSignature(CanGenericSignature canSig,
assert(prevReqt.compare(reqt) < 0 &&
"Out-of-order requirements");
}
// Make sure we don't have redundant protocol conformance requirements.
for (auto pair : conformances) {
const auto &protos = pair.second;
auto canonicalProtos = protos;
// canonicalizeProtocols() will sort them and filter out any protocols that
// are refined by other protocols in the list. It should be a no-op at this
// point.
ProtocolType::canonicalizeProtocols(canonicalProtos);
assert(protos.size() == canonicalProtos.size() &&
"redundant conformance requirements");
assert(std::equal(protos.begin(), protos.end(), canonicalProtos.begin()) &&
"out-of-order conformance requirements");
}
}
#endif