@@ -33,7 +33,8 @@ import SwiftShims
3333/// programming error.
3434///
3535/// - Parameter executor: the expected current executor
36- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
36+ @available ( SwiftStdlib 5 . 9 , * )
37+ @_transparent
3738public
3839func preconditionTaskOnExecutor(
3940 _ executor: some SerialExecutor ,
@@ -46,10 +47,9 @@ func preconditionTaskOnExecutor(
4647
4748 let expectationCheck = _taskIsCurrentExecutor ( executor. asUnownedSerialExecutor ( ) . executor)
4849
49- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
5050 precondition ( expectationCheck,
51- // TODO: offer information which executor we actually got
52- " Incorrect actor executor assumption; Expected '\( executor ) ' executor. \( message ( ) ) " ,
51+ " Expected ' \( _executorGetTypeName ( executor . asUnownedSerialExecutor ( ) . executor ) ) ' executor, " +
52+ " but was executing on '\( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
5353 file: file, line: line) // short-cut so we get the exact same failure reporting semantics
5454}
5555
@@ -70,7 +70,8 @@ func preconditionTaskOnExecutor(
7070/// programming error.
7171///
7272/// - Parameter actor: the actor whose serial executor we expect to be the current executor
73- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
73+ @available ( SwiftStdlib 5 . 9 , * )
74+ @_transparent
7475public
7576func preconditionTaskOnActorExecutor(
7677 _ actor : some Actor ,
@@ -83,10 +84,10 @@ func preconditionTaskOnActorExecutor(
8384
8485 let expectationCheck = _taskIsCurrentExecutor ( actor . unownedExecutor. executor)
8586
86- // TODO: offer information which executor we actually got
8787 precondition ( expectationCheck,
88- // TODO: figure out a way to get the typed repr out of the unowned executor
89- " Incorrect actor executor assumption; Expected ' \( actor . unownedExecutor) ' executor. \( message ( ) ) " ,
88+ " Expected same executor as actor ' \( actor ) ' " +
89+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
90+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. \( message ( ) ) " ,
9091 file: file, line: line)
9192}
9293
@@ -107,7 +108,8 @@ func preconditionTaskOnActorExecutor(
107108/// assumption is a serious programming error.
108109///
109110/// - Parameter executor: the expected current executor
110- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
111+ @available ( SwiftStdlib 5 . 9 , * )
112+ @_transparent
111113public
112114func assertTaskOnExecutor(
113115 _ executor: some SerialExecutor ,
@@ -119,10 +121,10 @@ func assertTaskOnExecutor(
119121 }
120122
121123 guard _taskIsCurrentExecutor ( executor. asUnownedSerialExecutor ( ) . executor) else {
122- // TODO: offer information which executor we actually got
123- let msg = " Incorrect actor executor assumption; Expected '\( executor) ' executor. \( message ( ) ) "
124- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
125- assertionFailure ( msg , file: file, line: line)
124+ assertionFailure (
125+ " Expected ' \( _executorGetTypeName ( executor. asUnownedSerialExecutor ( ) . executor ) ) ' executor, " +
126+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
127+ file: file, line: line)
126128 return
127129 }
128130}
@@ -142,7 +144,8 @@ func assertTaskOnExecutor(
142144///
143145///
144146/// - Parameter actor: the actor whose serial executor we expect to be the current executor
145- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
147+ @available ( SwiftStdlib 5 . 9 , * )
148+ @_transparent
146149public
147150func assertTaskOnActorExecutor(
148151 _ actor : some Actor ,
@@ -154,10 +157,11 @@ func assertTaskOnActorExecutor(
154157 }
155158
156159 guard _taskIsCurrentExecutor ( actor . unownedExecutor. executor) else {
157- // TODO: offer information which executor we actually got
158- // TODO: figure out a way to get the typed repr out of the unowned executor
159- let msg = " Incorrect actor executor assumption; Expected ' \( actor . unownedExecutor) ' executor. \( message ( ) ) "
160- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
160+ let msg =
161+ " Expected same executor as actor ' \( actor ) ' " +
162+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
163+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " +
164+ " \( message ( ) ) " ;
161165 assertionFailure ( msg, file: file, line: line) // short-cut so we get the exact same failure reporting semantics
162166 return
163167 }
@@ -179,7 +183,7 @@ func assertTaskOnActorExecutor(
179183/// if another actor uses the same serial executor--by using ``MainActor/sharedUnownedExecutor``
180184/// as its own ``Actor/unownedExecutor``--this check will succeed, as from a concurrency safety
181185/// perspective, the serial executor guarantees mutual exclusion of those two actors.
182- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
186+ @available ( SwiftStdlib 5 . 9 , * )
183187@_unavailableFromAsync ( message: " await the call to the @MainActor closure directly " )
184188public
185189func assumeOnMainActorExecutor< T> (
@@ -191,9 +195,13 @@ func assumeOnMainActorExecutor<T>(
191195
192196 /// This is guaranteed to be fatal if the check fails,
193197 /// as this is our "safe" version of this API.
194- guard _taskIsCurrentExecutor ( Builtin . buildMainActorExecutorRef ( ) ) else {
195- // TODO: offer information which executor we actually got
196- fatalError ( " Incorrect actor executor assumption; Expected 'MainActor' executor. " , file: file, line: line)
198+ let mainExecutor = Builtin . buildMainActorExecutorRef ( )
199+
200+ guard _taskIsCurrentExecutor ( mainExecutor) else {
201+ fatalError (
202+ " Expected ' \( _executorGetTypeName ( mainExecutor) ) ' executor, " +
203+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
204+ file: file, line: line)
197205 }
198206
199207 // To do the unsafe cast, we have to pretend it's @escaping.
@@ -217,7 +225,7 @@ func assumeOnMainActorExecutor<T>(
217225/// if another actor uses the same serial executor--by using that actor's ``Actor/unownedExecutor``
218226/// as its own ``Actor/unownedExecutor``--this check will succeed, as from a concurrency safety
219227/// perspective, the serial executor guarantees mutual exclusion of those two actors.
220- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
228+ @available ( SwiftStdlib 5 . 9 , * )
221229@_unavailableFromAsync ( message: " express the closure as an explicit function declared on the specified 'actor' instead " )
222230public
223231func assumeOnActorExecutor< Act: Actor , T> (
@@ -232,8 +240,11 @@ func assumeOnActorExecutor<Act: Actor, T>(
232240 /// as this is our "safe" version of this API.
233241 let executor : Builtin . Executor = actor . unownedExecutor. executor
234242 guard _taskIsCurrentExecutor ( executor) else {
235- // TODO: offer information which executor we actually got
236- fatalError ( " Incorrect actor executor assumption; Expected same executor as \( actor ) . " , file: file, line: line)
243+ fatalError (
244+ " Expected same executor as actor ' \( actor ) ' " +
245+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
246+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
247+ file: file, line: line)
237248 }
238249
239250 // To do the unsafe cast, we have to pretend it's @escaping.
@@ -244,4 +255,17 @@ func assumeOnActorExecutor<Act: Actor, T>(
244255 }
245256}
246257
258+ /// Specifically get the name of the current *active* executor, without falling back to assuming the generic one.
259+ /// I.e. if we're not executing within a task, we expect to have `<unknown>` executor rather than the generic one.
260+ @usableFromInline
261+ @available ( SwiftStdlib 5 . 9 , * )
262+ func _executorGetCurrentActiveExecutorName( ) -> String {
263+ let ( wasActive, ref) = _executorGetCurrentActiveExecutorRef ( )
264+ guard wasActive else {
265+ return " <unknown> "
266+ }
267+
268+ return _executorGetTypeName ( ref)
269+ }
270+
247271// TODO(ktoso): implement assume for distributed actors as well
0 commit comments