Skip to content

Commit

Permalink
Avoid cycles when computing a requirement signature
Browse files Browse the repository at this point in the history
Replace most remaining uses of isRequirementSignatureComputed by
isRequirementSignatureComputing which uses Evaluator::hasActiveRequest
to detect if the requirements are currently being computed.
  • Loading branch information
xymus committed May 9, 2019
1 parent 3cb1b6a commit cfae7bb
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 2 deletions.
3 changes: 3 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4305,6 +4305,9 @@ class ProtocolDecl final : public NominalTypeDecl {
/// requirements listed here become entries in the witness table.
ArrayRef<Requirement> getRequirementSignature() const;

/// Is the requirement signature currently being computed?
bool isComputingRequirementSignature() const;

/// Has the requirement signature been computed yet?
bool isRequirementSignatureComputed() const {
return RequirementSignature != nullptr;
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ class GenericSignatureBuilder::RequirementSource final
WrittenRequirementLoc writtenReqLoc)
: kind(kind), storageKind(StorageKind::StoredType),
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
usesRequirementSignature(protocol->isRequirementSignatureComputed()),
usesRequirementSignature(!protocol->isComputingRequirementSignature()),
parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
Expand Down
5 changes: 5 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,11 @@ ArrayRef<Requirement> ProtocolDecl::getRequirementSignature() const {
None);
}

bool ProtocolDecl::isComputingRequirementSignature() const {
return getASTContext().evaluator.hasActiveRequest(
RequirementSignatureRequest{const_cast<ProtocolDecl*>(this)});
}

void ProtocolDecl::setRequirementSignature(ArrayRef<Requirement> requirements) {
assert(!RequirementSignature && "requirement signature already set");
if (requirements.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4107,7 +4107,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
// Use the requirement signature to avoid rewalking the entire protocol. This
// cannot compute the requirement signature directly, because that may be
// infinitely recursive: this code is also used to construct it.
if (proto->isRequirementSignatureComputed()) {
if (!proto->isComputingRequirementSignature()) {
auto innerSource =
FloatingRequirementSource::viaProtocolRequirement(source, proto,
/*inferred=*/false);
Expand Down

0 comments on commit cfae7bb

Please sign in to comment.