Skip to content

Commit 6330776

Browse files
committed
AST: The underlying conformance of a specialized conformance is always a root conformance
1 parent 10f0d27 commit 6330776

12 files changed

+46
-59
lines changed

Diff for: include/swift/AST/ASTContext.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ namespace swift {
105105
class NormalProtocolConformance;
106106
class OpaqueTypeDecl;
107107
class InheritedProtocolConformance;
108+
class RootProtocolConformance;
108109
class SelfProtocolConformance;
109110
class SpecializedProtocolConformance;
110111
enum class BuiltinConformanceKind;
@@ -1245,7 +1246,7 @@ class ASTContext final {
12451246
/// specialized conformance from the generic conformance.
12461247
ProtocolConformance *
12471248
getSpecializedConformance(Type type,
1248-
ProtocolConformance *generic,
1249+
RootProtocolConformance *generic,
12491250
SubstitutionMap substitutions);
12501251

12511252
/// Produce an inherited conformance, for subclasses of a type

Diff for: include/swift/AST/ProtocolConformance.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ class SelfProtocolConformance : public RootProtocolConformance {
753753
class SpecializedProtocolConformance : public ProtocolConformance,
754754
public llvm::FoldingSetNode {
755755
/// The generic conformance from which this conformance was derived.
756-
ProtocolConformance *GenericConformance;
756+
RootProtocolConformance *GenericConformance;
757757

758758
/// The substitutions applied to the generic conformance to produce this
759759
/// conformance.
@@ -772,15 +772,15 @@ class SpecializedProtocolConformance : public ProtocolConformance,
772772
friend class ASTContext;
773773

774774
SpecializedProtocolConformance(Type conformingType,
775-
ProtocolConformance *genericConformance,
775+
RootProtocolConformance *genericConformance,
776776
SubstitutionMap substitutions);
777777

778778
void computeConditionalRequirements() const;
779779

780780
public:
781781
/// Get the generic conformance from which this conformance was derived,
782782
/// if there is one.
783-
ProtocolConformance *getGenericConformance() const {
783+
RootProtocolConformance *getGenericConformance() const {
784784
return GenericConformance;
785785
}
786786

@@ -866,7 +866,7 @@ class SpecializedProtocolConformance : public ProtocolConformance,
866866
}
867867

868868
static void Profile(llvm::FoldingSetNodeID &ID, Type type,
869-
ProtocolConformance *genericConformance,
869+
RootProtocolConformance *genericConformance,
870870
SubstitutionMap subs) {
871871
ID.AddPointer(type.getPointer());
872872
ID.AddPointer(genericConformance);

Diff for: include/swift/AST/RequirementEnvironment.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
namespace swift {
2424

25+
class RootProtocolConformance;
26+
2527
/// Describes the environment of a requirement that will be used when
2628
/// matching witnesses against the requirement and to form the resulting
2729
/// \c Witness value.
@@ -99,7 +101,7 @@ class RequirementEnvironment {
99101
GenericSignature reqSig,
100102
ProtocolDecl *proto,
101103
ClassDecl *covariantSelf,
102-
ProtocolConformance *conformance);
104+
RootProtocolConformance *conformance);
103105

104106
/// Retrieve the generic signature of the requirement.
105107
GenericSignature getRequirementSignature() const {

Diff for: lib/AST/ASTContext.cpp

+14-34
Original file line numberDiff line numberDiff line change
@@ -2387,48 +2387,28 @@ ASTContext::getBuiltinConformance(
23872387
return entry;
23882388
}
23892389

2390-
/// If one of the ancestor conformances already has a matching type, use
2391-
/// that instead.
2392-
static ProtocolConformance *collapseSpecializedConformance(
2393-
Type type,
2394-
ProtocolConformance *conformance,
2395-
SubstitutionMap substitutions) {
2396-
while (true) {
2397-
switch (conformance->getKind()) {
2398-
case ProtocolConformanceKind::Specialized:
2399-
conformance = cast<SpecializedProtocolConformance>(conformance)
2400-
->getGenericConformance();
2401-
break;
2402-
2403-
case ProtocolConformanceKind::Normal:
2404-
case ProtocolConformanceKind::Inherited:
2405-
case ProtocolConformanceKind::Self:
2406-
case ProtocolConformanceKind::Builtin:
2407-
// If the conformance matches, return it.
2408-
if (conformance->getType()->isEqual(type)) {
2409-
for (auto subConformance : substitutions.getConformances())
2410-
if (!subConformance.isAbstract())
2411-
return nullptr;
2412-
2413-
return conformance;
2414-
}
2390+
static bool collapseSpecializedConformance(Type type,
2391+
RootProtocolConformance *conformance,
2392+
SubstitutionMap substitutions) {
2393+
if (!conformance->getType()->isEqual(type))
2394+
return false;
24152395

2416-
return nullptr;
2417-
}
2396+
for (auto subConformance : substitutions.getConformances()) {
2397+
if (!subConformance.isAbstract())
2398+
return false;
24182399
}
2400+
2401+
return true;
24192402
}
24202403

24212404
ProtocolConformance *
24222405
ASTContext::getSpecializedConformance(Type type,
2423-
ProtocolConformance *generic,
2406+
RootProtocolConformance *generic,
24242407
SubstitutionMap substitutions) {
2425-
// If we are performing a substitution that would get us back to the
2426-
// a prior conformance (e.g., mapping into and then out of a conformance),
2427-
// return the existing conformance.
2428-
if (auto existing = collapseSpecializedConformance(type, generic,
2429-
substitutions)) {
2408+
// If the specialization is a no-op, use the root conformance instead.
2409+
if (collapseSpecializedConformance(type, generic, substitutions)) {
24302410
++NumCollapsedSpecializedProtocolConformances;
2431-
return existing;
2411+
return generic;
24322412
}
24332413

24342414
llvm::FoldingSetNodeID id;

Diff for: lib/AST/Module.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,8 @@ LookupConformanceInModuleRequest::evaluate(
14471447
auto subMap = type->getContextSubstitutionMap(mod, explicitConformanceDC);
14481448

14491449
// Create the specialized conformance entry.
1450-
auto result = ctx.getSpecializedConformance(type, conformance, subMap);
1450+
auto result = ctx.getSpecializedConformance(type,
1451+
cast<RootProtocolConformance>(conformance), subMap);
14511452
return ProtocolConformanceRef(result);
14521453
}
14531454
}

Diff for: lib/AST/ProtocolConformance.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -957,14 +957,11 @@ void NormalProtocolConformance::overrideWitness(ValueDecl *requirement,
957957

958958
SpecializedProtocolConformance::SpecializedProtocolConformance(
959959
Type conformingType,
960-
ProtocolConformance *genericConformance,
960+
RootProtocolConformance *genericConformance,
961961
SubstitutionMap substitutions)
962962
: ProtocolConformance(ProtocolConformanceKind::Specialized, conformingType),
963963
GenericConformance(genericConformance),
964-
GenericSubstitutions(substitutions)
965-
{
966-
assert(genericConformance->getKind() != ProtocolConformanceKind::Specialized);
967-
}
964+
GenericSubstitutions(substitutions) {}
968965

969966
void SpecializedProtocolConformance::computeConditionalRequirements() const {
970967
// already computed?
@@ -1181,9 +1178,11 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,
11811178

11821179
auto subMap = SubstitutionMap::get(getGenericSignature(),
11831180
subs, conformances);
1181+
1182+
auto *mutableThis = const_cast<ProtocolConformance *>(this);
11841183
return substType->getASTContext()
11851184
.getSpecializedConformance(substType,
1186-
const_cast<ProtocolConformance *>(this),
1185+
cast<NormalProtocolConformance>(mutableThis),
11871186
subMap);
11881187
}
11891188
case ProtocolConformanceKind::Builtin: {
@@ -1660,7 +1659,8 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() {
16601659
auto genericConformance = spec->getGenericConformance();
16611660
return Ctx.getSpecializedConformance(
16621661
getType()->getCanonicalType(),
1663-
genericConformance->getCanonicalConformance(),
1662+
cast<RootProtocolConformance>(
1663+
genericConformance->getCanonicalConformance()),
16641664
spec->getSubstitutionMap().getCanonical());
16651665
}
16661666
}

Diff for: lib/AST/RequirementEnvironment.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ RequirementEnvironment::RequirementEnvironment(
3636
GenericSignature reqSig,
3737
ProtocolDecl *proto,
3838
ClassDecl *covariantSelf,
39-
ProtocolConformance *conformance)
39+
RootProtocolConformance *conformance)
4040
: reqSig(reqSig) {
4141
ASTContext &ctx = conformanceDC->getASTContext();
4242

Diff for: lib/AST/Type.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3128,7 +3128,8 @@ getForeignRepresentable(Type type, ForeignLanguage language,
31283128
if (result.getKind() == ForeignRepresentableKind::Bridged
31293129
&& !result.getConformance()->getType()->isEqual(type)) {
31303130
auto specialized = type->getASTContext()
3131-
.getSpecializedConformance(type, result.getConformance(),
3131+
.getSpecializedConformance(type,
3132+
cast<RootProtocolConformance>(result.getConformance()),
31323133
boundGenericType->getContextSubstitutionMap(dc->getParentModule(),
31333134
boundGenericType->getDecl()));
31343135
result = ForeignRepresentationInfo::forBridged(specialized);

Diff for: lib/SIL/Parser/ParseSIL.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -7089,8 +7089,10 @@ ProtocolConformanceRef SILParser::parseProtocolConformanceHelper(
70897089
if (!subMap)
70907090
return ProtocolConformanceRef();
70917091

7092+
auto *rootConform = cast<RootProtocolConformance>(
7093+
genericConform.getConcrete());
70927094
auto result = P.Context.getSpecializedConformance(
7093-
ConformingTy, genericConform.getConcrete(), subMap);
7095+
ConformingTy, rootConform, subMap);
70947096
return ProtocolConformanceRef(result);
70957097
}
70967098

Diff for: lib/Sema/TypeCheckProtocol.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ swift::matchWitness(
874874
static const RequirementEnvironment &getOrCreateRequirementEnvironment(
875875
WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
876876
DeclContext *dc, GenericSignature reqSig, ProtocolDecl *proto,
877-
ClassDecl *covariantSelf, ProtocolConformance *conformance) {
877+
ClassDecl *covariantSelf, RootProtocolConformance *conformance) {
878878
WitnessChecker::RequirementEnvironmentCacheKey cacheKey(reqSig.getPointer(),
879879
covariantSelf);
880880
auto cacheIter = reqEnvCache.find(cacheKey);
@@ -992,7 +992,7 @@ static PossibleEffects getEffects(ValueDecl *value) {
992992

993993
RequirementMatch
994994
swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
995-
ProtocolDecl *proto, ProtocolConformance *conformance,
995+
ProtocolDecl *proto, RootProtocolConformance *conformance,
996996
DeclContext *dc, ValueDecl *req, ValueDecl *witness) {
997997
using namespace constraints;
998998

@@ -6834,7 +6834,7 @@ swift::findWitnessedObjCRequirements(const ValueDecl *witness,
68346834
if (accessorKind)
68356835
witnessToMatch = cast<AccessorDecl>(witness)->getStorage();
68366836

6837-
if (matchWitness(reqEnvCache, proto, *conformance,
6837+
if (matchWitness(reqEnvCache, proto, normal,
68386838
witnessToMatch->getDeclContext(), req,
68396839
const_cast<ValueDecl *>(witnessToMatch))
68406840
.isWellFormed()) {

Diff for: lib/Sema/TypeCheckProtocol.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ RequirementMatch matchWitness(
12541254

12551255
RequirementMatch
12561256
matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
1257-
ProtocolDecl *proto, ProtocolConformance *conformance,
1257+
ProtocolDecl *proto, RootProtocolConformance *conformance,
12581258
DeclContext *dc, ValueDecl *req, ValueDecl *witness);
12591259

12601260
/// If the given type is a direct reference to an associated type of

Diff for: lib/Serialization/Deserialization.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -553,11 +553,11 @@ ProtocolConformanceDeserializer::readSpecializedProtocolConformance(
553553
PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement());
554554
++NumNormalProtocolConformancesLoaded;
555555

556-
assert(genericConformance.isConcrete() && "Abstract generic conformance?");
556+
auto *rootConformance = cast<RootProtocolConformance>(
557+
genericConformance.getConcrete());
558+
557559
auto conformance =
558-
ctx.getSpecializedConformance(conformingType,
559-
genericConformance.getConcrete(),
560-
subMap);
560+
ctx.getSpecializedConformance(conformingType, rootConformance, subMap);
561561
return conformance;
562562
}
563563

0 commit comments

Comments
 (0)