Skip to content

Commit 8053b91

Browse files
committed
RequirementMachine: Implement GenericSignature::requiresProtocol() query
1 parent 7df09f1 commit 8053b91

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

include/swift/AST/RequirementMachine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class RequirementMachine final {
5050
~RequirementMachine();
5151

5252
bool requiresClass(Type depType) const;
53+
bool requiresProtocol(Type depType, const ProtocolDecl *proto) const;
5354
};
5455

5556
} // end namespace swift

lib/AST/GenericSignature.cpp

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -378,22 +378,53 @@ bool GenericSignatureImpl::requiresProtocol(Type type,
378378
ProtocolDecl *proto) const {
379379
assert(type->isTypeParameter() && "Expected a type parameter");
380380

381-
auto &builder = *getGenericSignatureBuilder();
382-
auto equivClass =
383-
builder.resolveEquivalenceClass(
384-
type,
385-
ArchetypeResolutionKind::CompleteWellFormed);
386-
if (!equivClass) return false;
381+
auto computeViaGSB = [&]() {
382+
auto &builder = *getGenericSignatureBuilder();
383+
auto equivClass =
384+
builder.resolveEquivalenceClass(
385+
type,
386+
ArchetypeResolutionKind::CompleteWellFormed);
387+
if (!equivClass) return false;
387388

388-
// FIXME: Optionally deal with concrete conformances here
389-
// or have a separate method do that additionally?
390-
//
391-
// If this type parameter was mapped to a concrete type, then there
392-
// are no requirements.
393-
if (equivClass->concreteType) return false;
389+
// FIXME: Optionally deal with concrete conformances here
390+
// or have a separate method do that additionally?
391+
//
392+
// If this type parameter was mapped to a concrete type, then there
393+
// are no requirements.
394+
if (equivClass->concreteType) return false;
395+
396+
// Check whether the representative conforms to this protocol.
397+
return equivClass->conformsTo.count(proto) > 0;
398+
};
399+
400+
auto computeViaRQM = [&]() {
401+
auto *machine = getRequirementMachine();
402+
return machine->requiresProtocol(type, proto);
403+
};
394404

395-
// Check whether the representative conforms to this protocol.
396-
return equivClass->conformsTo.count(proto) > 0;
405+
auto &ctx = getASTContext();
406+
if (ctx.LangOpts.EnableRequirementMachine) {
407+
bool rqmResult = computeViaRQM();
408+
409+
#ifndef NDEBUG
410+
bool gsbResult = computeViaGSB();
411+
412+
if (gsbResult != rqmResult) {
413+
llvm::errs() << "RequirementMachine::requiresProtocol() is broken\n";
414+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
415+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
416+
llvm::errs() << "Protocol: "; proto->dumpRef(llvm::errs());
417+
llvm::errs() << "\n";
418+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
419+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
420+
abort();
421+
}
422+
#endif
423+
424+
return rqmResult;
425+
} else {
426+
return computeViaGSB();
427+
}
397428
}
398429

399430
/// Determine whether the given dependent type is equal to a concrete type.

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,4 +351,25 @@ bool RequirementMachine::requiresClass(Type depType) const {
351351

352352
auto layout = equivClass->getLayoutConstraint();
353353
return (layout && layout->isClass());
354+
}
355+
356+
bool RequirementMachine::requiresProtocol(Type depType,
357+
const ProtocolDecl *proto) const {
358+
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
359+
/*proto=*/nullptr);
360+
Impl->System.simplify(term);
361+
362+
auto *equivClass = Impl->Map.lookUpEquivalenceClass(term);
363+
if (!equivClass)
364+
return false;
365+
366+
if (equivClass->isConcreteType())
367+
return false;
368+
369+
for (auto *otherProto : equivClass->getConformsTo()) {
370+
if (otherProto == proto)
371+
return true;
372+
}
373+
374+
return false;
354375
}

0 commit comments

Comments
 (0)