Skip to content

Commit 05b3f79

Browse files
committed
RequirementMachine: Implement GenericSignature::getRequiredProtocols() query
1 parent a37ad9f commit 05b3f79

File tree

3 files changed

+78
-18
lines changed

3 files changed

+78
-18
lines changed

include/swift/AST/RequirementMachine.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SWIFT_REQUIREMENTMACHINE_H
1414
#define SWIFT_REQUIREMENTMACHINE_H
1515

16+
#include "swift/AST/GenericSignature.h"
17+
1618
namespace llvm {
1719
class raw_ostream;
1820
}
@@ -21,9 +23,7 @@ namespace swift {
2123

2224
class ASTContext;
2325
class AssociatedTypeDecl;
24-
class CanGenericSignature;
2526
class CanType;
26-
class GenericSignature;
2727
class LayoutConstraint;
2828
class ProtocolDecl;
2929
class Requirement;
@@ -58,6 +58,7 @@ class RequirementMachine final {
5858
bool requiresClass(Type depType) const;
5959
LayoutConstraint getLayoutConstraint(Type depType) const;
6060
bool requiresProtocol(Type depType, const ProtocolDecl *proto) const;
61+
GenericSignature::RequiredProtocols getRequiredProtocols(Type depType) const;
6162
bool isConcreteType(Type depType) const;
6263
bool areSameTypeParameterInContext(Type depType1, Type depType2) const;
6364

lib/AST/GenericSignature.cpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -353,26 +353,62 @@ GenericSignature::RequiredProtocols
353353
GenericSignatureImpl::getRequiredProtocols(Type type) const {
354354
assert(type->isTypeParameter() && "Expected a type parameter");
355355

356-
auto &builder = *getGenericSignatureBuilder();
357-
auto equivClass =
358-
builder.resolveEquivalenceClass(
359-
type,
360-
ArchetypeResolutionKind::CompleteWellFormed);
361-
if (!equivClass) return { };
356+
auto computeViaGSB = [&]() -> GenericSignature::RequiredProtocols {
357+
auto &builder = *getGenericSignatureBuilder();
358+
auto equivClass =
359+
builder.resolveEquivalenceClass(
360+
type,
361+
ArchetypeResolutionKind::CompleteWellFormed);
362+
if (!equivClass) return { };
362363

363-
// If this type parameter was mapped to a concrete type, then there
364-
// are no requirements.
365-
if (equivClass->concreteType) return { };
364+
// If this type parameter was mapped to a concrete type, then there
365+
// are no requirements.
366+
if (equivClass->concreteType) return { };
366367

367-
// Retrieve the protocols to which this type conforms.
368-
GenericSignature::RequiredProtocols result;
369-
for (const auto &conforms : equivClass->conformsTo)
370-
result.push_back(conforms.first);
368+
// Retrieve the protocols to which this type conforms.
369+
GenericSignature::RequiredProtocols result;
370+
for (const auto &conforms : equivClass->conformsTo)
371+
result.push_back(conforms.first);
371372

372-
// Canonicalize the resulting set of protocols.
373-
ProtocolType::canonicalizeProtocols(result);
373+
// Canonicalize the resulting set of protocols.
374+
ProtocolType::canonicalizeProtocols(result);
374375

375-
return result;
376+
return result;
377+
};
378+
379+
auto computeViaRQM = [&]() {
380+
auto *machine = getRequirementMachine();
381+
return machine->getRequiredProtocols(type);
382+
};
383+
384+
auto &ctx = getASTContext();
385+
if (ctx.LangOpts.EnableRequirementMachine) {
386+
auto rqmResult = computeViaRQM();
387+
388+
#ifndef NDEBUG
389+
auto gsbResult = computeViaGSB();
390+
391+
if (gsbResult != rqmResult) {
392+
llvm::errs() << "RequirementMachine::getRequiredProtocols() is broken\n";
393+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
394+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
395+
llvm::errs() << "GenericSignatureBuilder says: ";
396+
for (auto *otherProto : gsbResult)
397+
llvm::errs() << " " << otherProto->getName();
398+
llvm::errs() << "\n";
399+
llvm::errs() << "RequirementMachine says: ";
400+
for (auto *otherProto : rqmResult)
401+
llvm::errs() << " " << otherProto->getName();
402+
llvm::errs() << "\n";
403+
getRequirementMachine()->dump(llvm::errs());
404+
abort();
405+
}
406+
#endif
407+
408+
return rqmResult;
409+
} else {
410+
return computeViaGSB();
411+
}
376412
}
377413

378414
bool GenericSignatureImpl::requiresProtocol(Type type,

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,29 @@ bool RequirementMachine::requiresProtocol(Type depType,
390390
return false;
391391
}
392392

393+
GenericSignature::RequiredProtocols
394+
RequirementMachine::getRequiredProtocols(Type depType) const {
395+
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
396+
/*proto=*/nullptr);
397+
Impl->System.simplify(term);
398+
399+
auto *equivClass = Impl->Map.lookUpEquivalenceClass(term);
400+
if (!equivClass)
401+
return { };
402+
403+
if (equivClass->isConcreteType())
404+
return { };
405+
406+
GenericSignature::RequiredProtocols result;
407+
for (auto *otherProto : equivClass->getConformsTo()) {
408+
result.push_back(const_cast<ProtocolDecl *>(otherProto));
409+
}
410+
411+
ProtocolType::canonicalizeProtocols(result);
412+
413+
return result;
414+
}
415+
393416
bool RequirementMachine::isConcreteType(Type depType) const {
394417
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
395418
/*proto=*/nullptr);

0 commit comments

Comments
 (0)