Skip to content

Commit 5e949b8

Browse files
authored
Merge pull request swiftlang#74674 from kubamracek/embedded-failable
[embedded] Fix crash when using failable initializers on generic classes
2 parents 5bbf6d0 + bda0c90 commit 5e949b8

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

lib/IRGen/MetadataRequest.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,15 @@ bool irgen::isCompleteSpecializedNominalTypeMetadataStaticallyAddressable(
916916
IRGenModule &IGM, CanType type,
917917
SpecializedMetadataCanonicality canonicality) {
918918
if (isa<ClassType>(type) || isa<BoundGenericClassType>(type)) {
919+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
920+
if (type->hasArchetype()) {
921+
llvm::errs() << "Cannot get metadata of generic class for type "
922+
<< type << "\n";
923+
llvm::report_fatal_error("cannot get metadata");
924+
}
925+
return true;
926+
}
927+
919928
// TODO: On platforms without ObjC interop, we can do direct access to
920929
// class metadata.
921930
return false;

test/embedded/failable-crash.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-emit-ir %s -module-name=main -enable-experimental-feature Embedded | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: OS=macosx || OS=linux-gnu
5+
6+
public func test() {
7+
_ = MyClass<String>(x: 42)
8+
}
9+
10+
public class MyClass<T> {
11+
private let member: Int
12+
13+
public init?(x: Int) {
14+
guard x > 0 else { return nil }
15+
self.member = 42
16+
}
17+
}
18+
19+
// CHECK: define {{.*}}@main(
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: executable_test
5+
// REQUIRES: optimized_stdlib
6+
// REQUIRES: OS=macosx || OS=linux-gnu
7+
8+
public struct FooError: Error {}
9+
10+
public class PrintingClass {
11+
init() { print("PrintingClass.init") }
12+
deinit { print("PrintingClass.deinit") }
13+
}
14+
15+
public class Foo<T> {
16+
var a: PrintingClass
17+
var b: PrintingClass
18+
init?(shouldFail: Bool) {
19+
a = PrintingClass()
20+
if shouldFail { return nil }
21+
b = PrintingClass()
22+
}
23+
}
24+
25+
public class Bar<T>: Foo<T> {
26+
var value: Int = 17
27+
}
28+
29+
public class Wibble<T>: Bar<T> {
30+
var c: PrintingClass = .init()
31+
}
32+
33+
_ = Wibble<Int>(shouldFail: true)
34+
print("OK 1")
35+
// CHECK: PrintingClass.init
36+
// CHECK: PrintingClass.init
37+
// CHECK: PrintingClass.deinit
38+
// CHECK: PrintingClass.deinit
39+
// CHECK: OK 1
40+
41+
_ = Wibble<Int>(shouldFail: false)
42+
print("OK 2")
43+
// CHECK: PrintingClass.init
44+
// CHECK: PrintingClass.init
45+
// CHECK: PrintingClass.init
46+
// CHECK: PrintingClass.deinit
47+
// CHECK: PrintingClass.deinit
48+
// CHECK: PrintingClass.deinit
49+
// CHECK: OK 2
50+
51+
public class Base<T> {
52+
var baseMember: PrintingClass
53+
init?(shouldFail: Bool) {
54+
if shouldFail { return nil }
55+
baseMember = PrintingClass()
56+
}
57+
}
58+
59+
class SubClass<T>: Base<T> {
60+
var subClassMember: PrintingClass = PrintingClass()
61+
override init?(shouldFail: Bool) {
62+
super.init(shouldFail: shouldFail)
63+
}
64+
}
65+
66+
_ = SubClass<String>(shouldFail: true)
67+
print("OK 3")
68+
// CHECK: PrintingClass.init
69+
// CHECK: PrintingClass.deinit
70+
// CHECK: OK 3
71+
72+
_ = SubClass<String>(shouldFail: false)
73+
print("OK 4")
74+
// CHECK: PrintingClass.init
75+
// CHECK: PrintingClass.init
76+
// CHECK: PrintingClass.deinit
77+
// CHECK: PrintingClass.deinit
78+
// CHECK: OK 4

test/embedded/init-failable.swift

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: executable_test
5+
// REQUIRES: optimized_stdlib
6+
// REQUIRES: OS=macosx || OS=linux-gnu
7+
8+
public struct FooError: Error {}
9+
10+
public class PrintingClass {
11+
init() { print("PrintingClass.init") }
12+
deinit { print("PrintingClass.deinit") }
13+
}
14+
15+
public class Foo {
16+
var a: PrintingClass
17+
var b: PrintingClass
18+
init?(shouldFail: Bool) {
19+
a = PrintingClass()
20+
if shouldFail { return nil }
21+
b = PrintingClass()
22+
}
23+
}
24+
25+
public class Bar: Foo {
26+
var value: Int = 17
27+
}
28+
29+
public class Wibble: Bar {
30+
var c: PrintingClass = .init()
31+
}
32+
33+
_ = Wibble(shouldFail: true)
34+
print("OK 1")
35+
// CHECK: PrintingClass.init
36+
// CHECK: PrintingClass.init
37+
// CHECK: PrintingClass.deinit
38+
// CHECK: PrintingClass.deinit
39+
// CHECK: OK 1
40+
41+
_ = Wibble(shouldFail: false)
42+
print("OK 2")
43+
// CHECK: PrintingClass.init
44+
// CHECK: PrintingClass.init
45+
// CHECK: PrintingClass.init
46+
// CHECK: PrintingClass.deinit
47+
// CHECK: PrintingClass.deinit
48+
// CHECK: PrintingClass.deinit
49+
// CHECK: OK 2
50+
51+
public class Base {
52+
var baseMember: PrintingClass
53+
init?(shouldFail: Bool) {
54+
if shouldFail { return nil }
55+
baseMember = PrintingClass()
56+
}
57+
}
58+
59+
class SubClass: Base {
60+
var subClassMember: PrintingClass = PrintingClass()
61+
override init?(shouldFail: Bool) {
62+
super.init(shouldFail: shouldFail)
63+
}
64+
}
65+
66+
_ = SubClass(shouldFail: true)
67+
print("OK 3")
68+
// CHECK: PrintingClass.init
69+
// CHECK: PrintingClass.deinit
70+
// CHECK: OK 3
71+
72+
_ = SubClass(shouldFail: false)
73+
print("OK 4")
74+
// CHECK: PrintingClass.init
75+
// CHECK: PrintingClass.init
76+
// CHECK: PrintingClass.deinit
77+
// CHECK: PrintingClass.deinit
78+
// CHECK: OK 4

0 commit comments

Comments
 (0)