@@ -1916,10 +1916,12 @@ bool EquivalenceClass::recordConformanceConstraint(
1916
1916
1917
1917
// If there is a concrete type that resolves this conformance requirement,
1918
1918
// record the conformance.
1919
- if (!builder.resolveConcreteConformance (type, proto)) {
1919
+ bool explicitConformance = !source->isDerivedRequirement ();
1920
+
1921
+ if (!builder.resolveConcreteConformance (type, proto, explicitConformance)) {
1920
1922
// Otherwise, determine whether there is a superclass constraint where the
1921
1923
// superclass conforms to this protocol.
1922
- (void )builder.resolveSuperConformance (type, proto);
1924
+ (void )builder.resolveSuperConformance (type, proto, explicitConformance );
1923
1925
}
1924
1926
}
1925
1927
@@ -2324,7 +2326,8 @@ void GenericSignatureBuilder::addConditionalRequirements(
2324
2326
2325
2327
const RequirementSource *
2326
2328
GenericSignatureBuilder::resolveConcreteConformance (ResolvedType type,
2327
- ProtocolDecl *proto) {
2329
+ ProtocolDecl *proto,
2330
+ bool explicitConformance) {
2328
2331
auto equivClass = type.getEquivalenceClass (*this );
2329
2332
auto concrete = equivClass->concreteType ;
2330
2333
if (!concrete) return nullptr ;
@@ -2378,21 +2381,22 @@ GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type,
2378
2381
equivClass->recordConformanceConstraint (*this , type, proto, concreteSource);
2379
2382
2380
2383
// Only infer conditional requirements from explicit sources.
2381
- bool hasExplicitSource = llvm::any_of (
2384
+ bool explicitConcreteType = llvm::any_of (
2382
2385
equivClass->concreteTypeConstraints ,
2383
2386
[](const ConcreteConstraint &constraint) {
2384
2387
return !constraint.source ->isDerivedRequirement ();
2385
2388
});
2386
2389
2387
- if (hasExplicitSource ) {
2390
+ if (explicitConformance || explicitConcreteType ) {
2388
2391
addConditionalRequirements (conformance, /* inferForModule=*/ nullptr );
2389
2392
}
2390
2393
2391
2394
return concreteSource;
2392
2395
}
2393
- const RequirementSource *GenericSignatureBuilder::resolveSuperConformance (
2394
- ResolvedType type,
2395
- ProtocolDecl *proto) {
2396
+ const RequirementSource *
2397
+ GenericSignatureBuilder::resolveSuperConformance (ResolvedType type,
2398
+ ProtocolDecl *proto,
2399
+ bool explicitConformance) {
2396
2400
// Get the superclass constraint.
2397
2401
auto equivClass = type.getEquivalenceClass (*this );
2398
2402
Type superclass = equivClass->superclass ;
@@ -2418,14 +2422,13 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
2418
2422
equivClass->recordConformanceConstraint (*this , type, proto, superclassSource);
2419
2423
2420
2424
// Only infer conditional requirements from explicit sources.
2421
- bool hasExplicitSource = llvm::any_of (
2422
- equivClass->superclassConstraints ,
2423
- [](const ConcreteConstraint &constraint) {
2424
- return (!constraint.source ->isDerivedRequirement () &&
2425
- constraint.source ->getLoc ().isValid ());
2426
- });
2425
+ bool explicitSuperclass = llvm::any_of (
2426
+ equivClass->superclassConstraints ,
2427
+ [](const ConcreteConstraint &constraint) {
2428
+ return !constraint.source ->isDerivedRequirement ();
2429
+ });
2427
2430
2428
- if (hasExplicitSource ) {
2431
+ if (explicitConformance || explicitSuperclass ) {
2429
2432
addConditionalRequirements (conformance, /* inferForModule=*/ nullptr );
2430
2433
}
2431
2434
@@ -4410,7 +4413,13 @@ bool GenericSignatureBuilder::updateSuperclass(
4410
4413
// when the superclass constraint changes.
4411
4414
auto updateSuperclassConformances = [&] {
4412
4415
for (const auto &conforms : equivClass->conformsTo ) {
4413
- (void )resolveSuperConformance (type, conforms.first );
4416
+ bool explicitConformance = std::find_if (
4417
+ conforms.second .begin (),
4418
+ conforms.second .end (),
4419
+ [](const Constraint<ProtocolDecl *> &constraint) {
4420
+ return !constraint.source ->isDerivedRequirement ();
4421
+ }) != conforms.second .end ();
4422
+ (void )resolveSuperConformance (type, conforms.first , explicitConformance);
4414
4423
}
4415
4424
4416
4425
// Eagerly resolve any existing nested types to their concrete forms (others
@@ -4809,8 +4818,15 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenTypeParameters(
4809
4818
equivClass2->concreteTypeConstraints .begin (),
4810
4819
equivClass2->concreteTypeConstraints .end ());
4811
4820
4812
- for (const auto &conforms : equivClass->conformsTo )
4813
- (void )resolveConcreteConformance (T1, conforms.first );
4821
+ for (const auto &conforms : equivClass->conformsTo ) {
4822
+ bool explicitConformance = std::find_if (
4823
+ conforms.second .begin (),
4824
+ conforms.second .end (),
4825
+ [](const Constraint<ProtocolDecl *> &constraint) {
4826
+ return !constraint.source ->isDerivedRequirement ();
4827
+ }) != conforms.second .end ();
4828
+ (void )resolveConcreteConformance (T1, conforms.first , explicitConformance);
4829
+ }
4814
4830
}
4815
4831
4816
4832
// Make T1 the representative of T2, merging the equivalence classes.
@@ -4946,7 +4962,13 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
4946
4962
// Make sure the concrete type fulfills the conformance requirements of
4947
4963
// this equivalence class.
4948
4964
for (const auto &conforms : equivClass->conformsTo ) {
4949
- if (!resolveConcreteConformance (type, conforms.first ))
4965
+ bool explicitConformance = std::find_if (
4966
+ conforms.second .begin (),
4967
+ conforms.second .end (),
4968
+ [](const Constraint<ProtocolDecl *> &constraint) {
4969
+ return !constraint.source ->isDerivedRequirement ();
4970
+ }) != conforms.second .end ();
4971
+ if (!resolveConcreteConformance (type, conforms.first , explicitConformance))
4950
4972
return ConstraintResult::Conflicting;
4951
4973
}
4952
4974
0 commit comments