10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
//
13
- // This file implements the main entry points into the requirement machine
14
- // via the request evaluator.
13
+ // This file implements the main entry points for computing minimized generic
14
+ // signatures using the requirement machine via the request evaluator.
15
+ //
16
+ // The actual logic for finding a minimal set of rewrite rules is implemented in
17
+ // HomotopyReduction.cpp and GeneratingConformances.cpp.
15
18
//
16
19
// ===----------------------------------------------------------------------===//
17
20
18
- #include " RequirementMachine.h"
19
21
#include " swift/AST/ASTContext.h"
20
22
#include " swift/AST/Decl.h"
23
+ #include " swift/AST/GenericSignature.h"
21
24
#include " swift/AST/GenericSignatureBuilder.h"
22
25
#include " swift/AST/LazyResolver.h"
26
+ #include " swift/AST/Requirement.h"
23
27
#include " swift/AST/TypeCheckRequests.h"
24
28
#include " swift/Basic/Statistic.h"
29
+ #include < vector>
30
+
31
+ #include " RequirementMachine.h"
25
32
26
33
using namespace swift ;
27
34
using namespace rewriting ;
@@ -33,6 +40,111 @@ STATISTIC(NumLazyRequirementSignaturesLoaded,
33
40
34
41
#undef DEBUG_TYPE
35
42
43
+ // / Convert a list of non-permanent, non-redundant rewrite rules into a minimal
44
+ // / protocol requirement signature for \p proto. The requirements are sorted in
45
+ // / canonical order, and same-type requirements are canonicalized.
46
+ std::vector<Requirement>
47
+ RequirementMachine::buildRequirementSignature (ArrayRef<unsigned > rules,
48
+ const ProtocolDecl *proto) const {
49
+ std::vector<Requirement> reqs;
50
+ llvm::SmallDenseMap<TypeBase *, llvm::SmallVector<Type, 2 >> sameTypeReqs;
51
+
52
+ auto genericParams = proto->getGenericSignature ().getGenericParams ();
53
+
54
+ // Convert a rewrite rule into a requirement.
55
+ auto createRequirementFromRule = [&](const Rule &rule) {
56
+ if (auto prop = rule.isPropertyRule ()) {
57
+ auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
58
+ System.getProtocols ());
59
+
60
+ switch (prop->getKind ()) {
61
+ case Symbol::Kind::Protocol:
62
+ reqs.emplace_back (RequirementKind::Conformance,
63
+ subjectType,
64
+ prop->getProtocol ()->getDeclaredInterfaceType ());
65
+ return ;
66
+
67
+ case Symbol::Kind::Layout:
68
+ case Symbol::Kind::ConcreteType:
69
+ case Symbol::Kind::Superclass:
70
+ // FIXME
71
+ return ;
72
+
73
+ case Symbol::Kind::Name:
74
+ case Symbol::Kind::AssociatedType:
75
+ case Symbol::Kind::GenericParam:
76
+ break ;
77
+ }
78
+
79
+ llvm_unreachable (" Invalid symbol kind" );
80
+ } else if (rule.getLHS ().back ().getKind () != Symbol::Kind::Protocol) {
81
+ auto constraintType = Context.getTypeForTerm (rule.getLHS (), genericParams,
82
+ System.getProtocols ());
83
+ auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
84
+ System.getProtocols ());
85
+
86
+ sameTypeReqs[subjectType.getPointer ()].push_back (constraintType);
87
+ }
88
+ };
89
+
90
+ // Build the list of requirements, storing same-type requirements off
91
+ // to the side.
92
+ for (unsigned ruleID : rules) {
93
+ const auto &rule = System.getRule (ruleID);
94
+ createRequirementFromRule (rule);
95
+ }
96
+
97
+ // A set of rewrite rules of the form:
98
+ //
99
+ // B => A
100
+ // C => A
101
+ // D => A
102
+ //
103
+ // Become a series of same-type requirements
104
+ //
105
+ // A == B, B == C, C == D
106
+ //
107
+ for (auto &pair : sameTypeReqs) {
108
+ std::sort (pair.second .begin (), pair.second .end (),
109
+ [](Type first, Type second) -> bool {
110
+ return compareDependentTypes (first, second) < 0 ;
111
+ });
112
+
113
+ Type subjectType (pair.first );
114
+ for (auto constraintType : pair.second ) {
115
+ reqs.emplace_back (RequirementKind::SameType, subjectType, constraintType);
116
+ subjectType = constraintType;
117
+ }
118
+ }
119
+
120
+ // Sort the requirements in canonical order.
121
+ std::sort (reqs.begin (), reqs.end (),
122
+ [](const Requirement &lhs, const Requirement &rhs) -> bool {
123
+ return lhs.compare (rhs) < 0 ;
124
+ });
125
+
126
+ return reqs;
127
+ }
128
+
129
+ // / Builds the requirement signatures for each protocol in this strongly
130
+ // / connected component.
131
+ llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>>
132
+ RequirementMachine::computeMinimalRequirements () {
133
+ assert (Protos.size () > 0 );
134
+ System.minimizeRewriteSystem ();
135
+
136
+ auto rules = System.getMinimizedRules (Protos);
137
+
138
+ // Note that we build 'result' by iterating over 'Protos' rather than
139
+ // 'rules'; this is intentional, so that even if a protocol has no
140
+ // rules, we still end up creating an entry for it in 'result'.
141
+ llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>> result;
142
+ for (const auto *proto : Protos)
143
+ result[proto] = buildRequirementSignature (rules[proto], proto);
144
+
145
+ return result;
146
+ }
147
+
36
148
ArrayRef<Requirement>
37
149
RequirementSignatureRequest::evaluate (Evaluator &evaluator,
38
150
ProtocolDecl *proto) const {
0 commit comments