Skip to content

Commit 1710d08

Browse files
authored
Merge pull request #25492 from slavapestov/verify-signatures-better
AST: Verify that all generic signatures can be re-built from their requirements
2 parents cc51106 + 24da27b commit 1710d08

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ NOTE(note_typo_candidate,none,
101101
NOTE(profile_read_error,none,
102102
"failed to load profile data '%0': '%1'", (StringRef, StringRef))
103103

104-
ERROR(generic_signature_not_minimal,none,
105-
"generic requirement '%0' is redundant in %1", (StringRef, StringRef))
106-
107104
WARNING(protocol_extension_redundant_requirement,none,
108105
"requirement of '%1' to '%2' is redundant in an extension of '%0'",
109106
(StringRef, StringRef, StringRef))
@@ -114,6 +111,15 @@ ERROR(attr_only_on_parameters, none,
114111
ERROR(function_type_no_parens,none,
115112
"single argument function types require parentheses", ())
116113

114+
// Used by -verify-generic-signatures
115+
ERROR(generic_signature_not_minimal,none,
116+
"generic requirement '%0' is redundant in %1", (StringRef, StringRef))
117+
ERROR(generic_signature_not_valid,none,
118+
"generic signature %0 is invalid", (StringRef))
119+
ERROR(generic_signature_not_equal,none,
120+
"generic signature %0 is not equal to new signature %1",
121+
(StringRef, StringRef))
122+
117123
// FIXME: Used by swift-api-digester. Don't want to set up a separate diagnostics
118124
// file just for a few errors.
119125
ERROR(sdk_node_unrecognized_key,none,

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7433,9 +7433,46 @@ void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
74337433
sig->print(llvm::errs());
74347434
llvm::errs() << "\n";
74357435

7436-
// Try removing each requirement in turn.
7436+
// Try building a new signature having the same requirements.
74377437
auto genericParams = sig->getGenericParams();
74387438
auto requirements = sig->getRequirements();
7439+
7440+
{
7441+
PrettyStackTraceGenericSignature debugStack("verifying", sig);
7442+
7443+
// Form a new generic signature builder.
7444+
GenericSignatureBuilder builder(context);
7445+
7446+
// Add the generic parameters.
7447+
for (auto gp : genericParams)
7448+
builder.addGenericParameter(gp);
7449+
7450+
// Add the requirements.
7451+
auto source = FloatingRequirementSource::forAbstract();
7452+
for (auto req : requirements)
7453+
builder.addRequirement(req, source, nullptr);
7454+
7455+
// If there were any errors, the signature was invalid.
7456+
if (builder.Impl->HadAnyError) {
7457+
context.Diags.diagnose(SourceLoc(), diag::generic_signature_not_valid,
7458+
sig->getAsString());
7459+
}
7460+
7461+
// Form a generic signature from the result.
7462+
auto newSig =
7463+
std::move(builder).computeGenericSignature(
7464+
SourceLoc(),
7465+
/*allowConcreteGenericParams=*/true,
7466+
/*allowBuilderToMove=*/true);
7467+
7468+
// The new signature should be equal.
7469+
if (newSig->getCanonicalSignature() != sig->getCanonicalSignature()) {
7470+
context.Diags.diagnose(SourceLoc(), diag::generic_signature_not_equal,
7471+
sig->getAsString(), newSig->getAsString());
7472+
}
7473+
}
7474+
7475+
// Try removing each requirement in turn.
74397476
for (unsigned victimIndex : indices(requirements)) {
74407477
PrettyStackTraceGenericSignature debugStack("verifying", sig, victimIndex);
74417478

@@ -7453,8 +7490,8 @@ void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
74537490
builder.addRequirement(requirements[i], source, nullptr);
74547491
}
74557492

7456-
// Finalize the generic signature. If there were any errors, we formed
7457-
// an invalid signature, so just continue.
7493+
// If there were any errors, we formed an invalid signature, so
7494+
// just continue.
74587495
if (builder.Impl->HadAnyError) continue;
74597496

74607497
// Form a generic signature from the result.

0 commit comments

Comments
 (0)