Skip to content

Commit aa4a1b2

Browse files
committed
AST: The generic conformance of a specialized conformance is always normal
1 parent 08ba88f commit aa4a1b2

File tree

10 files changed

+50
-36
lines changed

10 files changed

+50
-36
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,15 +1302,17 @@ class ASTContext final {
13021302
/// specialized conformance from the generic conformance.
13031303
ProtocolConformance *
13041304
getSpecializedConformance(Type type,
1305-
RootProtocolConformance *generic,
1305+
NormalProtocolConformance *generic,
13061306
SubstitutionMap substitutions);
13071307

1308-
/// Produce an inherited conformance, for subclasses of a type
1309-
/// that already conforms to a protocol.
1308+
/// Produce an inherited conformance, which forwards all operations to a
1309+
/// base conformance, except for getType(), which must return some subclass
1310+
/// of the base conformance's conforming type. This models the case where a
1311+
/// subclass conforms to a protocol because its superclass already conforms.
13101312
///
13111313
/// \param type The type for which we are retrieving the conformance.
13121314
///
1313-
/// \param inherited The inherited conformance.
1315+
/// \param inherited A normal or specialized conformance.
13141316
ProtocolConformance *
13151317
getInheritedConformance(Type type, ProtocolConformance *inherited);
13161318

include/swift/AST/ProtocolConformance.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ class SelfProtocolConformance : public RootProtocolConformance {
884884
class SpecializedProtocolConformance : public ProtocolConformance,
885885
public llvm::FoldingSetNode {
886886
/// The generic conformance from which this conformance was derived.
887-
RootProtocolConformance *GenericConformance;
887+
NormalProtocolConformance *GenericConformance;
888888

889889
/// The substitutions applied to the generic conformance to produce this
890890
/// conformance.
@@ -903,15 +903,15 @@ class SpecializedProtocolConformance : public ProtocolConformance,
903903
friend class ASTContext;
904904

905905
SpecializedProtocolConformance(Type conformingType,
906-
RootProtocolConformance *genericConformance,
906+
NormalProtocolConformance *genericConformance,
907907
SubstitutionMap substitutions);
908908

909909
void computeConditionalRequirements() const;
910910

911911
public:
912912
/// Get the generic conformance from which this conformance was derived,
913913
/// if there is one.
914-
RootProtocolConformance *getGenericConformance() const {
914+
NormalProtocolConformance *getGenericConformance() const {
915915
return GenericConformance;
916916
}
917917

@@ -997,7 +997,7 @@ class SpecializedProtocolConformance : public ProtocolConformance,
997997
}
998998

999999
static void Profile(llvm::FoldingSetNodeID &ID, Type type,
1000-
RootProtocolConformance *genericConformance,
1000+
NormalProtocolConformance *genericConformance,
10011001
SubstitutionMap subs) {
10021002
ID.AddPointer(type.getPointer());
10031003
ID.AddPointer(genericConformance);

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,7 +2592,7 @@ ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
25922592
}
25932593

25942594
static bool collapseSpecializedConformance(Type type,
2595-
RootProtocolConformance *conformance,
2595+
NormalProtocolConformance *conformance,
25962596
SubstitutionMap substitutions) {
25972597
if (!conformance->getType()->isEqual(type))
25982598
return false;
@@ -2607,7 +2607,7 @@ static bool collapseSpecializedConformance(Type type,
26072607

26082608
ProtocolConformance *
26092609
ASTContext::getSpecializedConformance(Type type,
2610-
RootProtocolConformance *generic,
2610+
NormalProtocolConformance *generic,
26112611
SubstitutionMap substitutions) {
26122612
// If the specialization is a no-op, use the root conformance instead.
26132613
if (collapseSpecializedConformance(type, generic, substitutions)) {

lib/AST/ConformanceLookup.cpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,12 @@ LookupConformanceInModuleRequest::evaluate(
643643
ExpandExtensionMacros{nominal},
644644
{ });
645645

646-
// Find the (unspecialized) conformance.
646+
// Find the root conformance in the nominal type declaration's
647+
// conformance lookup table.
647648
SmallVector<ProtocolConformance *, 2> conformances;
649+
650+
// If the conformance lookup table produced nothing, we try to derive the
651+
// conformance for a few special protocol kinds.
648652
if (!nominal->lookupConformance(protocol, conformances)) {
649653
if (protocol->isSpecificProtocol(KnownProtocolKind::Sendable)) {
650654
// Try to infer Sendable conformance.
@@ -706,6 +710,8 @@ LookupConformanceInModuleRequest::evaluate(
706710
}
707711
}
708712

713+
// We should have at least one conformance by now, or we would have returned
714+
// above.
709715
assert(!conformances.empty());
710716

711717
// If we have multiple conformances, first try to filter out any that are
@@ -754,27 +760,32 @@ LookupConformanceInModuleRequest::evaluate(
754760
return ProtocolConformanceRef(conformance);
755761
}
756762

757-
// If the type is specialized, find the conformance for the generic type.
763+
// We now have a root conformance for the nominal's declared interface type.
764+
// If our type is specialized, apply a substitution map to the root
765+
// conformance.
758766
if (type->isSpecialized()) {
759-
// Figure out the type that's explicitly conforming to this protocol.
760-
Type explicitConformanceType = conformance->getType();
761-
DeclContext *explicitConformanceDC = conformance->getDeclContext();
762-
763-
// If the explicit conformance is associated with a type that is different
764-
// from the type we're checking, retrieve generic conformance.
765-
if (!explicitConformanceType->isEqual(type)) {
766-
// Gather the substitutions we need to map the generic conformance to
767-
// the specialized conformance.
768-
auto subMap = type->getContextSubstitutionMap(mod, explicitConformanceDC);
769-
770-
// Create the specialized conformance entry.
771-
auto result = ctx.getSpecializedConformance(type,
772-
cast<RootProtocolConformance>(conformance), subMap);
773-
return ProtocolConformanceRef(result);
767+
if (!conformance->getType()->isEqual(type)) {
768+
// We use a builtin conformance for unconditional Copyable and Escapable
769+
// conformances. Avoid building a substitution map and just return the
770+
// correct builtin conformance for the specialized type.
771+
if (auto *builtinConf = dyn_cast<BuiltinProtocolConformance>(conformance)) {
772+
return ProtocolConformanceRef(
773+
ctx.getBuiltinConformance(type, protocol,
774+
builtinConf->getBuiltinConformanceKind()));
775+
}
776+
777+
// Otherwise, we have a normal conformance, so we're going to build a
778+
// specialized conformance from the context substitution map of the
779+
// specialized type.
780+
auto *normalConf = cast<NormalProtocolConformance>(conformance);
781+
auto *conformanceDC = normalConf->getDeclContext();
782+
auto subMap = type->getContextSubstitutionMap(mod, conformanceDC);
783+
return ProtocolConformanceRef(
784+
ctx.getSpecializedConformance(type, normalConf, subMap));
774785
}
775786
}
776787

777-
// Record and return the simple conformance.
788+
// Return the root conformance.
778789
return ProtocolConformanceRef(conformance);
779790
}
780791

lib/AST/ProtocolConformance.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ void NormalProtocolConformance::overrideWitness(ValueDecl *requirement,
731731

732732
SpecializedProtocolConformance::SpecializedProtocolConformance(
733733
Type conformingType,
734-
RootProtocolConformance *genericConformance,
734+
NormalProtocolConformance *genericConformance,
735735
SubstitutionMap substitutions)
736736
: ProtocolConformance(ProtocolConformanceKind::Specialized, conformingType),
737737
GenericConformance(genericConformance),
@@ -917,7 +917,7 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,
917917

918918
/// Check if the replacement is a one-element pack with a scalar type.
919919
static bool isVanishingTupleConformance(
920-
RootProtocolConformance *generic,
920+
NormalProtocolConformance *generic,
921921
SubstitutionMap substitutions) {
922922
if (!isa<BuiltinTupleDecl>(generic->getDeclContext()->getSelfNominalTypeDecl()))
923923
return false;
@@ -1515,7 +1515,7 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() {
15151515
auto genericConformance = spec->getGenericConformance();
15161516
return Ctx.getSpecializedConformance(
15171517
getType()->getCanonicalType(),
1518-
cast<RootProtocolConformance>(
1518+
cast<NormalProtocolConformance>(
15191519
genericConformance->getCanonicalConformance()),
15201520
spec->getSubstitutionMap().getCanonical());
15211521
}

lib/AST/RequirementEnvironment.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ RequirementEnvironment::RequirementEnvironment(
131131
substConcreteType->getContextSubstitutionMap(
132132
conformanceDC->getParentModule(), conformanceDC);
133133
specialized =
134-
ctx.getSpecializedConformance(substConcreteType, conformance,
134+
ctx.getSpecializedConformance(substConcreteType,
135+
cast<NormalProtocolConformance>(conformance),
135136
concreteSubs);
136137
}
137138

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3039,7 +3039,7 @@ getForeignRepresentable(Type type, ForeignLanguage language,
30393039
&& !result.getConformance()->getType()->isEqual(type)) {
30403040
auto specialized = type->getASTContext()
30413041
.getSpecializedConformance(type,
3042-
cast<RootProtocolConformance>(result.getConformance()),
3042+
cast<NormalProtocolConformance>(result.getConformance()),
30433043
boundGenericType->getContextSubstitutionMap(dc->getParentModule(),
30443044
boundGenericType->getDecl()));
30453045
result = ForeignRepresentationInfo::forBridged(specialized);

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7868,7 +7868,7 @@ ProtocolConformanceRef SILParser::parseProtocolConformanceHelper(
78687868
if (!subMap)
78697869
return ProtocolConformanceRef();
78707870

7871-
auto *rootConform = cast<RootProtocolConformance>(
7871+
auto *rootConform = cast<NormalProtocolConformance>(
78727872
genericConform.getConcrete());
78737873
auto result = P.Context.getSpecializedConformance(
78747874
ConformingTy, rootConform, subMap);

lib/SILGen/SILGen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
8585

8686
/// The conformance for any DistributedActor to the Actor protocol,
8787
/// used only by the `distributedActorAsAnyActor` builtin.
88-
RootProtocolConformance *distributedActorAsActorConformance = nullptr;
88+
NormalProtocolConformance *distributedActorAsActorConformance = nullptr;
8989

9090
size_t anonymousSymbolCounter = 0;
9191

lib/Serialization/Deserialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ ProtocolConformanceDeserializer::readSpecializedProtocolConformance(
846846
PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement());
847847
++NumNormalProtocolConformancesLoaded;
848848

849-
auto *rootConformance = cast<RootProtocolConformance>(
849+
auto *rootConformance = cast<NormalProtocolConformance>(
850850
genericConformance.getConcrete());
851851

852852
auto conformance =

0 commit comments

Comments
 (0)