From b7ab8e83c121b6fc7a214fff7304cdd826be4277 Mon Sep 17 00:00:00 2001 From: HE Shi-Jun Date: Wed, 13 May 2026 21:29:39 +0800 Subject: [PATCH 1/2] Document Swift TaskLocal functionality Added Swift TaskLocal section with examples and details. --- PRIOR-ARTS.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/PRIOR-ARTS.md b/PRIOR-ARTS.md index 8e48a38..037e853 100644 --- a/PRIOR-ARTS.md +++ b/PRIOR-ARTS.md @@ -13,6 +13,7 @@ The following table shows a general landscape of how the API behaves in these la | Python `ContextVar` | Both available | In scope mutation | | Ruby `Fiber` | No implicit feedback | In scope mutation | | Rust `tokio::task_local` | No implicit feedback | New scope mutation | +| Swift `TaskLocal` | No implicit feedback | New scope mutation | | Dart `Zone` | No implicit feedback | New scope mutation | | JS `Zone` | No implicit feedback | New scope mutation | | Node.js `AsyncLocalStorage` | No implicit feedback | Both available | @@ -394,6 +395,57 @@ From the tokio API, and the result, we can tell that: - Modification in a child task does not propagates to its sibling tasks. - Modification to a `task_local` does not propagate to the caller continuation, i.e. `await` in caller. +### Swift + +Swift 5.5 provides [`TaskLocal`][] for declaring values that are implicitly carried +with a `Task` and inherited by child tasks, such as tasks created by +`async let` or task groups. The design was introduced in [`SE-0311`](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0311-task-locals.md). + +Task-local values cannot be set directly. They must be bound with +`withValue(_:operation:)`, which creates a scope where the bound value is +available to the current task and child tasks created within that scope. + +> Test it yourself: [SwiftFiddle](https://swiftfiddle.com/thbylc3nivfvthmso57s3lma6q). + +```swift +@TaskLocal var traceID: String = "none" + +func read(_ label: String) async -> Void { + await Task.yield() + print("\(label): \(traceID)") +} + +await $traceID.withValue("main") { + async let inherited = read("inherited") + async let child = $traceID.withValue("child") { + await read("child") + } + + await (inherited, child) + print("parent: \(traceID)") +} + +print("after: \(traceID)") +``` + +This prints: + +```console +inherited: main +child: child +parent: main +after: none +``` + +From the `TaskLocal` API, and the result, we can tell that: +- `TaskLocal` declarations use `var`, but the task-local value cannot be + modified with direct assignment. +- `TaskLocal` values can only be rebound with `withValue`, which creates a + bounded scope. +- Modification in a child task does not propagate to its sibling tasks. +- Modification to a `TaskLocal` does not propagate to the caller continuation, + i.e. `await` in caller. + ### Dart Dart's [Zone](https://api.dart.dev/dart-async/Zone-class.html) provides much more functionality @@ -610,4 +662,5 @@ Error: Call stack [`AsyncLocal`]: https://learn.microsoft.com/en-us/dotnet/api/system.threading.asynclocal-1?view=net-9.0 [`CallContext`]: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.remoting.messaging.callcontext?view=netframework-4.8.1 [`ScopedValue`]: https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/ScopedValue.html +[`TaskLocal`]: https://developer.apple.com/documentation/swift/tasklocal [`zone.js`]: https://github.com/angular/angular/tree/main/packages/zone.js From 3dc3c79d2d3a6f9f8a90955485b665a0800229f6 Mon Sep 17 00:00:00 2001 From: HE Shi-Jun Date: Wed, 13 May 2026 22:37:54 +0800 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- PRIOR-ARTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIOR-ARTS.md b/PRIOR-ARTS.md index 037e853..2ecb534 100644 --- a/PRIOR-ARTS.md +++ b/PRIOR-ARTS.md @@ -392,7 +392,7 @@ main foo From the tokio API, and the result, we can tell that: - `task_local` can be only be modified with a `sync_scope` or a `scope`. -- Modification in a child task does not propagates to its sibling tasks. +- Modification in a child task does not propagate to its sibling tasks. - Modification to a `task_local` does not propagate to the caller continuation, i.e. `await` in caller. ### Swift