Skip to content

Commit 03e0c4a

Browse files
authored
Merge pull request #36209 from slavapestov/gsb-self-conforming-requirement-source
GSB: Record the original type for self-derived conformances
2 parents 59fa22b + ce8549b commit 03e0c4a

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,18 +1118,24 @@ class GenericSignatureBuilder::RequirementSource final
11181118
WrittenRequirementLoc writtenLoc =
11191119
WrittenRequirementLoc()) const;
11201120
public:
1121-
/// A requirement source that describes that a requirement that is resolved
1121+
/// A requirement source that describes a conformance requirement resolved
11221122
/// via a superclass requirement.
11231123
const RequirementSource *viaSuperclass(
11241124
GenericSignatureBuilder &builder,
11251125
ProtocolConformanceRef conformance) const;
11261126

1127-
/// A requirement source that describes that a requirement that is resolved
1128-
/// via a same-type-to-concrete requirement.
1127+
/// A requirement source that describes a conformance requirement resolved
1128+
/// via a concrete type requirement with a conforming nominal type.
11291129
const RequirementSource *viaConcrete(
11301130
GenericSignatureBuilder &builder,
11311131
ProtocolConformanceRef conformance) const;
11321132

1133+
/// A requirement source that describes that a requirement that is resolved
1134+
/// via a concrete type requirement with an existential self-conforming type.
1135+
const RequirementSource *viaConcrete(
1136+
GenericSignatureBuilder &builder,
1137+
Type existentialType) const;
1138+
11331139
/// A constraint source that describes a layout constraint that was implied
11341140
/// by a superclass requirement.
11351141
const RequirementSource *viaLayout(GenericSignatureBuilder &builder,

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -591,10 +591,10 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
591591
case Superclass:
592592
case Concrete:
593593
switch (storageKind) {
594+
case StorageKind::StoredType:
594595
case StorageKind::ProtocolConformance:
595596
return true;
596597

597-
case StorageKind::StoredType:
598598
case StorageKind::AssociatedTypeDecl:
599599
case StorageKind::None:
600600
return false;
@@ -1043,6 +1043,17 @@ const RequirementSource *RequirementSource::viaConcrete(
10431043
0, WrittenRequirementLoc());
10441044
}
10451045

1046+
const RequirementSource *RequirementSource::viaConcrete(
1047+
GenericSignatureBuilder &builder,
1048+
Type existentialType) const {
1049+
assert(existentialType->isExistentialType());
1050+
REQUIREMENT_SOURCE_FACTORY_BODY(
1051+
(nodeID, Concrete, this, existentialType.getPointer(),
1052+
nullptr, nullptr),
1053+
(Concrete, this, existentialType),
1054+
0, WrittenRequirementLoc());
1055+
}
1056+
10461057
const RequirementSource *RequirementSource::viaParent(
10471058
GenericSignatureBuilder &builder,
10481059
AssociatedTypeDecl *assocType) const {
@@ -1115,8 +1126,14 @@ const RequirementSource *RequirementSource::withoutRedundantSubpath(
11151126
getWrittenRequirementLoc());
11161127

11171128
case Concrete:
1118-
return parent->withoutRedundantSubpath(builder, start, end)
1119-
->viaConcrete(builder, getProtocolConformance());
1129+
if (auto existentialType = getStoredType()) {
1130+
assert(existentialType->isExistentialType());
1131+
return parent->withoutRedundantSubpath(builder, start, end)
1132+
->viaConcrete(builder, existentialType);
1133+
} else {
1134+
return parent->withoutRedundantSubpath(builder, start, end)
1135+
->viaConcrete(builder, getProtocolConformance());
1136+
}
11201137

11211138
case Layout:
11221139
return parent->withoutRedundantSubpath(builder, start, end)
@@ -2307,11 +2324,30 @@ GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type,
23072324
return nullptr;
23082325
}
23092326

2310-
concreteSource = concreteSource->viaConcrete(*this, conformance);
2311-
equivClass->recordConformanceConstraint(*this, type, proto, concreteSource);
2312-
if (addConditionalRequirements(conformance, /*inferForModule=*/nullptr,
2313-
concreteSource->getLoc()))
2314-
return nullptr;
2327+
if (concrete->isExistentialType()) {
2328+
// If we have an existential type, record the original type, and
2329+
// not the conformance.
2330+
//
2331+
// The conformance must be a self-conformance, and self-conformances
2332+
// do not record the original type in the case where a derived
2333+
// protocol self-conforms to a base protocol; for example:
2334+
//
2335+
// @objc protocol Base {}
2336+
//
2337+
// @objc protocol Derived {}
2338+
//
2339+
// struct S<T : Base> {}
2340+
//
2341+
// extension S where T == Derived {}
2342+
assert(isa<SelfProtocolConformance>(conformance.getConcrete()));
2343+
concreteSource = concreteSource->viaConcrete(*this, concrete);
2344+
} else {
2345+
concreteSource = concreteSource->viaConcrete(*this, conformance);
2346+
equivClass->recordConformanceConstraint(*this, type, proto, concreteSource);
2347+
if (addConditionalRequirements(conformance, /*inferForModule=*/nullptr,
2348+
concreteSource->getLoc()))
2349+
return nullptr;
2350+
}
23152351

23162352
return concreteSource;
23172353
}
@@ -2329,6 +2365,8 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
23292365
if (conformance.isInvalid())
23302366
return nullptr;
23312367

2368+
assert(!conformance.isAbstract());
2369+
23322370
// Conformance to this protocol is redundant; update the requirement source
23332371
// appropriately.
23342372
const RequirementSource *superclassSource;
@@ -2526,10 +2564,11 @@ static void concretizeNestedTypeFromConcreteParent(
25262564
conformance.getConcrete()->getTypeWitness(assocType);
25272565
if (!witnessType)
25282566
return; // FIXME: should we delay here?
2529-
} else if (auto archetype = concreteParent->getAs<ArchetypeType>()) {
2530-
witnessType = archetype->getNestedType(assocType->getName());
25312567
} else {
2532-
witnessType = DependentMemberType::get(concreteParent, assocType);
2568+
// Otherwise we have an abstract conformance to an opaque result type.
2569+
assert(conformance.isAbstract());
2570+
auto archetype = concreteParent->castTo<ArchetypeType>();
2571+
witnessType = archetype->getNestedType(assocType->getName());
25332572
}
25342573

25352574
builder.addSameTypeRequirement(
@@ -2549,8 +2588,7 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
25492588

25502589
Identifier name = assocType->getName();
25512590

2552-
// Look for either an unresolved potential archetype (which we can resolve
2553-
// now) or a potential archetype with the appropriate associated type.
2591+
// Look for a potential archetype with the appropriate associated type.
25542592
PotentialArchetype *resultPA = nullptr;
25552593
auto knownNestedTypes = NestedTypes.find(name);
25562594
bool shouldUpdatePA = false;

0 commit comments

Comments
 (0)