Skip to content

Commit 043f501

Browse files
authored
Merge pull request #38353 from slavapestov/requirement-machine-superclass
RequirementMachine: Fixes for nested type concretization, and some more queries
2 parents 9f5cf97 + 4184ebd commit 043f501

16 files changed

+1508
-457
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,13 @@ class ConformanceAccessPath {
8282

8383
friend class GenericSignatureImpl;
8484
friend class GenericSignatureBuilder;
85+
friend class RequirementMachine;
8586

8687
public:
8788
typedef const Entry *const_iterator;
8889
typedef const_iterator iterator;
8990

91+
unsigned size() const { return path.size(); }
9092
const_iterator begin() const { return path.begin(); }
9193
const_iterator end() const { return path.end(); }
9294

include/swift/AST/RequirementMachine.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,23 @@ class RequirementMachine final {
5555
public:
5656
~RequirementMachine();
5757

58-
// Generic signature queries
58+
// Generic signature queries. Generally you shouldn't have to construct a
59+
// RequirementMachine instance; instead, call the corresponding methods on
60+
// GenericSignature, which lazily create a RequirementMachine for you.
5961
bool requiresClass(Type depType) const;
6062
LayoutConstraint getLayoutConstraint(Type depType) const;
6163
bool requiresProtocol(Type depType, const ProtocolDecl *proto) const;
6264
GenericSignature::RequiredProtocols getRequiredProtocols(Type depType) const;
65+
Type getSuperclassBound(Type depType) const;
6366
bool isConcreteType(Type depType) const;
67+
Type getConcreteType(Type depType) const;
6468
bool areSameTypeParameterInContext(Type depType1, Type depType2) const;
69+
bool isCanonicalTypeInContext(Type type) const;
6570
Type getCanonicalTypeInContext(Type type,
6671
TypeArrayView<GenericTypeParamType> genericParams) const;
72+
ConformanceAccessPath getConformanceAccessPath(Type type,
73+
ProtocolDecl *protocol);
74+
TypeDecl *lookupNestedType(Type depType, Identifier name) const;
6775

6876
void dump(llvm::raw_ostream &out) const;
6977
};

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ add_swift_host_library(swiftAST STATIC
7676
RequirementMachine/EquivalenceClassMap.cpp
7777
RequirementMachine/ProtocolGraph.cpp
7878
RequirementMachine/RequirementMachine.cpp
79+
RequirementMachine/RewriteContext.cpp
7980
RequirementMachine/RewriteSystem.cpp
8081
RequirementMachine/RewriteSystemCompletion.cpp
8182
SILLayout.cpp

lib/AST/GenericSignature.cpp

Lines changed: 243 additions & 19 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;
341346

342-
// If this type was mapped to a concrete type, then there is no
343-
// requirement.
344-
if (equivClass->concreteType) return nullptr;
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();
345362

346-
// Retrieve the superclass bound.
347-
return equivClass->superclass;
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
385+
386+
return rqmResult;
387+
} else {
388+
return computeViaGSB();
389+
}
348390
}
349391

350392
/// Determine the set of protocols to which the given type parameter is
@@ -516,14 +558,56 @@ bool GenericSignatureImpl::isConcreteType(Type type) const {
516558
Type GenericSignatureImpl::getConcreteType(Type type) const {
517559
assert(type->isTypeParameter() && "Expected a type parameter");
518560

519-
auto &builder = *getGenericSignatureBuilder();
520-
auto equivClass =
561+
auto computeViaGSB = [&]() -> Type {
562+
auto &builder = *getGenericSignatureBuilder();
563+
auto equivClass =
521564
builder.resolveEquivalenceClass(
522565
type,
523566
ArchetypeResolutionKind::CompleteWellFormed);
524-
if (!equivClass) return Type();
567+
if (!equivClass) return nullptr;
525568

526-
return equivClass->concreteType;
569+
return equivClass->concreteType;
570+
};
571+
572+
auto computeViaRQM = [&]() {
573+
auto *machine = getRequirementMachine();
574+
return machine->getConcreteType(type);
575+
};
576+
577+
auto &ctx = getASTContext();
578+
if (ctx.LangOpts.EnableRequirementMachine) {
579+
auto rqmResult = computeViaRQM();
580+
581+
#ifndef NDEBUG
582+
auto gsbResult = computeViaGSB();
583+
584+
auto check = [&]() {
585+
if (!gsbResult || !rqmResult)
586+
return !gsbResult == !rqmResult;
587+
return gsbResult->isEqual(rqmResult);
588+
};
589+
590+
if (!check()) {
591+
llvm::errs() << "RequirementMachine::getConcreteType() is broken\n";
592+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
593+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
594+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
595+
if (gsbResult)
596+
gsbResult.dump(llvm::errs());
597+
llvm::errs() << "\n";
598+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
599+
if (rqmResult)
600+
rqmResult.dump(llvm::errs());
601+
llvm::errs() << "\n";
602+
getRequirementMachine()->dump(llvm::errs());
603+
abort();
604+
}
605+
#endif
606+
607+
return rqmResult;
608+
} else {
609+
return computeViaGSB();
610+
}
527611
}
528612

529613
LayoutConstraint GenericSignatureImpl::getLayoutConstraint(Type type) const {
@@ -703,8 +787,39 @@ bool GenericSignatureImpl::isCanonicalTypeInContext(Type type) const {
703787
if (!type->hasTypeParameter())
704788
return true;
705789

706-
auto &builder = *getGenericSignatureBuilder();
707-
return isCanonicalTypeInContext(type, builder);
790+
auto computeViaGSB = [&]() {
791+
auto &builder = *getGenericSignatureBuilder();
792+
return isCanonicalTypeInContext(type, builder);
793+
};
794+
795+
auto computeViaRQM = [&]() {
796+
auto *machine = getRequirementMachine();
797+
return machine->isCanonicalTypeInContext(type);
798+
};
799+
800+
auto &ctx = getASTContext();
801+
if (ctx.LangOpts.EnableRequirementMachine) {
802+
auto rqmResult = computeViaRQM();
803+
804+
#ifndef NDEBUG
805+
auto gsbResult = computeViaGSB();
806+
807+
if (gsbResult != rqmResult) {
808+
llvm::errs() << "RequirementMachine::isCanonicalTypeInContext() is broken\n";
809+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
810+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
811+
llvm::errs() << "\n";
812+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
813+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
814+
getRequirementMachine()->dump(llvm::errs());
815+
abort();
816+
}
817+
#endif
818+
819+
return rqmResult;
820+
} else {
821+
return computeViaGSB();
822+
}
708823
}
709824

710825
bool GenericSignatureImpl::isCanonicalTypeInContext(
@@ -791,8 +906,117 @@ CanGenericSignature::getGenericParams() const{
791906
ConformanceAccessPath
792907
GenericSignatureImpl::getConformanceAccessPath(Type type,
793908
ProtocolDecl *protocol) const {
794-
return getGenericSignatureBuilder()->getConformanceAccessPath(
795-
type, protocol, this);
909+
auto computeViaGSB = [&]() {
910+
return getGenericSignatureBuilder()->getConformanceAccessPath(
911+
type, protocol, this);
912+
};
913+
914+
auto computeViaRQM = [&]() {
915+
auto *machine = getRequirementMachine();
916+
return machine->getConformanceAccessPath(type, protocol);
917+
};
918+
919+
auto &ctx = getASTContext();
920+
if (ctx.LangOpts.EnableRequirementMachine) {
921+
auto rqmResult = computeViaRQM();
922+
923+
#ifndef NDEBUG
924+
auto gsbResult = computeViaGSB();
925+
926+
auto compare = [&]() {
927+
if (gsbResult.size() != rqmResult.size())
928+
return false;
929+
930+
auto *begin1 = gsbResult.begin();
931+
auto *end1 = gsbResult.end();
932+
auto *begin2 = rqmResult.begin();
933+
auto *end2 = rqmResult.end();
934+
935+
while (begin1 < end1) {
936+
assert(begin2 < end2);
937+
938+
if (!begin1->first->isEqual(begin2->first))
939+
return false;
940+
if (begin1->second != begin2->second)
941+
return false;
942+
943+
++begin1;
944+
++begin2;
945+
}
946+
947+
return true;
948+
};
949+
950+
if (!compare()) {
951+
llvm::errs() << "RequirementMachine::getConformanceAccessPath() is broken\n";
952+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
953+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
954+
llvm::errs() << "Protocol: "; protocol->dumpRef(llvm::errs());
955+
llvm::errs() << "\n";
956+
llvm::errs() << "GenericSignatureBuilder says: ";
957+
gsbResult.print(llvm::errs());
958+
llvm::errs() << "\n";
959+
llvm::errs() << "RequirementMachine says: ";
960+
rqmResult.print(llvm::errs());
961+
llvm::errs() << "\n\n";
962+
getRequirementMachine()->dump(llvm::errs());
963+
abort();
964+
}
965+
#endif
966+
967+
return rqmResult;
968+
} else {
969+
return computeViaGSB();
970+
}
971+
}
972+
973+
TypeDecl *
974+
GenericSignatureImpl::lookupNestedType(Type type, Identifier name) const {
975+
assert(type->isTypeParameter());
976+
977+
auto computeViaGSB = [&]() -> TypeDecl * {
978+
auto *builder = getGenericSignatureBuilder();
979+
auto equivClass =
980+
builder->resolveEquivalenceClass(
981+
type,
982+
ArchetypeResolutionKind::CompleteWellFormed);
983+
if (!equivClass)
984+
return nullptr;
985+
986+
return equivClass->lookupNestedType(*builder, name);
987+
};
988+
989+
auto computeViaRQM = [&]() {
990+
auto *machine = getRequirementMachine();
991+
return machine->lookupNestedType(type, name);
992+
};
993+
994+
auto &ctx = getASTContext();
995+
if (ctx.LangOpts.EnableRequirementMachine) {
996+
auto rqmResult = computeViaRQM();
997+
998+
#ifndef NDEBUG
999+
auto gsbResult = computeViaGSB();
1000+
1001+
if (gsbResult != rqmResult) {
1002+
llvm::errs() << "RequirementMachine::lookupNestedType() is broken\n";
1003+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
1004+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
1005+
llvm::errs() << "GenericSignatureBuilder says: ";
1006+
gsbResult->dumpRef(llvm::errs());
1007+
llvm::errs() << "\n";
1008+
llvm::errs() << "RequirementMachine says: ";
1009+
rqmResult->dumpRef(llvm::errs());
1010+
llvm::errs() << "\n";
1011+
getRequirementMachine()->dump(llvm::errs());
1012+
abort();
1013+
}
1014+
#endif
1015+
1016+
return rqmResult;
1017+
} else {
1018+
return computeViaGSB();
1019+
}
7961020
}
7971021

7981022
TypeDecl *

0 commit comments

Comments
 (0)