39
39
using namespace swift ;
40
40
using namespace rewriting ;
41
41
42
- // / Desugar a protocol conformance requirement by splitting up protocol
43
- // / compositions on the right hand side until conformance and superclass
44
- // / requirements.
45
- static void addTypeRequirement (Type subjectType, Type constraintType,
46
- SourceLoc loc, bool wasInferred,
47
- SmallVectorImpl<StructuralRequirement> &result) {
48
- // Check whether we have a reasonable constraint type at all.
49
- if (!constraintType->isExistentialType () &&
50
- !constraintType->getClassOrBoundGenericClass ()) {
51
- // FIXME: Diagnose
52
- return ;
53
- }
54
-
55
- // Protocol requirements.
56
- if (constraintType->isExistentialType ()) {
57
- auto layout = constraintType->getExistentialLayout ();
58
-
59
- if (auto layoutConstraint = layout.getLayoutConstraint ()) {
60
- result.push_back ({
61
- Requirement (RequirementKind::Layout, subjectType, layoutConstraint),
62
- loc, wasInferred});
63
- }
64
-
65
- if (auto superclass = layout.explicitSuperclass ) {
66
- result.push_back ({
67
- Requirement (RequirementKind::Superclass, subjectType, superclass),
68
- loc, wasInferred});
69
- }
70
-
71
- for (auto *proto : layout.getProtocols ()) {
72
- result.push_back ({
73
- Requirement (RequirementKind::Conformance, subjectType, proto),
74
- loc, wasInferred});
75
- }
76
-
77
- return ;
78
- }
79
-
80
- // Superclass constraint.
81
- result.push_back ({
82
- Requirement (RequirementKind::Superclass, subjectType, constraintType),
83
- loc, wasInferred});
84
- }
42
+ //
43
+ // Requirement desugaring -- used in two places:
44
+ //
45
+ // 1) AbstractGenericSignatureRequest, where the added requirements might have
46
+ // substitutions applied.
47
+ //
48
+ // 2) StructuralRequirementsRequest, which performs further processing to wrap
49
+ // desugared requirements with source location information.
50
+ //
85
51
86
52
// / Desugar a same-type requirement that possibly has concrete types on either
87
53
// / side into a series of same-type and concrete-type requirements where the
88
54
// / left hand side is always a type parameter.
89
- static void addSameTypeRequirement (Type lhs, Type rhs,
90
- SourceLoc loc, bool wasInferred,
91
- SmallVectorImpl<StructuralRequirement> &result) {
55
+ static void desugarSameTypeRequirement (Type lhs, Type rhs,
56
+ SmallVectorImpl<Requirement> &result) {
92
57
class Matcher : public TypeMatcher <Matcher> {
93
- SourceLoc loc;
94
- bool wasInferred;
95
- SmallVectorImpl<StructuralRequirement> &result;
58
+ SmallVectorImpl<Requirement> &result;
96
59
97
60
public:
98
- Matcher (SourceLoc loc, bool wasInferred,
99
- SmallVectorImpl<StructuralRequirement> &result)
100
- : loc(loc), wasInferred(wasInferred), result(result) {}
61
+ explicit Matcher (SmallVectorImpl<Requirement> &result)
62
+ : result(result) {}
101
63
102
64
bool mismatch (TypeBase *firstType, TypeBase *secondType,
103
65
Type sugaredFirstType) {
104
66
if (firstType->isTypeParameter () && secondType->isTypeParameter ()) {
105
- result.push_back ({Requirement (RequirementKind::SameType,
106
- firstType, secondType),
107
- loc, wasInferred});
67
+ result.emplace_back (RequirementKind::SameType,
68
+ firstType, secondType);
108
69
return true ;
109
70
}
110
71
111
72
if (firstType->isTypeParameter ()) {
112
- result.push_back ({Requirement (RequirementKind::SameType,
113
- firstType, secondType),
114
- loc, wasInferred});
73
+ result.emplace_back (RequirementKind::SameType,
74
+ firstType, secondType);
115
75
return true ;
116
76
}
117
77
118
78
if (secondType->isTypeParameter ()) {
119
- result.push_back ({Requirement (RequirementKind::SameType,
120
- secondType, firstType),
121
- loc, wasInferred});
79
+ result.emplace_back (RequirementKind::SameType,
80
+ secondType, firstType);
122
81
return true ;
123
82
}
124
83
125
- // FIXME: Diagnose concrete type conflict
84
+ // FIXME: Record concrete type conflict, diagnose upstream
126
85
return true ;
127
86
}
128
- } matcher (loc, wasInferred, result);
87
+ } matcher (result);
129
88
130
- // FIXME: If both sides concrete and was not inferred, diagnose redundancy
131
- // FIXME: If both sides are equal as type parameters and not inferred,
132
- // diagnose redundancy
89
+ // FIXME: Record redundancy and diagnose upstream
133
90
(void ) matcher.match (lhs, rhs);
134
91
}
135
92
93
+ static void desugarSuperclassRequirement (Type subjectType,
94
+ Type constraintType,
95
+ SmallVectorImpl<Requirement> &result) {
96
+ if (!subjectType->isTypeParameter ()) {
97
+ // FIXME: Perform unification, diagnose redundancy or conflict upstream
98
+ return ;
99
+ }
100
+
101
+ result.emplace_back (RequirementKind::Superclass, subjectType, constraintType);
102
+ }
103
+
104
+ static void desugarLayoutRequirement (Type subjectType,
105
+ LayoutConstraint layout,
106
+ SmallVectorImpl<Requirement> &result) {
107
+ if (!subjectType->isTypeParameter ()) {
108
+ // FIXME: Diagnose redundancy or conflict upstream
109
+ return ;
110
+ }
111
+
112
+ result.emplace_back (RequirementKind::Layout, subjectType, layout);
113
+ }
114
+
115
+ // / Desugar a protocol conformance requirement by splitting up protocol
116
+ // / compositions on the right hand side into conformance and superclass
117
+ // / requirements.
118
+ static void desugarConformanceRequirement (Type subjectType, Type constraintType,
119
+ SmallVectorImpl<Requirement> &result) {
120
+ // Fast path.
121
+ if (constraintType->is <ProtocolType>()) {
122
+ if (!subjectType->isTypeParameter ()) {
123
+ // FIXME: Check conformance, diagnose redundancy or conflict upstream
124
+ return ;
125
+ }
126
+
127
+ result.emplace_back (RequirementKind::Conformance, subjectType,
128
+ constraintType);
129
+ return ;
130
+ }
131
+
132
+ auto layout = constraintType->getExistentialLayout ();
133
+
134
+ if (auto layoutConstraint = layout.getLayoutConstraint ())
135
+ desugarLayoutRequirement (subjectType, layoutConstraint, result);
136
+
137
+ if (auto superclass = layout.explicitSuperclass )
138
+ desugarSuperclassRequirement (subjectType, superclass, result);
139
+
140
+ for (auto *proto : layout.getProtocols ()) {
141
+ if (!subjectType->isTypeParameter ()) {
142
+ // FIXME: Check conformance, diagnose redundancy or conflict upstream
143
+ return ;
144
+ }
145
+
146
+ result.emplace_back (RequirementKind::Conformance, subjectType,
147
+ proto);
148
+ }
149
+ }
150
+
151
+ // / Convert a requirement where the subject type might not be a type parameter,
152
+ // / or the constraint type in the conformance requirement might be a protocol
153
+ // / composition, into zero or more "proper" requirements which can then be
154
+ // / converted into rewrite rules by the RuleBuilder.
155
+ void
156
+ swift::rewriting::desugarRequirement (Requirement req,
157
+ SmallVectorImpl<Requirement> &result) {
158
+ auto firstType = req.getFirstType ();
159
+
160
+ switch (req.getKind ()) {
161
+ case RequirementKind::Conformance:
162
+ desugarConformanceRequirement (firstType, req.getSecondType (), result);
163
+ break ;
164
+
165
+ case RequirementKind::Superclass:
166
+ desugarSuperclassRequirement (firstType, req.getSecondType (), result);
167
+ break ;
168
+
169
+ case RequirementKind::Layout:
170
+ desugarLayoutRequirement (firstType, req.getLayoutConstraint (), result);
171
+ break ;
172
+
173
+ case RequirementKind::SameType:
174
+ desugarSameTypeRequirement (firstType, req.getSecondType (), result);
175
+ break ;
176
+ }
177
+ }
178
+
179
+ //
180
+ // StructuralRequirementsRequest computation.
181
+ //
182
+ // This realizes RequirementReprs into Requirements, desugars them using the
183
+ // above, performs requirement inference, and wraps them with source location
184
+ // information.
185
+ //
186
+
187
+ static void realizeTypeRequirement (Type subjectType, Type constraintType,
188
+ SourceLoc loc, bool wasInferred,
189
+ SmallVectorImpl<StructuralRequirement> &result) {
190
+ // Check whether we have a reasonable constraint type at all.
191
+ if (!constraintType->isExistentialType () &&
192
+ !constraintType->getClassOrBoundGenericClass ()) {
193
+ // FIXME: Diagnose
194
+ return ;
195
+ }
196
+
197
+ SmallVector<Requirement, 2 > reqs;
198
+
199
+ if (constraintType->isExistentialType ()) {
200
+ // Handle conformance requirements.
201
+ desugarConformanceRequirement (subjectType, constraintType, reqs);
202
+ } else {
203
+ // Handle superclass requirements.
204
+ desugarSuperclassRequirement (subjectType, constraintType, reqs);
205
+ }
206
+
207
+ // Add source location information.
208
+ for (auto req : reqs)
209
+ result.push_back ({req, loc, wasInferred});
210
+ }
211
+
136
212
static void inferRequirements (Type type, SourceLoc loc,
137
213
SmallVectorImpl<StructuralRequirement> &result) {
138
214
// FIXME: Implement
139
215
}
140
216
141
- static void addRequirement (Requirement req, RequirementRepr *reqRepr, bool infer,
142
- SmallVectorImpl<StructuralRequirement> &result) {
217
+ static void realizeRequirement (Requirement req, RequirementRepr *reqRepr, bool infer,
218
+ SmallVectorImpl<StructuralRequirement> &result) {
143
219
auto firstType = req.getFirstType ();
144
220
if (infer) {
145
221
auto firstLoc = (reqRepr ? reqRepr->getFirstTypeRepr ()->getStartLoc ()
@@ -152,31 +228,27 @@ static void addRequirement(Requirement req, RequirementRepr *reqRepr, bool infer
152
228
switch (req.getKind ()) {
153
229
case RequirementKind::Superclass:
154
230
case RequirementKind::Conformance: {
155
- if (!firstType->isTypeParameter ()) {
156
- // FIXME: Warn about redundancy if not inferred, diagnose conflicts
157
- break ;
158
- }
159
-
160
231
auto secondType = req.getSecondType ();
161
232
if (infer) {
162
233
auto secondLoc = (reqRepr ? reqRepr->getSecondTypeRepr ()->getStartLoc ()
163
234
: SourceLoc ());
164
235
inferRequirements (secondType, secondLoc, result);
165
236
}
166
237
167
- addTypeRequirement (firstType, secondType, loc, /* wasInferred=*/ false ,
168
- result);
238
+ realizeTypeRequirement (firstType, secondType, loc, /* wasInferred=*/ false ,
239
+ result);
169
240
break ;
170
241
}
171
242
172
- case RequirementKind::Layout:
173
- if (!firstType->isTypeParameter ()) {
174
- // FIXME: Warn about redundancy if not inferred, diagnose conflicts
175
- break ;
176
- }
243
+ case RequirementKind::Layout: {
244
+ SmallVector<Requirement, 2 > reqs;
245
+ desugarLayoutRequirement (firstType, req.getLayoutConstraint (), reqs);
246
+
247
+ for (auto req : reqs)
248
+ result.push_back ({req, loc, /* wasInferred=*/ false });
177
249
178
- result.push_back ({req, loc, /* wasInferred=*/ false });
179
250
break ;
251
+ }
180
252
181
253
case RequirementKind::SameType: {
182
254
auto secondType = req.getSecondType ();
@@ -186,15 +258,18 @@ static void addRequirement(Requirement req, RequirementRepr *reqRepr, bool infer
186
258
inferRequirements (secondType, secondLoc, result);
187
259
}
188
260
189
- addSameTypeRequirement (firstType, secondType, loc, /* wasInferred=*/ false ,
190
- result);
261
+ SmallVector<Requirement, 2 > reqs;
262
+ desugarSameTypeRequirement (req.getFirstType (), secondType, reqs);
263
+
264
+ for (auto req : reqs)
265
+ result.push_back ({req, loc, /* wasInferred=*/ false });
191
266
break ;
192
267
}
193
268
}
194
269
}
195
270
196
- static void addInheritedRequirements (TypeDecl *decl, Type type, bool infer,
197
- SmallVectorImpl<StructuralRequirement> &result) {
271
+ static void realizeInheritedRequirements (TypeDecl *decl, Type type, bool infer,
272
+ SmallVectorImpl<StructuralRequirement> &result) {
198
273
auto &ctx = decl->getASTContext ();
199
274
auto inheritedTypes = decl->getInherited ();
200
275
@@ -212,8 +287,8 @@ static void addInheritedRequirements(TypeDecl *decl, Type type, bool infer,
212
287
inferRequirements (inheritedType, loc, result);
213
288
}
214
289
215
- addTypeRequirement (type, inheritedType, loc, /* wasInferred=*/ false ,
216
- result);
290
+ realizeTypeRequirement (type, inheritedType, loc, /* wasInferred=*/ false ,
291
+ result);
217
292
}
218
293
}
219
294
@@ -228,13 +303,13 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
228
303
229
304
auto selfTy = proto->getSelfInterfaceType ();
230
305
231
- addInheritedRequirements (proto, selfTy,
232
- /* infer=*/ false , result);
306
+ realizeInheritedRequirements (proto, selfTy,
307
+ /* infer=*/ false , result);
233
308
234
309
// Add requirements from the protocol's own 'where' clause.
235
310
WhereClauseOwner (proto).visitRequirements (TypeResolutionStage::Structural,
236
311
[&](const Requirement &req, RequirementRepr *reqRepr) {
237
- addRequirement (req, reqRepr, /* infer=*/ false , result);
312
+ realizeRequirement (req, reqRepr, /* infer=*/ false , result);
238
313
return false ;
239
314
});
240
315
@@ -253,14 +328,14 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
253
328
for (auto assocTypeDecl : proto->getAssociatedTypeMembers ()) {
254
329
// Add requirements placed directly on this associated type.
255
330
auto assocType = assocTypeDecl->getDeclaredInterfaceType ();
256
- addInheritedRequirements (assocTypeDecl, assocType, /* infer=*/ false ,
257
- result);
331
+ realizeInheritedRequirements (assocTypeDecl, assocType, /* infer=*/ false ,
332
+ result);
258
333
259
334
// Add requirements from this associated type's where clause.
260
335
WhereClauseOwner (assocTypeDecl).visitRequirements (
261
336
TypeResolutionStage::Structural,
262
337
[&](const Requirement &req, RequirementRepr *reqRepr) {
263
- addRequirement (req, reqRepr, /* infer=*/ false , result);
338
+ realizeRequirement (req, reqRepr, /* infer=*/ false , result);
264
339
return false ;
265
340
});
266
341
}
@@ -302,6 +377,10 @@ ProtocolDependenciesRequest::evaluate(Evaluator &evaluator,
302
377
return ctx.AllocateCopy (result);
303
378
}
304
379
380
+ //
381
+ // Building rewrite rules from desugared requirements.
382
+ //
383
+
305
384
// / Given a concrete type that may contain type parameters in structural positions,
306
385
// / collect all the structural type parameter components, and replace them all with
307
386
// / fresh generic parameters. The fresh generic parameters all have a depth of 0,
@@ -556,8 +635,11 @@ void RuleBuilder::collectRulesFromReferencedProtocols() {
556
635
// we can trigger the computation of the requirement signatures of the
557
636
// next component recursively.
558
637
if (ProtocolMap[proto]) {
559
- for (auto req : proto->getStructuralRequirements ())
638
+ for (auto req : proto->getStructuralRequirements ()) {
639
+ // FIXME: Keep source location information around for redundancy
640
+ // diagnostics.
560
641
addRequirement (req.req .getCanonical (), proto);
642
+ }
561
643
} else {
562
644
for (auto req : proto->getRequirementSignature ())
563
645
addRequirement (req.getCanonical (), proto);
0 commit comments