@@ -34,7 +34,8 @@ import SwiftShims
3434/// programming error.
3535///
3636/// - Parameter executor: the expected current executor
37- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
37+ @available ( SwiftStdlib 5 . 9 , * )
38+ @_transparent
3839public
3940func preconditionTaskOnExecutor(
4041 _ executor: some SerialExecutor ,
@@ -47,10 +48,9 @@ func preconditionTaskOnExecutor(
4748
4849 let expectationCheck = _taskIsCurrentExecutor ( executor. asUnownedSerialExecutor ( ) . executor)
4950
50- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
5151 precondition ( expectationCheck,
52- // TODO: offer information which executor we actually got
53- " Incorrect actor executor assumption; Expected '\( executor ) ' executor. \( message ( ) ) " ,
52+ " Expected ' \( _executorGetTypeName ( executor . asUnownedSerialExecutor ( ) . executor ) ) ' executor, " +
53+ " but was executing on '\( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
5454 file: file, line: line) // short-cut so we get the exact same failure reporting semantics
5555}
5656
@@ -71,7 +71,8 @@ func preconditionTaskOnExecutor(
7171/// programming error.
7272///
7373/// - Parameter actor: the actor whose serial executor we expect to be the current executor
74- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
74+ @available ( SwiftStdlib 5 . 9 , * )
75+ @_transparent
7576public
7677func preconditionTaskOnActorExecutor(
7778 _ actor : some Actor ,
@@ -84,10 +85,10 @@ func preconditionTaskOnActorExecutor(
8485
8586 let expectationCheck = _taskIsCurrentExecutor ( actor . unownedExecutor. executor)
8687
87- // TODO: offer information which executor we actually got
8888 precondition ( expectationCheck,
89- // TODO: figure out a way to get the typed repr out of the unowned executor
90- " Incorrect actor executor assumption; Expected ' \( actor . unownedExecutor) ' executor. \( message ( ) ) " ,
89+ " Expected same executor as actor ' \( actor ) ' " +
90+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
91+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. \( message ( ) ) " ,
9192 file: file, line: line)
9293}
9394
@@ -108,7 +109,8 @@ func preconditionTaskOnActorExecutor(
108109/// assumption is a serious programming error.
109110///
110111/// - Parameter executor: the expected current executor
111- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
112+ @available ( SwiftStdlib 5 . 9 , * )
113+ @_transparent
112114public
113115func assertTaskOnExecutor(
114116 _ executor: some SerialExecutor ,
@@ -120,10 +122,10 @@ func assertTaskOnExecutor(
120122 }
121123
122124 guard _taskIsCurrentExecutor ( executor. asUnownedSerialExecutor ( ) . executor) else {
123- // TODO: offer information which executor we actually got
124- let msg = " Incorrect actor executor assumption; Expected '\( executor) ' executor. \( message ( ) ) "
125- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
126- assertionFailure ( msg , file: file, line: line)
125+ assertionFailure (
126+ " Expected ' \( _executorGetTypeName ( executor. asUnownedSerialExecutor ( ) . executor ) ) ' executor, " +
127+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
128+ file: file, line: line)
127129 return
128130 }
129131}
@@ -143,7 +145,8 @@ func assertTaskOnExecutor(
143145///
144146///
145147/// - Parameter actor: the actor whose serial executor we expect to be the current executor
146- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
148+ @available ( SwiftStdlib 5 . 9 , * )
149+ @_transparent
147150public
148151func assertTaskOnActorExecutor(
149152 _ actor : some Actor ,
@@ -155,10 +158,11 @@ func assertTaskOnActorExecutor(
155158 }
156159
157160 guard _taskIsCurrentExecutor ( actor . unownedExecutor. executor) else {
158- // TODO: offer information which executor we actually got
159- // TODO: figure out a way to get the typed repr out of the unowned executor
160- let msg = " Incorrect actor executor assumption; Expected ' \( actor . unownedExecutor) ' executor. \( message ( ) ) "
161- /// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
161+ let msg =
162+ " Expected same executor as actor ' \( actor ) ' " +
163+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
164+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " +
165+ " \( message ( ) ) " ;
162166 assertionFailure ( msg, file: file, line: line) // short-cut so we get the exact same failure reporting semantics
163167 return
164168 }
@@ -180,7 +184,7 @@ func assertTaskOnActorExecutor(
180184/// if another actor uses the same serial executor--by using ``MainActor/sharedUnownedExecutor``
181185/// as its own ``Actor/unownedExecutor``--this check will succeed, as from a concurrency safety
182186/// perspective, the serial executor guarantees mutual exclusion of those two actors.
183- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
187+ @available ( SwiftStdlib 5 . 9 , * )
184188@_unavailableFromAsync ( message: " await the call to the @MainActor closure directly " )
185189public
186190func assumeOnMainActorExecutor< T> (
@@ -192,9 +196,13 @@ func assumeOnMainActorExecutor<T>(
192196
193197 /// This is guaranteed to be fatal if the check fails,
194198 /// as this is our "safe" version of this API.
195- guard _taskIsCurrentExecutor ( Builtin . buildMainActorExecutorRef ( ) ) else {
196- // TODO: offer information which executor we actually got
197- fatalError ( " Incorrect actor executor assumption; Expected 'MainActor' executor. " , file: file, line: line)
199+ let mainExecutor = Builtin . buildMainActorExecutorRef ( )
200+
201+ guard _taskIsCurrentExecutor ( mainExecutor) else {
202+ fatalError (
203+ " Expected ' \( _executorGetTypeName ( mainExecutor) ) ' executor, " +
204+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
205+ file: file, line: line)
198206 }
199207
200208 // To do the unsafe cast, we have to pretend it's @escaping.
@@ -218,7 +226,7 @@ func assumeOnMainActorExecutor<T>(
218226/// if another actor uses the same serial executor--by using that actor's ``Actor/unownedExecutor``
219227/// as its own ``Actor/unownedExecutor``--this check will succeed, as from a concurrency safety
220228/// perspective, the serial executor guarantees mutual exclusion of those two actors.
221- @available ( SwiftStdlib 5 . 9 , * ) // FIXME: use @backDeploy(before: SwiftStdlib 5.9)
229+ @available ( SwiftStdlib 5 . 9 , * )
222230@_unavailableFromAsync ( message: " express the closure as an explicit function declared on the specified 'actor' instead " )
223231public
224232func assumeOnActorExecutor< Act: Actor , T> (
@@ -233,8 +241,11 @@ func assumeOnActorExecutor<Act: Actor, T>(
233241 /// as this is our "safe" version of this API.
234242 let executor : Builtin . Executor = actor . unownedExecutor. executor
235243 guard _taskIsCurrentExecutor ( executor) else {
236- // TODO: offer information which executor we actually got
237- fatalError ( " Incorrect actor executor assumption; Expected same executor as \( actor ) . " , file: file, line: line)
244+ fatalError (
245+ " Expected same executor as actor ' \( actor ) ' " +
246+ " (' \( _executorGetTypeName ( actor . unownedExecutor. executor) ) '), " +
247+ " but was executing on ' \( _executorGetCurrentActiveExecutorName ( ) ) '. " ,
248+ file: file, line: line)
238249 }
239250
240251 // To do the unsafe cast, we have to pretend it's @escaping.
@@ -245,5 +256,18 @@ func assumeOnActorExecutor<Act: Actor, T>(
245256 }
246257}
247258
259+ /// Specifically get the name of the current *active* executor, without falling back to assuming the generic one.
260+ /// I.e. if we're not executing within a task, we expect to have `<unknown>` executor rather than the generic one.
261+ @usableFromInline
262+ @available ( SwiftStdlib 5 . 9 , * )
263+ func _executorGetCurrentActiveExecutorName( ) -> String {
264+ let ( wasActive, ref) = _executorGetCurrentActiveExecutorRef ( )
265+ guard wasActive else {
266+ return " <unknown> "
267+ }
268+
269+ return _executorGetTypeName ( ref)
270+ }
271+
248272// TODO(ktoso): implement assume for distributed actors as well
249273#endif // not SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
0 commit comments