@@ -40,14 +40,71 @@ STATISTIC(NumLazyRequirementSignaturesLoaded,
40
40
41
41
#undef DEBUG_TYPE
42
42
43
+ namespace {
44
+
45
+ // / Represents a set of types related by same-type requirements, and an
46
+ // / optional concrete type requirement.
47
+ struct ConnectedComponent {
48
+ llvm::SmallVector<Type, 2 > Members;
49
+ Type ConcreteType;
50
+
51
+ void buildRequirements (Type subjectType, std::vector<Requirement> &reqs);
52
+ };
53
+
54
+ // / Case 1: A set of rewrite rules of the form:
55
+ // /
56
+ // / B => A
57
+ // / C => A
58
+ // / D => A
59
+ // /
60
+ // / Become a series of same-type requirements
61
+ // /
62
+ // / A == B, B == C, C == D
63
+ // /
64
+ // / Case 2: A set of rewrite rules of the form:
65
+ // /
66
+ // / A.[concrete: X] => A
67
+ // / B => A
68
+ // / C => A
69
+ // / D => A
70
+ // /
71
+ // / Become a series of same-type requirements
72
+ // /
73
+ // / A == X, B == X, C == X, D == X
74
+ void ConnectedComponent::buildRequirements (Type subjectType,
75
+ std::vector<Requirement> &reqs) {
76
+ std::sort (Members.begin (), Members.end (),
77
+ [](Type first, Type second) -> bool {
78
+ return compareDependentTypes (first, second) < 0 ;
79
+ });
80
+
81
+ if (!ConcreteType) {
82
+ for (auto constraintType : Members) {
83
+ reqs.emplace_back (RequirementKind::SameType,
84
+ subjectType, constraintType);
85
+ subjectType = constraintType;
86
+ }
87
+ } else {
88
+ reqs.emplace_back (RequirementKind::SameType,
89
+ subjectType, ConcreteType);
90
+
91
+ for (auto constraintType : Members) {
92
+ reqs.emplace_back (RequirementKind::SameType,
93
+ constraintType, ConcreteType);
94
+ }
95
+ }
96
+ }
97
+
98
+ } // end namespace
99
+
43
100
// / Convert a list of non-permanent, non-redundant rewrite rules into a minimal
44
101
// / protocol requirement signature for \p proto. The requirements are sorted in
45
102
// / canonical order, and same-type requirements are canonicalized.
46
103
std::vector<Requirement>
47
104
RequirementMachine::buildRequirementSignature (ArrayRef<unsigned > rules,
48
105
const ProtocolDecl *proto) const {
49
106
std::vector<Requirement> reqs;
50
- llvm::SmallDenseMap<TypeBase *, llvm::SmallVector<Type, 2 > > sameTypeReqs;
107
+ llvm::SmallDenseMap<TypeBase *, ConnectedComponent > sameTypeReqs;
51
108
52
109
auto genericParams = proto->getGenericSignature ().getGenericParams ();
53
110
const auto &protos = System.getProtocols ();
@@ -81,15 +138,18 @@ RequirementMachine::buildRequirementSignature(ArrayRef<unsigned> rules,
81
138
protos));
82
139
return ;
83
140
84
- case Symbol::Kind::ConcreteType:
85
- reqs.emplace_back (RequirementKind::SameType,
86
- subjectType,
87
- Context.getTypeFromSubstitutionSchema (
88
- prop->getConcreteType (),
89
- prop->getSubstitutions (),
90
- genericParams, MutableTerm (),
91
- protos));
141
+ case Symbol::Kind::ConcreteType: {
142
+ auto concreteType = Context.getTypeFromSubstitutionSchema (
143
+ prop->getConcreteType (),
144
+ prop->getSubstitutions (),
145
+ genericParams, MutableTerm (),
146
+ protos);
147
+
148
+ auto &component = sameTypeReqs[subjectType.getPointer ()];
149
+ assert (!component.ConcreteType );
150
+ component.ConcreteType = concreteType;
92
151
return ;
152
+ }
93
153
94
154
case Symbol::Kind::Name:
95
155
case Symbol::Kind::AssociatedType:
@@ -104,41 +164,41 @@ RequirementMachine::buildRequirementSignature(ArrayRef<unsigned> rules,
104
164
auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
105
165
protos);
106
166
107
- sameTypeReqs[subjectType.getPointer ()].push_back (constraintType);
167
+ sameTypeReqs[subjectType.getPointer ()].Members . push_back (constraintType);
108
168
}
109
169
};
110
170
171
+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
172
+ llvm::dbgs () << " Minimized rules:\n " ;
173
+ }
174
+
111
175
// Build the list of requirements, storing same-type requirements off
112
176
// to the side.
113
177
for (unsigned ruleID : rules) {
114
178
const auto &rule = System.getRule (ruleID);
179
+
180
+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
181
+ llvm::dbgs () << " - " << rule << " \n " ;
182
+ }
183
+
115
184
createRequirementFromRule (rule);
116
185
}
117
186
118
- // A set of rewrite rules of the form:
119
- //
120
- // B => A
121
- // C => A
122
- // D => A
123
- //
124
- // Become a series of same-type requirements
125
- //
126
- // A == B, B == C, C == D
127
- //
187
+ // Now, convert each connected component into a series of same-type
188
+ // requirements.
128
189
for (auto &pair : sameTypeReqs) {
129
- std::sort (pair.second .begin (), pair.second .end (),
130
- [](Type first, Type second) -> bool {
131
- return compareDependentTypes (first, second) < 0 ;
132
- });
133
-
134
- Type subjectType (pair.first );
135
- for (auto constraintType : pair.second ) {
136
- reqs.emplace_back (RequirementKind::SameType, subjectType, constraintType);
137
- subjectType = constraintType;
190
+ pair.second .buildRequirements (pair.first , reqs);
191
+ }
192
+
193
+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
194
+ llvm::dbgs () << " Requirements:\n " ;
195
+ for (const auto &req : reqs) {
196
+ req.dump (llvm::dbgs ());
197
+ llvm::dbgs () << " \n " ;
138
198
}
139
199
}
140
200
141
- // Sort the requirements in canonical order.
201
+ // Finally, sort the requirements in canonical order.
142
202
std::sort (reqs.begin (), reqs.end (),
143
203
[](const Requirement &lhs, const Requirement &rhs) -> bool {
144
204
return lhs.compare (rhs) < 0 ;
0 commit comments