Skip to content

Commit b5eb418

Browse files
committed
[AST] Handle classes properly in ProtocolConformanceRef::subst.
Previously ProtocolConformance::subst would crash because it was receiving things with an unexpected relationship between the conformance's type and the substituted self type. The compiler doesn't quite properly model "abstract" inherited conformances, so we end up using normal conformances instead, and we need to work around this in some cases.
1 parent 44045e2 commit b5eb418

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,18 @@ ProtocolConformanceRef::subst(Type origType,
8686

8787
// If we have a concrete conformance, we need to substitute the
8888
// conformance to apply to the new type.
89-
if (isConcrete())
89+
if (isConcrete()) {
90+
auto concrete = getConcrete();
91+
if (auto classDecl = concrete->getType()->getClassOrBoundGenericClass()) {
92+
// If this is a class, we need to traffic in the actual type that
93+
// implements the protocol, not 'Self' and not any subclasses (with their
94+
// inherited conformances).
95+
substType =
96+
substType->eraseDynamicSelfType()->getSuperclassForDecl(classDecl);
97+
}
9098
return ProtocolConformanceRef(
9199
getConcrete()->subst(substType, subs, conformances));
100+
}
92101

93102
// Opened existentials trivially conform and do not need to go through
94103
// substitution map lookup.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -O -emit-ir -primary-file %s | %FileCheck %s
2+
// This is a swift file because the crash doesn't reproduce with SIL.
3+
@inline(never)
4+
func callFoo<T: X>(_ x: T) {
5+
x.foo()
6+
}
7+
public func a(y: Sub) {
8+
callFoo(y)
9+
// specialization of callFoo for Sub:
10+
// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T033devirt_witness_method_conformance7callFooyxAA1XRzlFAA3SubC_Tg5Tf4d_n() local_unnamed_addr
11+
}
12+
protocol X {
13+
func foo()
14+
}
15+
extension X {
16+
func foo() {}
17+
}
18+
public class Base: X {}
19+
public class Sub: Base {}

0 commit comments

Comments
 (0)