Skip to content

Commit 148b57b

Browse files
authored
Merge pull request #11708 from swiftix/swift-4.0-branch-fixes1
Support concrete type propagation into witness_method instructions only for directly inherited conformances for now
2 parents 31c6cac + 86fa193 commit 148b57b

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -795,12 +795,23 @@ getConformanceAndConcreteType(FullApplySite AI,
795795
if (Requirement == Protocol) {
796796
return std::make_tuple(Conformance, ConcreteType, ConcreteTypeDef);
797797
}
798-
if (Requirement->inheritsFrom(Protocol)) {
799-
// If Requirement != Protocol, then the abstract conformance cannot be used
800-
// as is and we need to create a proper conformance.
801-
return std::make_tuple(Conformance.getInherited(Protocol), ConcreteType,
802-
ConcreteTypeDef);
803-
}
798+
// If Requirement != Protocol, then the abstract conformance cannot be
799+
// used as is and we need to create a proper conformance.
800+
// FIXME: We can handle only direct inheritance at the moment due to some
801+
// limitations of the init_existential_* instructions representation.
802+
// Once these instructions start using generic signatures instead of
803+
// conformances lists, it should be fairly easy to support the indirect
804+
// inheritance here by something like:
805+
// Substitution Sub(ConcreteType, Conformances);
806+
// IE->getGenericSignature()
807+
// ->getSubstitutionMap({Sub}).lookupConformance(GP00, Protocol);
808+
auto InheritedProtocols = Requirement->getInheritedProtocols();
809+
if (std::find(InheritedProtocols.begin(), InheritedProtocols.end(),
810+
Protocol) == InheritedProtocols.end())
811+
return None;
812+
// Requirement is directly inherited from Protocol.
813+
return std::make_tuple(Conformance.getInherited(Protocol), ConcreteType,
814+
ConcreteTypeDef);
804815
}
805816

806817
llvm_unreachable("couldn't find matching conformance in substitution?");

test/SILOptimizer/devirt_protocol_method_invocations.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ protocol PPP {
77
protocol QQQ : PPP {
88
}
99

10-
struct S : QQQ {}
10+
protocol RRR : QQQ {
11+
}
12+
13+
struct S : RRR {}
1114

1215
extension QQQ {
1316
@_semantics("optimize.sil.never")
@@ -25,6 +28,18 @@ public func testInheritedConformance() {
2528
(S() as QQQ).f()
2629
}
2730

31+
// Test that a witness_method instructions is not devirtualized yet, because
32+
// it uses indirect inheritance.
33+
// This test used to crash the compiler because it uses inherited conformances.
34+
// CHECK-LABEL: sil @_T034devirt_protocol_method_invocations34testIndirectlyInheritedConformanceyyF : $@convention(thin) () -> ()
35+
// CHECK: witness_method
36+
// CHECK: apply
37+
// CHECK: // end sil function '_T034devirt_protocol_method_invocations34testIndirectlyInheritedConformanceyyF'
38+
public func testIndirectlyInheritedConformance() {
39+
(S() as RRR).f()
40+
}
41+
42+
2843
public protocol Foo {
2944
func foo(_ x:Int) -> Int
3045
}

0 commit comments

Comments
 (0)