File: predates_concurrency_swift6.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (273 lines) | stat: -rw-r--r-- 11,105 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// RUN: %target-swift-frontend -target %target-swift-abi-5.1-triple -swift-version 6 %s -emit-sil -o /dev/null -verify

// REQUIRES: concurrency

@preconcurrency func unsafelySendableClosure(_ closure: @Sendable () -> Void) { }

@preconcurrency func unsafelyMainActorClosure(_ closure: @MainActor () -> Void) { }

@preconcurrency func unsafelyDoEverythingClosure(_ closure: @MainActor @Sendable () -> Void) { }

struct X {
  @preconcurrency func unsafelyDoEverythingClosure(_ closure: @MainActor @Sendable () -> Void) { }

  @preconcurrency var sendableVar: @Sendable () -> Void
  @preconcurrency var mainActorVar: @MainActor () -> Void

  @preconcurrency
  subscript(_: @MainActor () -> Void) -> (@Sendable () -> Void) { {} }

  @preconcurrency
  static subscript(statically _: @MainActor () -> Void) -> (@Sendable () -> Void) { { } }
}

@MainActor func onMainActor() { }

func testInAsync(x: X) async {
  let _: Int = unsafelySendableClosure // expected-error{{type '@Sendable (@Sendable () -> Void) -> ()'}}
  let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = x.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = X.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (X) -> @Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = (X.unsafelyDoEverythingClosure)(x) // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}

  let _: Int = x.sendableVar // expected-error{{type '@Sendable () -> Void'}}
  let _: Int = x.mainActorVar // expected-error{{type '@MainActor @Sendable () -> Void'}}

  let _: Int = x[{ onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
  let _: Int = X[statically: { onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
}

func testElsewhere(x: X) {
  let _: Int = unsafelySendableClosure // expected-error{{type '@Sendable (@Sendable () -> Void) -> ()'}}
  let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = x.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = X.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (X) -> @Sendable (@MainActor @Sendable () -> Void) -> ()'}}
  let _: Int = (X.unsafelyDoEverythingClosure)(x) // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}

  let _: Int = x.sendableVar // expected-error{{type '@Sendable () -> Void'}}
  let _: Int = x.mainActorVar // expected-error{{type '@MainActor @Sendable () -> Void'}}

  let _: Int = x[{ onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
  let _: Int = X[statically: { onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
}

@MainActor @preconcurrency func onMainActorAlways() { }
// expected-note@-1{{are implicitly asynchronous}}

@preconcurrency @MainActor class MyModelClass {
 func f() { }
  // expected-note@-1{{are implicitly asynchronous}}
}

func testCalls(x: X) {
  // expected-note@-1 2{{add '@MainActor' to make global function 'testCalls(x:)' part of global actor 'MainActor'}}
  onMainActorAlways() // expected-error{{call to main actor-isolated global function 'onMainActorAlways()' in a synchronous nonisolated context}}

  let _: () -> Void = onMainActorAlways // expected-error{{converting function value of type '@MainActor @Sendable () -> ()' to '() -> Void' loses global actor 'MainActor'}}

  let c = MyModelClass() // okay, synthesized init() is 'nonisolated'

  c.f() // expected-error{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
}

func testCallsWithAsync() async {
  onMainActorAlways() // expected-error{{expression is 'async' but is not marked with 'await'}}
  // expected-note@-1{{calls to global function 'onMainActorAlways()' from outside of its actor context are implicitly asynchronous}}

  let _: () -> Void = onMainActorAlways // expected-error{{converting function value of type '@MainActor @Sendable () -> ()' to '() -> Void' loses global actor 'MainActor'}}

  let c = MyModelClass() // okay, synthesized init() is 'nonisolated'

  c.f() // expected-error{{expression is 'async' but is not marked with 'await'}}
  // expected-note@-1{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
}

// ---------------------------------------------------------------------------
// Protocols that inherit Sendable and predate concurrency.
// ---------------------------------------------------------------------------
@preconcurrency protocol P: Sendable { }
protocol Q: P { }

class NS { } // expected-note 3{{class 'NS' does not conform to the 'Sendable' protocol}}

struct S1: P {
  var ns: NS // expected-error{{stored property 'ns' of 'Sendable'-conforming struct 'S1' has non-sendable type 'NS'}}
}

struct S2: Q {
  var ns: NS // expected-error{{stored property 'ns' of 'Sendable'-conforming struct 'S2' has non-sendable type 'NS'}}
}

struct S3: Q, Sendable {
  var ns: NS // expected-error{{stored property 'ns' of 'Sendable'-conforming struct 'S3' has non-sendable type 'NS'}}
}

// ---------------------------------------------------------------------------
// Historical attribute names do nothing (but are permitted)
// ---------------------------------------------------------------------------
func aFailedExperiment(@_unsafeSendable _ body: @escaping () -> Void) { }
// expected-warning@-1{{'_unsafeSendable' attribute has been removed in favor of @preconcurrency}}

func anothingFailedExperiment(@_unsafeMainActor _ body: @escaping () -> Void) { }
// expected-warning@-1{{'_unsafeMainActor' attribute has been removed in favor of @preconcurrency}}

// Override matching with @preconcurrency properties.
do {
  class Base {
    @preconcurrency
    open var test1 : ([any Sendable])? // expected-note {{overridden declaration is here}}

    @preconcurrency
    open var test2: [String: [Int: any Sendable]] // expected-note {{overridden declaration is here}}

    @preconcurrency
    open var test3: any Sendable // expected-note {{overridden declaration is here}}

    @preconcurrency
    open var test4: (((Any)?) -> Void)? { // expected-note {{overridden declaration is here}}
      nil
    }

    init() {
      self.test1 = nil
      self.test2 = [:]
      self.test3 = 42
    }
  }

  class Test : Base {
    override var test1: [Any]? {
      // expected-error@-1 {{declaration 'test1' has a type with different sendability from any potential overrides}}
      get { nil }
      set { }
    }

    override var test2: [String: [Int: Any]] {
      // expected-error@-1 {{declaration 'test2' has a type with different sendability from any potential overrides}}
      get { [:] }
      set {}
    }

    override var test3: Any {
      // expected-error@-1 {{declaration 'test3' has a type with different sendability from any potential overrides}}
      get { 42 }
      set { }
    }

    override var test4: (((any Sendable)?) -> Void)? {
      // expected-error@-1 {{declaration 'test4' has a type with different sendability from any potential overrides}}
      nil
    }
  }
}



@preconcurrency
func withSendableClosure(_: @Sendable () -> Void) {}

func conversionDowngrade() {
  let ns: () -> Void = {}
  withSendableClosure(ns)
  // expected-warning@-1 {{converting non-sendable function value to '@Sendable () -> Void' may introduce data races}}
}

@preconcurrency
func requireSendable<T: Sendable>(_: T) {}

@preconcurrency
struct RequireSendable<T: Sendable> {}

class NotSendable {} // expected-note 8 {{class 'NotSendable' does not conform to the 'Sendable' protocol}}

class UnavailableSendable {}

@available(*, unavailable)
extension UnavailableSendable: @unchecked Sendable {}
// expected-note@-1 8 {{conformance of 'UnavailableSendable' to 'Sendable' has been explicitly marked unavailable here}}

typealias T = RequireSendable<NotSendable>
// expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

typealias T2 = RequireSendable<UnavailableSendable>
// expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

class C {
  @preconcurrency
  func requireSendable<T: Sendable>(_: T) {}

  @preconcurrency
  static func requireSendableStatic<T: Sendable>(_: T) {}
}

func testRequirementDowngrade(ns: NotSendable, us: UnavailableSendable, c: C) {
  requireSendable(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  c.requireSendable(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  C.requireSendableStatic(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  requireSendable(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

  c.requireSendable(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

  C.requireSendableStatic(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}
}


protocol P2 {}

extension NotSendable: P2 {}

extension UnavailableSendable: P2 {}

@preconcurrency
func requireSendableExistential(_: any P2 & Sendable) {}

func requireSendableExistentialAlways(_: any P2 & Sendable) {}

extension C {
  @preconcurrency
  func requireSendableExistential(_: any P2 & Sendable) {}

  @preconcurrency
  static func requireSendableExistentialStatic(_: any P2 & Sendable) {}
}

func testErasureDowngrade(ns: NotSendable, us: UnavailableSendable, c: C) {
  requireSendableExistential(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  c.requireSendableExistential(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  C.requireSendableExistentialStatic(ns)
  // expected-warning@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

  requireSendableExistential(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

  c.requireSendableExistential(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

  C.requireSendableExistentialStatic(us)
  // expected-warning@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}

  withSendableClosure {
    let ns = NotSendable()
    requireSendableExistentialAlways(ns)
    // expected-error@-1 {{type 'NotSendable' does not conform to the 'Sendable' protocol}}

    let us = UnavailableSendable()
    requireSendableExistentialAlways(us)
    // expected-error@-1 {{conformance of 'UnavailableSendable' to 'Sendable' is unavailable}}
  }
}