@@ -698,7 +698,7 @@ struct GenericSignatureBuilder::Implementation {
698
698
bool HadAnyError = false ;
699
699
700
700
// / All explicit non-same type requirements that were added to the builder.
701
- SmallVector <ExplicitRequirement, 2 > ExplicitRequirements;
701
+ SmallSetVector <ExplicitRequirement, 2 > ExplicitRequirements;
702
702
703
703
// / All explicit same-type requirements that were added to the builder.
704
704
SmallVector<Requirement, 2 > ExplicitSameTypeRequirements;
@@ -2607,21 +2607,22 @@ GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type,
2607
2607
concreteSource = concreteSource->viaConcrete (*this , concrete);
2608
2608
} else {
2609
2609
concreteSource = concreteSource->viaConcrete (*this , conformance);
2610
- equivClass->recordConformanceConstraint (*this , type, proto, concreteSource);
2611
-
2612
- // Only infer conditional requirements from explicit sources.
2613
- bool hasExplicitSource = llvm::any_of (
2614
- equivClass->concreteTypeConstraints ,
2615
- [](const ConcreteConstraint &constraint) {
2616
- return (!constraint.source ->isDerivedRequirement () &&
2617
- constraint.source ->getLoc ().isValid ());
2618
- });
2610
+ }
2619
2611
2620
- if (hasExplicitSource) {
2621
- if (addConditionalRequirements (conformance, /* inferForModule=*/ nullptr ,
2622
- concreteSource->getLoc ()))
2623
- return nullptr ;
2624
- }
2612
+ equivClass->recordConformanceConstraint (*this , type, proto, concreteSource);
2613
+
2614
+ // Only infer conditional requirements from explicit sources.
2615
+ bool hasExplicitSource = llvm::any_of (
2616
+ equivClass->concreteTypeConstraints ,
2617
+ [](const ConcreteConstraint &constraint) {
2618
+ return (!constraint.source ->isDerivedRequirement () &&
2619
+ constraint.source ->getLoc ().isValid ());
2620
+ });
2621
+
2622
+ if (hasExplicitSource) {
2623
+ if (addConditionalRequirements (conformance, /* inferForModule=*/ nullptr ,
2624
+ concreteSource->getLoc ()))
2625
+ return nullptr ;
2625
2626
}
2626
2627
2627
2628
return concreteSource;
@@ -4507,8 +4508,9 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
4507
4508
auto resolvedSource = source.getSource (*this , type);
4508
4509
4509
4510
if (!resolvedSource->isDerivedRequirement ()) {
4510
- Impl->ExplicitRequirements .emplace_back (RequirementKind::Conformance,
4511
- resolvedSource, proto);
4511
+ Impl->ExplicitRequirements .insert (
4512
+ ExplicitRequirement (RequirementKind::Conformance,
4513
+ resolvedSource, proto));
4512
4514
}
4513
4515
4514
4516
// Add the conformance requirement, bailing out earlier if we've already
@@ -4529,8 +4531,9 @@ ConstraintResult GenericSignatureBuilder::addLayoutRequirementDirect(
4529
4531
auto resolvedSource = source.getSource (*this , type);
4530
4532
4531
4533
if (!resolvedSource->isDerivedRequirement ()) {
4532
- Impl->ExplicitRequirements .emplace_back (RequirementKind::Layout,
4533
- resolvedSource, layout);
4534
+ Impl->ExplicitRequirements .insert (
4535
+ ExplicitRequirement (RequirementKind::Layout,
4536
+ resolvedSource, layout));
4534
4537
}
4535
4538
4536
4539
auto equivClass = type.getEquivalenceClass (*this );
@@ -4670,8 +4673,9 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
4670
4673
auto resolvedSource = source.getSource (*this , type);
4671
4674
4672
4675
if (!resolvedSource->isDerivedRequirement ()) {
4673
- Impl->ExplicitRequirements .emplace_back (RequirementKind::Superclass,
4674
- resolvedSource, superclass);
4676
+ Impl->ExplicitRequirements .insert (
4677
+ ExplicitRequirement (RequirementKind::Superclass,
4678
+ resolvedSource, superclass));
4675
4679
}
4676
4680
4677
4681
// Record the constraint.
@@ -6466,14 +6470,16 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
6466
6470
checkLayoutConstraints (genericParams, &equivClass);
6467
6471
};
6468
6472
6469
- // FIXME: Expand all conformance requirements. This is expensive :(
6470
- for (auto &equivClass : Impl->EquivalenceClasses ) {
6473
+ if (!Impl->ExplicitSameTypeRequirements .empty ()) {
6474
+ // FIXME: Expand all conformance requirements. This is expensive :(
6475
+ for (auto &equivClass : Impl->EquivalenceClasses ) {
6471
6476
expandSameTypeConstraints (*this , &equivClass);
6472
- }
6477
+ }
6473
6478
6474
- // Check same-type constraints.
6475
- for (auto &equivClass : Impl->EquivalenceClasses ) {
6476
- checkSameTypeConstraints (genericParams, &equivClass);
6479
+ // Check same-type constraints.
6480
+ for (auto &equivClass : Impl->EquivalenceClasses ) {
6481
+ checkSameTypeConstraints (genericParams, &equivClass);
6482
+ }
6477
6483
}
6478
6484
6479
6485
// Check for generic parameters which have been made concrete or equated
@@ -7977,26 +7983,6 @@ bool GenericSignatureBuilder::isRedundantExplicitRequirement(
7977
7983
return (redundantReqs.find (req) != redundantReqs.end ());
7978
7984
}
7979
7985
7980
- namespace {
7981
- template <typename T>
7982
- bool hasNonRedundantRequirementSource (ArrayRef<Constraint<T>> constraints,
7983
- RequirementKind kind,
7984
- GenericSignatureBuilder &builder) {
7985
- for (auto constraint : constraints) {
7986
- if (constraint.source ->isDerivedRequirement ())
7987
- continue ;
7988
-
7989
- auto req = ExplicitRequirement::fromExplicitConstraint (kind, constraint);
7990
- if (builder.isRedundantExplicitRequirement (req))
7991
- continue ;
7992
-
7993
- return true ;
7994
- }
7995
-
7996
- return false ;
7997
- }
7998
- } // end anonymous namespace
7999
-
8000
7986
static Optional<Requirement> createRequirement (RequirementKind kind,
8001
7987
Type depTy,
8002
7988
RequirementRHS rhs,
@@ -8075,116 +8061,89 @@ void GenericSignatureBuilder::enumerateRequirements(
8075
8061
requirements.push_back (*req);
8076
8062
};
8077
8063
8078
- // Collect all of the subject types that will be involved in constraints.
8079
- for (auto &equivClass : Impl->EquivalenceClasses ) {
8080
- if (equivClass.derivedSameTypeComponents .empty ()) {
8081
- checkSameTypeConstraints (genericParams, &equivClass);
8082
- }
8083
-
8084
- for (unsigned i : indices (equivClass.derivedSameTypeComponents )) {
8085
- // Dig out the subject type and its corresponding component.
8086
- auto &component = equivClass.derivedSameTypeComponents [i];
8087
- Type subjectType = component.type ;
8088
-
8089
- assert (!subjectType->hasError ());
8090
- assert (!subjectType->findUnresolvedDependentMemberType ());
8064
+ // Collect all non-same type requirements.
8065
+ for (auto &req : Impl->ExplicitRequirements ) {
8066
+ if (isRedundantExplicitRequirement (req))
8067
+ continue ;
8091
8068
8092
- // If this equivalence class is bound to a concrete type, equate the
8093
- // anchor with a concrete type.
8094
- if (Type concreteType = equivClass.concreteType ) {
8095
- concreteType = getCanonicalTypeInContext (concreteType, genericParams);
8069
+ auto depTy = getCanonicalTypeInContext (
8070
+ req.getSource ()->getStoredType (), { });
8096
8071
8097
- // If the parent of this anchor is also a concrete type, don't
8098
- // create a requirement.
8099
- if (!subjectType->is <GenericTypeParamType>() &&
8100
- maybeResolveEquivalenceClass (
8101
- subjectType->castTo <DependentMemberType>()->getBase (),
8102
- ArchetypeResolutionKind::WellFormed,
8103
- /* wantExactPotentialArchetype=*/ false )
8104
- .getEquivalenceClass (*this )->concreteType )
8105
- continue ;
8072
+ // FIXME: This should be an assert once we ensure that concrete
8073
+ // same-type requirements always mark other requirements on the
8074
+ // same subject type as redundant or conflicting.
8075
+ if (!depTy->isTypeParameter ())
8076
+ continue ;
8106
8077
8107
- // Drop recursive and invalid concrete-type constraints.
8108
- if (equivClass. recursiveConcreteType ||
8109
- equivClass. invalidConcreteType )
8110
- continue ;
8078
+ auto rhs = req. getRHS ();
8079
+ if ( auto constraintType = rhs. dyn_cast <Type>()) {
8080
+ rhs = getCanonicalTypeInContext (constraintType, genericParams);
8081
+ }
8111
8082
8112
- // Filter out derived requirements... except for concrete-type
8113
- // requirements on generic parameters. The exception is due to
8114
- // the canonicalization of generic signatures, which never
8115
- // eliminates generic parameters even when they have been
8116
- // mapped to a concrete type.
8117
- if (subjectType->is <GenericTypeParamType>() ||
8118
- component.concreteTypeSource == nullptr ||
8119
- !component.concreteTypeSource ->isDerivedRequirement ()) {
8120
- recordRequirement (RequirementKind::SameType,
8121
- subjectType, concreteType);
8122
- }
8123
- continue ;
8124
- }
8083
+ recordRequirement (req.getKind (), depTy, rhs);
8084
+ }
8125
8085
8126
- std::function<void ()> deferredSameTypeRequirement;
8127
-
8128
- // If we're at the last anchor in the component, do nothing;
8129
- if (i + 1 != equivClass.derivedSameTypeComponents .size ()) {
8130
- // Form a same-type constraint from this anchor within the component
8131
- // to the next.
8132
- // FIXME: Distinguish between explicit and inferred here?
8133
- auto &nextComponent = equivClass.derivedSameTypeComponents [i + 1 ];
8134
- Type otherSubjectType = nextComponent.type ;
8135
- deferredSameTypeRequirement =
8136
- [&recordRequirement, subjectType, otherSubjectType] {
8137
- recordRequirement (RequirementKind::SameType,
8138
- subjectType, otherSubjectType);
8139
- };
8086
+ // Collect all same type requirements.
8087
+ if (!Impl->ExplicitSameTypeRequirements .empty ()) {
8088
+ for (auto &equivClass : Impl->EquivalenceClasses ) {
8089
+ if (equivClass.derivedSameTypeComponents .empty ()) {
8090
+ checkSameTypeConstraints (genericParams, &equivClass);
8140
8091
}
8141
8092
8142
- SWIFT_DEFER {
8143
- if (deferredSameTypeRequirement) deferredSameTypeRequirement ();
8144
- };
8145
-
8146
- // If this is not the first component anchor in its equivalence class,
8147
- // we're done.
8148
- if (i > 0 )
8149
- continue ;
8150
-
8151
- // If we have a superclass, produce a superclass requirement
8152
- if (auto superclass = equivClass.superclass ) {
8153
- superclass = getCanonicalTypeInContext (superclass, genericParams);
8093
+ for (unsigned i : indices (equivClass.derivedSameTypeComponents )) {
8094
+ // Dig out the subject type and its corresponding component.
8095
+ auto &component = equivClass.derivedSameTypeComponents [i];
8096
+ Type subjectType = component.type ;
8097
+
8098
+ assert (!subjectType->hasError ());
8099
+ assert (!subjectType->findUnresolvedDependentMemberType ());
8100
+
8101
+ // If this equivalence class is bound to a concrete type, equate the
8102
+ // anchor with a concrete type.
8103
+ if (Type concreteType = equivClass.concreteType ) {
8104
+ concreteType = getCanonicalTypeInContext (concreteType, genericParams);
8105
+
8106
+ // If the parent of this anchor is also a concrete type, don't
8107
+ // create a requirement.
8108
+ if (!subjectType->is <GenericTypeParamType>() &&
8109
+ maybeResolveEquivalenceClass (
8110
+ subjectType->castTo <DependentMemberType>()->getBase (),
8111
+ ArchetypeResolutionKind::WellFormed,
8112
+ /* wantExactPotentialArchetype=*/ false )
8113
+ .getEquivalenceClass (*this )->concreteType )
8114
+ continue ;
8154
8115
8155
- if (!equivClass.recursiveSuperclassType &&
8156
- hasNonRedundantRequirementSource<Type>(
8157
- equivClass.superclassConstraints ,
8158
- RequirementKind::Superclass, *this )) {
8159
- recordRequirement (RequirementKind::Superclass,
8160
- subjectType, superclass);
8161
- }
8162
- }
8116
+ // Drop recursive and invalid concrete-type constraints.
8117
+ if (equivClass.recursiveConcreteType ||
8118
+ equivClass.invalidConcreteType )
8119
+ continue ;
8163
8120
8164
- // If we have a layout constraint, produce a layout requirement.
8165
- if (equivClass.layout ) {
8166
- if (hasNonRedundantRequirementSource<LayoutConstraint>(
8167
- equivClass.layoutConstraints ,
8168
- RequirementKind::Layout, *this )) {
8169
- recordRequirement (RequirementKind::Layout,
8170
- subjectType, equivClass.layout );
8121
+ // Filter out derived requirements... except for concrete-type
8122
+ // requirements on generic parameters. The exception is due to
8123
+ // the canonicalization of generic signatures, which never
8124
+ // eliminates generic parameters even when they have been
8125
+ // mapped to a concrete type.
8126
+ if (subjectType->is <GenericTypeParamType>() ||
8127
+ component.concreteTypeSource == nullptr ||
8128
+ !component.concreteTypeSource ->isDerivedRequirement ()) {
8129
+ recordRequirement (RequirementKind::SameType,
8130
+ subjectType, concreteType);
8131
+ }
8132
+ continue ;
8171
8133
}
8172
- }
8173
8134
8174
- // Enumerate conformance requirements.
8175
- SmallVector<ProtocolDecl *, 4 > protocols;
8135
+ // If we're at the last anchor in the component, do nothing;
8136
+ if (i + 1 != equivClass.derivedSameTypeComponents .size ()) {
8137
+ // Form a same-type constraint from this anchor within the component
8138
+ // to the next.
8139
+ // FIXME: Distinguish between explicit and inferred here?
8140
+ auto &nextComponent = equivClass.derivedSameTypeComponents [i + 1 ];
8141
+ Type otherSubjectType = nextComponent.type ;
8176
8142
8177
- for (const auto &conforms : equivClass.conformsTo ) {
8178
- if (hasNonRedundantRequirementSource<ProtocolDecl *>(
8179
- conforms.second , RequirementKind::Conformance, *this )) {
8180
- protocols.push_back (conforms.first );
8143
+ recordRequirement (RequirementKind::SameType,
8144
+ subjectType, otherSubjectType);
8181
8145
}
8182
8146
}
8183
-
8184
- // Enumerate the conformance requirements.
8185
- for (auto proto : protocols) {
8186
- recordRequirement (RequirementKind::Conformance, subjectType, proto);
8187
- }
8188
8147
}
8189
8148
}
8190
8149
@@ -8310,6 +8269,14 @@ static void checkGenericSignature(CanGenericSignature canSig,
8310
8269
}
8311
8270
}
8312
8271
8272
+ // If we have a concrete same-type requirement, we shouldn't have any
8273
+ // other requirements on the same type.
8274
+ if (reqt.getKind () == RequirementKind::SameType &&
8275
+ !reqt.getSecondType ()->isTypeParameter ()) {
8276
+ assert (compareLHS < 0 &&
8277
+ " Concrete subject type should not have any other requirements" );
8278
+ }
8279
+
8313
8280
assert (compareRequirements (&prevReqt, &reqt) < 0 &&
8314
8281
" Out-of-order requirements" );
8315
8282
}
0 commit comments