Skip to content

Commit 65ad5ea

Browse files
committed
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.
1 parent 8817de5 commit 65ad5ea

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7997,6 +7997,9 @@ static void checkGenericSignature(CanGenericSignature canSig,
79977997

79987998
auto canonicalRequirements = canSig.getRequirements();
79997999

8000+
// We collect conformance requirements to check that they're minimal.
8001+
llvm::SmallDenseMap<CanType, SmallVector<ProtocolDecl *, 2>, 2> conformances;
8002+
80008003
// Check that the signature is canonical.
80018004
for (unsigned idx : indices(canonicalRequirements)) {
80028005
debugStack.setRequirement(idx);
@@ -8047,6 +8050,10 @@ static void checkGenericSignature(CanGenericSignature canSig,
80478050
"Left-hand side must be a type parameter");
80488051
assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
80498052
"Right-hand side of conformance isn't a protocol type");
8053+
8054+
// Collect all conformance requirements on each type parameter.
8055+
conformances[CanType(reqt.getFirstType())].push_back(
8056+
reqt.getProtocolDecl());
80508057
break;
80518058
}
80528059

@@ -8089,6 +8096,22 @@ static void checkGenericSignature(CanGenericSignature canSig,
80898096
assert(prevReqt.compare(reqt) < 0 &&
80908097
"Out-of-order requirements");
80918098
}
8099+
8100+
// Make sure we don't have redundant protocol conformance requirements.
8101+
for (auto pair : conformances) {
8102+
const auto &protos = pair.second;
8103+
auto canonicalProtos = protos;
8104+
8105+
// canonicalizeProtocols() will sort them and filter out any protocols that
8106+
// are refined by other protocols in the list. It should be a no-op at this
8107+
// point.
8108+
ProtocolType::canonicalizeProtocols(canonicalProtos);
8109+
8110+
assert(protos.size() == canonicalProtos.size() &&
8111+
"redundant conformance requirements");
8112+
assert(std::equal(protos.begin(), protos.end(), canonicalProtos.begin()) &&
8113+
"out-of-order conformance requirements");
8114+
}
80928115
}
80938116
#endif
80948117

0 commit comments

Comments
 (0)