@@ -5429,7 +5429,9 @@ namespace {
5429
5429
// / Retrieve the representative constraint that will be used for diagnostics.
5430
5430
template <typename T>
5431
5431
Optional<Constraint<T>> findRepresentativeConstraint (
5432
+ GenericSignatureBuilder &builder,
5432
5433
ArrayRef<Constraint<T>> constraints,
5434
+ RequirementKind kind,
5433
5435
llvm::function_ref<bool (const Constraint<T> &)>
5434
5436
isSuitableRepresentative) {
5435
5437
Optional<Constraint<T>> fallbackConstraint;
@@ -5453,6 +5455,26 @@ namespace {
5453
5455
continue ;
5454
5456
}
5455
5457
5458
+ if (kind != RequirementKind::SameType) {
5459
+ // We prefer non-redundant explicit constraints over everything else.
5460
+ bool thisIsNonRedundantExplicit =
5461
+ (!constraint.source ->isDerivedNonRootRequirement () &&
5462
+ !builder.isRedundantExplicitRequirement (
5463
+ ExplicitRequirement::fromExplicitConstraint (
5464
+ kind, constraint)));
5465
+ bool representativeIsNonRedundantExplicit =
5466
+ (!representativeConstraint->source ->isDerivedNonRootRequirement () &&
5467
+ !builder.isRedundantExplicitRequirement (
5468
+ ExplicitRequirement::fromExplicitConstraint (
5469
+ kind, *representativeConstraint)));
5470
+
5471
+ if (thisIsNonRedundantExplicit != representativeIsNonRedundantExplicit) {
5472
+ if (thisIsNonRedundantExplicit)
5473
+ representativeConstraint = constraint;
5474
+ continue ;
5475
+ }
5476
+ }
5477
+
5456
5478
// We prefer derived constraints to non-derived constraints.
5457
5479
bool thisIsDerived = constraint.source ->isDerivedRequirement ();
5458
5480
bool representativeIsDerived =
@@ -6302,7 +6324,9 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
6302
6324
// Try to find an exact constraint that matches 'other'.
6303
6325
auto repConstraint =
6304
6326
findRepresentativeConstraint<Type>(
6327
+ *this ,
6305
6328
equivClass->sameTypeConstraints ,
6329
+ RequirementKind::SameType,
6306
6330
[pa, other](const Constraint<Type> &constraint) {
6307
6331
return (constraint.isSubjectEqualTo (pa) &&
6308
6332
constraint.value ->isEqual (other->getDependentType ())) ||
@@ -6315,7 +6339,9 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
6315
6339
if (!repConstraint) {
6316
6340
repConstraint =
6317
6341
findRepresentativeConstraint<Type>(
6342
+ *this ,
6318
6343
equivClass->sameTypeConstraints ,
6344
+ RequirementKind::SameType,
6319
6345
[](const Constraint<Type> &constraint) {
6320
6346
return true ;
6321
6347
});
@@ -6466,6 +6492,7 @@ template<typename T>
6466
6492
Constraint<T> GenericSignatureBuilder::checkConstraintList (
6467
6493
TypeArrayView<GenericTypeParamType> genericParams,
6468
6494
std::vector<Constraint<T>> &constraints,
6495
+ RequirementKind kind,
6469
6496
llvm::function_ref<bool (const Constraint<T> &)>
6470
6497
isSuitableRepresentative,
6471
6498
llvm::function_ref<
@@ -6475,7 +6502,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
6475
6502
conflictingDiag,
6476
6503
Diag<Type, T> redundancyDiag,
6477
6504
Diag<unsigned , Type, T> otherNoteDiag) {
6478
- return checkConstraintList<T, T>(genericParams, constraints,
6505
+ return checkConstraintList<T, T>(genericParams, constraints, kind,
6479
6506
isSuitableRepresentative, checkConstraint,
6480
6507
conflictingDiag, redundancyDiag,
6481
6508
otherNoteDiag,
@@ -6570,6 +6597,7 @@ template<typename T, typename DiagT>
6570
6597
Constraint<T> GenericSignatureBuilder::checkConstraintList (
6571
6598
TypeArrayView<GenericTypeParamType> genericParams,
6572
6599
std::vector<Constraint<T>> &constraints,
6600
+ RequirementKind kind,
6573
6601
llvm::function_ref<bool (const Constraint<T> &)>
6574
6602
isSuitableRepresentative,
6575
6603
llvm::function_ref<
@@ -6591,7 +6619,8 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
6591
6619
6592
6620
// Find a representative constraint.
6593
6621
auto representativeConstraint =
6594
- findRepresentativeConstraint<T>(constraints, isSuitableRepresentative);
6622
+ findRepresentativeConstraint<T>(*this , constraints, kind,
6623
+ isSuitableRepresentative);
6595
6624
6596
6625
// Local function to provide a note describing the representative constraint.
6597
6626
auto noteRepresentativeConstraint = [&] {
@@ -6748,7 +6777,7 @@ void GenericSignatureBuilder::checkConformanceConstraints(
6748
6777
removeSelfDerived (*this , entry.second , entry.first );
6749
6778
6750
6779
checkConstraintList<ProtocolDecl *, ProtocolDecl *>(
6751
- genericParams, entry.second ,
6780
+ genericParams, entry.second , RequirementKind::Conformance,
6752
6781
[](const Constraint<ProtocolDecl *> &constraint) {
6753
6782
return true ;
6754
6783
},
@@ -7376,7 +7405,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
7376
7405
if (constraints.empty ()) continue ;
7377
7406
7378
7407
checkConstraintList<Type, Type>(
7379
- genericParams, constraints,
7408
+ genericParams, constraints, RequirementKind::SameType,
7380
7409
[](const Constraint<Type> &) { return true ; },
7381
7410
[](const Constraint<Type> &constraint) {
7382
7411
// Ignore nested-type-name-match constraints.
@@ -7569,7 +7598,7 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
7569
7598
resolveDependentMemberTypes (*this , equivClass->concreteType );
7570
7599
7571
7600
checkConstraintList<Type>(
7572
- genericParams, equivClass->concreteTypeConstraints ,
7601
+ genericParams, equivClass->concreteTypeConstraints , RequirementKind::SameType,
7573
7602
[&](const ConcreteConstraint &constraint) {
7574
7603
if (constraint.value ->isEqual (resolvedConcreteType))
7575
7604
return true ;
@@ -7612,7 +7641,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
7612
7641
7613
7642
auto representativeConstraint =
7614
7643
checkConstraintList<Type>(
7615
- genericParams, equivClass->superclassConstraints ,
7644
+ genericParams, equivClass->superclassConstraints , RequirementKind::Superclass,
7616
7645
[&](const ConcreteConstraint &constraint) {
7617
7646
if (constraint.value ->isEqual (resolvedSuperclass))
7618
7647
return true ;
@@ -7692,7 +7721,7 @@ void GenericSignatureBuilder::checkLayoutConstraints(
7692
7721
if (!equivClass->layout ) return ;
7693
7722
7694
7723
checkConstraintList<LayoutConstraint>(
7695
- genericParams, equivClass->layoutConstraints ,
7724
+ genericParams, equivClass->layoutConstraints , RequirementKind::Layout,
7696
7725
[&](const Constraint<LayoutConstraint> &constraint) {
7697
7726
return constraint.value == equivClass->layout ;
7698
7727
},
@@ -7720,20 +7749,22 @@ bool GenericSignatureBuilder::isRedundantExplicitRequirement(
7720
7749
}
7721
7750
7722
7751
namespace {
7723
- // / Retrieve the best requirement source from a set of constraints.
7724
7752
template <typename T>
7725
- const RequirementSource *
7726
- getBestConstraintSource (ArrayRef<Constraint<T>> constraints ,
7727
- llvm::function_ref< bool ( const T&)> matches ) {
7728
- const RequirementSource *bestSource = nullptr ;
7729
- for ( const auto & constraint : constraints) {
7730
- if (! matches (constraint. value )) continue ;
7753
+ bool hasNonRedundantRequirementSource (ArrayRef<Constraint<T>> constraints,
7754
+ RequirementKind kind ,
7755
+ GenericSignatureBuilder &builder ) {
7756
+ for ( auto constraint : constraints) {
7757
+ if ( constraint. source -> isDerivedRequirement ())
7758
+ continue ;
7731
7759
7732
- if (!bestSource || constraint.source ->compare (bestSource) < 0 )
7733
- bestSource = constraint.source ;
7760
+ auto req = ExplicitRequirement::fromExplicitConstraint (kind, constraint);
7761
+ if (builder.isRedundantExplicitRequirement (req))
7762
+ continue ;
7763
+
7764
+ return true ;
7734
7765
}
7735
7766
7736
- return bestSource ;
7767
+ return false ;
7737
7768
}
7738
7769
7739
7770
using SameTypeComponentRef = std::pair<EquivalenceClass *, unsigned >;
@@ -7855,27 +7886,19 @@ void GenericSignatureBuilder::enumerateRequirements(
7855
7886
if (equivClass->superclass &&
7856
7887
!equivClass->recursiveSuperclassType &&
7857
7888
!equivClass->superclass ->hasError ()) {
7858
- auto bestSource =
7859
- getBestConstraintSource<Type>(equivClass->superclassConstraints ,
7860
- [&](const Type &type) {
7861
- return type->isEqual (equivClass->superclass );
7862
- });
7863
-
7864
- if (!bestSource->isDerivedRequirement ()) {
7889
+ if (hasNonRedundantRequirementSource<Type>(
7890
+ equivClass->superclassConstraints ,
7891
+ RequirementKind::Superclass, *this )) {
7865
7892
recordRequirement (RequirementKind::Superclass,
7866
7893
subjectType, equivClass->superclass );
7867
7894
}
7868
7895
}
7869
7896
7870
7897
// If we have a layout constraint, produce a layout requirement.
7871
7898
if (equivClass->layout ) {
7872
- auto bestSource = getBestConstraintSource<LayoutConstraint>(
7873
- equivClass->layoutConstraints ,
7874
- [&](const LayoutConstraint &layout) {
7875
- return layout == equivClass->layout ;
7876
- });
7877
-
7878
- if (!bestSource->isDerivedRequirement ()) {
7899
+ if (hasNonRedundantRequirementSource<LayoutConstraint>(
7900
+ equivClass->layoutConstraints ,
7901
+ RequirementKind::Layout, *this )) {
7879
7902
recordRequirement (RequirementKind::Layout,
7880
7903
subjectType, equivClass->layout );
7881
7904
}
@@ -7885,14 +7908,10 @@ void GenericSignatureBuilder::enumerateRequirements(
7885
7908
SmallVector<ProtocolDecl *, 4 > protocols;
7886
7909
7887
7910
for (const auto &conforms : equivClass->conformsTo ) {
7888
- auto *bestSource = getBestConstraintSource<ProtocolDecl *>(
7889
- conforms.second ,
7890
- [&](ProtocolDecl *proto) {
7891
- return proto == conforms.first ;
7892
- });
7893
-
7894
- if (!bestSource->isDerivedRequirement ())
7911
+ if (hasNonRedundantRequirementSource<ProtocolDecl *>(
7912
+ conforms.second , RequirementKind::Conformance, *this )) {
7895
7913
protocols.push_back (conforms.first );
7914
+ }
7896
7915
}
7897
7916
7898
7917
// Sort the protocols in canonical order.
0 commit comments