Skip to content

Commit c22c96b

Browse files
Joe ShajrawiJoe Shajrawi
authored andcommitted
[Devirtualize] Support devirtualization of witness methods when we have a polymorphic type and no substitutions required
SILGen is generating code with “shadow” requirements: convention(witness_method: ApplyRegStruct) <τ_0_0 where τ_0_0 == Type> (@inout Array<Type>) -> () { // no use of τ_0_0 inside In this case we have an empty substitution map but a polymorphic function type We should relax the assert when creating apply instructions to support this case.
1 parent 7f1ba5d commit c22c96b

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2438,7 +2438,9 @@ CanSILFunctionType
24382438
SILFunctionType::substGenericArgs(SILModule &silModule,
24392439
SubstitutionList subs) {
24402440
if (subs.empty()) {
2441-
assert(!isPolymorphic() && "no args for polymorphic substitution");
2441+
assert(
2442+
(!isPolymorphic() || getGenericSignature()->areAllParamsConcrete()) &&
2443+
"no args for non-concrete polymorphic substitution");
24422444
return CanSILFunctionType(this);
24432445
}
24442446

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// RUN: %target-swift-frontend -O -emit-ir -primary-file %s | %FileCheck %s
2+
3+
public struct PublicStruct {
4+
}
5+
6+
public enum PublicEnum {
7+
}
8+
9+
struct RegStruct {
10+
enum EnumInRegStruct {
11+
case case1
12+
case case2
13+
}
14+
15+
private var optNode: Any?
16+
private var ClassInRegStructs = [ClassInRegStruct]()
17+
18+
var isEmpty: Bool {
19+
return optNode == nil && ClassInRegStructs.isEmpty
20+
}
21+
22+
private func funcInRegStruct() -> RegStruct? {
23+
var funcInRegStruct = RegStruct()
24+
return funcInRegStruct
25+
}
26+
27+
func func2InRegStruct(boolParam: Bool = false,
28+
_ body: (inout Bool) -> Void) {
29+
var finished = false
30+
func2InRegStruct(body, boolParam: boolParam, &finished)
31+
}
32+
33+
private func func2InRegStruct(_ body: (inout Bool) -> Void,
34+
boolParam: Bool = false, _ finished: inout Bool) {
35+
funcInRegStruct()?.func2InRegStruct(body, boolParam: boolParam, &finished)
36+
}
37+
38+
private static func func2InRegStruct(_ ClassInRegStructs: [ClassInRegStruct],
39+
_ body: (inout Bool) -> Void,
40+
boolParam: Bool, _ finished: inout Bool) {
41+
}
42+
43+
func funcInStructAndProtAndExt(_ EnumInRegStruct: EnumInRegStruct, space: PublicEnum,
44+
_ body: () -> Void) {
45+
guard !isEmpty else { return }
46+
47+
func2InRegStruct(boolParam: !EnumInRegStruct.isDownwards) { finished in
48+
}
49+
}
50+
51+
final private class ClassInRegStruct {
52+
}
53+
}
54+
55+
extension RegStruct.EnumInRegStruct {
56+
fileprivate var isDownwards: Bool {
57+
switch self {
58+
case .case1:
59+
return true
60+
case .case2:
61+
return false
62+
}
63+
}
64+
}
65+
66+
private protocol ApplyRegStruct {
67+
mutating func applyTransform()
68+
}
69+
70+
protocol RegStructable {
71+
mutating func funcInStructAndProtAndExt(from space: PublicEnum, transform: RegStruct)
72+
}
73+
74+
extension ApplyRegStruct {
75+
mutating func funcInStructAndProtAndExt(
76+
from space: PublicEnum, transform: RegStruct
77+
) {
78+
transform.funcInStructAndProtAndExt(.case2, space: space) {
79+
// CHECK-LABEL: define hidden swiftcc void @"$SSa39devirt_witness_method_empty_conformanceAA12PublicStructVRszlE14applyTransformyyF"(%TSa* nocapture swiftself dereferenceable
80+
// CHECK-NEXT: entry
81+
// CHECK-NEXT: ret void
82+
applyTransform()
83+
}
84+
}
85+
}
86+
87+
extension Array : ApplyRegStruct, RegStructable where Element == PublicStruct {
88+
mutating func applyTransform() {
89+
}
90+
}

0 commit comments

Comments
 (0)