@@ -365,7 +365,7 @@ struct SemanticsDeclHeaderVisitor : public SemanticsDeclVisitorBase,
365
365
366
366
void visitGenericTypeConstraintDecl(GenericTypeConstraintDecl* decl);
367
367
368
- bool checkGenericTypeEqualityCanonicalOrder (GenericTypeConstraintDecl* decl);
368
+ void checkGenericTypeEqualityConstraintSubType (GenericTypeConstraintDecl* decl);
369
369
370
370
void visitTypeCoercionConstraintDecl(TypeCoercionConstraintDecl* decl);
371
371
@@ -3258,6 +3258,20 @@ bool SemanticsDeclHeaderVisitor::validateGenericConstraintSubType(
3258
3258
TypeExp type,
3259
3259
DiagnosticSink* sink)
3260
3260
{
3261
+ auto diagnose = [&]()
3262
+ {
3263
+ if (sink)
3264
+ {
3265
+ if (decl->isEqualityConstraint)
3266
+ {
3267
+ sink->diagnose(type.exp, Diagnostics::invalidEqualityConstraintSubType, type);
3268
+ }
3269
+ else
3270
+ {
3271
+ sink->diagnose(type.exp, Diagnostics::invalidConstraintSubType, type);
3272
+ }
3273
+ }
3274
+ };
3261
3275
// Validate that the sub type of a constraint is in valid form.
3262
3276
//
3263
3277
if (auto subDeclRef = isDeclRefTypeOf<Decl>(type.type))
@@ -3276,8 +3290,7 @@ bool SemanticsDeclHeaderVisitor::validateGenericConstraintSubType(
3276
3290
auto dependentGeneric = getShared()->getDependentGenericParent(subDeclRef);
3277
3291
if (dependentGeneric.getDecl() != decl->parentDecl)
3278
3292
{
3279
- if (sink)
3280
- sink->diagnose(type.exp, Diagnostics::invalidConstraintSubType, type);
3293
+ diagnose();
3281
3294
return false;
3282
3295
}
3283
3296
}
@@ -3296,8 +3309,7 @@ bool SemanticsDeclHeaderVisitor::validateGenericConstraintSubType(
3296
3309
auto lookupDeclRef = as<LookupDeclRef>(subDeclRef.declRefBase);
3297
3310
if (!lookupDeclRef)
3298
3311
{
3299
- if (sink)
3300
- sink->diagnose(type.exp, Diagnostics::invalidConstraintSubType, type);
3312
+ diagnose();
3301
3313
return false;
3302
3314
}
3303
3315
@@ -3311,8 +3323,7 @@ bool SemanticsDeclHeaderVisitor::validateGenericConstraintSubType(
3311
3323
auto baseType = as<Type>(lookupDeclRef->getLookupSource());
3312
3324
if (!baseType)
3313
3325
{
3314
- if (sink)
3315
- sink->diagnose(type.exp, Diagnostics::invalidConstraintSubType, type);
3326
+ diagnose();
3316
3327
return false;
3317
3328
}
3318
3329
type.type = baseType;
@@ -3323,8 +3334,7 @@ bool SemanticsDeclHeaderVisitor::validateGenericConstraintSubType(
3323
3334
{
3324
3335
// It is meaningless for certain types to be used in type constraints.
3325
3336
// For example, `IFoo<T>` should not appear as the left-hand-side of a generic constraint.
3326
- if (sink)
3327
- sink->diagnose(type.exp, Diagnostics::invalidConstraintSubType, type);
3337
+ diagnose();
3328
3338
return false;
3329
3339
}
3330
3340
return true;
@@ -3452,19 +3462,9 @@ void SemanticsDeclHeaderVisitor::visitGenericTypeConstraintDecl(GenericTypeConst
3452
3462
// Check for forward references in generic constraints after type translation
3453
3463
checkForwardReferencesInGenericConstraint(decl);
3454
3464
3455
- bool equalityCannon = true;
3456
3465
if (decl->isEqualityConstraint)
3457
3466
{
3458
- equalityCannon = checkGenericTypeEqualityCanonicalOrder(decl);
3459
- }
3460
-
3461
- bool validSub = validateGenericConstraintSubType(decl, decl->sub, getSink());
3462
- if (decl->isEqualityConstraint)
3463
- {
3464
- if (!validSub && !equalityCannon)
3465
- {
3466
- getSink()->diagnose(decl, Diagnostics::failedEqualityConstraintCanonicalOrder);
3467
- }
3467
+ checkGenericTypeEqualityConstraintSubType(decl);
3468
3468
if (!isProperConstraineeType(decl->sup) && !as<ErrorType>(decl->sup.type))
3469
3469
{
3470
3470
getSink()->diagnose(
@@ -3475,6 +3475,7 @@ void SemanticsDeclHeaderVisitor::visitGenericTypeConstraintDecl(GenericTypeConst
3475
3475
}
3476
3476
else
3477
3477
{
3478
+ validateGenericConstraintSubType(decl, decl->sub, getSink());
3478
3479
if (!isValidGenericConstraintType(decl->sup) && !as<ErrorType>(decl->sup.type))
3479
3480
{
3480
3481
getSink()->diagnose(
@@ -3487,11 +3488,12 @@ void SemanticsDeclHeaderVisitor::visitGenericTypeConstraintDecl(GenericTypeConst
3487
3488
}
3488
3489
3489
3490
ContainerDecl* findDeclsLowestCommonAncestor(Decl*& a, Decl*& b);
3491
+ int compareDecls(Decl* lhs, Decl* rhs);
3490
3492
3491
- bool SemanticsDeclHeaderVisitor::checkGenericTypeEqualityCanonicalOrder (
3493
+ void SemanticsDeclHeaderVisitor::checkGenericTypeEqualityConstraintSubType (
3492
3494
GenericTypeConstraintDecl* decl)
3493
3495
{
3494
- auto compare = [&]() -> int
3496
+ auto checkAndCompare = [&]() -> int
3495
3497
{
3496
3498
bool subOk = validateGenericConstraintSubType(decl, decl->sub);
3497
3499
bool supOk = validateGenericConstraintSubType(decl, decl->sup);
@@ -3502,8 +3504,10 @@ bool SemanticsDeclHeaderVisitor::checkGenericTypeEqualityCanonicalOrder(
3502
3504
}
3503
3505
else if (!(subOk || supOk))
3504
3506
{
3505
- // None is qualified, the generic constraint is not valid anyway.
3506
- // There is no point in comparing further.
3507
+ getSink()->diagnose(decl, Diagnostics::noValidEqualityConstraintSubType);
3508
+ // Re-run the validation to emit the diagnostic this time
3509
+ validateGenericConstraintSubType(decl, decl->sub, getSink());
3510
+ validateGenericConstraintSubType(decl, decl->sup, getSink());
3507
3511
return -1;
3508
3512
}
3509
3513
// Both sub and sup are qualified
@@ -3517,7 +3521,7 @@ bool SemanticsDeclHeaderVisitor::checkGenericTypeEqualityCanonicalOrder(
3517
3521
auto ancestor = findDeclsLowestCommonAncestor(subAncestor, supAncestor);
3518
3522
if (!ancestor)
3519
3523
{
3520
- return 0 ;
3524
+ return compareDecls(subAncestor, supAncestor) ;
3521
3525
}
3522
3526
3523
3527
auto subIndex = ancestor->getMembers().binarySearch(subAncestor);
@@ -3526,17 +3530,16 @@ bool SemanticsDeclHeaderVisitor::checkGenericTypeEqualityCanonicalOrder(
3526
3530
return int(supIndex - subIndex);
3527
3531
};
3528
3532
3529
- bool res = true;
3530
- int cmp = compare();
3533
+ int cmp = checkAndCompare();
3531
3534
if (cmp > 0)
3532
3535
{
3533
3536
Swap(decl->sub, decl->sup);
3534
3537
}
3535
- if (cmp == 0 && decl->sub != decl->sup)
3538
+ else if (cmp == 0 && decl->sub != decl->sup)
3536
3539
{
3537
- res = false;
3540
+ // The comparison was not fully handled for this case.
3541
+ getSink()->diagnose(decl, Diagnostics::failedEqualityConstraintCanonicalOrder);
3538
3542
}
3539
- return res;
3540
3543
}
3541
3544
3542
3545
void SemanticsDeclHeaderVisitor::visitGenericTypeParamDecl(GenericTypeParamDecl* decl)
0 commit comments