@@ -253,7 +253,10 @@ bool RequirementSource::isDerivedViaConcreteConformance() const {
253
253
return false ;
254
254
}
255
255
256
- bool RequirementSource::isSelfDerivedSource (PotentialArchetype *pa) const {
256
+ bool RequirementSource::isSelfDerivedSource (PotentialArchetype *pa,
257
+ bool &derivedViaConcrete) const {
258
+ derivedViaConcrete = false ;
259
+
257
260
// If it's not a derived requirement, it's not self-derived.
258
261
if (!isDerivedRequirement ()) return false ;
259
262
@@ -274,10 +277,15 @@ bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
274
277
case RequirementSource::Parent:
275
278
return currentPA->isInSameEquivalenceClassAs (pa);
276
279
277
- case RequirementSource::NestedTypeNameMatch:
278
- case RequirementSource::Concrete:
279
280
case RequirementSource::ProtocolRequirement:
280
281
case RequirementSource::InferredProtocolRequirement:
282
+ // Note whether we saw derivation through a concrete type.
283
+ if (currentPA->isConcreteType ())
284
+ derivedViaConcrete = true ;
285
+ return false ;
286
+
287
+ case RequirementSource::NestedTypeNameMatch:
288
+ case RequirementSource::Concrete:
281
289
case RequirementSource::Superclass:
282
290
return false ;
283
291
}
@@ -3768,6 +3776,38 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
3768
3776
/* removeSelfDerived=*/ true );
3769
3777
}
3770
3778
3779
+ namespace {
3780
+ // / Remove self-derived sources from the given vector of constraints.
3781
+ template <typename T>
3782
+ void removeSelfDerived (std::vector<Constraint<T>> &constraints) {
3783
+ // Remove self-derived constraints.
3784
+ Optional<Constraint<T>> remainingConcrete;
3785
+ constraints.erase (
3786
+ std::remove_if (constraints.begin (), constraints.end (),
3787
+ [&](const Constraint<T> &constraint) {
3788
+ bool derivedViaConcrete;
3789
+ if (constraint.source ->isSelfDerivedSource (
3790
+ constraint.archetype , derivedViaConcrete))
3791
+ return true ;
3792
+
3793
+ if (!derivedViaConcrete)
3794
+ return false ;
3795
+
3796
+ // Drop derived-via-concrete requirements.
3797
+ if (!remainingConcrete)
3798
+ remainingConcrete = constraint;
3799
+
3800
+ return true ;
3801
+ }),
3802
+ constraints.end ());
3803
+
3804
+ if (constraints.empty () && remainingConcrete)
3805
+ constraints.push_back (*remainingConcrete);
3806
+
3807
+ assert (!constraints.empty () && " All constraints were self-derived!" );
3808
+ }
3809
+ }
3810
+
3771
3811
template <typename T, typename DiagT>
3772
3812
Constraint<T> GenericSignatureBuilder::checkConstraintList (
3773
3813
ArrayRef<GenericTypeParamType *> genericParams,
@@ -3784,15 +3824,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
3784
3824
bool removeSelfDerived) {
3785
3825
assert (!constraints.empty () && " No constraints?" );
3786
3826
if (removeSelfDerived) {
3787
- // Remove self-derived constraints.
3788
- constraints.erase (
3789
- std::remove_if (constraints.begin (), constraints.end (),
3790
- [&](const Constraint<T> &constraint) {
3791
- return constraint.source ->isSelfDerivedSource (
3792
- constraint.archetype );
3793
- }),
3794
- constraints.end ());
3795
- assert (!constraints.empty () && " All constraints were self-derived!" );
3827
+ ::removeSelfDerived (constraints);
3796
3828
}
3797
3829
3798
3830
// Sort the constraints, so we get a deterministic ordering of diagnostics.
@@ -4132,15 +4164,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
4132
4164
auto &constraints = entry.second ;
4133
4165
4134
4166
// Remove self-derived constraints.
4135
- assert (!constraints.empty () && " No constraints?" );
4136
- constraints.erase (
4137
- std::remove_if (constraints.begin (), constraints.end (),
4138
- [&](const Constraint<PotentialArchetype *> &constraint) {
4139
- return constraint.source ->isSelfDerivedSource (
4140
- constraint.archetype );
4141
- }),
4142
- constraints.end ());
4143
- assert (!constraints.empty () && " All constraints were self-derived!" );
4167
+ removeSelfDerived (constraints);
4144
4168
4145
4169
// Sort the constraints, so we get a deterministic ordering of diagnostics.
4146
4170
llvm::array_pod_sort (constraints.begin (), constraints.end ());
0 commit comments