Skip to content

Commit 52afa15

Browse files
committed
AST: Fix two bugs with SelfProtocolConformance
There were two problems that have been there for years: - SubstitutionMap::lookupConformance() assumes that every concrete conformance in the path has a root normal conformance. But calling getRootNormalConformance() on a self conformance would assert. - SelfProtocolConformance::getAssociatedConformance() was not implemented. While self-conforming protocols do not have associated types, they can inherit from other protocols, and we model this with an associated conformance requirement having a subject type of `Self`. Both problems were hidden by the fact that ProtocolConformanceRef::subst() directly handled self-conforming existentials without calling into the substitution map. But that is the wrong place for other reasons. The refactoring in a209ff8 exposed both of the above issues. Fixes rdar://problem/151162470.
1 parent 9993d29 commit 52afa15

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -918,9 +918,7 @@ class SelfProtocolConformance : public RootProtocolConformance {
918918
}
919919

920920
ProtocolConformanceRef getAssociatedConformance(Type assocType,
921-
ProtocolDecl *protocol) const{
922-
llvm_unreachable("self-conformances never have associated types");
923-
}
921+
ProtocolDecl *protocol) const;
924922

925923
bool hasWitness(ValueDecl *requirement) const {
926924
return true;

lib/AST/ProtocolConformance.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,13 @@ NormalProtocolConformance::getWitnessUncached(ValueDecl *requirement) const {
739739
return entry->second;
740740
}
741741

742+
ProtocolConformanceRef
743+
SelfProtocolConformance::getAssociatedConformance(Type assocType,
744+
ProtocolDecl *protocol) const {
745+
ASSERT(assocType->isEqual(protocol->getSelfInterfaceType()));
746+
return lookupConformance(getType(), protocol);
747+
}
748+
742749
Witness SelfProtocolConformance::getWitness(ValueDecl *requirement) const {
743750
return Witness(requirement, SubstitutionMap(), nullptr, SubstitutionMap(),
744751
GenericSignature(), std::nullopt);

lib/AST/SubstitutionMap.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,12 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
285285
// anything but still end up with an ErrorType in the AST.
286286
if (conformance.isConcrete()) {
287287
auto concrete = conformance.getConcrete();
288-
auto normal = concrete->getRootNormalConformance();
289-
290-
if (!normal->hasComputedAssociatedConformances()) {
291-
if (proto->getASTContext().evaluator.hasActiveRequest(
292-
ResolveTypeWitnessesRequest{normal})) {
293-
return ProtocolConformanceRef::forInvalid();
288+
if (auto normal = dyn_cast<NormalProtocolConformance>(concrete->getRootConformance())) {
289+
if (!normal->hasComputedAssociatedConformances()) {
290+
if (proto->getASTContext().evaluator.hasActiveRequest(
291+
ResolveTypeWitnessesRequest{normal})) {
292+
return ProtocolConformanceRef::forInvalid();
293+
}
294294
}
295295
}
296296
}

test/SILOptimizer/specialize_self_conforming.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,26 @@
55

66
import Foundation
77

8-
@objc protocol P {}
8+
@objc protocol P: Q {
9+
func foo()
10+
}
11+
12+
@objc protocol Q {
13+
func bar()
14+
}
15+
16+
@_optimize(none)
17+
func takesP<T : P>(_ t: T) {}
918

1019
@_optimize(none)
11-
func takesP<T : P>(_: T) {}
20+
func takesQ<T : Q>(_ t: T) {}
1221

1322
@inline(__always)
1423
func callsTakesP<T : P>(_ t: T) {
1524
takesP(t)
25+
takesQ(t)
26+
t.foo()
27+
t.bar()
1628
}
1729

1830
// CHECK-LABEL: sil hidden @$s26specialize_self_conforming16callsTakesPWithPyyAA1P_pF : $@convention(thin) (@guaranteed any P) -> () {

0 commit comments

Comments
 (0)