Skip to content

Commit 4a32b06

Browse files
committed
add new tests for async initializers
1 parent be98908 commit 4a32b06

File tree

5 files changed

+551
-0
lines changed

5 files changed

+551
-0
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// RUN: %target-run-simple-swift(-parse-as-library -Xfrontend -enable-experimental-concurrency %import-libdispatch) | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
// REQUIRES: concurrency
5+
// REQUIRES: libdispatch
6+
7+
// rdar://76038845
8+
// UNSUPPORTED: use_os_stdlib
9+
10+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
11+
actor NameGenerator {
12+
private var counter = 0
13+
private var prefix : String
14+
init(_ title: String) { self.prefix = title }
15+
func getName() -> String {
16+
counter += 1
17+
return "\(prefix) \(counter)"
18+
}
19+
}
20+
21+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
22+
protocol Person {
23+
init() async
24+
var name : String { get set }
25+
}
26+
27+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
28+
class EarthPerson : Person {
29+
private static let oracle = NameGenerator("Earthling")
30+
31+
var name : String
32+
33+
required init() async {
34+
self.name = await EarthPerson.oracle.getName()
35+
}
36+
37+
init(name: String) async {
38+
self.name = await (detach { name }).get()
39+
}
40+
}
41+
42+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
43+
class NorthAmericaPerson : EarthPerson {
44+
private static let oracle = NameGenerator("NorthAmerican")
45+
required init() async {
46+
await super.init()
47+
self.name = await NorthAmericaPerson.oracle.getName()
48+
}
49+
50+
override init(name: String) async {
51+
await super.init(name: name)
52+
}
53+
}
54+
55+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
56+
class PrecariousClass {
57+
init?(nilIt : Int) async {
58+
let _ : Optional<Int> = await (detach { nil }).get()
59+
return nil
60+
}
61+
62+
init(throwIt : Double) async throws {
63+
if await (detach { 0 }).get() != 1 {
64+
throw Something.bogus
65+
}
66+
}
67+
68+
init?(nilOrThrowIt shouldThrow: Bool) async throws {
69+
let flag = await (detach { shouldThrow }).get()
70+
if flag {
71+
throw Something.bogus
72+
}
73+
return nil
74+
}
75+
76+
init!(crashOrThrowIt shouldThrow: Bool) async throws {
77+
let flag = await (detach { shouldThrow }).get()
78+
if flag {
79+
throw Something.bogus
80+
}
81+
return nil
82+
}
83+
}
84+
85+
enum Something : Error {
86+
case bogus
87+
}
88+
89+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
90+
struct PrecariousStruct {
91+
init?(nilIt : Int) async {
92+
let _ : Optional<Int> = await (detach { nil }).get()
93+
return nil
94+
}
95+
96+
init(throwIt : Double) async throws {
97+
if await (detach { 0 }).get() != 1 {
98+
throw Something.bogus
99+
}
100+
}
101+
}
102+
103+
104+
105+
// CHECK: Earthling 1
106+
// CHECK-NEXT: Alice
107+
// CHECK-NEXT: Earthling 2
108+
// CHECK-NEXT: Bob
109+
// CHECK-NEXT: Earthling 3
110+
// CHECK-NEXT: Alex
111+
// CHECK-NEXT: NorthAmerican 1
112+
// CHECK-NEXT: NorthAmerican 2
113+
// CHECK-NEXT: Earthling 6
114+
115+
// CHECK-NEXT: class was nil
116+
// CHECK-NEXT: class threw
117+
// CHECK-NEXT: nilOrThrowIt init was nil
118+
// CHECK-NEXT: nilOrThrowIt init threw
119+
// CHECK-NEXT: crashOrThrowIt init threw
120+
// CHECK-NEXT: struct was nil
121+
// CHECK-NEXT: struct threw
122+
// CHECK: done
123+
124+
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
125+
@main struct RunIt {
126+
static func main() async {
127+
let people : [Person] = [
128+
await EarthPerson(),
129+
await NorthAmericaPerson(name: "Alice"),
130+
await EarthPerson(),
131+
await NorthAmericaPerson(name: "Bob"),
132+
await EarthPerson(),
133+
await NorthAmericaPerson(name: "Alex"),
134+
await NorthAmericaPerson(),
135+
await NorthAmericaPerson(),
136+
await EarthPerson()
137+
]
138+
139+
for p in people {
140+
print(p.name)
141+
}
142+
143+
// ----
144+
145+
if await PrecariousClass(nilIt: 0) == nil {
146+
print("class was nil")
147+
}
148+
149+
do { let _ = try await PrecariousClass(throwIt: 0.0) } catch {
150+
print("class threw")
151+
}
152+
153+
if try! await PrecariousClass(nilOrThrowIt: false) == nil {
154+
print("nilOrThrowIt init was nil")
155+
}
156+
157+
do { let _ = try await PrecariousClass(nilOrThrowIt: true) } catch {
158+
print("nilOrThrowIt init threw")
159+
}
160+
161+
do { let _ = try await PrecariousClass(crashOrThrowIt: true) } catch {
162+
print("crashOrThrowIt init threw")
163+
}
164+
165+
if await PrecariousStruct(nilIt: 0) == nil {
166+
print("struct was nil")
167+
}
168+
169+
do { let _ = try await PrecariousStruct(throwIt: 0.0) } catch {
170+
print("struct threw")
171+
}
172+
173+
print("done")
174+
}
175+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
4+
5+
////
6+
// some functions to play with
7+
8+
func f() async {
9+
let _ = Person() // expected-error {{call is 'async' but is not marked with 'await'}} {{11-11=await }}
10+
}
11+
12+
func g() {}
13+
14+
////
15+
// test super.init interactions
16+
17+
class Person {
18+
init() async {
19+
f() // expected-error {{call is 'async' but is not marked with 'await'}} {{5-5=await }}
20+
}
21+
22+
convenience init(_ s: String) async {
23+
await self.init()
24+
}
25+
}
26+
27+
class Bertrand: Person {
28+
override init() {} // expected-error {{missing call to superclass's initializer; 'super.init' is 'async' and requires an explicit call}}
29+
init(_ x: Int) async {} // expected-error {{missing call to superclass's initializer; 'super.init' is 'async' and requires an explicit call}}
30+
}
31+
32+
class Barbara: Person {
33+
// expected-note@+2 {{add 'async' to function 'init(_:)' to make it asynchronous}} {{20-20= async}}
34+
// expected-error@+1 {{missing call to superclass's initializer; 'super.init' is 'async' and requires an explicit call}}
35+
init(_ d: Double) {
36+
f() // expected-error{{'async' call in a function that does not support concurrency}}
37+
}
38+
39+
init(x: Int, y: Int) async {
40+
await super.init()
41+
}
42+
43+
convenience init(a: Double, b: Double) async {
44+
await self.init(x: 0, y: 0)
45+
}
46+
}
47+
48+
class Fruit {
49+
init() async {}
50+
init(name: String) {}
51+
}
52+
53+
class Banana: Fruit {
54+
override init() {
55+
super.init(name: "banana")
56+
}
57+
}
58+
59+
class Cat {} // expected-note {{overridden declaration is here}}
60+
61+
class Calico: Cat {
62+
override init() async {} // expected-error {{cannot override non-async initializer with async initializer}}
63+
}
64+
65+
func reconstruct(c: Cat) {
66+
c.init() // expected-error {{'init' is a member of the type}}
67+
}
68+
69+
////
70+
// test reasync initializers
71+
72+
class MyType {
73+
init(_ f: () async -> Void) reasync {
74+
await f()
75+
}
76+
}
77+
78+
func beep() async {
79+
let _ = MyType(f) // expected-error{{call is 'async' but is not marked with 'await'}}
80+
let _ = await MyType(f)
81+
82+
let _ = MyType(g)
83+
}
84+
85+
////
86+
// test other types with constructors
87+
88+
actor A {
89+
init() async {
90+
await f()
91+
}
92+
}
93+
94+
// NOTE: actor inheritance is probably being removed soon, so just remove this def of B
95+
actor B: A {
96+
init(x : String) async {} // expected-error {{missing call to superclass's initializer; 'super.init' is 'async' and requires an explicit call}}
97+
}
98+
99+
enum E {
100+
init() async {
101+
await f()
102+
}
103+
}
104+
105+
struct SomeStruct {
106+
@MainActor init(asyncMainActor: Int) async {}
107+
@MainActor init(mainActor: Int) {} // expected-note {{calls to initializer 'init(mainActor:)' from outside of its actor context are implicitly asynchronous}}
108+
@MainActor(unsafe) init(asyncMainActorUnsafe: Int) async {}
109+
@MainActor(unsafe) init(mainActorUnsafe: Int) {}
110+
}
111+
112+
// expected-note@+2 {{add '@MainActor' to make global function 'globActorTest1()' part of global actor 'MainActor'}}
113+
// expected-note@+1 2 {{add 'async' to function 'globActorTest1()' to make it asynchronous}}
114+
func globActorTest1() {
115+
_ = SomeStruct(asyncMainActor: 0) // expected-error {{'async' call in a function that does not support concurrency}}
116+
117+
_ = SomeStruct(mainActor: 0) // expected-error {{initializer 'init(mainActor:)' isolated to global actor 'MainActor' can not be referenced from this synchronous context}}
118+
119+
_ = SomeStruct(asyncMainActorUnsafe: 0) // expected-error {{'async' call in a function that does not support concurrency}}
120+
121+
_ = SomeStruct(mainActorUnsafe: 0)
122+
}
123+
124+
func globActorTestAsyncEdition() async {
125+
_ = await SomeStruct(asyncMainActor: 0)
126+
_ = await SomeStruct(mainActor: 0)
127+
_ = await SomeStruct(asyncMainActorUnsafe: 0)
128+
_ = await SomeStruct(mainActorUnsafe: 0)
129+
}
130+
131+
////
132+
// check protocol conformance & inheritance
133+
134+
protocol AsyncDefaultConstructable {
135+
init() async
136+
}
137+
138+
protocol DefaultConstructable {
139+
init() // expected-note {{protocol requires initializer 'init()' with type '()'; do you want to add a stub?}} {{43-43=\n init() {\n <#code#>\n \}\n}}
140+
}
141+
142+
struct Location {
143+
var x : Int
144+
var y : Int
145+
init() async { // expected-note {{candidate is 'async', but protocol requirement is not}}
146+
self.x = 0
147+
self.y = 0
148+
}
149+
}
150+
151+
extension Location: DefaultConstructable {} // expected-error {{type 'Location' does not conform to protocol 'DefaultConstructable'}}
152+
153+
extension Location: AsyncDefaultConstructable {}
154+
155+
protocol Plain {
156+
// expected-note@+2 {{overridden declaration is here}}
157+
// expected-note@+1 {{attempt to override convenience initializer here}}
158+
init()
159+
}
160+
161+
protocol Spicy: Plain {
162+
// expected-error@+2 {{cannot override non-async initializer with async initializer}}
163+
// expected-error@+1 {{initializer does not override a designated initializer from its parent protocol}}
164+
override init() async
165+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
class X: NSObject {
8+
// expected-error@+1 {{'async' initializer cannot be represented in Objective-C}}
9+
@objc init(_ i : Int) async { }
10+
}
11+

0 commit comments

Comments
 (0)