Skip to content

Commit 060f490

Browse files
committed
RequirementMachine: Implement GenericSignature::getSuperclassBound() query
1 parent e4173ad commit 060f490

File tree

5 files changed

+90
-11
lines changed

5 files changed

+90
-11
lines changed

include/swift/AST/RequirementMachine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class RequirementMachine final {
6060
LayoutConstraint getLayoutConstraint(Type depType) const;
6161
bool requiresProtocol(Type depType, const ProtocolDecl *proto) const;
6262
GenericSignature::RequiredProtocols getRequiredProtocols(Type depType) const;
63+
Type getSuperclassBound(Type depType) const;
6364
bool isConcreteType(Type depType) const;
6465
bool areSameTypeParameterInContext(Type depType1, Type depType2) const;
6566
Type getCanonicalTypeInContext(Type type,

lib/AST/GenericSignature.cpp

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -332,19 +332,61 @@ Type GenericSignatureImpl::getSuperclassBound(Type type) const {
332332
assert(type->isTypeParameter() &&
333333
"Only type parameters can have superclass requirements");
334334

335-
auto &builder = *getGenericSignatureBuilder();
336-
auto equivClass =
337-
builder.resolveEquivalenceClass(
338-
type,
339-
ArchetypeResolutionKind::CompleteWellFormed);
340-
if (!equivClass) return nullptr;
335+
auto computeViaGSB = [&]() -> Type {
336+
auto &builder = *getGenericSignatureBuilder();
337+
auto equivClass =
338+
builder.resolveEquivalenceClass(
339+
type,
340+
ArchetypeResolutionKind::CompleteWellFormed);
341+
if (!equivClass) return nullptr;
342+
343+
// If this type was mapped to a concrete type, then there is no
344+
// requirement.
345+
if (equivClass->concreteType) return nullptr;
346+
347+
// Retrieve the superclass bound.
348+
return equivClass->superclass;
349+
};
350+
351+
auto computeViaRQM = [&]() {
352+
auto *machine = getRequirementMachine();
353+
return machine->getSuperclassBound(type);
354+
};
355+
356+
auto &ctx = getASTContext();
357+
if (ctx.LangOpts.EnableRequirementMachine) {
358+
auto rqmResult = computeViaRQM();
359+
360+
#ifndef NDEBUG
361+
auto gsbResult = computeViaGSB();
341362

342-
// If this type was mapped to a concrete type, then there is no
343-
// requirement.
344-
if (equivClass->concreteType) return nullptr;
363+
auto check = [&]() {
364+
if (!gsbResult || !rqmResult)
365+
return !gsbResult == !rqmResult;
366+
return gsbResult->isEqual(rqmResult);
367+
};
368+
369+
if (!check()) {
370+
llvm::errs() << "RequirementMachine::getSuperclassBound() is broken\n";
371+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
372+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
373+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
374+
if (gsbResult)
375+
gsbResult.dump(llvm::errs());
376+
llvm::errs() << "\n";
377+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
378+
if (rqmResult)
379+
rqmResult.dump(llvm::errs());
380+
llvm::errs() << "\n";
381+
getRequirementMachine()->dump(llvm::errs());
382+
abort();
383+
}
384+
#endif
345385

346-
// Retrieve the superclass bound.
347-
return equivClass->superclass;
386+
return rqmResult;
387+
} else {
388+
return computeViaGSB();
389+
}
348390
}
349391

350392
/// Determine the set of protocols to which the given type parameter is

lib/AST/RequirementMachine/EquivalenceClassMap.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ static Type getTypeFromSubstitutionSchema(Type schema,
129129
});
130130
}
131131

132+
/// Get the superclass bound of this equivalence class.
133+
///
134+
/// Asserts if this equivalence class does not have a superclass bound.
135+
Type EquivalenceClass::getSuperclassBound(
136+
TypeArrayView<GenericTypeParamType> genericParams,
137+
const ProtocolGraph &protos,
138+
RewriteContext &ctx) const {
139+
return getTypeFromSubstitutionSchema(Superclass->getSuperclass(),
140+
Superclass->getSubstitutions(),
141+
genericParams,
142+
protos,
143+
ctx);
144+
}
145+
132146
/// Get the concrete type of this equivalence class.
133147
///
134148
/// Asserts if this equivalence class is not concrete.

lib/AST/RequirementMachine/EquivalenceClassMap.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ class EquivalenceClass {
8787
return Superclass.hasValue();
8888
}
8989

90+
Type getSuperclassBound(
91+
TypeArrayView<GenericTypeParamType> genericParams,
92+
const ProtocolGraph &protos,
93+
RewriteContext &ctx) const;
94+
9095
bool isConcreteType() const {
9196
return ConcreteType.hasValue();
9297
}

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,23 @@ RequirementMachine::getRequiredProtocols(Type depType) const {
508508
return result;
509509
}
510510

511+
Type RequirementMachine::getSuperclassBound(Type depType) const {
512+
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
513+
/*proto=*/nullptr);
514+
Impl->System.simplify(term);
515+
Impl->verify(term);
516+
517+
auto *equivClass = Impl->Map.lookUpEquivalenceClass(term);
518+
if (!equivClass)
519+
return Type();
520+
521+
if (!equivClass->hasSuperclassBound())
522+
return Type();
523+
524+
auto &protos = Impl->System.getProtocols();
525+
return equivClass->getSuperclassBound({ }, protos, Impl->Context);
526+
}
527+
511528
bool RequirementMachine::isConcreteType(Type depType) const {
512529
auto term = Impl->Context.getMutableTermForType(depType->getCanonicalType(),
513530
/*proto=*/nullptr);

0 commit comments

Comments
 (0)