Skip to content

Commit 7df09f1

Browse files
committed
RequirementMachine: Implement GenericSignature::requiresClass() query
1 parent 6fa7a3f commit 7df09f1

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

include/swift/AST/RequirementMachine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class CanType;
2222
class GenericSignature;
2323
class ProtocolDecl;
2424
class Requirement;
25+
class Type;
2526

2627
/// Wraps a rewrite system with higher-level operations in terms of
2728
/// generic signatures and interface types.
@@ -47,6 +48,8 @@ class RequirementMachine final {
4748

4849
public:
4950
~RequirementMachine();
51+
52+
bool requiresClass(Type depType) const;
5053
};
5154

5255
} // end namespace swift

lib/AST/GenericSignature.cpp

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -280,21 +280,50 @@ bool GenericSignatureImpl::requiresClass(Type type) const {
280280
assert(type->isTypeParameter() &&
281281
"Only type parameters can have superclass requirements");
282282

283-
auto &builder = *getGenericSignatureBuilder();
284-
auto equivClass =
285-
builder.resolveEquivalenceClass(
286-
type,
287-
ArchetypeResolutionKind::CompleteWellFormed);
288-
if (!equivClass) return false;
283+
auto computeViaGSB = [&]() {
284+
auto &builder = *getGenericSignatureBuilder();
285+
auto equivClass =
286+
builder.resolveEquivalenceClass(
287+
type,
288+
ArchetypeResolutionKind::CompleteWellFormed);
289+
if (!equivClass) return false;
289290

290-
// If this type was mapped to a concrete type, then there is no
291-
// requirement.
292-
if (equivClass->concreteType) return false;
291+
// If this type was mapped to a concrete type, then there is no
292+
// requirement.
293+
if (equivClass->concreteType) return false;
293294

294-
// If there is a layout constraint, it might be a class.
295-
if (equivClass->layout && equivClass->layout->isClass()) return true;
295+
// If there is a layout constraint, it might be a class.
296+
if (equivClass->layout && equivClass->layout->isClass()) return true;
296297

297-
return false;
298+
return false;
299+
};
300+
301+
auto computeViaRQM = [&]() {
302+
auto *machine = getRequirementMachine();
303+
return machine->requiresClass(type);
304+
};
305+
306+
auto &ctx = getASTContext();
307+
if (ctx.LangOpts.EnableRequirementMachine) {
308+
bool rqmResult = computeViaRQM();
309+
310+
#ifndef NDEBUG
311+
bool gsbResult = computeViaGSB();
312+
313+
if (gsbResult != rqmResult) {
314+
llvm::errs() << "RequirementMachine::requiresClass() is broken\n";
315+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
316+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
317+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
318+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
319+
abort();
320+
}
321+
#endif
322+
323+
return rqmResult;
324+
} else {
325+
return computeViaGSB();
326+
}
298327
}
299328

300329
/// Determine the superclass bound on the given dependent type.

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,3 +336,19 @@ void RequirementMachine::computeCompletion(CanGenericSignature sig) {
336336
bool RequirementMachine::isComplete() const {
337337
return Impl->Complete;
338338
}
339+
340+
bool RequirementMachine::requiresClass(Type depType) const {
341+
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
342+
/*proto=*/nullptr);
343+
Impl->System.simplify(term);
344+
345+
auto *equivClass = Impl->Map.lookUpEquivalenceClass(term);
346+
if (!equivClass)
347+
return false;
348+
349+
if (equivClass->isConcreteType())
350+
return false;
351+
352+
auto layout = equivClass->getLayoutConstraint();
353+
return (layout && layout->isClass());
354+
}

0 commit comments

Comments
 (0)