profile
viewpoint
Tony Parker parkera Apple, Inc. Cupertino, CA

numist/Diffing 26

A proposal for adding diffing functionality to the Swift standard library

parkera/Thud 6

A graphical client for BTech MUX

parkera/swift-corelibs-foundation 1

The Foundation Project, providing core utilities, internationalization, and OS independence

parkera/swift 0

The Swift Programming Language

parkera/swift-corelibs-xctest 0

The XCTest Project, A Swift core library for providing unit test support

parkera/swift-evolution 0

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!

ktoso

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 &amp; 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!

ktoso

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

filip-sakel

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!

filip-sakel

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?

filip-sakel

comment created time in 8 hours

created tagapple/swift-corelibs-libdispatch

tagswift-5.4-DEVELOPMENT-SNAPSHOT-2021-01-23-a

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

created time in 11 hours

created tagapple/swift-corelibs-foundation

tagswift-5.4-DEVELOPMENT-SNAPSHOT-2021-01-23-a

The Foundation Project, providing core utilities, internationalization, and OS independence

created time in 11 hours

created tagapple/swift-corelibs-xctest

tagswift-5.4-DEVELOPMENT-SNAPSHOT-2021-01-23-a

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!

filip-sakel

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.

filip-sakel

comment created time in 13 hours

Pull request review commentapple/swift-corelibs-foundation

Parse JSON with value types

 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

fabianfett

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?

ktoso

comment created time in 16 hours

push eventapple/swift-evolution

Chris Lattner

commit sha 5b72af9135317d9522057a12895efc2176d970bc

fix typo

view details

push time in a day

push eventapple/swift-evolution

Frederick Kellison-Linn

commit sha d3f19b3ed92e0bb00d9d8e7ce4764c1e11bec743

Add Acknowledgements section to proposal template (#1254)

view details

push time in a day

PR merged apple/swift-evolution

Reviewers
Add Acknowledgements section to proposal template

@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

+6 -0

1 comment

1 changed file

Jumhyn

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?

filip-sakel

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 ?

Jumhyn

comment created time in a day

created tagapple/swift-corelibs-libdispatch

tagswift-DEVELOPMENT-SNAPSHOT-2021-01-23-a

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

created time in 2 days

created tagapple/swift-corelibs-foundation

tagswift-DEVELOPMENT-SNAPSHOT-2021-01-23-a

The Foundation Project, providing core utilities, internationalization, and OS independence

created time in 2 days

created tagapple/swift-corelibs-xctest

tagswift-DEVELOPMENT-SNAPSHOT-2021-01-23-a

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

mustafagunes

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
mustafagunes

comment created time in 2 days

PR opened apple/swift-corelibs-foundation

[UserDefaults.swift] - Improved readability of some codes.

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.

+68 -68

0 comment

1 changed file

pr created time in 2 days

pull request commentapple/swift-corelibs-libdispatch

cmake: link BlocksRuntime only on non-Darwin

@swift-ci test

holymonson

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.

filip-sakel

comment created time in 3 days

push eventapple/swift-evolution

Joe Groff

commit sha a362a8d505344bc89458c9c218c3a4a9e2e74f69

SE-300: Remove unnecessary invariant

view details

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.

parkera

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

holymonson

comment created time in 4 days

pull request commentapple/swift-corelibs-foundation

dont include objc when INCLUDE_OBJC not set

@swift-ci test

holymonson

comment created time in 4 days

pull request commentapple/swift-evolution

Community feedback: Remove explicit cancellation

+1, thanks Tony

parkera

comment created time in 4 days

more