Skip to content

Commit e14ac9e

Browse files
committed
RequirementMachine: Clean up desugarRequirement() a bit
1 parent e635dd3 commit e14ac9e

File tree

1 file changed

+86
-106
lines changed

1 file changed

+86
-106
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 86 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ using namespace rewriting;
173173
/// Desugar a same-type requirement that possibly has concrete types on either
174174
/// side into a series of same-type and concrete-type requirements where the
175175
/// left hand side is always a type parameter.
176-
static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
176+
static void desugarSameTypeRequirement(Requirement req, SourceLoc loc,
177177
SmallVectorImpl<Requirement> &result,
178178
SmallVectorImpl<RequirementError> &errors) {
179179
class Matcher : public TypeMatcher<Matcher> {
@@ -183,7 +183,6 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
183183

184184
public:
185185
bool recordedErrors = false;
186-
bool recordedRequirements = false;
187186

188187
explicit Matcher(SourceLoc loc,
189188
SmallVectorImpl<Requirement> &result,
@@ -206,21 +205,18 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
206205
if (firstType->isTypeParameter() && secondType->isTypeParameter()) {
207206
result.emplace_back(RequirementKind::SameType,
208207
sugaredFirstType, secondType);
209-
recordedRequirements = true;
210208
return true;
211209
}
212210

213211
if (firstType->isTypeParameter()) {
214212
result.emplace_back(RequirementKind::SameType,
215213
sugaredFirstType, secondType);
216-
recordedRequirements = true;
217214
return true;
218215
}
219216

220217
if (secondType->isTypeParameter()) {
221218
result.emplace_back(RequirementKind::SameType,
222219
secondType, sugaredFirstType);
223-
recordedRequirements = true;
224220
return true;
225221
}
226222

@@ -231,149 +227,138 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
231227
}
232228
} matcher(loc, result, errors);
233229

234-
(void) matcher.match(lhs, rhs);
230+
(void) matcher.match(req.getFirstType(), req.getSecondType());
235231

236232
// If neither side is directly a type parameter, the type parameter
237233
// must be in structural position where the enclosing type is redundant.
238-
if (!lhs->isTypeParameter() && !rhs->isTypeParameter() &&
234+
if (!req.getFirstType()->isTypeParameter() &&
235+
!req.getSecondType()->isTypeParameter() &&
239236
!matcher.recordedErrors) {
240237
// FIXME: Add a tailored error message when requirements were
241238
// recorded, e.g. Array<Int> == Array<T>. The outer type is
242239
// redundant, but the inner requirement T == Int is not.
243-
errors.push_back(RequirementError::forRedundantRequirement(
244-
{RequirementKind::SameType, lhs, rhs}, loc));
240+
errors.push_back(RequirementError::forRedundantRequirement(req, loc));
245241
}
246242
}
247243

248-
static void desugarSuperclassRequirement(Type subjectType,
249-
Type constraintType,
244+
static void desugarSuperclassRequirement(Requirement req,
250245
SourceLoc loc,
251246
SmallVectorImpl<Requirement> &result,
252247
SmallVectorImpl<RequirementError> &errors) {
253-
if (!subjectType->isTypeParameter()) {
254-
Requirement requirement(RequirementKind::Superclass,
255-
subjectType, constraintType);
256-
if (constraintType->isExactSuperclassOf(subjectType)) {
257-
errors.push_back(
258-
RequirementError::forRedundantRequirement(requirement, loc));
259-
} else {
260-
errors.push_back(
261-
RequirementError::forInvalidRequirementSubject(requirement, loc));
262-
}
263-
248+
if (req.getFirstType()->isTypeParameter()) {
249+
result.push_back(req);
264250
return;
265251
}
266252

267-
result.emplace_back(RequirementKind::Superclass, subjectType, constraintType);
253+
if (req.getSecondType()->isExactSuperclassOf(req.getFirstType())) {
254+
errors.push_back(RequirementError::forRedundantRequirement(req, loc));
255+
} else {
256+
errors.push_back(RequirementError::forInvalidRequirementSubject(req, loc));
257+
}
268258
}
269259

270-
static void desugarLayoutRequirement(Type subjectType,
271-
LayoutConstraint layout,
260+
static void desugarLayoutRequirement(Requirement req,
272261
SourceLoc loc,
273262
SmallVectorImpl<Requirement> &result,
274263
SmallVectorImpl<RequirementError> &errors) {
275-
if (!subjectType->isTypeParameter()) {
276-
Requirement requirement(RequirementKind::Layout,
277-
subjectType, layout);
278-
if (layout->isClass() && subjectType->isAnyClassReferenceType()) {
279-
errors.push_back(
280-
RequirementError::forRedundantRequirement(requirement, loc));
281-
} else {
282-
errors.push_back(
283-
RequirementError::forInvalidRequirementSubject(requirement, loc));
284-
}
285-
264+
if (req.getFirstType()->isTypeParameter()) {
265+
result.push_back(req);
286266
return;
287267
}
288268

289-
result.emplace_back(RequirementKind::Layout, subjectType, layout);
269+
if (req.getLayoutConstraint()->isClass() &&
270+
req.getFirstType()->isAnyClassReferenceType()) {
271+
errors.push_back(RequirementError::forRedundantRequirement(req, loc));
272+
} else {
273+
errors.push_back(RequirementError::forInvalidRequirementSubject(req, loc));
274+
}
290275
}
291276

292277
/// Desugar a protocol conformance requirement by splitting up protocol
293278
/// compositions on the right hand side into conformance and superclass
294279
/// requirements.
295-
static void desugarConformanceRequirement(Type subjectType, Type constraintType,
280+
static void desugarConformanceRequirement(Requirement req,
296281
SourceLoc loc,
297282
SmallVectorImpl<Requirement> &result,
298283
SmallVectorImpl<RequirementError> &errors) {
299284
// Fast path.
300-
if (constraintType->is<ProtocolType>()) {
301-
if (!subjectType->isTypeParameter()) {
302-
// Check if the subject type actually conforms.
303-
auto *protoDecl = constraintType->castTo<ProtocolType>()->getDecl();
304-
auto *module = protoDecl->getParentModule();
305-
auto conformance = module->lookupConformance(
306-
subjectType, protoDecl, /*allowMissing=*/true);
307-
if (conformance.isInvalid()) {
308-
errors.push_back(RequirementError::forInvalidRequirementSubject(
309-
{RequirementKind::Conformance, subjectType, constraintType}, loc));
310-
return;
311-
}
285+
if (req.getSecondType()->is<ProtocolType>()) {
286+
if (req.getFirstType()->isTypeParameter()) {
287+
result.push_back(req);
288+
return;
289+
}
312290

313-
errors.push_back(RequirementError::forRedundantRequirement(
314-
{RequirementKind::Conformance, subjectType, constraintType}, loc));
291+
// Check if the subject type actually conforms.
292+
auto *protoDecl = req.getProtocolDecl();
293+
auto *module = protoDecl->getParentModule();
294+
auto conformance = module->lookupConformance(
295+
req.getFirstType(), protoDecl, /*allowMissing=*/true);
296+
if (conformance.isInvalid()) {
297+
errors.push_back(RequirementError::forInvalidRequirementSubject(req, loc));
298+
return;
299+
}
315300

316-
if (conformance.isConcrete()) {
317-
// Introduce conditional requirements if the conformance is concrete.
318-
for (auto req : conformance.getConcrete()->getConditionalRequirements()) {
319-
desugarRequirement(req, loc, result, errors);
320-
}
321-
}
301+
errors.push_back(RequirementError::forRedundantRequirement(req, loc));
322302

323-
return;
303+
if (conformance.isConcrete()) {
304+
// Introduce conditional requirements if the conformance is concrete.
305+
for (auto condReq : conformance.getConcrete()->getConditionalRequirements()) {
306+
desugarRequirement(condReq, loc, result, errors);
307+
}
324308
}
325309

326-
result.emplace_back(RequirementKind::Conformance, subjectType,
327-
constraintType);
328310
return;
329311
}
330312

331-
if (auto *paramType = constraintType->getAs<ParameterizedProtocolType>()) {
332-
desugarConformanceRequirement(subjectType, paramType->getBaseType(),
333-
loc, result, errors);
334-
313+
if (auto *paramType = req.getSecondType()->getAs<ParameterizedProtocolType>()) {
335314
SmallVector<Requirement, 2> reqs;
336-
paramType->getRequirements(subjectType, reqs);
315+
316+
reqs.emplace_back(RequirementKind::Conformance, req.getFirstType(),
317+
paramType->getBaseType());
318+
paramType->getRequirements(req.getFirstType(), reqs);
337319

338320
for (const auto &req : reqs)
339321
desugarRequirement(req, loc, result, errors);
340322

341323
return;
342324
}
343325

344-
auto *compositionType = constraintType->castTo<ProtocolCompositionType>();
326+
auto *compositionType = req.getSecondType()->castTo<ProtocolCompositionType>();
327+
SmallVector<Requirement, 2> memberReqs;
345328
if (compositionType->hasExplicitAnyObject()) {
346-
desugarLayoutRequirement(subjectType,
347-
LayoutConstraint::getLayoutConstraint(
348-
LayoutConstraintKind::Class),
349-
loc, result, errors);
329+
memberReqs.emplace_back(RequirementKind::Layout, req.getFirstType(),
330+
LayoutConstraint::getLayoutConstraint(
331+
LayoutConstraintKind::Class));
350332
}
351333

352334
for (auto memberType : compositionType->getMembers()) {
353-
if (memberType->isConstraintType())
354-
desugarConformanceRequirement(subjectType, memberType,
355-
loc, result, errors);
356-
else
357-
desugarSuperclassRequirement(subjectType, memberType,
358-
loc, result, errors);
335+
memberReqs.emplace_back(
336+
memberType->isConstraintType()
337+
? RequirementKind::Conformance
338+
: RequirementKind::Superclass,
339+
req.getFirstType(), memberType);
359340
}
341+
342+
for (auto memberReq : memberReqs)
343+
desugarRequirement(memberReq, loc, result, errors);
360344
}
361345

362346
/// Desugar same-shape requirements by equating the shapes of the
363347
/// root pack types, and diagnose shape requirements on non-pack
364348
/// types.
365-
static void desugarSameShapeRequirement(Type lhs, Type rhs, SourceLoc loc,
349+
static void desugarSameShapeRequirement(Requirement req, SourceLoc loc,
366350
SmallVectorImpl<Requirement> &result,
367351
SmallVectorImpl<RequirementError> &errors) {
368352
// For now, only allow shape requirements directly between pack types.
369-
if (!lhs->isParameterPack() || !rhs->isParameterPack()) {
353+
if (!req.getFirstType()->isParameterPack() ||
354+
!req.getSecondType()->isParameterPack()) {
370355
errors.push_back(RequirementError::forInvalidShapeRequirement(
371-
{RequirementKind::SameShape, lhs, rhs}, loc));
356+
req, loc));
372357
}
373358

374359
result.emplace_back(RequirementKind::SameShape,
375-
lhs->getRootGenericParam(),
376-
rhs->getRootGenericParam());
360+
req.getFirstType()->getRootGenericParam(),
361+
req.getSecondType()->getRootGenericParam());
377362
}
378363

379364
/// Convert a requirement where the subject type might not be a type parameter,
@@ -384,32 +369,25 @@ void
384369
swift::rewriting::desugarRequirement(Requirement req, SourceLoc loc,
385370
SmallVectorImpl<Requirement> &result,
386371
SmallVectorImpl<RequirementError> &errors) {
387-
auto firstType = req.getFirstType();
388-
389372
switch (req.getKind()) {
390373
case RequirementKind::SameShape:
391-
desugarSameShapeRequirement(firstType, req.getSecondType(),
392-
loc, result, errors);
374+
desugarSameShapeRequirement(req, loc, result, errors);
393375
break;
394376

395377
case RequirementKind::Conformance:
396-
desugarConformanceRequirement(firstType, req.getSecondType(),
397-
loc, result, errors);
378+
desugarConformanceRequirement(req, loc, result, errors);
398379
break;
399380

400381
case RequirementKind::Superclass:
401-
desugarSuperclassRequirement(firstType, req.getSecondType(),
402-
loc, result, errors);
382+
desugarSuperclassRequirement(req, loc, result, errors);
403383
break;
404384

405385
case RequirementKind::Layout:
406-
desugarLayoutRequirement(firstType, req.getLayoutConstraint(),
407-
loc, result, errors);
386+
desugarLayoutRequirement(req, loc, result, errors);
408387
break;
409388

410389
case RequirementKind::SameType:
411-
desugarSameTypeRequirement(firstType, req.getSecondType(),
412-
loc, result, errors);
390+
desugarSameTypeRequirement(req, loc, result, errors);
413391
break;
414392
}
415393
}
@@ -453,11 +431,11 @@ static void realizeTypeRequirement(DeclContext *dc,
453431
}
454432

455433
if (constraintType->isConstraintType()) {
456-
// Handle conformance requirements.
457-
desugarConformanceRequirement(subjectType, constraintType, loc, reqs, errors);
434+
Requirement req(RequirementKind::Conformance, subjectType, constraintType);
435+
desugarRequirement(req, loc, reqs, errors);
458436
} else if (constraintType->getClassOrBoundGenericClass()) {
459-
// Handle superclass requirements.
460-
desugarSuperclassRequirement(subjectType, constraintType, loc, reqs, errors);
437+
Requirement req(RequirementKind::Superclass, subjectType, constraintType);
438+
desugarRequirement(req, loc, reqs, errors);
461439
} else {
462440
errors.push_back(
463441
RequirementError::forInvalidTypeRequirement(subjectType,
@@ -641,7 +619,6 @@ void swift::rewriting::realizeRequirement(
641619
bool shouldInferRequirements,
642620
SmallVectorImpl<StructuralRequirement> &result,
643621
SmallVectorImpl<RequirementError> &errors) {
644-
auto firstType = req.getFirstType();
645622
auto loc = (reqRepr ? reqRepr->getSeparatorLoc() : SourceLoc());
646623
auto *moduleForInference = dc->getParentModule();
647624

@@ -651,7 +628,9 @@ void swift::rewriting::realizeRequirement(
651628

652629
case RequirementKind::Superclass:
653630
case RequirementKind::Conformance: {
631+
auto firstType = req.getFirstType();
654632
auto secondType = req.getSecondType();
633+
655634
if (shouldInferRequirements) {
656635
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
657636
: SourceLoc());
@@ -668,14 +647,14 @@ void swift::rewriting::realizeRequirement(
668647

669648
case RequirementKind::Layout: {
670649
if (shouldInferRequirements) {
650+
auto firstType = req.getFirstType();
671651
auto firstLoc = (reqRepr ? reqRepr->getSubjectRepr()->getStartLoc()
672652
: SourceLoc());
673653
inferRequirements(firstType, firstLoc, moduleForInference, dc, result);
674654
}
675655

676656
SmallVector<Requirement, 2> reqs;
677-
desugarLayoutRequirement(firstType, req.getLayoutConstraint(),
678-
loc, reqs, errors);
657+
desugarRequirement(req, loc, reqs, errors);
679658

680659
for (auto req : reqs)
681660
result.push_back({req, loc, /*wasInferred=*/false});
@@ -684,20 +663,20 @@ void swift::rewriting::realizeRequirement(
684663
}
685664

686665
case RequirementKind::SameType: {
687-
auto secondType = req.getSecondType();
688666
if (shouldInferRequirements) {
667+
auto firstType = req.getFirstType();
689668
auto firstLoc = (reqRepr ? reqRepr->getFirstTypeRepr()->getStartLoc()
690669
: SourceLoc());
691670
inferRequirements(firstType, firstLoc, moduleForInference, dc, result);
692671

672+
auto secondType = req.getSecondType();
693673
auto secondLoc = (reqRepr ? reqRepr->getSecondTypeRepr()->getStartLoc()
694674
: SourceLoc());
695675
inferRequirements(secondType, secondLoc, moduleForInference, dc, result);
696676
}
697677

698678
SmallVector<Requirement, 2> reqs;
699-
desugarSameTypeRequirement(req.getFirstType(), secondType, loc,
700-
reqs, errors);
679+
desugarRequirement(req, loc, reqs, errors);
701680

702681
for (auto req : reqs)
703682
result.push_back({req, loc, /*wasInferred=*/false});
@@ -928,8 +907,9 @@ TypeAliasRequirementsRequest::evaluate(Evaluator &evaluator,
928907
// An inferred same-type requirement between the two type declarations
929908
// within this protocol or a protocol it inherits.
930909
auto recordInheritedTypeRequirement = [&](TypeDecl *first, TypeDecl *second) {
931-
desugarSameTypeRequirement(getStructuralType(first),
932-
getStructuralType(second),
910+
desugarRequirement(Requirement(RequirementKind::SameType,
911+
getStructuralType(first),
912+
getStructuralType(second)),
933913
SourceLoc(), result, errors);
934914
};
935915

0 commit comments

Comments
 (0)