Skip to content

Commit 4a1b0c8

Browse files
committed
RequirementMachine: Install placeholder requirement signature if completion fails
I did this if there was a request cycle but forgot the other obvious case.
1 parent 53193f1 commit 4a1b0c8

File tree

5 files changed

+65
-60
lines changed

5 files changed

+65
-60
lines changed

include/swift/AST/RequirementSignature.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class RequirementSignature final {
8383
const PrintOptions &Options = PrintOptions()) const;
8484
void print(ProtocolDecl *owner, ASTPrinter &Printer,
8585
const PrintOptions &Opts = PrintOptions()) const;
86+
87+
static RequirementSignature getPlaceholderRequirementSignature(
88+
const ProtocolDecl *proto, GenericSignatureErrors errors);
8689
};
8790

8891
} // end namespace swift

lib/AST/Decl.cpp

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6858,63 +6858,12 @@ ProtocolDecl::getProtocolDependencies() const {
68586858
std::nullopt);
68596859
}
68606860

6861-
/// If we hit a request cycle, give the protocol a requirement signature that
6862-
/// still has inherited protocol requirements on Self, and also conformances
6863-
/// to Copyable and Escapable for all associated types. Otherwise, we'll see
6864-
/// invariant violations from the inheritance clause mismatch, as well as
6865-
/// spurious downstream diagnostics concerning move-only types.
6866-
static RequirementSignature getPlaceholderRequirementSignature(
6867-
const ProtocolDecl *proto) {
6868-
auto &ctx = proto->getASTContext();
6869-
6870-
SmallVector<ProtocolDecl *, 2> inheritedProtos;
6871-
for (auto *inheritedProto : proto->getInheritedProtocols()) {
6872-
inheritedProtos.push_back(inheritedProto);
6873-
}
6874-
6875-
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
6876-
for (auto ip : InvertibleProtocolSet::full()) {
6877-
auto *otherProto = ctx.getProtocol(getKnownProtocolKind(ip));
6878-
inheritedProtos.push_back(otherProto);
6879-
}
6880-
}
6881-
6882-
ProtocolType::canonicalizeProtocols(inheritedProtos);
6883-
6884-
SmallVector<Requirement, 2> requirements;
6885-
6886-
for (auto *inheritedProto : inheritedProtos) {
6887-
requirements.emplace_back(RequirementKind::Conformance,
6888-
proto->getSelfInterfaceType(),
6889-
inheritedProto->getDeclaredInterfaceType());
6890-
}
6891-
6892-
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
6893-
for (auto *assocTypeDecl : proto->getAssociatedTypeMembers()) {
6894-
for (auto ip : InvertibleProtocolSet::full()) {
6895-
auto *otherProto = ctx.getProtocol(getKnownProtocolKind(ip));
6896-
requirements.emplace_back(RequirementKind::Conformance,
6897-
assocTypeDecl->getDeclaredInterfaceType(),
6898-
otherProto->getDeclaredInterfaceType());
6899-
}
6900-
}
6901-
}
6902-
6903-
// Maintain invariants.
6904-
llvm::array_pod_sort(requirements.begin(), requirements.end(),
6905-
[](const Requirement *lhs, const Requirement *rhs) -> int {
6906-
return lhs->compare(*rhs);
6907-
});
6908-
6909-
return RequirementSignature(ctx.AllocateCopy(requirements),
6910-
ArrayRef<ProtocolTypeAlias>());
6911-
}
6912-
69136861
RequirementSignature ProtocolDecl::getRequirementSignature() const {
69146862
return getASTContext().evaluator(
6915-
RequirementSignatureRequest { const_cast<ProtocolDecl *>(this) },
6863+
RequirementSignatureRequest{const_cast<ProtocolDecl *>(this)},
69166864
[this]() {
6917-
return getPlaceholderRequirementSignature(this);
6865+
return RequirementSignature::getPlaceholderRequirementSignature(
6866+
this, GenericSignatureErrors());
69186867
});
69196868
}
69206869

lib/AST/GenericSignature.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,59 @@ void GenericSignatureImpl::getRequirementsWithInverses(
12911291
}
12921292
}
12931293

1294+
/// If we we can't build a requirement signature because of a request cycle or
1295+
/// failure in Knuth-Bendix completion, we give the protocol a requirement
1296+
/// signature that still has inherited protocol requirements on Self, and also
1297+
/// conformances to Copyable and Escapable for all associated types. Otherwise,
1298+
/// we'll see invariant violations from the inheritance clause mismatch, as
1299+
/// well as spurious downstream diagnostics concerning move-only types.
1300+
RequirementSignature RequirementSignature::getPlaceholderRequirementSignature(
1301+
const ProtocolDecl *proto, GenericSignatureErrors errors) {
1302+
auto &ctx = proto->getASTContext();
1303+
1304+
SmallVector<ProtocolDecl *, 2> inheritedProtos;
1305+
for (auto *inheritedProto : proto->getInheritedProtocols()) {
1306+
inheritedProtos.push_back(inheritedProto);
1307+
}
1308+
1309+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
1310+
for (auto ip : InvertibleProtocolSet::full()) {
1311+
auto *otherProto = ctx.getProtocol(getKnownProtocolKind(ip));
1312+
inheritedProtos.push_back(otherProto);
1313+
}
1314+
}
1315+
1316+
ProtocolType::canonicalizeProtocols(inheritedProtos);
1317+
1318+
SmallVector<Requirement, 2> requirements;
1319+
1320+
for (auto *inheritedProto : inheritedProtos) {
1321+
requirements.emplace_back(RequirementKind::Conformance,
1322+
proto->getSelfInterfaceType(),
1323+
inheritedProto->getDeclaredInterfaceType());
1324+
}
1325+
1326+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
1327+
for (auto *assocTypeDecl : proto->getAssociatedTypeMembers()) {
1328+
for (auto ip : InvertibleProtocolSet::full()) {
1329+
auto *otherProto = ctx.getProtocol(getKnownProtocolKind(ip));
1330+
requirements.emplace_back(RequirementKind::Conformance,
1331+
assocTypeDecl->getDeclaredInterfaceType(),
1332+
otherProto->getDeclaredInterfaceType());
1333+
}
1334+
}
1335+
}
1336+
1337+
// Maintain invariants.
1338+
llvm::array_pod_sort(requirements.begin(), requirements.end(),
1339+
[](const Requirement *lhs, const Requirement *rhs) -> int {
1340+
return lhs->compare(*rhs);
1341+
});
1342+
1343+
return RequirementSignature(ctx.AllocateCopy(requirements),
1344+
ArrayRef<ProtocolTypeAlias>());
1345+
}
1346+
12941347
void RequirementSignature::getRequirementsWithInverses(
12951348
ProtocolDecl *owner,
12961349
SmallVector<Requirement, 2> &reqs,

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator,
342342

343343
unsigned attempt = 0;
344344
for (;;) {
345-
for (const auto *proto : component) {
346-
auto &requirements = protos[proto];
345+
for (const auto *otherProto : component) {
346+
auto &requirements = protos[otherProto];
347347

348348
// Preprocess requirements to eliminate conformances on type parameters
349349
// which are made concrete.
@@ -384,11 +384,13 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator,
384384
if (otherProto != proto) {
385385
ctx.evaluator.cacheOutput(
386386
RequirementSignatureRequest{const_cast<ProtocolDecl *>(otherProto)},
387-
RequirementSignature(GenericSignatureErrorFlags::CompletionFailed));
387+
RequirementSignature::getPlaceholderRequirementSignature(
388+
otherProto, GenericSignatureErrorFlags::CompletionFailed));
388389
}
389390
}
390391

391-
return RequirementSignature(GenericSignatureErrorFlags::CompletionFailed);
392+
return RequirementSignature::getPlaceholderRequirementSignature(
393+
proto, GenericSignatureErrorFlags::CompletionFailed);
392394
}
393395

394396
auto minimalRequirements = machine->computeMinimalProtocolRequirements();

test/Generics/infinite_concrete_type.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// RUN: %target-typecheck-verify-swift
22

3-
// XFAIL: noncopyable_generics
4-
53
class G<T> {}
64

75
protocol P1 { // expected-error {{cannot build rewrite system for protocol; concrete nesting limit exceeded}}

0 commit comments

Comments
 (0)