Skip to content

Commit bc85d66

Browse files
committed
AST: Don't call ProtocolDecl::getSuperclass() in lookupExistentialConformance()
1 parent e3d434f commit bc85d66

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

lib/AST/ConformanceLookup.cpp

+13-24
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
7676
return type;
7777
};
7878

79-
auto lookupSuperclassConformance = [&](ExistentialLayout &layout) {
80-
if (auto superclass = layout.explicitSuperclass) {
79+
auto lookupSuperclassConformance = [&](Type superclass) {
80+
if (superclass) {
8181
if (auto result =
8282
lookupConformance(superclass, protocol, /*allowMissing=*/false)) {
8383
if (protocol->isSpecificProtocol(KnownProtocolKind::Sendable) &&
@@ -101,7 +101,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
101101
auto layout = type->getExistentialLayout();
102102
if (llvm::all_of(layout.getProtocols(),
103103
[](const auto *P) { return P->isMarkerProtocol(); })) {
104-
if (auto conformance = lookupSuperclassConformance(layout)) {
104+
if (auto conformance = lookupSuperclassConformance(layout.explicitSuperclass)) {
105105
return ProtocolConformanceRef(
106106
ctx.getInheritedConformance(type, conformance.getConcrete()));
107107
}
@@ -113,15 +113,12 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
113113

114114
auto layout = type->getExistentialLayout();
115115

116-
// Due to an IRGen limitation, witness tables cannot be passed from an
117-
// existential to an archetype parameter, so for now we restrict this to
118-
// @objc protocols and marker protocols.
116+
// If the existential contains non-@objc protocols and the protocol we're
117+
// conforming to needs a witness table, the existential must have a
118+
// self-conformance witness table. For now, Swift.Error is the only one.
119119
if (!layout.isObjC() && !protocol->isMarkerProtocol()) {
120120
auto constraint = getConstraintType();
121-
// There's a specific exception for protocols with self-conforming
122-
// witness tables, but the existential has to be *exactly* that type.
123-
// TODO: synthesize witness tables on-demand for protocol compositions
124-
// that can satisfy the requirement.
121+
// The existential has to be *exactly* that type.
125122
if (protocol->requiresSelfConformanceWitnessTable() &&
126123
constraint->is<ProtocolType>() &&
127124
constraint->castTo<ProtocolType>()->getDecl() == protocol)
@@ -130,31 +127,23 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
130127
return ProtocolConformanceRef::forInvalid();
131128
}
132129

133-
// If the existential is class-constrained, the class might conform
134-
// concretely.
135-
if (auto conformance = lookupSuperclassConformance(layout))
136-
return conformance;
137-
138-
// Otherwise, the existential might conform abstractly.
130+
// The existential might conform abstractly.
139131
for (auto protoDecl : layout.getProtocols()) {
140-
141132
// If we found the protocol we're looking for, return an abstract
142133
// conformance to it.
143134
if (protoDecl == protocol)
144135
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
145136

146-
// If the protocol has a superclass constraint, we might conform
147-
// concretely.
148-
if (auto superclass = protoDecl->getSuperclass()) {
149-
if (auto result = lookupConformance(superclass, protocol))
150-
return result;
151-
}
152-
153137
// Now check refined protocols.
154138
if (protoDecl->inheritsFrom(protocol))
155139
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
156140
}
157141

142+
// If the existential is class-constrained, the class might conform
143+
// concretely.
144+
if (auto conformance = lookupSuperclassConformance(layout.getSuperclass()))
145+
return conformance;
146+
158147
// We didn't find our protocol in the existential's list; it doesn't
159148
// conform.
160149
return ProtocolConformanceRef::forInvalid();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
@_marker protocol Q {}
4+
struct G<T: Q> {}
5+
6+
typealias A1 = G<any Q>
7+
8+
//
9+
10+
class C: Q {}
11+
typealias A2 = G<C>
12+
13+
//
14+
15+
protocol Q2: Q {}
16+
typealias A3 = G<any Q2>
17+
18+
//
19+
20+
protocol P1: C {}
21+
protocol P2 where Self: C {}
22+
23+
typealias A4 = G<any P1>
24+
typealias A5 = G<any P2>

0 commit comments

Comments
 (0)