A proposal for adding diffing functionality to the Swift standard library
A graphical client for BTech MUX
parkera/swift-corelibs-foundation 1
The Foundation Project, providing core utilities, internationalization, and OS independence
The Swift Programming Language
parkera/swift-corelibs-xctest 0
The XCTest Project, A Swift core library for providing unit test support
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
parkera/swift-package-manager 0
The Package Manager for the Swift Programming Language
Pull request review commentapple/swift-evolution
[Concurrency] Task Local Values
A task local key declaration nested under in the `TaskLocalValues` and consists > This design may remind you of SwiftUI's `@Environment` concept, and indeed the shape of how values are declared is fairly similar. However, it differs tremendously in *where* the child/parent relationship is expressed. In a later section we'll make a more detailed comparison with SwiftUI. -Next, in order to access the value one has to `await Task.local(_:)` it:+Next, in order to access the value one has to `Task.local(_:)` it: ```swift-func printRequestID() async {- let id = await Task.local(\.requestID) ?? "<unknown>"+func asyncPrintRequestID() async {+ let id = Task.local(\.requestID) print("request-id: \(id)") }-``` -Since it is not known statically if the value will be present or not, the returned value is an `Optional<String>`.+func syncPrintRequestID() async {
Yes thanks!
comment created time in 5 hours
Pull request review commentapple/swift-evolution
[Concurrency] Task Local Values
+# Task Local Values++* Proposal: [SE-NNNN](NNNN-task-local.md)+* Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso)+* Review Manager: TBD+* Status: Awaiting review+* Implementation: [apple/swift#34722](https://github.com/apple/swift/pull/34722)++## Table of Contents++* [Introduction](#introduction)+* [Motivation](#motivation)+* [Proposed solution](#proposed-solution)+ * [Task Local Values](#task-local-values-1)+* [Detailed design](#detailed-design)+ * [Declaring task-local values](#declaring-task-local-values)+ * [Binding task-local values](#binding-task-local-values)+ * [Binding values for the duration of a child-task](#binding-values-for-the-duration-of-a-child-task)+ * [Task-local value lifecycle](#task-local-value-lifecycle)+ * [Reading task-local values](#reading-task-local-values)+ * [Reading task-local values: implementation details](#reading-task-local-values-implementation-details)+ * [Similarities and differences with SwiftUI Environment](#similarities-and-differences-with-swiftui-environment)+* [Prior Art](#prior-art)+ * [Kotlin: CoroutineContext[T]](#kotlin-coroutinecontextt)+ * [Java/Loom: Scope Variables](#javaloom-scope-variables)+ * [Go: explicit context passing all the way](#go-explicit-context-passing-all-the-way)+* [Rejected Alternatives](#rejected-alternatives)+ * [Plain-old Thread Local variables](#plain-old-thread-local-variables)+ * [Dispatch Queue Specific Values](#dispatch-queue-specific-values)+* [Intended use-cases](#intended-use-cases)+ * [Use case: Distributed Tracing & Contextual Logging](#use-case-distributed-tracing--contextual-logging)+ * [Contextual Logging](#contextual-logging)+ * [Function Tracing](#function-tracing)+ * [Distributed Tracing](#distributed-tracing)+ * [Future direction: Function wrapper interaction](#future-direction-function-wrapper-interaction)+ * [Use case: Mocking internals (Swift System)](#use-case-mocking-internals-swift-system)+ * [Use case: Progress Monitoring](#use-case-progress-monitoring)+ * [Use case: Executor configuration](#use-case-executor-configuration)+* [Future Directions](#future-directions)+ * [Tracing annotations with Function Wrappers](#tracing-annotations-with-function-wrappers)+* [Revision history](#revision-history)+* [Source compatibility](#source-compatibility)+* [Effect on ABI stability](#effect-on-abi-stability)+* [Effect on API resilience](#effect-on-api-resilience)++## Introduction++With Swift embracing asynchronous functions and actors, asynchronous code will be everywhere. ++Therefore, the need for debugging, tracing and otherwise instrumenting asynchronous code becomes even more necessary than before. At the same time, tools which instrumentation systems could have used before to carry information along requests -- such as thread locals or queue-specific values -- are no longer compatible with Swift's Task-focused take on concurrency.++Previously, tool developers could have relied on thread-local or queue-specific values as containers to associate information with a task and carry it across suspension boundaries. However, these mechanisms do not compose well in general, have known "gotchas" (e.g., forgetting to carefully maintain and clear state from these containers after a task has completed to avoid leaking them), and do not compose at all with Swift's task-first approach to concurrency. Furthermore, those mechanisms do not feel "right" given Swift's focus on Structured Concurrency, because they are inherently unstructured.++This proposal defines the semantics of _Task Local Values_. That is, values which are local to a `Task`.++Task local values set in a task _cannot_ out-live the task, solving many of the pain points relating to un-structured primitives such as thread-locals, as well as aligning this feature closely with Swift's take on Structured Concurrency.++Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/t/pitch-task-local-values/42829/15)++## Motivation++Task Local Values are a significant improvement over thread-local storage in that it is a better fit for Swift's concurrency model because it takes advantage of its structured nature. In existing code, developers have used thread-local or queue-specific values to associate state with each thread/queue, however the exact semantics of those mechanisms made it difficult and error prone in reality.++Specifically, previously developers could have used thread-local or queue-specific values to achieve some of these features, however the exact semantics of those made it difficult and error prone in reality. ++> The use of thread-locals in highly asynchronous libraries is generally frowned upon because it is so difficult to get right, and generally only adds to the confusion rather than helping one achieve transparent context propagation. +> +> This is why currently [Swift Distributed Tracing](https://github.com/apple/swift-distributed-tracing) had to revert to using explicit context passing, making asynchronous APIs even more verbose than they already are.+++Finally, those mechanisms are outright incompatible with asynchronous code that hops between execution contexts, which also includes Swift's async/await execution semantics which guarantee specific _executors_ or _actors_ to be used for execution, however never guarantees any specific queue or thread use at all.++> For discussion about alternative approaches to this problem please refer to [Prior Art](#prior-art) and [Alternatives Considered](#alternatives-considered).++## Proposed solution++### Task Local Values++Tasks already require the capability to "carry metadata with them," and that metadata used to implement both cancellation, deadlines as well as priority propagation for a `Task` and its child tasks. Specifically Task API's exhibiting similar behavior are: `Task.currentPriority()`, `Task.currentDeadline()` and `Task.isCancelled()`. Task local values do not directly use the same storage mechanism, as cancellation and priority is somewhat optimized because _all_ tasks carry them, but the semantics are the same.++We propose to expose the Task's internal ability to "carry metadata with it" via a Swift API, *aimed for library and instrumentation authors* such that they can participate in carrying additional information with Tasks, the same way as Tasks already do with priority and deadlines and other metadata.++Task local values may only be accessed from contexts that are running in a task: asynchronous functions. As such all operations, except declaring the task-local value's handle are asynchronous operations.++Declaring a task local value begins with declaring a `TaskLocalKey` that will be used to retrieve it from the task:++```swift+extension TaskLocalValues {+ + public struct RequestIDKey: TaskLocalKey {+ public static var defaultValue: String { "<no-request-id>" } + + // alternatively, one may declare a nil default value:+ // public static var defaultValue: String? { nil } + }+ public var requestID: RequestIDKey { .init() }+ +}+```++A task local key declaration nested under in the `TaskLocalValues` and consists of two things:++- a `TaskLocalKey` type declaration, where the `defaultValue`'s type is used to infer the type of the task local value+ - depending on the value, one might opt for declaring the type as `Optional` or not, for example if a good "empty" default value exists for the type+- a computed property `requestID` which returning the key - it is only used to lookup the key, and no set operation is necessary for it (unlike in SwiftUI's Environment model, due to differences in how the values are actually looked up). ++> This design may remind you of SwiftUI's `@Environment` concept, and indeed the shape of how values are declared is fairly similar. However, it differs tremendously in *where* the child/parent relationship is expressed. In a later section we'll make a more detailed comparison with SwiftUI.++Next, in order to access the value one has to `Task.local(_:)` it:++```swift+func asyncPrintRequestID() async {+ let id = Task.local(\.requestID)+ print("request-id: \(id)")+}++func syncPrintRequestID() async {
func syncPrintRequestID() {
yes thanks!
comment created time in 5 hours
Pull request review commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
struct TextEditor { } ``` +### Extending property wrappers to patterns++Property-wrapper backing-storage initialization in the the pattern of a closure argument was supported in first revision. Building on this syntax, the core team suggested the extension of property-wrapper application to places where patterns exist. Of course, the design has been amended so as to preserve the expectation that the backing storage be private; extending property wrappers to patterns, though, is still a viable future direction. ++Enabling the application of property wrappers where patterns are available is quite straightforward and could be introduced in as part of two separate features. The first could be to enable utility wrappers –– such as `@Asserted` –– in patterns. The second could be enabling projected-value initialization, which would facilitate intuitive and effortless access to property wrappers in native language constructs, as shown below:
It's pretty clear that this future direction would involve a lot of design work. I think trying to get into that design here is distracting, so I think we should simplify the section and just say that it was suggested as a design for closures, we chose not to go with that design because it makes more sense for closures to behave the same way as functions, but property wrappers in patterns is still something that could be pursued in the future
comment created time in 5 hours
pull request commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
@xAlien95 Yes, I rewrote a for-loop into this while-loop forgetting to add an iterator and "start" is a typo.
Thanks!
comment created time in 8 hours
Pull request review commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
struct TextEditor { } ``` +### Extending property wrappers to patterns++Property-wrapper backing-storage initialization in the the pattern of a closure argument was supported in first revision. Building on this syntax, the core team suggested the extension of property-wrapper application to places where patterns exist. Of course, the design has been amended so as to preserve the expectation that the backing storage be private; extending property wrappers to patterns, though, is still a viable future direction. ++Enabling the application of property wrappers where patterns are available is quite straightforward and could be introduced in as part of two separate features. The first could be to enable utility wrappers –– such as `@Asserted` –– in patterns. The second could be enabling projected-value initialization, which would facilitate intuitive and effortless access to property wrappers in native language constructs, as shown below:
Sorry for taking so long to reply!
What type is the user providing on the right side?
The user is providing the wrapped value's type; I'll clarify that.
Is this initializing a new property wrapper, or "binding" userRatings to the wrapped value of an existing property wrapper?
That's what I meant by two features: the first feature is initializing a new property wrapper that wraps a given value extracted by the pattern; the second is binding the wrapped declaration to an existing property wrapper.
I thought the goal of property wrappers in patterns was the latter.
I think it could be both; being able to apply a wrapper to a value extracted by a pattern (i.e. a value extracted by the pattern found in guard let
) would too be immensely useful. For instance, application of a wrapper to the entire –– "non-extracted" –– value is sometimes pointless (it does not make sense to apply @Lowercased
to a String?
-bound declaration).
Do you think the feature should be separated into two different future directions?
comment created time in 8 hours
created tagapple/swift-corelibs-libdispatch
The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware
created time in 11 hours
created tagapple/swift-corelibs-foundation
The Foundation Project, providing core utilities, internationalization, and OS independence
created time in 11 hours
created tagapple/swift-corelibs-xctest
The XCTest Project, A Swift core library for providing unit test support
created time in 11 hours
pull request commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
@lattner If you mean me, then yes, Wednesday works!
comment created time in 12 hours
pull request commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
@lattner Yes, that works for me. I'll make sure this is merged by Wednesday.
comment created time in 13 hours
Pull request review commentapple/swift-corelibs-foundation
internal extension JSONSerialization { return .utf8 } - static func parseBOM(_ bytes: UnsafePointer<UInt8>, length: Int) -> (encoding: String.Encoding, skipLength: Int)? {- if length >= 2 {- switch (bytes[0], bytes[1]) {- case (0xEF, 0xBB):- if length >= 3 && bytes[2] == 0xBF {- return (.utf8, 3)- }- case (0x00, 0x00):- if length >= 4 && bytes[2] == 0xFE && bytes[3] == 0xFF {- return (.utf32BigEndian, 4)- }- case (0xFF, 0xFE):- if length >= 4 && bytes[2] == 0 && bytes[3] == 0 {- return (.utf32LittleEndian, 4)- }- return (.utf16LittleEndian, 2)- case (0xFE, 0xFF):- return (.utf16BigEndian, 2)- default:- break+ static func parseBOM(_ bytes: UnsafeRawBufferPointer) -> (encoding: String.Encoding, skipLength: Int)? {+ guard bytes.count >= 2 else {
filed as https://bugs.swift.org/browse/SR-14102
comment created time in 14 hours
Pull request review commentapple/swift-evolution
[Concurrency] Task Local Values
A task local key declaration nested under in the `TaskLocalValues` and consists > This design may remind you of SwiftUI's `@Environment` concept, and indeed the shape of how values are declared is fairly similar. However, it differs tremendously in *where* the child/parent relationship is expressed. In a later section we'll make a more detailed comparison with SwiftUI. -Next, in order to access the value one has to `await Task.local(_:)` it:+Next, in order to access the value one has to `Task.local(_:)` it: ```swift-func printRequestID() async {- let id = await Task.local(\.requestID) ?? "<unknown>"+func asyncPrintRequestID() async {+ let id = Task.local(\.requestID) print("request-id: \(id)") }-``` -Since it is not known statically if the value will be present or not, the returned value is an `Optional<String>`.+func syncPrintRequestID() async {
Is this meant to be non-async
?
comment created time in 16 hours
push eventapple/swift-evolution
commit sha 5b72af9135317d9522057a12895efc2176d970bc
fix typo
push time in a day
push eventapple/swift-evolution
commit sha d3f19b3ed92e0bb00d9d8e7ce4764c1e11bec743
Add Acknowledgements section to proposal template (#1254)
push time in a day
PR merged apple/swift-evolution
@hborla recently added this section to SE-0293, and it seemed like it would be a good thing to prompt all contributors to think about over the course of their work on a proposal.
cc @hborla @airspeedswift
pr closed time in a day
pull request commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
Hey @hborla, Ted would like to kick off the second round of review for this proposal on Wednesday. Will that work for you, and will it be merged in by then?
comment created time in a day
pull request commentapple/swift-evolution
Add Acknowledgements section to proposal template
This LGTM, any concerns merging this @tkremenek or @DougGregor ?
comment created time in a day
created tagapple/swift-corelibs-libdispatch
The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware
created time in 2 days
created tagapple/swift-corelibs-foundation
The Foundation Project, providing core utilities, internationalization, and OS independence
created time in 2 days
created tagapple/swift-corelibs-xctest
The XCTest Project, A Swift core library for providing unit test support
created time in 2 days
pull request commentapple/swift-corelibs-foundation
[UserDefaults.swift] - Improved readability of some codes.
@swift-ci please test
comment created time in 2 days
Pull request review commentapple/swift-corelibs-foundation
[UserDefaults.swift] - Improved readability of some codes.
open class UserDefaults: NSObject { return true } - let isOfCommonTypes = value is String || value is Data || value is Date || value is Int || value is Bool || value is CGFloat+ let isOfCommonTypes = value is String || value is Data || value is Date || value is Int || value is Bool || value is CGFloat
I wanted to reconfigure such long lines of code as follows, but I want to ask first. Are you writing such long lines of code because of performance anxiety? Or is that how it was forgotten?
let isOfCommonTypes = value is String
|| value is Data
|| value is Date
|| value is Int
|| value is Bool
|| value is CGFloat
comment created time in 2 days
PR opened apple/swift-corelibs-foundation
Hello, everybody 🖐 My first time contributing to Apple open source projects. My goal is to make the UserDefaults class more readable. I've reconfigured some codes without breaking the logical fictions.
pr created time in 2 days
pull request commentapple/swift-corelibs-libdispatch
cmake: link BlocksRuntime only on non-Darwin
@swift-ci test
comment created time in 3 days
Pull request review commentapple/swift-evolution
[Proposal Revision] Extend property wrappers to functions and closure parameters.
struct TextEditor { } ``` +### Extending property wrappers to patterns++Property-wrapper backing-storage initialization in the the pattern of a closure argument was supported in first revision. Building on this syntax, the core team suggested the extension of property-wrapper application to places where patterns exist. Of course, the design has been amended so as to preserve the expectation that the backing storage be private; extending property wrappers to patterns, though, is still a viable future direction. ++Enabling the application of property wrappers where patterns are available is quite straightforward and could be introduced in as part of two separate features. The first could be to enable utility wrappers –– such as `@Asserted` –– in patterns. The second could be enabling projected-value initialization, which would facilitate intuitive and effortless access to property wrappers in native language constructs, as shown below:
I don't understand the "two separate features" approach. For this line of code:
let (@Traceable userRatings, ... ) = ...
What type is the user providing on the right side? Is this initializing a new property wrapper, or "binding" userRatings
to the wrapped value of an existing property wrapper? I thought the goal of property wrappers in patterns was the latter.
comment created time in 3 days
push eventapple/swift-evolution
commit sha a362a8d505344bc89458c9c218c3a4a9e2e74f69
SE-300: Remove unnecessary invariant
push time in 3 days
pull request commentapple/swift-evolution
Community feedback: Remove explicit cancellation
Thanks, Tony. I'm going to hold off on merging this right now because we generally don't want the proposal to change substantially in the middle of a review.
comment created time in 4 days
pull request commentapple/swift-corelibs-foundation
dont include objc when INCLUDE_OBJC not set
@swift-ci Please test macOS platform
comment created time in 4 days
pull request commentapple/swift-corelibs-foundation
dont include objc when INCLUDE_OBJC not set
@swift-ci test
comment created time in 4 days
pull request commentapple/swift-evolution
Community feedback: Remove explicit cancellation
+1, thanks Tony
comment created time in 4 days