Skip to content

Commit ba9bfaf

Browse files
committed
VTableSpecializer: fix a crash for methods which have their own generic parameters
rdar://133334324
1 parent e27f195 commit ba9bfaf

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

lib/SILOptimizer/Transforms/VTableSpecializer.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,26 @@ static bool specializeVTablesOfSuperclasses(SILModule &module,
150150
return changed;
151151
}
152152

153+
static SubstitutionMap getMethodSubs(SILFunction *method, SubstitutionMap classContextSubs) {
154+
GenericSignature genericSig =
155+
method->getLoweredFunctionType()->getInvocationGenericSignature();
156+
157+
if (!genericSig || genericSig->areAllParamsConcrete())
158+
return SubstitutionMap();
159+
160+
return SubstitutionMap::get(genericSig,
161+
QuerySubstitutionMap{classContextSubs},
162+
LookUpConformanceInModule());
163+
}
164+
165+
static bool hasInvalidConformance(SubstitutionMap subs) {
166+
for (auto substConf : subs.getConformances()) {
167+
if (substConf.isInvalid())
168+
return true;
169+
}
170+
return false;
171+
}
172+
153173
SILVTable *swift::specializeVTableForType(SILType classTy, SILModule &module,
154174
SILTransform *transform) {
155175
CanType astType = classTy.getASTType();
@@ -182,8 +202,20 @@ SILVTable *swift::specializeVTableForType(SILType classTy, SILModule &module,
182202

183203
for (const SILVTableEntry &entry : origVtable->getEntries()) {
184204
SILFunction *origMethod = entry.getImplementation();
205+
206+
auto methodSubs = getMethodSubs(origMethod, subs);
207+
208+
// If the resulting substitution map is not valid this means that the method
209+
// itself has generic parameters.
210+
if (hasInvalidConformance(methodSubs)) {
211+
module.getASTContext().Diags.diagnose(
212+
entry.getMethod().getDecl()->getLoc(), diag::non_final_generic_class_function);
213+
continue;
214+
}
215+
185216
SILFunction *specializedMethod =
186-
specializeVTableMethod(origMethod, subs, module, transform);
217+
specializeVTableMethod(origMethod, methodSubs, module, transform);
218+
187219
newEntries.push_back(SILVTableEntry(entry.getMethod(), specializedMethod,
188220
entry.getKind(),
189221
entry.isNonOverridden()));

test/embedded/classes-non-final-method-no-stdlib.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,23 @@ public class MyClass {
66
func foo<T>(t: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
77
func bar() { }
88
}
9+
10+
final class C2<Element> {
11+
// TODO: this shouldn't be a problem because the class is final
12+
init<T>(x: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
13+
}
14+
15+
struct S {}
16+
17+
func testit2() -> C2<S> {
18+
return C2(x: S())
19+
}
20+
21+
open class C3<X> {
22+
public func foo<T>(t: T) {} // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
23+
}
24+
25+
func testit3() -> C3<S> {
26+
return C3<S>()
27+
}
28+

test/embedded/generic-classes.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,52 @@ public func makeInner() -> Outer<Int>.Inner {
4646
return Outer<Int>.Inner()
4747
}
4848

49+
final class List<Element> where Element: ~Copyable {
50+
init(x: Element) where Element: Copyable { }
51+
}
52+
53+
func testList() -> List<Int> {
54+
return List(x: 0)
55+
}
56+
57+
open class OpenClass<Element> where Element: ~Copyable {
58+
public func foo(x: Element) where Element: Copyable { }
59+
}
60+
61+
func testOpenClass() -> OpenClass<Int> {
62+
return OpenClass()
63+
}
64+
65+
66+
class Base<T> {
67+
func foo(_: T) {}
68+
}
69+
70+
class Derived<T>: Base<Array<T>> {}
71+
72+
func testBaseDerived() -> Derived<Int> {
73+
return Derived()
74+
}
75+
76+
class Base2<T> {
77+
func foo(_: T) {}
78+
}
79+
80+
class Derived2<T>: Base2<(T, T)> {}
81+
82+
func testBaseDerived2() -> Derived2<Int> {
83+
return Derived2()
84+
}
85+
86+
class Base3<T> {
87+
func foo(_: T) {}
88+
}
89+
class Derived3<T, U>: Base3<(T, U)> {}
90+
91+
func testBaseDerived3() -> Derived3<Int, Bool> {
92+
return Derived3()
93+
}
94+
4995
@main
5096
struct Main {
5197
static func main() {
@@ -56,6 +102,11 @@ struct Main {
56102
let x = SubClass2()
57103
x.test()
58104
makeInner().foo()
105+
testList()
106+
testOpenClass()
107+
testBaseDerived()
108+
testBaseDerived2()
109+
testBaseDerived3()
59110
}
60111
}
61112

0 commit comments

Comments
 (0)