|
28 | 28 | #include "swift/AST/DiagnosticsSema.h" |
29 | 29 | #include "swift/AST/ExistentialLayout.h" |
30 | 30 | #include "swift/AST/Requirement.h" |
| 31 | +#include "swift/AST/RequirementSignature.h" |
31 | 32 | #include "swift/AST/TypeCheckRequests.h" |
32 | 33 | #include "swift/AST/TypeMatcher.h" |
33 | 34 | #include "swift/AST/TypeRepr.h" |
@@ -1014,6 +1015,38 @@ void RuleBuilder::addRequirement(const StructuralRequirement &req, |
1014 | 1015 | addRequirement(req.req.getCanonical(), proto); |
1015 | 1016 | } |
1016 | 1017 |
|
| 1018 | +/// Lowers a protocol typealias to a rewrite rule. |
| 1019 | +void RuleBuilder::addTypeAlias(const ProtocolTypeAlias &alias, |
| 1020 | + const ProtocolDecl *proto) { |
| 1021 | + // Build the term [P].T, where P is the protocol and T is a name symbol. |
| 1022 | + MutableTerm subjectTerm; |
| 1023 | + subjectTerm.add(Symbol::forProtocol(proto, Context)); |
| 1024 | + subjectTerm.add(Symbol::forName(alias.getName(), Context)); |
| 1025 | + |
| 1026 | + auto constraintType = alias.getUnderlyingType()->getCanonicalType(); |
| 1027 | + MutableTerm constraintTerm; |
| 1028 | + |
| 1029 | + if (constraintType->isTypeParameter()) { |
| 1030 | + // If the underlying type of the typealias is a type parameter X, build |
| 1031 | + // a rule [P].T => X, where X, |
| 1032 | + constraintTerm = Context.getMutableTermForType( |
| 1033 | + constraintType, proto); |
| 1034 | + } else { |
| 1035 | + // If the underlying type of the typealias is a concrete type C, build |
| 1036 | + // a rule [P].T.[concrete: C] => [P].T. |
| 1037 | + constraintTerm = subjectTerm; |
| 1038 | + |
| 1039 | + SmallVector<Term, 1> result; |
| 1040 | + auto concreteType = |
| 1041 | + Context.getSubstitutionSchemaFromType( |
| 1042 | + constraintType, proto, result); |
| 1043 | + |
| 1044 | + constraintTerm.add(Symbol::forConcreteType(concreteType, result, Context)); |
| 1045 | + } |
| 1046 | + |
| 1047 | + RequirementRules.emplace_back(subjectTerm, constraintTerm); |
| 1048 | +} |
| 1049 | + |
1017 | 1050 | /// Record information about a protocol if we have no seen it yet. |
1018 | 1051 | void RuleBuilder::addProtocol(const ProtocolDecl *proto, |
1019 | 1052 | bool initialComponent) { |
@@ -1077,6 +1110,8 @@ void RuleBuilder::collectRulesFromReferencedProtocols() { |
1077 | 1110 | auto reqs = proto->getRequirementSignature(); |
1078 | 1111 | for (auto req : reqs.getRequirements()) |
1079 | 1112 | addRequirement(req.getCanonical(), proto); |
| 1113 | + for (auto alias : reqs.getTypeAliases()) |
| 1114 | + addTypeAlias(alias, proto); |
1080 | 1115 | } |
1081 | 1116 |
|
1082 | 1117 | if (Dump) { |
|
0 commit comments