From 368591a2b2620fd550a83688c725b504a614460c Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 9 Mar 2024 21:54:39 +0000 Subject: [PATCH 001/505] Initial draft of "A Vision for WebAssembly Support in Swift" --- visions/webassembly.md | 90 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 visions/webassembly.md diff --git a/visions/webassembly.md b/visions/webassembly.md new file mode 100644 index 0000000000..a53c2e1428 --- /dev/null +++ b/visions/webassembly.md @@ -0,0 +1,90 @@ +# A Vision for WebAssembly Support in Swift + +## Introduction + +WebAssembly (abbreviated [Wasm](https://webassembly.github.io/spec/core/intro/introduction.html#wasm)) is a virtual +machine instruction set focused on portability, security, and high performance. It is vendor-neutral, designed and +developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a +*WebAssembly runtime*, or [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). + +Despite its origins in the browser, it is a general-purpose technology that has use cases in client-side and +server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, +and also brings it to the browser where it previously wasn't available at all. + +### Portability + +An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. This is useful not +only for certain applications and libraries, but for the Swift toolchain itself. To quote +[a GSoC 2024 idea](https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly): + +> WebAssembly could provide a way to build Swift macros into binaries that can be distributed and run anywhere, +> eliminating the need to rebuild them continually. + +This can be applicable not only to Swift macros, but also SwiftPM manifests and plugins. + +### Security + +WebAssembly instruction set has useful properties from a security perspective, as it has +no interrupts or peripherals access instructions. Access to the underlying system is always done by calling a +explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly +runtime itself. The runtime has full control over interactions of the virtual machine with the outside world. + +WebAssembly code and data live in completely separate address spaces, with all executable code in a given module loaded +and validated by the runtime upfront. Combined with the lack of "jump to address" and a limited set of control flow +instructions that require explicit labels in the same function body, this makes a certain class of attacks impossible to +execute in a correctly implemented spec-compliant WebAssembly runtime. + +### Performance + +WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-interpreted or +compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm +specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can +generate native binary code that implements these features with little performance overhead. + +### 64-bit Support + +WebAssembly specifies support for both 32-bit and 64-bit integers and floats as a baseline. Currently, the most common +pointer size used by Wasm binaries is 32-bit. A large proportion of Wasm applications and libraries don't need to +address more than 4 GiB of memory. Support for 64-bit pointers was added to the WebAssembly spec and widely used +runtimes later as an extension. Wasm binaries utilizing certain pointer width are referred as supporting `wasm32` +and `wasm64` "architectures" respectively. + +### WebAssembly System Interface (WASI) + +WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 +don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating system, and +for a Wasm module it's provided by a runtime that executes it. + +A standardized set of APIs implemented by a Wasm runtime for interaction with the host +operating system is called [WebAssembly System Interface](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm +can already use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current +implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. + +### The WebAssembly Component Model + +Initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` used by its Wasm module name) was +inspired by C ABI and POSIX, and WASI libc itself is a fork of a portable [Musl libc](http://musl.libc.org) used on +Linux. This proved to be limiting with continued development of WASI, especially as it does not necessarily have to +be constrained by C ABI and POSIX, as it can abstract these away in more powerful runtime implementations. + +At the same time, W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type +system](https://github.com/webassembly/interface-types) and +[module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined +[Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on +[WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/preview2/README.md), which served as playground for +the new design. + +The Component Model defines these core concepts: + +- A *component* is a composable container for one or more WebAssembly modules that have a predefined interface; +- *WebAssembly Interface Types (WIT) language* allows defining contracts between components; +- *Canonical ABI* is an ABI for types defined by WIT and used by component interfaces in the Component Model. + +WIT is a high-level language with [an advanced type system](https://component-model.bytecodealliance.org/design/wit.html#built-in-types). It can be particularly interesting for Swift, as it allows significantly more Swift APIs to be exposed directly in interfaces of Wasm +components compiled from Swift. + +Preliminary support for WIT has been implemented in +[the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit +CLI. + +## Goals \ No newline at end of file From f0813d9b9890760855beffd97258c108ed7cbb9e Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 9 Mar 2024 21:55:16 +0000 Subject: [PATCH 002/505] Placeholder for "Goals" section --- visions/webassembly.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index a53c2e1428..704edf2ff2 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -87,4 +87,6 @@ Preliminary support for WIT has been implemented in [the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit CLI. -## Goals \ No newline at end of file +## Goals + +TBD From 4ceaf019d51628e136a6b25f3e759daf4674a7ce Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 9 Mar 2024 21:57:01 +0000 Subject: [PATCH 003/505] Fix line length --- visions/webassembly.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 704edf2ff2..147b3c8a64 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -52,13 +52,13 @@ and `wasm64` "architectures" respectively. ### WebAssembly System Interface (WASI) WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 -don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating system, and -for a Wasm module it's provided by a runtime that executes it. +don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating +system, and for a Wasm module it's provided by a runtime that executes it. -A standardized set of APIs implemented by a Wasm runtime for interaction with the host -operating system is called [WebAssembly System Interface](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm -can already use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current -implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. +A standardized set of APIs implemented by a Wasm runtime for interaction with the host operating system is called +[WebAssembly System Interface](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already +use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of +Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. ### The WebAssembly Component Model @@ -80,8 +80,10 @@ The Component Model defines these core concepts: - *WebAssembly Interface Types (WIT) language* allows defining contracts between components; - *Canonical ABI* is an ABI for types defined by WIT and used by component interfaces in the Component Model. -WIT is a high-level language with [an advanced type system](https://component-model.bytecodealliance.org/design/wit.html#built-in-types). It can be particularly interesting for Swift, as it allows significantly more Swift APIs to be exposed directly in interfaces of Wasm -components compiled from Swift. +WIT is a high-level language with +[an advanced type system](https://component-model.bytecodealliance.org/design/wit.html#built-in-types). It can be +particularly interesting for Swift, as it allows significantly more Swift APIs to be exposed directly in interfaces of +Wasm components compiled from Swift. Preliminary support for WIT has been implemented in [the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit From f3bd451a1d7337b855a53e264e956514deacbfa0 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 9 Mar 2024 22:20:46 +0000 Subject: [PATCH 004/505] Apply suggestions from code review --- visions/webassembly.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 147b3c8a64..68a19d592b 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -5,7 +5,7 @@ WebAssembly (abbreviated [Wasm](https://webassembly.github.io/spec/core/intro/introduction.html#wasm)) is a virtual machine instruction set focused on portability, security, and high performance. It is vendor-neutral, designed and developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a -*WebAssembly runtime*, or [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). +*WebAssembly runtime*, or an [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). Despite its origins in the browser, it is a general-purpose technology that has use cases in client-side and server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, @@ -36,7 +36,7 @@ execute in a correctly implemented spec-compliant WebAssembly runtime. ### Performance -WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-interpreted or +WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can generate native binary code that implements these features with little performance overhead. @@ -62,10 +62,10 @@ Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C lib ### The WebAssembly Component Model -Initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` used by its Wasm module name) was -inspired by C ABI and POSIX, and WASI libc itself is a fork of a portable [Musl libc](http://musl.libc.org) used on +Initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` by its module name) was +inspired by C ABI and POSIX, and WASI libc itself is a fork of [Musl libc](http://musl.libc.org) originally developed for Linux. This proved to be limiting with continued development of WASI, especially as it does not necessarily have to -be constrained by C ABI and POSIX, as it can abstract these away in more powerful runtime implementations. +be constrained by C ABI and POSIX. A more powerful runtime implementation can abstract these away. At the same time, W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type system](https://github.com/webassembly/interface-types) and From c51de074a2ba70c29c0e5fc2d1c99b913e078267 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 10:23:36 +0100 Subject: [PATCH 005/505] Restructure "Introduction", mention a few goals --- visions/webassembly.md | 59 ++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 68a19d592b..03a3e420e3 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -7,14 +7,14 @@ machine instruction set focused on portability, security, and high performance. developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a *WebAssembly runtime*, or an [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). -Despite its origins in the browser, it is a general-purpose technology that has use cases in client-side and +An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. Despite its origins +in the browser, it is a general-purpose technology that has use cases in client-side and server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, -and also brings it to the browser where it previously wasn't available at all. +and also brings it to the browser where it previously wasn't available at all. It facilitates a broader adoption of +Swift in more environments and contexts. -### Portability - -An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. This is useful not -only for certain applications and libraries, but for the Swift toolchain itself. To quote +We can't anticipate every possible application Swift developers are going to create with Wasm, but we can provide a few +examples of its possible adoption in the Swift toolchain itself. To quote [a GSoC 2024 idea](https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly): > WebAssembly could provide a way to build Swift macros into binaries that can be distributed and run anywhere, @@ -22,8 +22,6 @@ only for certain applications and libraries, but for the Swift toolchain itself. This can be applicable not only to Swift macros, but also SwiftPM manifests and plugins. -### Security - WebAssembly instruction set has useful properties from a security perspective, as it has no interrupts or peripherals access instructions. Access to the underlying system is always done by calling a explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly @@ -34,22 +32,21 @@ and validated by the runtime upfront. Combined with the lack of "jump to address instructions that require explicit labels in the same function body, this makes a certain class of attacks impossible to execute in a correctly implemented spec-compliant WebAssembly runtime. -### Performance +In the context of Swift developer tools, arbitrary code execution during build time can be more easily virtualized. +While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can also apply strong +security guarantees on other platforms that have a compatible Wasm runtime available. WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can -generate native binary code that implements these features with little performance overhead. +generate a restricted subset of native binary code that implements these features with little performance overhead. -### 64-bit Support +This means that adoption of Wasm in developer tools does not imply unavoidable performance overhead. In fact, with +security guarantees that virtualization brings there's no longer a need to spawn a separate process for each +Swift compiler and SwiftPM plugin/manifest invocation. Virtualized Wasm binaries can run in the host process of a +Wasm runtime, removing the overhead of new process setup and IPC infrastructure. -WebAssembly specifies support for both 32-bit and 64-bit integers and floats as a baseline. Currently, the most common -pointer size used by Wasm binaries is 32-bit. A large proportion of Wasm applications and libraries don't need to -address more than 4 GiB of memory. Support for 64-bit pointers was added to the WebAssembly spec and widely used -runtimes later as an extension. Wasm binaries utilizing certain pointer width are referred as supporting `wasm32` -and `wasm64` "architectures" respectively. - -### WebAssembly System Interface (WASI) +### WebAssembly System Interface and the Component Model WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating @@ -60,8 +57,6 @@ A standardized set of APIs implemented by a Wasm runtime for interaction with th use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. -### The WebAssembly Component Model - Initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` by its module name) was inspired by C ABI and POSIX, and WASI libc itself is a fork of [Musl libc](http://musl.libc.org) originally developed for Linux. This proved to be limiting with continued development of WASI, especially as it does not necessarily have to @@ -87,8 +82,28 @@ Wasm components compiled from Swift. Preliminary support for WIT has been implemented in [the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit -CLI. +CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from `.wit` +files. ## Goals -TBD +As of March 2024 all patches necessary for basic Wasm and WASI support have been merged to the Swift toolchain and +core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift +ecosystem: + +1. Ensure that Swift toolchain and core libraries have a regularly running test suite for supported Wasm and WASI +triples. + +2. Allow Swift developers to easily install and build with a Swift SDK for WASI. This requires an implementation +of corresponding build scripts and CI jobs to generate and publish such SDK. Some parts of Swift toolchain and core +libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support +for this platform. + +3. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, +multi-threading, file system access, and localization need special support in Wasm runtimes and certain amount of +consideration from a developer adopting these APIs. We should focus on simplifying the adoption and increasing +API coverage for these features in Swift core libraries. + +4. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall +management of Swift SDKs for cross-compilation in general, which is beneficial not only foe WebAssembly, but for all +platforms. From 1a427daae34beac8debe51eb8bf1b3bbce22deb1 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 10:49:29 +0100 Subject: [PATCH 006/505] Wording cleanup, add Wasm Component Model goal --- visions/webassembly.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 03a3e420e3..4b74cc81d5 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -23,7 +23,7 @@ examples of its possible adoption in the Swift toolchain itself. To quote This can be applicable not only to Swift macros, but also SwiftPM manifests and plugins. WebAssembly instruction set has useful properties from a security perspective, as it has -no interrupts or peripherals access instructions. Access to the underlying system is always done by calling a +no interrupts or peripherals access instructions. Access to the underlying system is always done by calling an explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly runtime itself. The runtime has full control over interactions of the virtual machine with the outside world. @@ -32,8 +32,8 @@ and validated by the runtime upfront. Combined with the lack of "jump to address instructions that require explicit labels in the same function body, this makes a certain class of attacks impossible to execute in a correctly implemented spec-compliant WebAssembly runtime. -In the context of Swift developer tools, arbitrary code execution during build time can be more easily virtualized. -While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can also apply strong +In the context of Swift developer tools, arbitrary code execution during build time can be virtualized with Wasm. +While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can provide stronger security guarantees on other platforms that have a compatible Wasm runtime available. WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or @@ -99,11 +99,16 @@ of corresponding build scripts and CI jobs to generate and publish such SDK. Som libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support for this platform. -3. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, +3. Make to easier to evaluate and adopt Wasm with increased API coverage for this platform in Swift core libraries. As a +virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, and localization need special support in Wasm runtimes and certain amount of -consideration from a developer adopting these APIs. We should focus on simplifying the adoption and increasing -API coverage for these features in Swift core libraries. +consideration from a developer adopting these APIs. 4. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall management of Swift SDKs for cross-compilation in general, which is beneficial not only foe WebAssembly, but for all platforms. + +5. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure +that future versions of WASI are available to Swift developers targeting Wasm. A more ambitious long-term goal to +consider is making interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With +a formal specification for Canonical ABI progressing, this goal will become more achievable with time. From 9e07dd276929f327b7625a4aec541a9e03ba7249 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 11:40:58 +0100 Subject: [PATCH 007/505] Add "Proposed Language Features" section --- visions/webassembly.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/visions/webassembly.md b/visions/webassembly.md index 4b74cc81d5..a5bbef8693 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -112,3 +112,24 @@ platforms. that future versions of WASI are available to Swift developers targeting Wasm. A more ambitious long-term goal to consider is making interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal specification for Canonical ABI progressing, this goal will become more achievable with time. + +### Proposed Language Features + +In our work on Wasm support in Swift we experimented with a few function attributes that could be considered +as pitches and eventually Swift Evolution proposals, if the community is interested in their wider adoption. +These attributes allow easier interoperation between Swift code and other Wasm modules linked with it by a Wasm +runtime. + +* [`@_extern(wasm)` attribute](https://github.com/apple/swift/pull/69107) that corresponds to Clang's +[`__attribute__((import_name("declaration_name")))`](https://clang.llvm.org/docs/AttributeReference.html#export-name) +and [`__attribute__((import_module("module_name")))`](https://clang.llvm.org/docs/AttributeReference.html#import-module). +This indicates that function's implementation is not provided together with its declaration in Swift and is +available externally, imported by a Wasm runtime during the linking phase. The declaration is added to current Wasm +module's imports section. Without `@_extern(wasm)` developers need to rely on C interop to create a declaration in a C +header using the Clang version of attributes. + +* [`@_expose_(wasm)` attribute](https://github.com/apple/swift/pull/68524) that corresponds to Clang's +[`__attribute__((export_name("name")))`](https://clang.llvm.org/docs/AttributeReference.html#export-name), which +is the counterpart of `@_extern(wasm)` working in the opposite direction. This explicitly makes a Swift declaration +available outside of the current module, added to its exports section under a given name. Again, the lack of +this attribute in Swift requires use of C headers as a workaround. From bd1b5c6e69f45690fccb83ba87893e6611fdd7dc Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 12:39:49 +0100 Subject: [PATCH 008/505] Update webassembly.md Co-authored-by: Yuta Saito --- visions/webassembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index a5bbef8693..e1d55f7406 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -128,7 +128,7 @@ available externally, imported by a Wasm runtime during the linking phase. The d module's imports section. Without `@_extern(wasm)` developers need to rely on C interop to create a declaration in a C header using the Clang version of attributes. -* [`@_expose_(wasm)` attribute](https://github.com/apple/swift/pull/68524) that corresponds to Clang's +* [`@_expose(wasm)` attribute](https://github.com/apple/swift/pull/68524) that corresponds to Clang's [`__attribute__((export_name("name")))`](https://clang.llvm.org/docs/AttributeReference.html#export-name), which is the counterpart of `@_extern(wasm)` working in the opposite direction. This explicitly makes a Swift declaration available outside of the current module, added to its exports section under a given name. Again, the lack of From 699af86284f917b00b9a2553c968b2d169d581c6 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 17:27:34 +0100 Subject: [PATCH 009/505] Apply suggestions from code review Co-authored-by: Ben Barham --- visions/webassembly.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index e1d55f7406..ba0a5e51e0 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -57,7 +57,7 @@ A standardized set of APIs implemented by a Wasm runtime for interaction with th use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. -Initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` by its module name) was +The initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` by its module name) was inspired by C ABI and POSIX, and WASI libc itself is a fork of [Musl libc](http://musl.libc.org) originally developed for Linux. This proved to be limiting with continued development of WASI, especially as it does not necessarily have to be constrained by C ABI and POSIX. A more powerful runtime implementation can abstract these away. @@ -99,13 +99,13 @@ of corresponding build scripts and CI jobs to generate and publish such SDK. Som libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support for this platform. -3. Make to easier to evaluate and adopt Wasm with increased API coverage for this platform in Swift core libraries. As a +3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in Swift core libraries. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, and localization need special support in Wasm runtimes and certain amount of consideration from a developer adopting these APIs. 4. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall -management of Swift SDKs for cross-compilation in general, which is beneficial not only foe WebAssembly, but for all +management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all platforms. 5. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure From 8e48421f5949e9c5d6276918882b8dd7cc483a4f Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 17:55:52 +0100 Subject: [PATCH 010/505] Address PR feedback --- visions/webassembly.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index ba0a5e51e0..3a1359f7a3 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -57,11 +57,6 @@ A standardized set of APIs implemented by a Wasm runtime for interaction with th use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. -The initial version of WASI (referred to as "Preview 1" or as `wasi_snapshot_preview1` by its module name) was -inspired by C ABI and POSIX, and WASI libc itself is a fork of [Musl libc](http://musl.libc.org) originally developed for -Linux. This proved to be limiting with continued development of WASI, especially as it does not necessarily have to -be constrained by C ABI and POSIX. A more powerful runtime implementation can abstract these away. - At the same time, W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined @@ -75,11 +70,6 @@ The Component Model defines these core concepts: - *WebAssembly Interface Types (WIT) language* allows defining contracts between components; - *Canonical ABI* is an ABI for types defined by WIT and used by component interfaces in the Component Model. -WIT is a high-level language with -[an advanced type system](https://component-model.bytecodealliance.org/design/wit.html#built-in-types). It can be -particularly interesting for Swift, as it allows significantly more Swift APIs to be exposed directly in interfaces of -Wasm components compiled from Swift. - Preliminary support for WIT has been implemented in [the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from `.wit` @@ -108,7 +98,9 @@ consideration from a developer adopting these APIs. management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all platforms. -5. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure +5. Explore and prototype virtualization of SwiftPM manifests/plugins and Swift macros with Wasm. + +6. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure that future versions of WASI are available to Swift developers targeting Wasm. A more ambitious long-term goal to consider is making interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal specification for Canonical ABI progressing, this goal will become more achievable with time. From edb2c31dc1f3d9cf1249205a789b05fcd8d3eb6c Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 22:07:15 +0100 Subject: [PATCH 011/505] Apply suggestions from code review Co-authored-by: Alex Hoppen --- visions/webassembly.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 3a1359f7a3..b3adef9e6c 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -20,7 +20,7 @@ examples of its possible adoption in the Swift toolchain itself. To quote > WebAssembly could provide a way to build Swift macros into binaries that can be distributed and run anywhere, > eliminating the need to rebuild them continually. -This can be applicable not only to Swift macros, but also SwiftPM manifests and plugins. +This can be applicable not only to Swift macros, but also for the evaluation of SwiftPM manifests and plugins. WebAssembly instruction set has useful properties from a security perspective, as it has no interrupts or peripherals access instructions. Access to the underlying system is always done by calling an @@ -36,7 +36,7 @@ In the context of Swift developer tools, arbitrary code execution during build t While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can provide stronger security guarantees on other platforms that have a compatible Wasm runtime available. -WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or +The WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can generate a restricted subset of native binary code that implements these features with little performance overhead. @@ -53,11 +53,11 @@ don't "support" those directly either. Actual implementation of I/O for a hardwa system, and for a Wasm module it's provided by a runtime that executes it. A standardized set of APIs implemented by a Wasm runtime for interaction with the host operating system is called -[WebAssembly System Interface](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already +[WebAssembly System Interface (WASI)](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. -At the same time, W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type +At the same time, the W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined [Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on From 387b8fd627a8c2de3f7173be71931fd1e450084e Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 14 Mar 2024 22:07:43 +0100 Subject: [PATCH 012/505] Apply suggestions from code review Co-authored-by: Alex Hoppen --- visions/webassembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index b3adef9e6c..e9c3dd4d37 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -48,7 +48,7 @@ Wasm runtime, removing the overhead of new process setup and IPC infrastructure. ### WebAssembly System Interface and the Component Model -WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 +The WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating system, and for a Wasm module it's provided by a runtime that executes it. From ae72732eed45bda5aa9684253d1d433732ca1078 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 15 Mar 2024 10:31:15 +0100 Subject: [PATCH 013/505] Apply suggestions from code review Co-authored-by: Hamish Knight --- visions/webassembly.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index e9c3dd4d37..b042f26bd2 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -22,8 +22,8 @@ examples of its possible adoption in the Swift toolchain itself. To quote This can be applicable not only to Swift macros, but also for the evaluation of SwiftPM manifests and plugins. -WebAssembly instruction set has useful properties from a security perspective, as it has -no interrupts or peripherals access instructions. Access to the underlying system is always done by calling an +The WebAssembly instruction set has useful properties from a security perspective, as it has +no interrupts or peripheral access instructions. Access to the underlying system is always done by calling explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly runtime itself. The runtime has full control over interactions of the virtual machine with the outside world. @@ -85,13 +85,13 @@ ecosystem: triples. 2. Allow Swift developers to easily install and build with a Swift SDK for WASI. This requires an implementation -of corresponding build scripts and CI jobs to generate and publish such SDK. Some parts of Swift toolchain and core +of corresponding build scripts and CI jobs to generate and publish such SDK. Some parts of the Swift toolchain and core libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support for this platform. 3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in Swift core libraries. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, -multi-threading, file system access, and localization need special support in Wasm runtimes and certain amount of +multi-threading, file system access, and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. 4. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall From e177c67d0b00f5931ff29861e8f5d2ccef9965f4 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 15 Mar 2024 10:42:04 +0100 Subject: [PATCH 014/505] Define WasmKit in the introduction section --- visions/webassembly.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/visions/webassembly.md b/visions/webassembly.md index b042f26bd2..03f94cd292 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -7,6 +7,9 @@ machine instruction set focused on portability, security, and high performance. developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a *WebAssembly runtime*, or an [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). +One prominent spec-compliant implementation of a Wasm runtime in Swift is [WasmKit](https://github.com/swiftwasm/WasmKit). It is available as a Swift package, supports multiple +host platforms, and has a simple API for interaction with guest Wasm modules. + An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. Despite its origins in the browser, it is a general-purpose technology that has use cases in client-side and server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, From 9f4fddfd6614fb3305c77072bb9c3559a520eaae Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 18 Mar 2024 17:42:37 +0000 Subject: [PATCH 015/505] Update webassembly.md --- visions/webassembly.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 03f94cd292..da4dea6d77 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -58,10 +58,11 @@ system, and for a Wasm module it's provided by a runtime that executes it. A standardized set of APIs implemented by a Wasm runtime for interaction with the host operating system is called [WebAssembly System Interface (WASI)](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of -Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. +Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. It is important for WASI support in +Swift to be as complete as possible to ensure portability of Swift code in the broader Wasm ecosystem. -At the same time, the W3C WebAssembly Working Group was considering multiple proposals for improving the WebAssembly [type -system](https://github.com/webassembly/interface-types) and +In the last few years, W3C WebAssembly Working Group considered multiple proposals for improving the WebAssembly +[type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined [Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on [WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/preview2/README.md), which served as playground for @@ -101,9 +102,7 @@ consideration from a developer adopting these APIs. management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all platforms. -5. Explore and prototype virtualization of SwiftPM manifests/plugins and Swift macros with Wasm. - -6. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure +5. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure that future versions of WASI are available to Swift developers targeting Wasm. A more ambitious long-term goal to consider is making interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal specification for Canonical ABI progressing, this goal will become more achievable with time. From 51e5d1b2333feda5579b64a8818850c1bad88cdd Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 18 Mar 2024 17:54:48 +0000 Subject: [PATCH 016/505] Update visions/webassembly.md --- visions/webassembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index da4dea6d77..4cd3fe9306 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -93,7 +93,7 @@ of corresponding build scripts and CI jobs to generate and publish such SDK. Som libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support for this platform. -3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in Swift core libraries. As a +3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. From f1195a6a28d8e025e7e0fb249fe6bd995c293715 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 26 Mar 2024 15:41:42 +0000 Subject: [PATCH 017/505] Apply suggestions from code review Co-authored-by: Alastair Houghton --- visions/webassembly.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 4cd3fe9306..d1b406c071 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -5,7 +5,7 @@ WebAssembly (abbreviated [Wasm](https://webassembly.github.io/spec/core/intro/introduction.html#wasm)) is a virtual machine instruction set focused on portability, security, and high performance. It is vendor-neutral, designed and developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a -*WebAssembly runtime*, or an [*embedder*](https://webassembly.github.io/spec/core/intro/overview.html#embedder). +*WebAssembly runtime*. One prominent spec-compliant implementation of a Wasm runtime in Swift is [WasmKit](https://github.com/swiftwasm/WasmKit). It is available as a Swift package, supports multiple host platforms, and has a simple API for interaction with guest Wasm modules. @@ -51,9 +51,7 @@ Wasm runtime, removing the overhead of new process setup and IPC infrastructure. ### WebAssembly System Interface and the Component Model -The WebAssembly instruction set on its own doesn't "support" file I/O or networking, in the same way that ARM64 or x86_64 -don't "support" those directly either. Actual implementation of I/O for a hardware CPU is provided by the operating -system, and for a Wasm module it's provided by a runtime that executes it. +The WebAssembly virtual machine has no in-built support for I/O; instead, a Wasm module's access to I/O is dependent entirely upon the runtime that executes it. A standardized set of APIs implemented by a Wasm runtime for interaction with the host operating system is called [WebAssembly System Interface (WASI)](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already @@ -61,7 +59,7 @@ use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc) Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. It is important for WASI support in Swift to be as complete as possible to ensure portability of Swift code in the broader Wasm ecosystem. -In the last few years, W3C WebAssembly Working Group considered multiple proposals for improving the WebAssembly +In the last few years, the W3C WebAssembly Working Group considered multiple proposals for improving the WebAssembly [type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined [Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on @@ -75,7 +73,7 @@ The Component Model defines these core concepts: - *Canonical ABI* is an ABI for types defined by WIT and used by component interfaces in the Component Model. Preliminary support for WIT has been implemented in -[the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of WasmKit +[the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of the WasmKit CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from `.wit` files. From b665179a3c02569648dd5d0b00a738060a55ffd0 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 15 Oct 2024 18:12:16 +0100 Subject: [PATCH 018/505] Incorporate recent vision feedback --- visions/webassembly.md | 82 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index d1b406c071..c1ba36f46c 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -2,7 +2,7 @@ ## Introduction -WebAssembly (abbreviated [Wasm](https://webassembly.github.io/spec/core/intro/introduction.html#wasm)) is a virtual +WebAssembly (abbreviated [Wasm](https://webassembly.github.io/spec/core/intro/introduction.html#wasm)) is a virtual machine instruction set focused on portability, security, and high performance. It is vendor-neutral, designed and developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a *WebAssembly runtime*. @@ -125,3 +125,83 @@ header using the Clang version of attributes. is the counterpart of `@_extern(wasm)` working in the opposite direction. This explicitly makes a Swift declaration available outside of the current module, added to its exports section under a given name. Again, the lack of this attribute in Swift requires use of C headers as a workaround. + +## Platform-specific Considerations + +### Debugging + +Debugging Wasm modules is challenging because Wasm does not expose ways to introspect and control the execution of +the Wasm instance, so a debugger cannot be built on top of Wasm itself. Therefore, special support from the Wasm +execution engine is necessary for debugging. + +The current state of debugging tools in the Wasm ecosystem is not as mature as other platforms but there are two +main directions: + +1. LLDB debugger with Wasm runtime supporting GDB Remote Serial Protocol [1] +2. Wasm runtime with a built-in debugger [2] + +The first approach provides an almost equivalent experience to existing debugging workflows on other platforms. It +can utilize LLDB's Swift support, remote metadata inspection and serialized Swift module information. However, since +Wasm is a Harvard architecture and has no way to allocate executable memory space at runtime, implementing expression +evaluation with JIT in user space is challenging. In other words, gdb stub in Wasm engines need tricky implementations +or need to extend the GDB Remote Serial Protocol. + +The second approach embeds the debugger within the Wasm engine. In scenarios where the Wasm engine is embedded as a guest +language in another host language engine (e.g. within a Web Browser), this approach allows seamless debugging experiences +with the host language by integrating with the host debugger. For example, in cases where JavaScript and Wasm call frames +are interleaved, the debugger works well in both contexts without switching tools. Debugging tools like Chrome DevTools +can use DWARF information embedded in Wasm file to provide debugging support. However, supporting Swift-specific +metadata information and JIT-based expression evaluation will require integrating LLDB's Swift plugin with these debuggers +in some way. + +Given that both approaches can utilize DWARF information, the Swift toolchain should generate as much DWARF information as possible +for statically known things. Also, making Swift type information DWARF-friendly is desirable because the current debug +information generated by the Swift compiler assumes that debuggers can understand certain Swift primitives (e.g. `Swift.Int` +is currently represented as a `DW_TAG_structure_type` node without any member but ideally such types should be represented +as `DW_TAG_base_type` nodes with `DW_AT_encoding` attribute or provide a debug summary string by LLDB Summary Strings) + +[1]: https://github.com/llvm/llvm-project/pull/77949 +[2]: https://github.com/ChromeDevTools/devtools-frontend/blob/main/extensions/cxx_debugging + +### Multi-threading and Concurrency + +WebAssembly has [atomic operations in the instruction set](https://github.com/WebAssembly/threads) (only sequential +consistency is supported), but it does not have a built-in way to create threads. Instead, it relies on the host +environment to provide multi-threading support. This means that multi-threading in Wasm is dependent on the Wasm runtime +that executes the module. There are two proposals to standardize ways to create threads in Wasm: (1) [wasi-threads](https://github.com/WebAssembly/wasi-threads), +which is already supported by some toolchains, runtimes, and libraries but has been superseded by the new one. (2) The +new proposal [shared-everything-threads](https://github.com/WebAssembly/shared-everything-threads) is still in the +early stages of spec development but is expected to be the future of multi-threading in Wasm. + +Swift currently supports two threading models in Wasm: single-threaded (`wasm32-unknown-wasi`) and multi-threaded +using wasi-threads (`wasm32-unknown-wasip1-threads`). Despite the latter supporting multi-threading, Swift Concurrency defaults +to a cooperative single-threaded executor due to the lack of wasi-threads support in libdispatch. Preparing for the +shared-everything-threads proposal is crucial to ensure that Swift Concurrency can adapt to future multi-threading +standards in Wasm. + +### 64-bit address space + +WebAssembly currently uses a 32-bit address space, but the specification is going to support [64-bit address space](https://github.com/WebAssembly/memory64/). +Swift already has support on 64-bit for other platforms, however, WebAssembly is the first platform where relative reference +from data to code is not allowed. Alternative solutions like image-base relative addressing or small "code model" for fitting +64-bit pointer in 32-bit are unavailable, at least for now. This means that we need cooperation from the WebAssembly toolchain +side or different memory layout in Swift metadata to support 64-bit in WebAssembly. + +### Shared libraries + +There are two approaches to using shared libraries in WebAssembly ecosystem: + +1. [Emscripten-style dynamic linking](https://emscripten.org/docs/compiling/Dynamic-Linking.html) +2. [Component Model-based "ahead-of-time" linking](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Linking.md) +Emscripten-style dynamic linking is a traditional way to use shared libraries in WebAssembly, where the host environment provides +non-standard dynamic loading capabilities. + +Component Model-based AOT linking is a new way that transforms shared library WebAssembly Core modules compiled with +Emscripten's dynamic linking ABI into a single WebAssembly Component at build time. The latter approach cannot fully replace the former, +as it is not able to handle dynamic loading of shared libraries at runtime, but it is more portable way to distribute programs linked +with shared libraries because it does not require the host environment to provide any special capabilities except for Component Model +support. + +From the Swift toolchain perspective, they both use the Emscripten's dynamic linking ABI, so the support for shared libraries in +Swift is mostly about making sure that Swift programs can be compiled in position-independent code mode and linked with shared +libraries by following the dynamic linking ABI. From 67909f0dec64a7c84c70be65fff7db20aae6290c Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 16 Oct 2024 11:41:04 +0100 Subject: [PATCH 019/505] Clean up wording and formatting --- visions/webassembly.md | 64 ++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index c1ba36f46c..eee743e3a6 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -7,14 +7,15 @@ machine instruction set focused on portability, security, and high performance. developed by [W3C](https://w3.org). An implementation of a WebAssembly virtual machine is usually called a *WebAssembly runtime*. -One prominent spec-compliant implementation of a Wasm runtime in Swift is [WasmKit](https://github.com/swiftwasm/WasmKit). It is available as a Swift package, supports multiple -host platforms, and has a simple API for interaction with guest Wasm modules. +One prominent spec-compliant implementation of a Wasm runtime in Swift is [WasmKit](https://github.com/swiftwasm/WasmKit). +It is available as a Swift package, supports multiple host platforms, and has a simple API for interaction with guest +Wasm modules. An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. Despite its origins -in the browser, it is a general-purpose technology that has use cases in client-side and -server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, -and also brings it to the browser where it previously wasn't available at all. It facilitates a broader adoption of -Swift in more environments and contexts. +in the browser, it is a general-purpose technology that has use cases in client-side and server-side applications and +services. WebAssembly support in Swift makes the language more appealing in those settings, and also brings it to the +browser where it previously wasn't available at all. It facilitates a broader adoption of Swift in more environments +and contexts. We can't anticipate every possible application Swift developers are going to create with Wasm, but we can provide a few examples of its possible adoption in the Swift toolchain itself. To quote @@ -25,10 +26,10 @@ examples of its possible adoption in the Swift toolchain itself. To quote This can be applicable not only to Swift macros, but also for the evaluation of SwiftPM manifests and plugins. -The WebAssembly instruction set has useful properties from a security perspective, as it has -no interrupts or peripheral access instructions. Access to the underlying system is always done by calling -explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly -runtime itself. The runtime has full control over interactions of the virtual machine with the outside world. +The WebAssembly instruction set has useful properties from a security perspective, as it has no interrupts or +peripheral access instructions. Access to the underlying system is always done by calling explicitly imported +functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly runtime itself. +The runtime has full control over interactions of the virtual machine with the outside world. WebAssembly code and data live in completely separate address spaces, with all executable code in a given module loaded and validated by the runtime upfront. Combined with the lack of "jump to address" and a limited set of control flow @@ -44,20 +45,21 @@ compiled on a client machine to an optimized native binary ahead of time. With r specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can generate a restricted subset of native binary code that implements these features with little performance overhead. -This means that adoption of Wasm in developer tools does not imply unavoidable performance overhead. In fact, with -security guarantees that virtualization brings there's no longer a need to spawn a separate process for each -Swift compiler and SwiftPM plugin/manifest invocation. Virtualized Wasm binaries can run in the host process of a -Wasm runtime, removing the overhead of new process setup and IPC infrastructure. +Adoption of Wasm in developer tools does not imply unavoidable performance overhead. With security guarantees that +virtualization brings, there's no longer a need to spawn a separate process for each Swift compiler and SwiftPM +plugin/manifest invocation. Virtualized Wasm binaries can run in the host process of a Wasm runtime, removing the +overhead of new process setup and IPC infrastructure. ### WebAssembly System Interface and the Component Model -The WebAssembly virtual machine has no in-built support for I/O; instead, a Wasm module's access to I/O is dependent entirely upon the runtime that executes it. +The WebAssembly virtual machine has no in-built support for I/O; instead, a Wasm module's access to I/O is dependent +entirely upon the runtime that executes it. A standardized set of APIs implemented by a Wasm runtime for interaction with the host operating system is called -[WebAssembly System Interface (WASI)](https://wasi.dev). A layer on top of WASI that Swift apps compiled to Wasm can already -use thanks to C interop is [WASI libc](https://github.com/WebAssembly/wasi-libc). In fact, the current implementation of -Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. It is important for WASI support in -Swift to be as complete as possible to ensure portability of Swift code in the broader Wasm ecosystem. +[WebAssembly System Interface (WASI)](https://wasi.dev). [WASI libc](https://github.com/WebAssembly/wasi-libc) is a +layer on top of WASI that Swift apps compiled to Wasm can already use thanks to C interop. The current implementation +of Swift stdlib and runtime for `wasm32-unknown-wasi` triple is based on this C library. It is important for WASI +support in Swift to be as complete as possible to ensure portability of Swift code in the broader Wasm ecosystem. In the last few years, the W3C WebAssembly Working Group considered multiple proposals for improving the WebAssembly [type system](https://github.com/webassembly/interface-types) and @@ -73,9 +75,9 @@ The Component Model defines these core concepts: - *Canonical ABI* is an ABI for types defined by WIT and used by component interfaces in the Component Model. Preliminary support for WIT has been implemented in -[the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of the WasmKit -CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from `.wit` -files. +[the `wit-tool` subcommand](https://github.com/swiftwasm/WasmKit/blob/0.0.3/Sources/WITTool/WITTool.swift) of the +WasmKit CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from +`.wit` files. ## Goals @@ -87,12 +89,12 @@ ecosystem: triples. 2. Allow Swift developers to easily install and build with a Swift SDK for WASI. This requires an implementation -of corresponding build scripts and CI jobs to generate and publish such SDK. Some parts of the Swift toolchain and core -libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing support -for this platform. +of corresponding build scripts and CI jobs to generate and publish the Swift SDK. Some parts of the Swift toolchain and +core libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing +support for this platform. -3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. As a -virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, +3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. +As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. @@ -107,7 +109,7 @@ a formal specification for Canonical ABI progressing, this goal will become more ### Proposed Language Features -In our work on Wasm support in Swift we experimented with a few function attributes that could be considered +In our work on Wasm support in Swift, we experimented with a few function attributes that could be considered as pitches and eventually Swift Evolution proposals, if the community is interested in their wider adoption. These attributes allow easier interoperation between Swift code and other Wasm modules linked with it by a Wasm runtime. @@ -131,10 +133,10 @@ this attribute in Swift requires use of C headers as a workaround. ### Debugging Debugging Wasm modules is challenging because Wasm does not expose ways to introspect and control the execution of -the Wasm instance, so a debugger cannot be built on top of Wasm itself. Therefore, special support from the Wasm -execution engine is necessary for debugging. +a Wasm module instance, so a debugger cannot be built on top of Wasm itself. Special support from the Wasm execution +engine is necessary for debugging. -The current state of debugging tools in the Wasm ecosystem is not as mature as other platforms but there are two +The current state of debugging tools in the Wasm ecosystem is not as mature as other platforms, but there are two main directions: 1. LLDB debugger with Wasm runtime supporting GDB Remote Serial Protocol [1] From a88c667196d4ea390d0ecfb71963a55a5c8a5d12 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 16 Oct 2024 12:37:10 +0100 Subject: [PATCH 020/505] Address feedback --- visions/webassembly.md | 163 +++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 88 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index eee743e3a6..c46c3d7a54 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -17,15 +17,6 @@ services. WebAssembly support in Swift makes the language more appealing in thos browser where it previously wasn't available at all. It facilitates a broader adoption of Swift in more environments and contexts. -We can't anticipate every possible application Swift developers are going to create with Wasm, but we can provide a few -examples of its possible adoption in the Swift toolchain itself. To quote -[a GSoC 2024 idea](https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly): - -> WebAssembly could provide a way to build Swift macros into binaries that can be distributed and run anywhere, -> eliminating the need to rebuild them continually. - -This can be applicable not only to Swift macros, but also for the evaluation of SwiftPM manifests and plugins. - The WebAssembly instruction set has useful properties from a security perspective, as it has no interrupts or peripheral access instructions. Access to the underlying system is always done by calling explicitly imported functions, implementations for which are provided by an imported WebAssembly module or a WebAssembly runtime itself. @@ -36,20 +27,6 @@ and validated by the runtime upfront. Combined with the lack of "jump to address instructions that require explicit labels in the same function body, this makes a certain class of attacks impossible to execute in a correctly implemented spec-compliant WebAssembly runtime. -In the context of Swift developer tools, arbitrary code execution during build time can be virtualized with Wasm. -While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can provide stronger -security guarantees on other platforms that have a compatible Wasm runtime available. - -The WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or -compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm -specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can -generate a restricted subset of native binary code that implements these features with little performance overhead. - -Adoption of Wasm in developer tools does not imply unavoidable performance overhead. With security guarantees that -virtualization brings, there's no longer a need to spawn a separate process for each Swift compiler and SwiftPM -plugin/manifest invocation. Virtualized Wasm binaries can run in the host process of a Wasm runtime, removing the -overhead of new process setup and IPC infrastructure. - ### WebAssembly System Interface and the Component Model The WebAssembly virtual machine has no in-built support for I/O; instead, a Wasm module's access to I/O is dependent @@ -79,33 +56,51 @@ Preliminary support for WIT has been implemented in WasmKit CLI. Users of this tool can generate `.wit` files from Swift declarations, and vice versa: Swift bindings from `.wit` files. +## Use Cases + +We can't anticipate every possible application Swift developers are going to create with Wasm, but we can provide a few +examples of its possible adoption in the Swift toolchain itself. To quote +[a GSoC 2024 idea](https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly): + +> WebAssembly could provide a way to build Swift macros into binaries that can be distributed and run anywhere, +> eliminating the need to rebuild them continually. + +This can be applicable not only to Swift macros, but also for the evaluation of SwiftPM manifests and plugins. + +In the context of Swift developer tools, arbitrary code execution during build time can be virtualized with Wasm. +While Swift macros, SwiftPM manifests, and plugins are sandboxed on Darwin platforms, with Wasm we can provide stronger +security guarantees on other platforms that have a compatible Wasm runtime available. + +The WebAssembly instruction set is designed with performance in mind. A WebAssembly module can be JIT-compiled or +compiled on a client machine to an optimized native binary ahead of time. With recently accepted proposals to the Wasm +specification it now supports features such as SIMD, atomics, multi-threading, and more. A WebAssembly runtime can +generate a restricted subset of native binary code that implements these features with little performance overhead. + +Adoption of Wasm in developer tools does not imply unavoidable performance overhead. With security guarantees that +virtualization brings, there's no longer a need to spawn a separate process for each Swift compiler and SwiftPM +plugin/manifest invocation. Virtualized Wasm binaries can run in the host process of a Wasm runtime, removing the +overhead of new process setup and IPC infrastructure. + ## Goals As of March 2024 all patches necessary for basic Wasm and WASI support have been merged to the Swift toolchain and core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift ecosystem: -1. Ensure that Swift toolchain and core libraries have a regularly running test suite for supported Wasm and WASI -triples. - -2. Allow Swift developers to easily install and build with a Swift SDK for WASI. This requires an implementation -of corresponding build scripts and CI jobs to generate and publish the Swift SDK. Some parts of the Swift toolchain and -core libraries need a Swift SDK for running tests for WASI, so this will benefit the previous point in stabilizing -support for this platform. - -3. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. +1. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. -4. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall +2. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all platforms. -5. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure -that future versions of WASI are available to Swift developers targeting Wasm. A more ambitious long-term goal to -consider is making interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With -a formal specification for Canonical ABI progressing, this goal will become more achievable with time. +3. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure +that future versions of WASI are available to Swift developers targeting Wasm. + +4. Make interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal +specification for Canonical ABI progressing, this will become more achievable with time. ### Proposed Language Features @@ -114,20 +109,6 @@ as pitches and eventually Swift Evolution proposals, if the community is interes These attributes allow easier interoperation between Swift code and other Wasm modules linked with it by a Wasm runtime. -* [`@_extern(wasm)` attribute](https://github.com/apple/swift/pull/69107) that corresponds to Clang's -[`__attribute__((import_name("declaration_name")))`](https://clang.llvm.org/docs/AttributeReference.html#export-name) -and [`__attribute__((import_module("module_name")))`](https://clang.llvm.org/docs/AttributeReference.html#import-module). -This indicates that function's implementation is not provided together with its declaration in Swift and is -available externally, imported by a Wasm runtime during the linking phase. The declaration is added to current Wasm -module's imports section. Without `@_extern(wasm)` developers need to rely on C interop to create a declaration in a C -header using the Clang version of attributes. - -* [`@_expose(wasm)` attribute](https://github.com/apple/swift/pull/68524) that corresponds to Clang's -[`__attribute__((export_name("name")))`](https://clang.llvm.org/docs/AttributeReference.html#export-name), which -is the counterpart of `@_extern(wasm)` working in the opposite direction. This explicitly makes a Swift declaration -available outside of the current module, added to its exports section under a given name. Again, the lack of -this attribute in Swift requires use of C headers as a workaround. - ## Platform-specific Considerations ### Debugging @@ -143,24 +124,25 @@ main directions: 2. Wasm runtime with a built-in debugger [2] The first approach provides an almost equivalent experience to existing debugging workflows on other platforms. It -can utilize LLDB's Swift support, remote metadata inspection and serialized Swift module information. However, since +can utilize LLDB's Swift support, remote metadata inspection, and serialized Swift module information. However, since Wasm is a Harvard architecture and has no way to allocate executable memory space at runtime, implementing expression evaluation with JIT in user space is challenging. In other words, gdb stub in Wasm engines need tricky implementations or need to extend the GDB Remote Serial Protocol. -The second approach embeds the debugger within the Wasm engine. In scenarios where the Wasm engine is embedded as a guest -language in another host language engine (e.g. within a Web Browser), this approach allows seamless debugging experiences -with the host language by integrating with the host debugger. For example, in cases where JavaScript and Wasm call frames +The second approach embeds the debugger within the Wasm engine. In scenarios where the Wasm engine is embedded as a +guest in another host engine (e.g. within a Web Browser), this approach allows seamless debugging experiences with the +host language by integrating with the host debugger. For example, in cases where JavaScript and Wasm call frames are interleaved, the debugger works well in both contexts without switching tools. Debugging tools like Chrome DevTools can use DWARF information embedded in Wasm file to provide debugging support. However, supporting Swift-specific -metadata information and JIT-based expression evaluation will require integrating LLDB's Swift plugin with these debuggers -in some way. +metadata information and JIT-based expression evaluation will require integrating LLDB's Swift plugin with these +debuggers in some way. -Given that both approaches can utilize DWARF information, the Swift toolchain should generate as much DWARF information as possible -for statically known things. Also, making Swift type information DWARF-friendly is desirable because the current debug -information generated by the Swift compiler assumes that debuggers can understand certain Swift primitives (e.g. `Swift.Int` -is currently represented as a `DW_TAG_structure_type` node without any member but ideally such types should be represented -as `DW_TAG_base_type` nodes with `DW_AT_encoding` attribute or provide a debug summary string by LLDB Summary Strings) +Given that both approaches can utilize DWARF information, the Swift toolchain should generate as much DWARF information +as possible for what's statically known. Also, making Swift type information DWARF-friendly is desirable, since the +current debug information generated by the Swift compiler assumes that debuggers can understand certain Swift +primitives. E.g. `Swift.Int` is currently represented as a `DW_TAG_structure_type` node without any member, but ideally +such types should be represented as `DW_TAG_base_type` nodes with `DW_AT_encoding` attribute or provide a debug summary +string by LLDB Summary Strings). [1]: https://github.com/llvm/llvm-project/pull/77949 [2]: https://github.com/ChromeDevTools/devtools-frontend/blob/main/extensions/cxx_debugging @@ -170,40 +152,45 @@ as `DW_TAG_base_type` nodes with `DW_AT_encoding` attribute or provide a debug s WebAssembly has [atomic operations in the instruction set](https://github.com/WebAssembly/threads) (only sequential consistency is supported), but it does not have a built-in way to create threads. Instead, it relies on the host environment to provide multi-threading support. This means that multi-threading in Wasm is dependent on the Wasm runtime -that executes the module. There are two proposals to standardize ways to create threads in Wasm: (1) [wasi-threads](https://github.com/WebAssembly/wasi-threads), -which is already supported by some toolchains, runtimes, and libraries but has been superseded by the new one. (2) The -new proposal [shared-everything-threads](https://github.com/WebAssembly/shared-everything-threads) is still in the -early stages of spec development but is expected to be the future of multi-threading in Wasm. +that executes a module. There are two proposals to standardize ways to create threads in Wasm: + +(1) [wasi-threads](https://github.com/WebAssembly/wasi-threads), which is already supported by some toolchains, +runtimes, and libraries but has been superseded; + +(2) The new [shared-everything-threads](https://github.com/WebAssembly/shared-everything-threads) proposal is still +in the early stages, but is expected to be the future of multi-threading in Wasm. Swift currently supports two threading models in Wasm: single-threaded (`wasm32-unknown-wasi`) and multi-threaded -using wasi-threads (`wasm32-unknown-wasip1-threads`). Despite the latter supporting multi-threading, Swift Concurrency defaults -to a cooperative single-threaded executor due to the lack of wasi-threads support in libdispatch. Preparing for the -shared-everything-threads proposal is crucial to ensure that Swift Concurrency can adapt to future multi-threading -standards in Wasm. +using wasi-threads (`wasm32-unknown-wasip1-threads`). Despite the latter supporting multi-threading, Swift Concurrency +defaults to a cooperative single-threaded executor due to the lack of wasi-threads support in libdispatch. Preparing +for the shared-everything-threads proposal is crucial to ensure that Swift Concurrency can adapt to future +multi-threading standards in Wasm. ### 64-bit address space -WebAssembly currently uses a 32-bit address space, but the specification is going to support [64-bit address space](https://github.com/WebAssembly/memory64/). -Swift already has support on 64-bit for other platforms, however, WebAssembly is the first platform where relative reference -from data to code is not allowed. Alternative solutions like image-base relative addressing or small "code model" for fitting -64-bit pointer in 32-bit are unavailable, at least for now. This means that we need cooperation from the WebAssembly toolchain -side or different memory layout in Swift metadata to support 64-bit in WebAssembly. +WebAssembly currently uses a 32-bit address space, but [64-bit address space](https://github.com/WebAssembly/memory64/) +proposal is already in the implementation phase. + +Swift supports 64-bit pointers on other platforms where available, however WebAssembly is the first platform where +relative reference from data to code is not allowed. Alternative solutions like image-base relative addressing or +"small code model" for fitting 64-bit pointer in 32-bit are unavailable, at least for now. This means that we need +cooperation from the WebAssembly toolchain side or different memory layout in Swift metadata to support 64-bit linear +memory support in WebAssembly. ### Shared libraries -There are two approaches to using shared libraries in WebAssembly ecosystem: +There are two approaches to using shared libraries in the WebAssembly ecosystem: 1. [Emscripten-style dynamic linking](https://emscripten.org/docs/compiling/Dynamic-Linking.html) 2. [Component Model-based "ahead-of-time" linking](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Linking.md) -Emscripten-style dynamic linking is a traditional way to use shared libraries in WebAssembly, where the host environment provides -non-standard dynamic loading capabilities. - -Component Model-based AOT linking is a new way that transforms shared library WebAssembly Core modules compiled with -Emscripten's dynamic linking ABI into a single WebAssembly Component at build time. The latter approach cannot fully replace the former, -as it is not able to handle dynamic loading of shared libraries at runtime, but it is more portable way to distribute programs linked -with shared libraries because it does not require the host environment to provide any special capabilities except for Component Model -support. - -From the Swift toolchain perspective, they both use the Emscripten's dynamic linking ABI, so the support for shared libraries in -Swift is mostly about making sure that Swift programs can be compiled in position-independent code mode and linked with shared -libraries by following the dynamic linking ABI. + +Emscripten-style dynamic linking is a traditional way to use shared libraries in WebAssembly, where the host +environment provides non-standard dynamic loading capabilities. + +The latter approach cannot fully replace the former, as it is unable to handle dynamic loading of shared libraries at +runtime, but it is more portable way to distribute programs linked with shared libraries, as it does not require the +host environment to provide any special capabilities except for Component Model support. + +Support for shared libraries in Swift for Wasm is mostly about making sure that Swift programs can be compiled in +position-independent code mode and linked with shared libraries by following the corresponding dynamic linking ABI. + From 33e4eb55141d4e73adfcc9d8a929e899e71638d4 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 31 Oct 2024 15:14:16 +0000 Subject: [PATCH 021/505] Apply suggestions from code review Co-authored-by: Danielle --- visions/webassembly.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index c46c3d7a54..565b79c608 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -83,13 +83,13 @@ overhead of new process setup and IPC infrastructure. ## Goals -As of March 2024 all patches necessary for basic Wasm and WASI support have been merged to the Swift toolchain and +As of March 2024 all patches necessary for basic Wasm and WASI Preview 1 support have been merged to the Swift toolchain and core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift ecosystem: 1. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, -multi-threading, file system access, and localization need special support in Wasm runtimes and a certain amount of +multi-threading, file system access, networking and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. 2. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall @@ -100,7 +100,7 @@ platforms. that future versions of WASI are available to Swift developers targeting Wasm. 4. Make interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal -specification for Canonical ABI progressing, this will become more achievable with time. +specification for Canonical ABI progressing, this will become more achievable with time. This includes consuming components from, and building components with Swift. ### Proposed Language Features From 00063f52a49a7757cb8c5f21a5b52fb5abb4b255 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 8 Nov 2024 15:03:50 +0000 Subject: [PATCH 022/505] Address PSG meeting feedback --- visions/webassembly.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 565b79c608..35587aebf8 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -83,12 +83,13 @@ overhead of new process setup and IPC infrastructure. ## Goals -As of March 2024 all patches necessary for basic Wasm and WASI Preview 1 support have been merged to the Swift toolchain and -core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift +As of March 2024 all patches necessary for basic Wasm and WASI Preview 1 support have been merged to the Swift +toolchain and core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift ecosystem: 1. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. -As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, +Main prerequisite for that is setting up CI jobs for those libraries that run tests for WASI and also Embedded Wasm, where +possible. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, multi-threading, file system access, networking and localization need special support in Wasm runtimes and a certain amount of consideration from a developer adopting these APIs. @@ -100,7 +101,8 @@ platforms. that future versions of WASI are available to Swift developers targeting Wasm. 4. Make interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal -specification for Canonical ABI progressing, this will become more achievable with time. This includes consuming components from, and building components with Swift. +specification for Canonical ABI progressing, this will become more achievable with time. This includes consuming +components from, and building components with Swift. ### Proposed Language Features @@ -137,12 +139,8 @@ can use DWARF information embedded in Wasm file to provide debugging support. Ho metadata information and JIT-based expression evaluation will require integrating LLDB's Swift plugin with these debuggers in some way. -Given that both approaches can utilize DWARF information, the Swift toolchain should generate as much DWARF information -as possible for what's statically known. Also, making Swift type information DWARF-friendly is desirable, since the -current debug information generated by the Swift compiler assumes that debuggers can understand certain Swift -primitives. E.g. `Swift.Int` is currently represented as a `DW_TAG_structure_type` node without any member, but ideally -such types should be represented as `DW_TAG_base_type` nodes with `DW_AT_encoding` attribute or provide a debug summary -string by LLDB Summary Strings). +In summary, debugging in the browser and outside of the browser context are sufficiently different activities to +require separate implementation approaches. [1]: https://github.com/llvm/llvm-project/pull/77949 [2]: https://github.com/ChromeDevTools/devtools-frontend/blob/main/extensions/cxx_debugging From c5d8bae2bb489131d0b2e246c447f3c3cbb1812c Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 13 Nov 2024 16:52:59 +0000 Subject: [PATCH 023/505] Add debugging as a separate goal to the "Goals" section --- visions/webassembly.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 35587aebf8..3ae48a47af 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -88,21 +88,25 @@ toolchain and core libraries. Based on this, we propose a high-level roadmap for ecosystem: 1. Make it easier to evaluate and adopt Wasm with increased API coverage for this platform in the Swift core libraries. -Main prerequisite for that is setting up CI jobs for those libraries that run tests for WASI and also Embedded Wasm, where -possible. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, -multi-threading, file system access, networking and localization need special support in Wasm runtimes and a certain amount of -consideration from a developer adopting these APIs. + Main prerequisite for that is setting up CI jobs for those libraries that run tests for WASI and also Embedded Wasm, where + possible. As a virtualized embeddable platform, not all system APIs are always available or easy to port to WASI. For example, + multi-threading, file system access, networking and localization need special support in Wasm runtimes and a certain amount of + consideration from a developer adopting these APIs. 2. Improve support for cross-compilation in Swift and SwiftPM. We can simplify versioning, installation, and overall -management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all -platforms. + management of Swift SDKs for cross-compilation in general, which is beneficial not only for WebAssembly, but for all + platforms. 3. Continue work on Wasm Component Model support in Swift as the Component Model proposal is stabilized. Ensure -that future versions of WASI are available to Swift developers targeting Wasm. + that future versions of WASI are available to Swift developers targeting Wasm. 4. Make interoperability with Wasm components as smooth as C and C++ interop already is for Swift. With a formal -specification for Canonical ABI progressing, this will become more achievable with time. This includes consuming -components from, and building components with Swift. + specification for Canonical ABI progressing, this will become more achievable with time. This includes consuming + components from, and building components with Swift. + +5. Improve debugging experience of Swift code compiled to Wasm. While rudimentary support for debugging + exists in some Wasm runtimes, we aim to improve it and, where possible, make it as good as debugging Swift code + compiled to other platforms. ### Proposed Language Features From 73f8452f1bcd38305e2e5cad19de45fdbd5d4706 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 2 Jan 2025 16:00:34 +0000 Subject: [PATCH 024/505] Mark SE-0450 (package traits) as implemented in 6.1 This feature was cherry-picked to 6.1 with experimental flags were removed after SE acceptance. --- proposals/0450-swiftpm-package-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0450-swiftpm-package-traits.md b/proposals/0450-swiftpm-package-traits.md index c00ecea147..737364f821 100644 --- a/proposals/0450-swiftpm-package-traits.md +++ b/proposals/0450-swiftpm-package-traits.md @@ -3,7 +3,7 @@ * Proposal: [SE-0450](0450-swiftpm-package-traits.md) * Authors: [Franz Busch](https://github.com/FranzBusch), [Max Desiatov](https://github.com/MaxDesiatov) * Review Manager: [Mishal Shah](https://github.com/shahmishal) -* Status: **Accepted** +* Status: Implemented (Swift 6.1) * Implementation: https://github.com/swiftlang/swift-package-manager/pull/7704, https://github.com/swiftlang/swift-package-manager/pull/7703, https://github.com/swiftlang/swift-package-manager/pull/7702, https://github.com/swiftlang/swift-package-manager/pull/7701, https://github.com/swiftlang/swift-package-manager/pull/7694, https://github.com/swiftlang/swift-package-manager/pull/7689, https://github.com/swiftlang/swift-package-manager/pull/8178 * Experimental Implementation: Gated on `@_spi(ExperimentalTraits)` in package manifests and `--experimental` prefix for CLI options * Review: ([pitch](https://forums.swift.org/t/pitch-package-traits/72191)) ([review](https://forums.swift.org/t/se-0450-package-traits/75598)) From 1a3020256ce7f2cda9805d89ae9801ec10895eed Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 5 Jan 2025 20:04:13 +0000 Subject: [PATCH 025/505] Apply suggestions from code review Co-authored-by: Ben Rimmington --- proposals/0450-swiftpm-package-traits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0450-swiftpm-package-traits.md b/proposals/0450-swiftpm-package-traits.md index 737364f821..e634bd8206 100644 --- a/proposals/0450-swiftpm-package-traits.md +++ b/proposals/0450-swiftpm-package-traits.md @@ -3,10 +3,10 @@ * Proposal: [SE-0450](0450-swiftpm-package-traits.md) * Authors: [Franz Busch](https://github.com/FranzBusch), [Max Desiatov](https://github.com/MaxDesiatov) * Review Manager: [Mishal Shah](https://github.com/shahmishal) -* Status: Implemented (Swift 6.1) +* Status: **Implemented (Swift 6.1)** * Implementation: https://github.com/swiftlang/swift-package-manager/pull/7704, https://github.com/swiftlang/swift-package-manager/pull/7703, https://github.com/swiftlang/swift-package-manager/pull/7702, https://github.com/swiftlang/swift-package-manager/pull/7701, https://github.com/swiftlang/swift-package-manager/pull/7694, https://github.com/swiftlang/swift-package-manager/pull/7689, https://github.com/swiftlang/swift-package-manager/pull/8178 * Experimental Implementation: Gated on `@_spi(ExperimentalTraits)` in package manifests and `--experimental` prefix for CLI options -* Review: ([pitch](https://forums.swift.org/t/pitch-package-traits/72191)) ([review](https://forums.swift.org/t/se-0450-package-traits/75598)) +* Review: ([pitch](https://forums.swift.org/t/pitch-package-traits/72191)) ([review](https://forums.swift.org/t/se-0450-package-traits/75598)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0450-package-traits/76705)) ## Introduction From 88a94372cc78c5db38ea1d31bd9ce2711063e95b Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 6 Jan 2025 09:17:25 +0000 Subject: [PATCH 026/505] Update 0450-swiftpm-package-traits.md Co-authored-by: Ben Rimmington --- proposals/0450-swiftpm-package-traits.md | 1 - 1 file changed, 1 deletion(-) diff --git a/proposals/0450-swiftpm-package-traits.md b/proposals/0450-swiftpm-package-traits.md index e634bd8206..2e7924c3c4 100644 --- a/proposals/0450-swiftpm-package-traits.md +++ b/proposals/0450-swiftpm-package-traits.md @@ -5,7 +5,6 @@ * Review Manager: [Mishal Shah](https://github.com/shahmishal) * Status: **Implemented (Swift 6.1)** * Implementation: https://github.com/swiftlang/swift-package-manager/pull/7704, https://github.com/swiftlang/swift-package-manager/pull/7703, https://github.com/swiftlang/swift-package-manager/pull/7702, https://github.com/swiftlang/swift-package-manager/pull/7701, https://github.com/swiftlang/swift-package-manager/pull/7694, https://github.com/swiftlang/swift-package-manager/pull/7689, https://github.com/swiftlang/swift-package-manager/pull/8178 -* Experimental Implementation: Gated on `@_spi(ExperimentalTraits)` in package manifests and `--experimental` prefix for CLI options * Review: ([pitch](https://forums.swift.org/t/pitch-package-traits/72191)) ([review](https://forums.swift.org/t/se-0450-package-traits/75598)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0450-package-traits/76705)) ## Introduction From 97ef144633405eeb2424e84bdcbc8e6206e5e9b1 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Thu, 23 Jan 2025 17:27:10 -0800 Subject: [PATCH 027/505] Add Section Placement Control draft --- proposals/0nnn-section-control.md | 447 ++++++++++++++++++++++++++++++ 1 file changed, 447 insertions(+) create mode 100644 proposals/0nnn-section-control.md diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md new file mode 100644 index 0000000000..985be91e6f --- /dev/null +++ b/proposals/0nnn-section-control.md @@ -0,0 +1,447 @@ +# Section Placement Control + +* Proposal: [SE-0NNN](0nnn-section-control.md) +* Authors: [Kuba Mracek](https://github.com/kubamracek) +* Status: Pitch #3 +* Discussion threads: + * Pitch #1: https://forums.swift.org/t/pitch-low-level-linkage-control-attributes-used-and-section/65877 + * Pitch #2: https://forums.swift.org/t/pitch-2-low-level-linkage-control/69752 + * Pitch #3: TBD + +## Introduction + +This proposal builds on top of [Swift Compile-Time Values](https://TBD) and adds two new attributes into the Swift language: `@section` and `@used`. These allow users to directly control which section of the resulting binary should globals variables be emitted into, and give users the ability to disable DCE (dead code elimination) on those. The goal is to enable systems and embedded programming use cases like runtime discovery of test metadata from multiple modules, and also to serve as a low-level building block for higher-level features (e.g. linker sets, plugins). + +The intention is that these attributes are to be used rarely and only by specific use cases; high-level application code should not need to use them directly and instead should rely on libraries, macros and other abstractions over the low-level attributes. + +The scope of this proposal is limited to compile-time behavior and compile-time control. We expect that full user-facing solutions for features like linker sets, test discovery or plugins will also require runtime implementations to discover and iterate the contents of custom sections, possibly from multiple modules. This proposal makes sure to provide the right building blocks and artifacts in binaries for the runtime components, but doesn’t prescribe the shape of those. However, it is providing a significant step towards generalized and safe high-level mechanisms for those use cases. See the discussion of that in the sections [Runtime discovery of data in custom sections](#runtime-discovery-of-data-in-custom-sections) and [Linker sets, plugins as high-level APIs](#linker-sets-plugins-as-high-level-apis) in Future Directions. + +## Motivation + +**Testing frameworks** need to be able to produce test metadata about user’s types and other declarations (e.g. standalone test entrypoints) in a way that they are discoverable and enumerable at runtime. In dynamic languages like Objective-C, this is typically done at runtime using reflection, by querying the language runtime, and/or walking lists of types or exported symbols: + +```swift +// MyXCTestModule +@objc class TableValidationTests: XCTestCase { + func test1() { ... } +} + +// Testing framework, pseudo-code +let classList = objc_copyClassList(...) +for aClass in classList { + if aClass is XCTestCase { + let methodList = class_copyMethodList(aClass) + ... + } +} +``` + +A similarly dynamic approach was proposed in [SE-0385 (Custom Reflection Metadata)](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0385-custom-reflection-metadata.md), but was rejected because for Swift, a more static approach would be a better fit: If Swift code had the ability to produce custom metadata directly into the resulting binaries in a well-understood way, we would be able to directly access the data at runtime via platform loader’s APIs and also use offline binary inspection tools (such as objdump, objcopy, otool). This would be more efficient and not require the language runtime and thus also be palatable in embedded use cases using Embedded Swift. + +Mainstream operating systems support dynamically loading modules from disk at runtime, and large applications tend to build **plugin systems** as a way to separate the development of subsystems, or to support separate compilation of 3rd party code. Loading a module from disk can be done using standard APIs like `dlopen`, but discovering and calling the interface in the plugin usually requires using unsafe C constructs (dlsym, casting of pointers) and/or querying the language runtime for type information, similarly to the testing enumerating approach mentioned above. A better approach could publish the information about a plugin in a structured way into the binary, and a runtime component could locate this metadata, and provide access to it in a type-safe way. + +This proposal recommends to use sections of the various object file formats as the vehicle for custom metadata produced by Swift code. This approach is a good fit to the above mentioned use cases, but also enables others: + +* “**Linker sets**” are an approach in systems programming that collects data from multiple source files or subsystems using a standard linker behavior of collocating symbols that belong to the same section. In principle, this is simply a generalization of the test enumeration and plugin discovery use cases mentioned above. The primary goal is decentralization of the information, for example, linker sets can be used to describe memory requirements of each subsystem (and a boot step at runtime can process those to figure out how much heap should be made available). +* Emitting custom metadata into binaries can be used to convey **information to the debugger**. The `@DebugDescription` macro generates a “summary string” for LLDB that summarizes the contents of the fields of a type without the need for runtime evaluation, but rather as a composition of the fields that LLDB assembles. To make those summary strings discoverable by LLDB, placing them into a custom section is a clean solution allowing LLDB to consume them in the case where LLDB has access to the binary on disk, or even without that. Embedded programs might need to rely on such a mechanism as the only way to get enhanced data visualization in the debugger, because runtime evaluation from a debugger is commonly not possible at all in firmware. + +```swift +@DebugDescription struct Student { + var name: String + var id: Int + + /* synthesized by the @DebugDescription macro, made discoverable by LLDB */ + let __Student_lldb_summary = ("PupilKit.Student", "${var.id}: ${var.name}") +} +``` + +* More embedded and systems programming use cases often require directly control of section placement as well, for example to adhere to a **startup contract** with platform libraries, SDK’s linker scripts or the hardware itself. Such contract can be pre-existing in the platform and require placing a specific data structure into a specific section. Enabling doing that directly in Swift will provide a more intuitive and safer implementation option, and users of Swift for embedded devices won’t need to reach for C/C++ as a workaround. + +## Proposed Solution + +The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". The `@section` attribute relies heavily on the facilities provided by [Swift Compile-Time Values](https://TBD), namely the ability to enforce constantness of an expressions. Using `@section` requires that the initializer expression is a constant expression: + +```swift +// Place entry into a section, mark as "do not dead strip". +// Initializer expression must be a constant expression. +// The global variable is implicitly made statically initialized. +@section("__DATA,mysection") +@used +let myLinkerSetEntry: Int = 42 // ✅ + +// Non-constant or statically non-initializable expressions are disallowed +@section("__DATA,mysection") +let myLinkerSetEntry: Int = Int.random(in: 0 ..< 10) // ❌ error + +// Section-placed globals can be "var", the initializer expression still must be constant +@section("__DATA,mysection") +var mutableVariable: Int = 42 // ✅ + +// Some complex data types are allowed (static strings, functions) +typealias PluginData = (version: Int, name: String, initializer: @convention(c) ()->()) + +@section("__DATA,plugins") +@used +let myPlugin: PluginData = ( + version: 1, + name: "MyPlugin", + initializer: { print("init") } +) +``` + +On top of specifying a custom section name with the `@section` attribute, marking a variable as `@used` is needed to prevent otherwise unused symbols from being removed by the compiler. When using section placement to e.g. implement linker sets, such values are typically going to have no usage at compile time, and at the same time they should not be exposed in public interface of libraries (not be made public), therefore we the need the `@used` attribute. + +A related new attribute, `@constInitialized` is to be added, which can be used to enforce that a global or static variable is statically initialized, without placing it into a custom section. Using attribute `@section` implies `@constInitialized`. + +```swift +// Static initialization can be requested separately +@constInitialized +var fourPages = 4 * 4096 +``` + +Different object file formats (ELF, Mach-O, COFF) have different restrictions and rules on what are valid section names, and cross-platform code will have to use different names for different file formats. To support that, custom section names can be specified as either a string literal, or by referencing a constant global/static declaration that contains the name. The name will be directly set for the symbol in the resulting object file, without any processing. A new `#if objectFileFormat(...)` conditional compilation directive will be provided to support conditionalizing based on the file format: + +```swift +#if objectFileFormat(ELF) +@const let mySectionName = ".mysection" +#elseif objectFileFormat(MachO) +@const let mySectionName = "__DATA,mysection" +#endif + +@section(mySectionName) +var global = ... +``` + +For the ELF file format specifically, the compiler will also emit a “section index” into produced object files, containing an entry about each custom section used in the compilation. This is a solution to an ELF specific problem where the behavior of ELF linkers and loaders means that sections are not easily discoverable at runtime. + +## Detailed design + +### Attributes @section and @used on global and static variables + +Two new attributes are to be added: `@section`, which has a single argument specifying the section name, and a argument-less `@used` attribute. The section name must be either a string literal, or a reference to a constant string declaration. + +```swift +// (1) +@section("__DATA,mysection") +@used +let global = ... // ✅ + +// (2) +@const let mySectionName = "__DATA,mysection" + +@section(mySectionName) +let global = ... // ✅ + +// (3) +@section(Bool.rand() ? "a" : "b") +let global = ... // ❌ +``` + +The section name must not be one of Swift’s runtime reserved sections (e.g. `__swift5_types`, etc.), such sections would be rejected: + +```swift +@section("__TEXT,__swift5_types") +let global = ... // ❌ +``` + +The new attributes (`@section` and `@used`) can be used on variable declarations under these circumstances: + +* the variable must be a global variable or a static member variable (no local variables, no non-static member variables) +* the variable must not be declared inside a generic context (either directly in generic type or nested in a generic type) +* the variable must be a stored property (not be a computed property) +* the variable must not have property observers (didSet, willSet) +* the initial expression assigned to the variable must be a constant expression, and it must be eligible for static initilization + +*Note: These restrictions limit the `@section` and `@used` attributes to only be allowed on variables that are expected to be represented as exactly one statically-initialized global storage symbol (in the linker sense) for the variable’s content. This is generally true for all global and static variables in C and C++, but in Swift global variables might have zero global storage symbols (e.g. a computed property), or need non-trivial storage (e.g. lazily initialized variables with runtime code in the initializer expression).* + +```swift +@section("__DATA,mysection") @used +let global = 42 // ✅ + +@section("__DATA,mysection") @used +var global = 42 // ✅ + +@section("__DATA,mysection") @used +var computed: Int { return 42 } // ❌ ERROR: @section cannot be used on computed properties + +struct MyStruct { + @section("__DATA,mysection") @used + static let staticMemberLet = 42 // ✅ + + @section("__DATA,mysection") @used + static var staticMemberVar = 42 // ✅ + + @section("__DATA,mysection") @used + let member = 42 // ❌ ERROR: @section cannot be used on non-static members + + @section("__DATA,mysection") @used + var member = 42 // ❌ ERROR: @section cannot be used on non-static members +} + +struct MyGenericStruct { + @section("__DATA,mysection") @used + static let staticMember = 42 // ❌ ERROR: @section cannot be used in a generic context + + @section("__DATA,mysection") @used + static var staticMember = 42 // ❌ ERROR: @section cannot be used in a generic context +} +``` + +When allowed, the `@section` attribute on a variable declaration has the following effects: + +1. The variable’s initializer expression is going to be constant folded at compile-time, and assigned as the initial value to the storage symbol for the variable, i.e. the variable will be **statically initialized**. The variable’s value will not be lazily computed at runtime, and it will not use the one-time initialization helper code and token. If that’s not possible, an error is diagnosed. +2. The storage symbol for the variable will be placed into a custom section with the specified name. +3. If applied to a global that is declared as part of top-level executable code (i.e. main.swift), the usual non-top-level-code initialization behavior is applied to the global. I.e. the variable is not sequentially initialized at startup. + +When allowed, the `@used` attribute on a variable declaration has the following effect: + +1. The storage symbol for the variable will be marked as “do not dead-strip”. + +The effects described above are applied to the storage symbols and don’t generally affect optimizations and other transformations in the compiler. For example, the compiler is still allowed to propagate and copy a the constant value to code that uses the value, so there’s no guarantee that a value stored into a global with a custom section will not be propagated and “leak” outside of the section. The `@used` annotation, however, does inform the optimizer that such a variable cannot be removed, even when it doesn’t have any observed users or even if it’s inaccessible due to language rules (e.g. if it’s a private static member on an otherwise empty type). + +### Guaranteed static initialization + +Using attribute `@section` requires the initializer expression of the variable to be a constant expression. The `@const` annotation on the expression is not required (it’s implied). On top of the constant-ness, `@section` on a global or static variable enforces **static initialization** on that variable. The variable can be statically initialized, if the constant expression not only represents a valid compile-time constant, but also is able to be constant-folded into a representation that does not require any runtime initialization (pointer relocations/fixups done automatically by the loader are not considered runtime initialization for this purpose). + +This is a property that `@const` alone does not provide, but it’s necessary because we expect the data to be readable without any runtime mechanisms (i.e. reading raw bytes from the section at runtime, or offline binary inspection). + +```swift +@section("__DATA,mysection") +let a = 42 // ✅ + +@section("__DATA,mysection") +let b = @const 42 // warning: @const is superfluous + +@section("__DATA,mysection") +let sectionPlaced = ...expression... // guaranteed to be statically initialized + +let justConstant = @const ...expression... // not guaranteed to be statically initialized +``` + +*Note: As of this writing, all valid constant values are also eligible to be statically initialized, but we don’t expect that to hold in the future. So it’s important to distinguish between (a) a global variable being initialized with a language-level constant value (`@const`), and (b) a global variable that is guaranteed to be statically initialized. The difference can be subtle, and in some cases immaterial in practice, but future enhancements of constant values in Swift might take advantage of this difference — i.e. not all constant values are going to be statically initializable. Consider the following example: If a future language versions allows dictionary literals to be constant values, such values might not be statically initializable because of randomized hash seeding:* + +```swift +let d1 = @const ["a": 42, "b": 777] // constant, but not statically initializable +let d2 = @const d1.count // statically initializable +``` + +*However, using a statically non-initializable value in an expression does not preclude the outer expression from being statically initialized either. In this example, `d1` would not be allowed to be placed into a custom section because it’s not statically initializable. But `d2` could still potentially be statically initializable (even though the definition of `d2` uses a sub-expression that is not statically initializable), as it’s simply an integer.* + +As described in [Swift Compile-Time Values](https://TBD), values of function types are eligible for being compile-time evaluable. Their concrete pointer value is not fully known until link-time or program load-time (depending on type of linking, ASLR, PAC, etc.). For the purposes of guaranteed static initialization, function values are statically initialized into a function pointer. This pointer is still subject to normal linking and loading resolutions and fixups. + +```swift +func foo() { ... } + +@section("__DATA,mysection") +let a = (42, foo) // "foo" is statically initialized into a + // linkable/relocatable pointer +``` + +### Attribute `@constInitialized` + +Static initialization of a global can be useful on its own, without placing data into a custom section. For that, a new attribute `@constInitialized` can be used. This attribute can be only used on variable declarations under the same conditions that `@section` and `@used` require (e.g. only on globals and statics, not in generic contexts, etc.) + +```swift +@constInitialized +var fourPages = 4 * 4096 // ✅ + +struct S { + @constInitialized + var fourPages = 4 * 4096 // ❌ +} +``` + +The effect of this attribute is the same as of the `@section` attribute (static initialization, normal initalization behavior if top-level code) except the symbol is not actually placed into any custom sections. + +### Cross-platform object file format support + +The custom section name specified in the `@section` attribute is not validated by the compiler, instead it’s passed directly as a string to the linker. Different platforms supported by Swift are using different object and binary file formats (Linux uses ELF, Darwin uses Mach-O, Windows uses COFF), and that implies different restrictions and rules on what are valid section names. Because of that, a multi-platform library code is expected to use `#if os(...)` to use different section names for different platforms. Because of that, it’s expected that the attributes are to be typically only used indirectly via macros that hide the low-level nature of sections and object file formats from higher-level code developers: + +```swift +// Example of a potential project-specific "@RegisterPlugin" macro: +@RegisterPlugin +let plugin = ... + +// The macro expands to: +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +@section("__DATA_CONST,plugins") +#elseif os(Linux) +@section("plugins") +#elseif os(Windows) +@section(".plugins") +#endif +let plugin = ... +``` + +See [Structured section specifiers](#structured-section-specifiers) below for more rationale. + +In some cases, it’s not possible to differentiate on the OS to support multiple object file formats, for example when using Embedded Swift to target baremetal systems without any OS. For that, a new `#if objectFileFormat(...)` conditional compilation directive will be provided. The allowed values in this directive will match the set of supported object file formats by the Swift compiler (and expand as needed in the future). Currently, they exact values will be (case sensitive): + +* COFF +* ELF +* MachO +* Wasm + +```swift +#if objectFileFormat(MachO) +@section("__DATA_CONST,mysection") +#elseif objectFileFormat(ELF) +@section(".mysection") +#endif +let value = ... +``` + +### ELF section index + +The goal of placing metadata into custom section is to make them discoverable both via offline inspection (e.g. objdump or otool) and at runtime. The facilities for that are dependent on the type of linking (static vs dynamic), and platform’s linker and loader: + +* For **static linking**, the bounds of a section can be statically determined by the linker and on all supported platforms and their file formats (COFF, ELF, MachO, Wasm), the linker-provided “**encapsulation symbols**” can be used to retrieve those bounds. + * In ELF and Wasm formats, these symbols are `__start_
` / `__stop_
`. + * In Mach-O, these symbols are `section$start$$` / `section$end$$`. + * In COFF, these symbols need to be manually constructed by using “grouped sections” (section name is suffixed with a $ + string) which are automatically lexicographically ordered by the linker. For example, by manually placing a start symbol into `.section$A` , end symbol into `.section$C` and all actual section entries into `.section$B`, the two helper symbols’s addresses effectively describe the bounds of the section. +* For **dynamic linking**, the above mentioned encapsulation symbols are available too, but they always only describe the bounds of the section in the current module. Retrieving section content process-wide means collecting metadata from multiple images at runtime, which requires further assistance or support from the loader. + * In Mach-O (Darwin OS's), image headers are present in the address space, and they include section bounds information. The loader provides straightforward image iteration APIs (`_dyld_get_image_header`), as well as image load callbacks (`_dyld_register_func_for_add_image`), and an API to lookup section bounds by name from a particular image (getsectiondata). + * In COFF (Windows), image headers are present in the address space, and they include section bounds information. `Module32FirstW`/`Module32NextW` can be used to enumerate images, and structures such as `IMAGE_DOS_HEADER`, `IMAGE_NT_HEADERS`, `IMAGE_FILE_HEADER`, and `IMAGE_SECTION_HEADER` can be used to walk a module and find its section bounds. + * In Wasm, dynamic linking is work in progress and not generally available yet. + * In ELF, however, section bounds are not guaranteed to be present in the address space at runtime, and in practice they are typically not present. This creates a challenge for retrieving section data in this configuration (ELF + multiple modules with dynamic linking) at runtime. + +To solve this problem for the ELF object file format, the Swift compiler is going to emit a “**section index**” into every compilation that uses any symbols placed into a custom section. The index will be emitted only when producing ELF files, and consists of entries added into its own separate well-named section called `swift5_sections`. Each entry will have the following structure: + +```c +struct SectionIndexEntry { + const char *name; + const void *start; // effectively equal to __start_ + const void *stop; // effectively equal to __stop_ +}; +``` + +The section index will describe the bounds of all custom sections used in Swift code. When compiling into a single object file (e.g. in WMO mode without -num-threads), there will be only a single entry per distinct section name, but in compilation modes that produce multiple object files for a single module, there may be multiple entries for the same section. The entries are going to be “linkonce_odr”, i.e. duplicate entries will be collapsed at link time, so in a linked module, only one entry per section will remain. + +This way, runtime code present in the same module, for example SwiftRT-ELF helper code (swiftrt.o) which is currently being silently linked in to all modules, can walk over the section index using the encapsulation symbols, and register the section bounds in a globally maintained data structure in the Swift runtime. Implementation of that and exposing such a facility in an actual API from the Swift runtime is left as a future direction. + +## Source compatibility + +This proposal is purely additive (adding new attributes), without impact on source compatibility. + +## Effect on ABI stability + +This change does not impact ABI stability for existing code. + +Adding, removing, or changing the `@section` attribute on variables should generally be viewed as an ABI breaking change, section placement can affect linking behavior of that symbol. In some cases, it is possible to make careful non-ABI-breaking changes via the `@section` attribute. + +Adding `@used` does not affect ABI stability. Removing `@used` can be viewed as an ABI breaking change, however not in the traditional sense: The effect of `@used` only exists on symbols that would normally not be exported (e.g. private symbols), which shouldn’t be part of a ABI in the first place. However, dynamic lookups of such symbols are still possible, and if the behavior of those is considered ABI, then removing `@used` can be ABI breaking. + +## Effect on API resilience + +This change does not impact API resilience for existing code. + +Adding, removing, or changing the `@section` attribute on variables does not affect API resilience. + +Adding or removing `@used` does not affect API resilience. + +## Future Directions + +### Section placement for functions + +This proposal only allows data placement into custom sections, however, placing code into custom sections is a relatively useful and common approach in systems and embedded programming. In the future, the `@section` and `@used` attributes could be extended to apply to function declarations, and possibly other language constructs that generate executable code (e.g. closures). A prominent use case is firmware entry points and booting schemes, which often require startup code to be in a predefined section: + +```swift +// code for the function is placed into the custom section +@section("__TEXT,boot") +func firmwareBootEntrypoint() { ... } +``` + +This will require some design decisions to be made around when should that be allowed, whether the attribute should be automatically inherited, and what exact behavior should we expect from the compiler around thunks, compiler-generated helper functions, getters and setters, etc. + +### Runtime discovery of data in custom sections + +As described in [ELF section index](#elf-section-index), accessing records in a custom section at runtime is heavily dependent on the object file format (ELF, Mach-O, Wasm, COFF), type of linking (static vs dynamic) and available APIs from the operating system. For a single configuration, users can directly use an appropriate method of accessing the section data, and e.g. in embedded firmwares this might be completely fine as projects are commonly avoiding any attempts to be multi-platform or portable. + +However, for multi-platform libraries and general purpose packages, supporting the full matrix of combinations would be very impractical. Because of that, it’s expected that a unified API for accessing the bounds and contents of a section (across multiple modules in presence of dynamic linking) is provided either as part of the Swift runtime, the standard library, or as a portable package. This API would likely still be a relatively low-level API, providing access to the raw bytes of sections across multiple loaded modules, but it would provide an shared abstraction across platforms, file formats, and linking types. + +### Linker sets, plugins as high-level APIs + +This proposal only builds the compile-time half of a user-facing “linker set” mechanism (placing structured data into sections). To access and enumerate the data at runtime, one can imagine a direct, still relatively low-level API like this: + +```swift +func enumerateLinkerSet(fromSectionNamed: String) -> Sequence { + // extract section data, assuming the raw data in the section are records of "T" + // probably built on top of a cross-platform section access API mentioned in previous section +} +``` + +But a solution based on macros could achieve a higher-level abstraction for the entire “linker set” mechanism: + +```swift +@DefineLinkerSet("name", type: Int) // other macros understand that linker set "name" + // has entries of type Int + +@LinkerSetEntry("name") let entry1: Int = 42 // ok +@LinkerSetEntry("name") let entry2: Float = 7.7 // error + +for entry in #enumerateLinkerSet("name") { + print(entry) +} +``` + +Similarly, a plugin registration and discovery mechanism based on macros could provide full type safety and hide the low-level aspects completely: + +```swift +// In PluginModule: +@PluginRecord(protocol: PluginProtocol, type: MyPluginType) +let plugin = PluginData(name: "myPlugin", version: 1, initialization: { ... }) + +// In MainModule: +... load available plugins via dlopen ... +for plugin in Plugin.enumerateLoadedPlugins(for: PluginProtocol.self) { + print(plugin.name) + let t = plugin.instantiateType() + ... +} +``` + +### Access to a stable address + +Generally, Swift values and variables do not have a stable address, and converting an inout reference to a UnsafePointer does not guarantee a stable address even on a global variable. However, statically initialized globals/static (either via the `@section` attribute, or via `@constInitialized`) do fundamentally have a stable address because they have an exact location in the binary on disk and in the module’s image at runtime. It’d be useful to provide direct access to that, in a way that adds the missing stable-address guarantees compared to inout-to-pointer conversions, and also allow fetching an address of a `let` variable (inout references only work on `var`): + +```swift +@constInitialized let x = 42 + +let address: UnsafePointer = #address(x) // would only work on statically initialized + // globals/statics +``` + +## Alternatives Considered + +### Requiring explicitly spelled out `@const` when using `@section` + +`@section` annotated globals/statics require their initializer expressions to be constant expressions, but the expression does not have to be marked as `@const` manually, it’s implied instead. An alternative of requiring the `@const` was considered: + +```swift +@section(...) let global: Int = @const 42 +``` + +Because `@const` does not affect parsing or type resolution of the expression, it’s not helpful to the compiler, and it doesn’t seem to improve readability for users either: If the expression is a constant expression or not statically initializable, it will be rejected from compilation with a clear explanation. Adding a `@const` does not convey any new information. + +### Structured section specifiers + +In Mach-O, custom section names are written as a pair of segment (e.g. `__DATA`) + section (e.g. `mysection`). Structured section names with separate segment and section names, `@section(segment: "...", section: "...")` were considered instead, however this pattern does not generalize across object file formats, and is Mach-O specific (ELF and PE/COFF don’t have segments). + +Because different object file formats impose different restrictions on custom section names (length, “.” prefix), a shorthand syntax to specify different section names for different object file formats was considered: `@section(ELF: “...”, MachO: “...”, COFF: “...”)`. This, however, has drawbacks of repeating the file format in cases where the code is only ever targeting a single format (common for example for embedded firmwares on ELF). The benefits of a shorthand syntax is marginal, given that we don’t expect normal application code to used the `@section` attribute directly but instead rely on macros or other higher-level API. + +The alternative of using conditional compilation is what is expected to be used for those cases instead. + +### Umbrella attribute for linkage properties + +Instead of separate `@section` and `@used` attributes, a unified attribute with parameters to control individual linkage properties was considered, spelled for example `@linkage(section: ..., used)`. Further linkage control features would be added into this umbrella attribute. + +This, however, adds challenges on composability — one umbrella attribute would need to allow multiple occurrences and the design would need rules for merging of individual properties from multiple attributes. Separate standalone attributes compose trivially, and also they play nicely with the existing `#if hasAttribute(...)` conditional compilation mechanism. There is currently no mechanism for conditional compilation based on whether a sub-feature of a umbrella attribute is available in the compiler. + +Given the above, and also given that controlling symbol and linker level properties is not something that we expect normal application code to do directly, it’s more appropriate to keep the attribute system simple, and have individual orthogonal composable attributes. + +### `@section` implying `@used` + +In a lot of the list code snippets in this proposal, both `@section` and `@used` were used together, and so it may seem that it’s not necessary for those to be two separate attributes. However: + +* `@section` and `@used` represent separate concepts and all combinations of them can be useful. An example of using `@section` without `@used` is to place for example a large data table from a library into its own section for binary size accounting reasons (so that it shows up separately in per-section binary size listings), but where we’d still expect the data table to be dead-code removed if not used. +* It’s already common to have those attributes as separate options in existing popular systems programming languages (C, C++, Rust). From bc15c64a72b7c40f9949158d0b751299d86fb007 Mon Sep 17 00:00:00 2001 From: "Kuba (Brecka) Mracek" Date: Fri, 24 Jan 2025 09:41:56 -0800 Subject: [PATCH 028/505] Update links --- proposals/0nnn-section-control.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md index 985be91e6f..3f0d9e0aca 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0nnn-section-control.md @@ -6,11 +6,11 @@ * Discussion threads: * Pitch #1: https://forums.swift.org/t/pitch-low-level-linkage-control-attributes-used-and-section/65877 * Pitch #2: https://forums.swift.org/t/pitch-2-low-level-linkage-control/69752 - * Pitch #3: TBD + * Pitch #3: https://forums.swift.org/t/pitch-3-section-placement-control/77435 ## Introduction -This proposal builds on top of [Swift Compile-Time Values](https://TBD) and adds two new attributes into the Swift language: `@section` and `@used`. These allow users to directly control which section of the resulting binary should globals variables be emitted into, and give users the ability to disable DCE (dead code elimination) on those. The goal is to enable systems and embedded programming use cases like runtime discovery of test metadata from multiple modules, and also to serve as a low-level building block for higher-level features (e.g. linker sets, plugins). +This proposal builds on top of [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md) and adds two new attributes into the Swift language: `@section` and `@used`. These allow users to directly control which section of the resulting binary should globals variables be emitted into, and give users the ability to disable DCE (dead code elimination) on those. The goal is to enable systems and embedded programming use cases like runtime discovery of test metadata from multiple modules, and also to serve as a low-level building block for higher-level features (e.g. linker sets, plugins). The intention is that these attributes are to be used rarely and only by specific use cases; high-level application code should not need to use them directly and instead should rely on libraries, macros and other abstractions over the low-level attributes. @@ -59,7 +59,7 @@ This proposal recommends to use sections of the various object file formats as t ## Proposed Solution -The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". The `@section` attribute relies heavily on the facilities provided by [Swift Compile-Time Values](https://TBD), namely the ability to enforce constantness of an expressions. Using `@section` requires that the initializer expression is a constant expression: +The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". The `@section` attribute relies heavily on the facilities provided by [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), namely the ability to enforce constantness of an expressions. Using `@section` requires that the initializer expression is a constant expression: ```swift // Place entry into a section, mark as "do not dead strip". @@ -227,7 +227,7 @@ let d2 = @const d1.count // statically initializable *However, using a statically non-initializable value in an expression does not preclude the outer expression from being statically initialized either. In this example, `d1` would not be allowed to be placed into a custom section because it’s not statically initializable. But `d2` could still potentially be statically initializable (even though the definition of `d2` uses a sub-expression that is not statically initializable), as it’s simply an integer.* -As described in [Swift Compile-Time Values](https://TBD), values of function types are eligible for being compile-time evaluable. Their concrete pointer value is not fully known until link-time or program load-time (depending on type of linking, ASLR, PAC, etc.). For the purposes of guaranteed static initialization, function values are statically initialized into a function pointer. This pointer is still subject to normal linking and loading resolutions and fixups. +As described in [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), values of function types are eligible for being compile-time evaluable. Their concrete pointer value is not fully known until link-time or program load-time (depending on type of linking, ASLR, PAC, etc.). For the purposes of guaranteed static initialization, function values are statically initialized into a function pointer. This pointer is still subject to normal linking and loading resolutions and fixups. ```swift func foo() { ... } From c107545a564d4307ce33832c08ffc184deb5c9e3 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Sun, 2 Feb 2025 00:45:10 +0000 Subject: [PATCH 029/505] Replaceable Library Plugins --- proposals/0461-replaceable-library-plugins.md | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 proposals/0461-replaceable-library-plugins.md diff --git a/proposals/0461-replaceable-library-plugins.md b/proposals/0461-replaceable-library-plugins.md new file mode 100644 index 0000000000..10b3603c35 --- /dev/null +++ b/proposals/0461-replaceable-library-plugins.md @@ -0,0 +1,154 @@ +# Replaceable Library Plugins + +* Proposal: [SE-0461](0641-replaceable-library-plugins.md) +* Authors: [tayloraswift](https://github.com/tayloraswift) +* Review Manager: TBD +* Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) +* Bugs: [SR-5714](https://github.com/swiftlang/swift-package-manager/issues/5714) + +## Introduction + +SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Replaceable Library Plugins**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Replaceable Library Plugins through the existing `.artifactbundle` format. + +Swift-evolution thread: [Discussion thread topic for that +proposal](https://forums.swift.org/) + + +## Motivation + +Many of us in the Server World have a Big App with a small component that changes very rapidly, much more rapidly than the rest of the App. This component might be something like a filter, or an algorithm, or a plugin that is being constantly tuned. + +We could, for argument’s sake, try and turn this component into data that can be consumed by the Big App, which would probably involve designing a bytecode and an interpreter, and maybe even a whole interpreted domain-specific programming language. But that is Really Hard and we would rather just write this thing In Swift, and let Swift code call Swift code. + +While macOS has Dynamic Library support through XCFrameworks, on Linux we currently have to recompile the Big App from source and redeploy the Big App every time the filter changes, and we don’t want to do that. What we really want instead is to have the Big App link the filter as a Dynamic Library, and redeploy the Dynamic Library as needed. + + +## Proposed solution + +On Linux, there are a lot of obstacles to having fully general support for Dynamic Libraries. Swift is not ABI stable on Linux, and Linux itself is not a single platform but a wide range of similar platforms that provide few binary compatibility guarantees. This means it is pretty much impossible for a public Swift library to vend precompiled binaries that will Just Work for everyone, and we are not going to try to solve that problem in this proposal. + +Instead, we will focus on **Replaceable Library Plugins** (RLPs). We choose this term to emphasize the distinction between our use case and fully general Dynamic Libraries. + +### Organization-Defined Platforms (ODPs) + +Unlike fully general Dynamic Libraries, you would distribute Replaceable Library Plugins strictly for internal consumption within an organization, or to a small set of paying clients. + +The organization that distributes an RLP is responsible for defining what exactly constitutes a “platform” for their purposes. An Organization-Defined Platform (ODP) is not necessarily an operating system or architecture, or even a specific distribution of an operating system. A trivial example of two ODPs might be: + +1. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift` +2. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift-runtime` + +Concepts like Platform Triples are not sufficient to describe an ODP. Even though both ODPs above would probably share the Triple `aarch64-unknown-linux-gnu`, code compiled for one would never be able to run on the other. + +Organizations add and remove ODPs as needed, and trying to define a global registry of all possible ODPs is a non-goal. + +To keep things simple, we identify ODPs by the URL of the Artifact Bundle that contains the RLP. + +### Creating RLPs + +To compile an RLP, you just need to build an ordinary SwiftPM library product with the `-enable-library-evolution` flag. This requires no modifications to SwiftPM. + +You would package an RLP as an `.artifactbundle` just as you would an executable, with the following differences: + +- The `info.json` must have `schemaVersion` set to `1.2` or higher. +- The artifact type must be `library`, a new enum case introduced in this proposal. +- The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. +- The artifact payload must include the `.swiftinterface` file corresponding to the actual library object. + +Because SwiftPM is not (and cannot be) aware of a particular organization’s ODPs, this enforces the requirement that each ODP must have its own Artifact Bundle. + +The organization that distributes the RLP is responsible for upholding ABI stability guarantees, including the exact Swift compiler and runtime versions needed to safely consume the RLP. + + +### Consuming RLPs + +To consume an RLP, you would add a `binaryTarget` to your `Package.swift` manifest, just as you would for an executable. Because ODPs are identified by the URL of the Artifact Bundle, there are no new fields in the `PackageDescription` API. + +We expect that the logic for selecting the correct RLP for a given ODP would live within the `Package.swift` file, that it would be highly organization-specific, and that it would be manipulated using existing means such as environment variables. + + +### Deploying RLPs + +Deploying RLPs does not involve SwiftPM or Artifact Bundles at all. You would deploy an RLP by copying the latest binaries to the appropriate `@rpath` location on each machine in your fleet. The `@rpath` location is part of the ODP definition, and is not modeled by SwiftPM. + +Some organizations might choose to forgo the `@rpath` mechanism entirely and simply install the RLPs in a system-wide location. + + +## Detailed design + +### Schema extensions + +We will extend the `ArtifactsArchiveMetadata` schema to include a new `library` case in the `ArtifactType` enum. + +```diff +public enum ArtifactType: String, RawRepresentable, Decodable { + case executable ++ case library + case swiftSDK +} +``` + +This also bumps the latest `schemaVersion` to `1.2`. + + +### Artifact Bundle layout + +Below is an example of an `info.json` file for an Artifact Bundle containing a single library called `MyLibrary`. + +```json +{ + "schemaVersion": "1.2", + "artifacts": { + "MyLibrary": { + "type": "library", + "version": "1.0.0", + "variants": [{ "path": "MyLibrary" }] + } + } +} +``` + +The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. An RLP Artifact Bundle can contain multiple libraries at the top level. + +Below is an example of the layout of an Artifact Bundle containing a single library called `MyLibrary`. Only the `info.json` must appear at the root of the Artifact Bundle; all other files can appear at whatever paths are defined in the `info.json`, as long as they are within the Artifact Bundle. + +```text +📂 example.artifactbundle + 📂 MyLibrary + ⚙️ libMyLibrary.so + 📝 MyLibrary.swiftinterface + 📝 info.json +``` + +A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. RLPs will be supported on macOS, although we expect this will be an exceedingly rare use case. + + +## Security + +RLPs are not intended for public distribution, and are not subject to the same security concerns as public libraries. Organizations that distribute RLPs are responsible for ensuring that the RLPs are safe to consume. + + +## Impact on existing packages + +There will be no impact on existing packages. All Artifact Bundle schema changes are additive. + + +## Alternatives considered + +### Extending Platform Triples to model ODPs + +SwiftPM currently uses Platform Triples to select among artifact variants when consuming executables. This is workable because it is usually feasible to build executables that are portable across the range of platforms encompassed by a single Platform Triple. + +We could extend Platform Triples to model ODPs, but this would privilege a narrow set of predefined deployment architectures, and if you wanted to add a new ODP, you would have to modify SwiftPM to teach it to recognize the new ODP. + +### Supporting multiple variants of an RLP in the same Artifact Bundle + +We could allow an Artifact Bundle to contain multiple variants of an RLP, but we would still need to support a way to identify those variants, which in practice makes SwiftPM aware of ODPs. + +We also don’t see much value in this feature, as you would probably package and upload RLPs using one CI/CD workflow per ODP anyway. Combining artifacts would require some kind of synchronization mechanism to await all pipelines before fetching and merging bundles. + +One benefit of merging bundles would be that it reduces the number of checksums you need to keep track of, but we expect that most organizations will have a very small number of ODPs, with new ODPs continously phasing out old ODPs. + +### Using a different `ArtifactType` name besides `library` + +We intentionally preserved the structure of the `variants` list in the `info.json` file, despite imposing the current restriction of one variant per library, in order to allow this format to be extended in the future to support fully general Dynamic Libraries. From f3a13de34a3b2b8c957630e2f30a38ef4cad67b5 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Sun, 2 Feb 2025 00:56:25 +0000 Subject: [PATCH 030/505] links to example projects --- proposals/0461-replaceable-library-plugins.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proposals/0461-replaceable-library-plugins.md b/proposals/0461-replaceable-library-plugins.md index 10b3603c35..6b952b95ae 100644 --- a/proposals/0461-replaceable-library-plugins.md +++ b/proposals/0461-replaceable-library-plugins.md @@ -13,12 +13,15 @@ SwiftPM currently has no support for non-system binary library dependencies on L Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/) +Example Producer: [swift-rlp-example](https://github.com/tayloraswift/swift-rlp-example) + +Example Consumer: [swift-rlp-example-client](https://github.com/tayloraswift/swift-rlp-example-client) ## Motivation Many of us in the Server World have a Big App with a small component that changes very rapidly, much more rapidly than the rest of the App. This component might be something like a filter, or an algorithm, or a plugin that is being constantly tuned. -We could, for argument’s sake, try and turn this component into data that can be consumed by the Big App, which would probably involve designing a bytecode and an interpreter, and maybe even a whole interpreted domain-specific programming language. But that is Really Hard and we would rather just write this thing In Swift, and let Swift code call Swift code. +We could, for argument’s sake, try and turn this component into data that can be consumed by the Big App, which would probably involve designing a bytecode and an interpreter, and maybe even a whole interpreted domain-specific programming language. But that is very hard and we would rather just write this thing in Swift, and let Swift code call Swift code. While macOS has Dynamic Library support through XCFrameworks, on Linux we currently have to recompile the Big App from source and redeploy the Big App every time the filter changes, and we don’t want to do that. What we really want instead is to have the Big App link the filter as a Dynamic Library, and redeploy the Dynamic Library as needed. @@ -38,7 +41,7 @@ The organization that distributes an RLP is responsible for defining what exactl 1. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift` 2. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift-runtime` -Concepts like Platform Triples are not sufficient to describe an ODP. Even though both ODPs above would probably share the Triple `aarch64-unknown-linux-gnu`, code compiled for one would never be able to run on the other. +Concepts like Platform Triples are not sufficient to describe an ODP. Even though both ODPs above would probably share the Triple `aarch64-unknown-linux-gnu`, Swift code compiled (without `--static-swift-stdlib`) for one would never be able to run on the other. Organizations add and remove ODPs as needed, and trying to define a global registry of all possible ODPs is a non-goal. From 686a8c96f0121cd183444815390985045b1086ed Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Sun, 2 Feb 2025 01:11:11 +0000 Subject: [PATCH 031/505] link to Forums thread --- proposals/0461-replaceable-library-plugins.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0461-replaceable-library-plugins.md b/proposals/0461-replaceable-library-plugins.md index 6b952b95ae..a89ccffc52 100644 --- a/proposals/0461-replaceable-library-plugins.md +++ b/proposals/0461-replaceable-library-plugins.md @@ -10,8 +10,7 @@ SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Replaceable Library Plugins**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Replaceable Library Plugins through the existing `.artifactbundle` format. -Swift-evolution thread: [Discussion thread topic for that -proposal](https://forums.swift.org/) +Swift-evolution thread: [Discussion thread](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605) Example Producer: [swift-rlp-example](https://github.com/tayloraswift/swift-rlp-example) From b02a4ac7241a110e46e0273a81631b575162f7c8 Mon Sep 17 00:00:00 2001 From: Dianna Date: Sat, 1 Feb 2025 21:02:44 -0600 Subject: [PATCH 032/505] unassigned number --- ...e-library-plugins.md => NNNN-replaceable-library-plugins.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{0461-replaceable-library-plugins.md => NNNN-replaceable-library-plugins.md} (99%) diff --git a/proposals/0461-replaceable-library-plugins.md b/proposals/NNNN-replaceable-library-plugins.md similarity index 99% rename from proposals/0461-replaceable-library-plugins.md rename to proposals/NNNN-replaceable-library-plugins.md index a89ccffc52..35f2d9e1c3 100644 --- a/proposals/0461-replaceable-library-plugins.md +++ b/proposals/NNNN-replaceable-library-plugins.md @@ -1,6 +1,6 @@ # Replaceable Library Plugins -* Proposal: [SE-0461](0641-replaceable-library-plugins.md) +* Proposal: [SE-NNNN](NNNN-replaceable-library-plugins.md) * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) From ce8b4bd6bf1d1c0ea385ea9b45ad69497aad3a87 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 4 Feb 2025 10:30:29 -0800 Subject: [PATCH 033/505] SE-0458: Allow @safe declarations to subsume some responsibility for their arguments --- proposals/0458-strict-memory-safety.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index b973058c7d..7a5998d53e 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -125,7 +125,7 @@ extension UnsafeMutableBufferPointer { @unsafe public func swapAt(_ i: Index, _ j: Index) { guard i != j else { return } precondition(i >= 0 && j >= 0) - precondition(unsafe i < endIndex && j < endIndex) + precondition(i < endIndex && j < endIndex) let pi = unsafe (baseAddress! + i) let pj = unsafe (baseAddress! + j) let tmp = unsafe pi.move() @@ -217,7 +217,7 @@ There are a few exemptions to the rule that any unsafe constructs within the sig ### `@safe` attribute -Like the `@unsafe` attribute, the `@safe` attribute ise used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is consider safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: +Like the `@unsafe` attribute, the `@safe` attribute is used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is consider safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: ```swift extension UnsafeBufferPointer { @@ -249,6 +249,20 @@ extension Array { } ``` +The `@safe` annotation on a declaration takes responsibility for its direct arguments, so (for example) a variable of unsafe type used as an argument to a `@safe` function (or as the `self` for a property or subscript reference) will not be diagnosed as unsafe: + +```swift +extension Array { + func sum() -> Int { + withUnsafeBufferPointer { buffer in + let count = buffer.count // count is `@safe`, no diagnostic even though 'buffer' has unsafe type + let address = buffer.baseAddress // warning: 'buffer' and 'baseAddress' are both unsafe + c_library_sum_function(address, count, 0) // warning: 'c_library_sum_function' and 'address' are both unsafe + } + } +} +``` + ### `unsafe` expression When a declaration is marked `@unsafe`, it is free to use any other unsafe types as part of its interface. Any time there is executable code that makes use of unsafe constructs, that code must be within an `unsafe` expression or it will receive a diagnostic about uses of unsafe code. In the example from the previous section, `wrapper` can be marked as `@unsafe` to suppress diagnostics by explicitly propagating unsafety to their clients: From b302ea65f68c90675ec8a16d1a26d6f731530998 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 4 Feb 2025 10:44:28 -0800 Subject: [PATCH 034/505] Improve wording of this carve-out a bit --- proposals/0458-strict-memory-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 7a5998d53e..950098c0c1 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -249,7 +249,7 @@ extension Array { } ``` -The `@safe` annotation on a declaration takes responsibility for its direct arguments, so (for example) a variable of unsafe type used as an argument to a `@safe` function (or as the `self` for a property or subscript reference) will not be diagnosed as unsafe: +The `@safe` annotation on a declaration takes responsibility for any variables of unsafe type that are used as its direct arguments (including the `self`). If such a variable is used to access a `@safe` property or subscript, or in a function call to a `@safe` function, it will not be diagnosed as unsafe: ```swift extension Array { From 46c6781a92c8f76d8275192b86c3cf1d986977c0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 4 Feb 2025 17:23:30 -0800 Subject: [PATCH 035/505] SE-0458: Add revision history --- proposals/0458-strict-memory-safety.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 950098c0c1..63e6a315ad 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -430,6 +430,11 @@ Other than the source break above, the introduction of this strict safety checki The attributes, `unsafe` expression, and strict memory-safety checking model proposed here have no impact on ABI. +## Revision history + +* **Revision 2 (following first review)** + * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. + ## Future Directions ### The `SerialExecutor` and `Actor` protocols From 86c1028817fabed4bb1816925db6175f98a135ff Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Feb 2025 13:25:43 -0800 Subject: [PATCH 036/505] SE-0458: Add Alternatives Considered section on unsafe conformances/overrides --- proposals/0458-strict-memory-safety.md | 64 +++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 63e6a315ad..12d4288ae6 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -217,7 +217,7 @@ There are a few exemptions to the rule that any unsafe constructs within the sig ### `@safe` attribute -Like the `@unsafe` attribute, the `@safe` attribute is used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is consider safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: +Like the `@unsafe` attribute, the `@safe` attribute is used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is considered safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: ```swift extension UnsafeBufferPointer { @@ -430,11 +430,6 @@ Other than the source break above, the introduction of this strict safety checki The attributes, `unsafe` expression, and strict memory-safety checking model proposed here have no impact on ABI. -## Revision history - -* **Revision 2 (following first review)** - * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. - ## Future Directions ### The `SerialExecutor` and `Actor` protocols @@ -489,6 +484,57 @@ We have several options here: ## Alternatives considered +### Prohibiting unsafe conformances and overrides entirely + +This proposal introduces two places where polymorphism interacts with unsafety: protocol conformances and overrides. In both cases, a safe abstraction (e.g., a superclass or protocol) has a specific implementation that is unsafe, and there is a way to note the unsafety: + +* When overriding a safe declaration with an unsafe one, the overriding subclass must be marked `@unsafe`. +* When implementing a safe protocol requirement with an unsafe declaration, the corresponding conformance must be marked `@unsafe`. + +In both cases, the current proposal will consider uses of the type (in the overriding case) or conformance (for that case) as unsafe, respectively. However, that unsafety is not localized, because code that's generally safe can now cause safety problems when calling through polymorphic operations. For example, consider a function that operates on a general collection: + +```swift +func parse(_ input: some Collection) -> ParseResult +``` + +Calling this function with an unsafe buffer pointer will produce a diagnostic due to the use of the unsafe conformance of `UnsafeBufferPointer` to `Collection`: + +```swift +let result = parse(unsafeBufferPointer) // warning: use of unsafe conformance +``` + +Marking the call as `unsafe` will address the diagnostic. However, because `UnsafeBufferPointer` doesn't perform bounds checking, the `parse` function itself can introduce a memory safety problem if it subscripts into the collection with an invalid index. There isn't a way to communicate how the code that is `unsafe` is addressing memory safety issues within the context of the call. + +This proposal could prohibit use of unsafe conformances and overrides entirely, for example by making it impossible to suppress the diagnostics associated with their definition and use. This would require the `parse(unsafeBufferPointer)` call to be refactored to avoid the unsafe conformance, for example by introducing a wrapper type: + +```swift +@safe struct ImmortalBufferWrapper : Collection { + let buffer: UnsafeBufferPointer + + @unsafe init(_ withImmortalBuffer: UnsafeBufferPointer) { + self.buffer = unsafe buffer + } + + subscript(index: Index) -> Element { + precondition(index >= 0 && index < buffer.count) + return unsafe buffer[index] + } + + /* Also: Index, startIndex, endIndex, index(after:) */ +} +``` + +The call would then look like this: + +```swift +let wrapper = unsafe ImmortalBufferWrapper(withImmortalBuffer: buffer) +let result = parse(wrapper) +``` + +This approach is better than the prior one: it improves bounds safety by introducing bounds checking. It clearly documents the assumptions made around lifetime safety. It is both functionally safer (due to bounds checks) and makes it easier to reason that the `unsafe` is correctly used. It does require a lot more code, and the code itself requires careful reasoning about safety (e.g., the right preconditions for bounds checking; the right naming to capture the lifetime implications). + +Unsafe conformances and overrides remain part of this proposal because prohibiting them doesn't fundamentally change the safety model. Rather, it requires the introduction of more abstractions that could be safer--or could just be boilerplate. Swift has a number of constructs that are functionally similar to unsafe conformances, where safety checking can be disabled locally despite that having wide-ranging consequences: `@unchecked Sendable`, `nonisolated(unsafe)`, `unowned(unsafe)`, and `@preconcurrency` all fall into this category. + ### `@unsafe` implying `unsafe` throughout a function body A function marked `@unsafe` is unsafe to use, so any clients that have enabled strict safety checking will need to put uses of the function into an `unsafe` expression. The implementation of that function is likely to use unsafe code (possibly a lot of it), which could result in a large number of annotations: @@ -654,6 +700,12 @@ There are downsides to this approach. It partially undermines the source compati We could introduce an optional `message` argument to the `@unsafe` attribute, which would allow programmers to indicate *why* the use of a particular declaration is unsafe and, more importantly, how to safely write code that uses it. However, this argument isn't strictly necessary: a comment could provide the same information, and there is established tooling to expose comments to programmers that wouldn't be present for this attribute's message, so we have omitted this feature. +## Revision history + +* **Revision 2 (following first review)** + * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. + * Add an Alternatives Considered section on prohibiting unsafe conformances and overrides. + ## Acknowledgments This proposal has been greatly improved by the feedback from Félix Cloutier, Geoff Garen, Gábor Horváth, Frederick Kellison-Linn, Karl Wagner, and Xiaodi Wu. From a3947c847485b4ccc43ec5983051ec47ac3df569 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Feb 2025 13:34:17 -0800 Subject: [PATCH 037/505] SE-0458: Require types to be marked @safe/@unsafe if their storage is unsafe --- proposals/0458-strict-memory-safety.md | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 12d4288ae6..0ec06c1bb2 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -331,6 +331,35 @@ There are a number of compiler flags that intentionally disable some safety-rela * `-strict-concurrency=` for anything other than "complete", because the memory safety model requires strict concurrency to eliminate thread safety issues. * `-disable-access-control`, which allows one to break invariants of a type that can lead to memory-safety issues, such as breaking the invariant of `Range` that the lower bound not exceed the upper bound. +### Types with unsafe storage + +Types that wrap unsafe types will often encapsulate the unsafe behavior to provide safe interfaces. However, this requires deliberate design and implementation, potentially involving adding specific preconditions. When strict safety checking is enabled, a type whose storage is unsafe will be diagnosed as involving unsafe code. This diagnostic can be suppressed by marking the type as `@safe` or `@unsafe`, in the same manner as any other declaration that has unsafe types or conformances in its signature: + +```swift +// @safe is required to suppress a diagnostic about the 'buffer' property's use +// of an unsafe type. +@safe +struct ImmortalBufferWrapper : Collection { + let buffer: UnsafeBufferPointer + + @unsafe init(_ withImmortalBuffer: UnsafeBufferPointer) { + self.buffer = unsafe buffer + } + + subscript(index: Index) -> Element { + precondition(index >= 0 && index < buffer.count) + return unsafe buffer[index] + } + + /* Also: Index, startIndex, endIndex, index(after:) */ +} +``` + +A type has unsafe storage if: + +* Any stored instance property (for `actor`, `class`, and `struct` types) or associated value (for cases of `enum` types) have a type that involves an unsafe type or conformance. +* Any stored instance property uses one of the unsafe language features (such as `unowned(unsafe)`). + ### Unsafe overrides Overriding a safe method within an `@unsafe` one could introduce unsafety, so it will produce a diagnostic in the strict safety mode: @@ -704,6 +733,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh * **Revision 2 (following first review)** * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. + * Require types whose storage involves an unsafe type or conformance to be marked as `@safe` or `@unsafe`, much like other declarations that have unsafe types or conformances in their signature. * Add an Alternatives Considered section on prohibiting unsafe conformances and overrides. ## Acknowledgments From 06ef7bcc8ca908f6af190462ce81e58fe4541383 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Feb 2025 14:01:23 -0800 Subject: [PATCH 038/505] Add a Future Directions section on handling unsafe code in macro expansions. --- proposals/0458-strict-memory-safety.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 0ec06c1bb2..4538a6b2f6 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -511,6 +511,14 @@ We have several options here: if case unsafe .rawOffsetIntoGlobalArray(let offset) = weirdAddress { ... } ``` +### Handling unsafe code in macro expansions + +A macro can expand to any code. If the macro-expanded code contains uses of unsafe constructs not properly covered by `@safe`, `@unsafe`, or an `unsafe` expression within the macro, then strict safety checking will diagnose those safety issues within the macro expansion. In this case, the client of the macro does not have any way to suppress diagnostics within the macro expansion itself without modifying the implementation of the macro. + +There are a number of possible approaches that one could use for suppression. The `unsafe` expression could be made to apply to everything in the macro expansion, which would also require some spelling for attached attributes and other places where expressions aren't permitted. Alternatively, Swift could introduce a general syntax for suppressing a class of warnings within a block of code, and that could be used to surround the macro expansion. + +Note that both of these approaches trade away some of the benefits of the strict safety mode for the convenience of suppressing safety-related diagnostics. + ## Alternatives considered ### Prohibiting unsafe conformances and overrides entirely @@ -735,6 +743,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. * Require types whose storage involves an unsafe type or conformance to be marked as `@safe` or `@unsafe`, much like other declarations that have unsafe types or conformances in their signature. * Add an Alternatives Considered section on prohibiting unsafe conformances and overrides. + * Add a Future Directions section on handling unsafe code in macro expansions. ## Acknowledgments From 15f57c72f53d6c36f0a2c1d34ca925d259101945 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 5 Feb 2025 17:55:58 -0500 Subject: [PATCH 039/505] Link to the previous revision --- proposals/0458-strict-memory-safety.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 4538a6b2f6..c63ca13241 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -7,6 +7,7 @@ * Feature name: `StrictMemorySafety` * Vision: [Opt-in Strict Memory Safety Checking (Prospective)](https://github.com/swiftlang/swift-evolution/pull/2581) * Implementation: On main with experimental feature flags `AllowUnsafeAttribute` and `WarnUnsafe` +* Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/f2cab4ddc3381d1dc7a970e813ed29e27b5ae43f/proposals/0458-strict-memory-safety.md) * Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) ## Introduction From 9d180aea291c6b430bcc816ce12ef0174ec0237b Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 5 Feb 2025 18:13:00 -0500 Subject: [PATCH 040/505] Extend the SE-0458 review --- proposals/0458-strict-memory-safety.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index c63ca13241..c194e8dd49 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -3,12 +3,12 @@ * Proposal: [SE-0458](0458-strict-memory-safety.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active Review (January 17th...27th, 2025)** +* Status: **Active Review (January 17th...February 11th, 2025)** * Feature name: `StrictMemorySafety` * Vision: [Opt-in Strict Memory Safety Checking (Prospective)](https://github.com/swiftlang/swift-evolution/pull/2581) * Implementation: On main with experimental feature flags `AllowUnsafeAttribute` and `WarnUnsafe` * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/f2cab4ddc3381d1dc7a970e813ed29e27b5ae43f/proposals/0458-strict-memory-safety.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) +* Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) ([mid-review revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/33)) ## Introduction From bdc64a33ba9e6b51810defcbf8b8ff5c77542894 Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Thu, 6 Feb 2025 21:33:34 +0000 Subject: [PATCH 041/505] [SE-0459] Fix metadata of `enumerated()` proposal (#2671) --- proposals/0459-enumerated-collection.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/0459-enumerated-collection.md b/proposals/0459-enumerated-collection.md index 4018b8b7b9..a2df267080 100644 --- a/proposals/0459-enumerated-collection.md +++ b/proposals/0459-enumerated-collection.md @@ -1,17 +1,17 @@ # Add `Collection` conformances for `enumerated()` -* Previous proposal: [SE-0312](0312-indexed-and-enumerated-zip-collections.md) +* Proposal: [SE-0459](0459-enumerated-collection.md) * Author: [Alejandro Alonso](https://github.com/Azoy) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Active Review (28 Jan - February 7 2025)** -* Implementation: [apple/swift#78092](https://github.com/swiftlang/swift/pull/78092) +* Status: **Active review (January 28 – February 7, 2025)** +* Implementation: [swiftlang/swift#78092](https://github.com/swiftlang/swift/pull/78092) +* Previous Proposal: [SE-0312](0312-indexed-and-enumerated-zip-collections.md) +* Review: ([pitch](https://forums.swift.org/t/pitch-add-collection-conformance-for-enumeratedsequence/76680)) ([review](https://forums.swift.org/t/se-0459-add-collection-conformances-for-enumerated/77509)) ## Introduction This proposal aims to fix the lack of `Collection` conformance of the sequence returned by `enumerated()`, preventing it from being used in a context that requires a `Collection`. -Swift-evolution thread: [Pitch](https://forums.swift.org/t/pitch-add-indexed-and-collection-conformances-for-enumerated-and-zip/47288) - ## Motivation Currently, `EnumeratedSequence` type conforms to `Sequence`, but not to any of the collection protocols. Adding these conformances was impossible before [SE-0234 Remove `Sequence.SubSequence`](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0234-remove-sequence-subsequence.md), and would have been an ABI breaking change before the language allowed `@available` annotations on protocol conformances ([PR](https://github.com/apple/swift/pull/34651)). Now we can add them! From c27e570d3a0e2fe9f07a2fed8d2f6e14756340a2 Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Thu, 6 Feb 2025 22:07:57 +0000 Subject: [PATCH 042/505] [SE-0460] Fix metadata of `@specialized` proposal (#2686) --- proposals/0460-specialized.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0460-specialized.md b/proposals/0460-specialized.md index 4a1ba283bf..6f0979f9e7 100644 --- a/proposals/0460-specialized.md +++ b/proposals/0460-specialized.md @@ -5,7 +5,7 @@ * Review Manager: [Steve Canon](https://github.com/stephentyrone) * Status: **Active Review (January 29 ... February 11, 2025)** * Implementation: Available in nightly toolchains using the underscored `@_specialize` -* Discussion: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967))([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) +* Review: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967)) ([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) ## Introduction From 8b38f1739a17b40f939a30deb799144bf48663bc Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 7 Feb 2025 05:29:58 -0800 Subject: [PATCH 043/505] [SE-0453] Rename Vector to InlineArray (#2682) --- proposals/0453-vector.md | 307 ++++++++++++++++++++------------------- 1 file changed, 156 insertions(+), 151 deletions(-) diff --git a/proposals/0453-vector.md b/proposals/0453-vector.md index 17e5f7924d..9828b90203 100644 --- a/proposals/0453-vector.md +++ b/proposals/0453-vector.md @@ -1,4 +1,4 @@ -# Vector, a fixed-size array +# InlineArray, a fixed-size array * Proposal: [SE-0453](0453-vector.md) * Authors: [Alejandro Alonso](https://github.com/Azoy) @@ -10,7 +10,7 @@ ## Introduction -This proposal introduces a new type to the standard library, `Vector`, which is +This proposal introduces a new type to the standard library, `InlineArray`, which is a fixed-size array. This is analogous to the [classical C arrays `T[N]`](https://en.cppreference.com/w/c/language/array), [C++'s `std::array`](https://en.cppreference.com/w/cpp/container/array), @@ -73,18 +73,18 @@ utilities. ## Proposed solution -We introduce a new top level type, `Vector`, to the standard library which is a +We introduce a new top level type, `InlineArray`, to the standard library which is a fixed-size contiguously inline allocated array. We're defining "inline" as using the most natural allocation pattern depending on the context of where this is used. It will be stack allocated most of the time, but as a class property member it will be inline allocated on the heap with the rest of the properties. -`Vector` will never introduce an implicit heap allocation just for its storage +`InlineArray` will never introduce an implicit heap allocation just for its storage alone. ```swift func complexAlgorithm() -> Int { // This is a stack allocation, no 'malloc's or reference counting here! - let elements: Vector<4, Int> = [1, 2, 3, 4] + let elements: InlineArray<4, Int> = [1, 2, 3, 4] for i in elements.indices { compute(elements[i]) // OK @@ -92,43 +92,43 @@ func complexAlgorithm() -> Int { } ``` -Vectors of noncopyable values will be possible by using any of the closure based +InlineArrays of noncopyable values will be possible by using any of the closure based taking initializers or the literal initializer: ```swift // [Atomic(0), Atomic(1), Atomic(2), Atomic(3)] -let incrementingAtomics = Vector<4, Atomic> { i in +let incrementingAtomics = InlineArray<4, Atomic> { i in Atomic(i) } // [Sprite(), Sprite(), Sprite(), Sprite()] // Where the 2nd, 3rd, and 4th elements are all copies of their previous // element. -let copiedSprites = Vector<4, _>(first: Sprite()) { $0.copy() } +let copiedSprites = InlineArray<4, _>(first: Sprite()) { $0.copy() } -// Inferred to be Vector<3, Mutex> -let literalMutexes: Vector = [Mutex(0), Mutex(1), Mutex(2)] +// Inferred to be InlineArray<3, Mutex> +let literalMutexes: InlineArray = [Mutex(0), Mutex(1), Mutex(2)] ``` These closure based initializers are not limited to noncopyable values however! ## Detailed design -`Vector` will be a simple noncopyable struct capable of storing other potentially +`InlineArray` will be a simple noncopyable struct capable of storing other potentially noncopyable elements. It will be conditionally copyable only when its elements are. ```swift -public struct Vector: ~Copyable {} +public struct InlineArray: ~Copyable {} -extension Vector: Copyable where Element: Copyable {} -extension Vector: BitwiseCopyable where Element: BitwiseCopyable {} -extension Vector: Sendable where Element: Sendable {} +extension InlineArray: Copyable where Element: Copyable {} +extension InlineArray: BitwiseCopyable where Element: BitwiseCopyable {} +extension InlineArray: Sendable where Element: Sendable {} ``` ### MemoryLayout -The memory layout of a `Vector` is defined by taking its `Element`'s stride and +The memory layout of a `InlineArray` is defined by taking its `Element`'s stride and multiplying that by its `count` for its size and stride. Its alignment is equal to that of its `Element`: @@ -136,9 +136,9 @@ to that of its `Element`: MemoryLayout.stride == 1 MemoryLayout.alignment == 1 -MemoryLayout>.size == 4 -MemoryLayout>.stride == 4 -MemoryLayout>.alignment == 1 +MemoryLayout>.size == 4 +MemoryLayout>.stride == 4 +MemoryLayout>.alignment == 1 struct Uneven { let x: UInt32 @@ -148,176 +148,176 @@ struct Uneven { MemoryLayout.stride == 8 MemoryLayout.alignment == 4 -MemoryLayout>.size == 32 -MemoryLayout>.stride == 32 -MemoryLayout>.alignment == 4 +MemoryLayout>.size == 32 +MemoryLayout>.stride == 32 +MemoryLayout>.alignment == 4 struct ACoupleOfUInt8s { - let x: Vector<2, UInt8> + let x: InlineArray<2, UInt8> } MemoryLayout.stride == 2 MemoryLayout.alignment == 1 -MemoryLayout>.size == 4 -MemoryLayout>.stride == 4 -MemoryLayout>.alignment == 1 +MemoryLayout>.size == 4 +MemoryLayout>.stride == 4 +MemoryLayout>.alignment == 1 ``` ### Literal Initialization Before discussing any of the API, we need to discuss how the array literal -syntax will be used to initialize a value of `Vector`. While naively we could +syntax will be used to initialize a value of `InlineArray`. While naively we could conform to `ExpressibleByArrayLiteral`, the shape of the initializer always takes an actual `Array` value. This could be optimized away in the simple cases, but fundamentally it doesn't make sense to have to do an array allocation to -initialize a stack allocated `Vector`. Therefore, the array literal -initialization for `Vector` will be a special case, at least to start out with. -A stack allocated vector using a vector literal will do in place initialization +initialize a stack allocated `InlineArray`. Therefore, the array literal +initialization for `InlineArray` will be a special case, at least to start out with. +A stack allocated InlineArray using a InlineArray literal will do in place initialization of each element at its stack slot. The two below are roughly equivalent: ```swift -let numbers: Vector<3, Int> = [1, 2, 3] +let numbers: InlineArray<3, Int> = [1, 2, 3] // Roughly gets compiled as: -// This is not a real 'Vector' initializer! -let numbers: Vector<3, Int> = Vector() +// This is not a real 'InlineArray' initializer! +let numbers: InlineArray<3, Int> = InlineArray() numbers[0] = 1 numbers[1] = 2 numbers[2] = 3 ``` -There shouldn't be any intermediary values being copied or moved into the vector. +There shouldn't be any intermediary values being copied or moved into the InlineArray. -Note that the array literal syntax will only create a `Vector` value when the -compiler knows concretely that it is a `Vector` value. We don't want to break +Note that the array literal syntax will only create a `InlineArray` value when the +compiler knows concretely that it is a `InlineArray` value. We don't want to break source whatsoever, so whatever current rules the compiler has will still be intact. Consider the following uses of the array literal syntax and where each -call site creates either a `Swift.Array` or a `Swift.Vector`. +call site creates either a `Swift.Array` or a `Swift.InlineArray`. ```swift let a = [1, 2, 3] // Swift.Array -let b: Vector<3, Int> = [1, 2, 3] // Swift.Vector +let b: InlineArray<3, Int> = [1, 2, 3] // Swift.InlineArray func generic(_: T) {} generic([1, 2, 3]) // passes a Swift.Array -generic([1, 2, 3] as Vector<3, Int>) // passes a Swift.Vector +generic([1, 2, 3] as InlineArray<3, Int>) // passes a Swift.InlineArray func test(_: T) {} test([1, 2, 3]) // passes a Swift.Array -test([1, 2, 3] as Vector<3, Int>) // error: 'Vector<3, Int>' does not conform to 'ExpressibleByArrayLiteral' +test([1, 2, 3] as InlineArray<3, Int>) // error: 'InlineArray<3, Int>' does not conform to 'ExpressibleByArrayLiteral' func array(_: [T]) {} array([1, 2, 3]) // passes a Swift.Array -array([1, 2, 3] as Vector<3, Int>) // error: 'Vector<3, Int>' is not convertible to 'Array' +array([1, 2, 3] as InlineArray<3, Int>) // error: 'InlineArray<3, Int>' is not convertible to 'Array' -func vector(_: Vector<3, T>) {} +func InlineArray(_: InlineArray<3, T>) {} -vector([1, 2, 3]) // passes a Swift.Vector -vector([1, 2, 3] as [Int]) // error: 'Array' is not convertible to 'Vector<3, Int>' +InlineArray([1, 2, 3]) // passes a Swift.InlineArray +InlineArray([1, 2, 3] as [Int]) // error: 'Array' is not convertible to 'InlineArray<3, Int>' ``` -I discuss later about a hypothetical `ExpressibleByVectorLiteral` and the design -challenges there in [Future Directions](#expressiblebyvectorliteral). +I discuss later about a hypothetical `ExpressibleByInlineArrayLiteral` and the design +challenges there in [Future Directions](#expressiblebyInlineArrayliteral). The literal initialization allows for more type inference just like the current literal syntax does by inferring not only the element type, but also the count as well: ```swift -let a: Vector<_, Int> = [1, 2, 3] // Vector<3, Int> -let b: Vector<3, _> = [1, 2, 3] // Vector<3, Int> -let c: Vector<_, _> = [1, 2, 3] // Vector<3, Int> -let d: Vector = [1, 2, 3] // Vector<3, Int> +let a: InlineArray<_, Int> = [1, 2, 3] // InlineArray<3, Int> +let b: InlineArray<3, _> = [1, 2, 3] // InlineArray<3, Int> +let c: InlineArray<_, _> = [1, 2, 3] // InlineArray<3, Int> +let d: InlineArray = [1, 2, 3] // InlineArray<3, Int> -func takesGenericVector(_: Vector) {} +func takesGenericInlineArray(_: InlineArray) {} -takesGenericVector([1, 2, 3]) // Ok, N is inferred to be '3'. +takesGenericInlineArray([1, 2, 3]) // Ok, N is inferred to be '3'. ``` A compiler diagnostic will occur if the number of elements within the literal do not match the desired count (as well as element with the usual diagnostic): ```swift -// error: expected '2' elements in vector literal, but got '3' -let x: Vector<2, Int> = [1, 2, 3] +// error: expected '2' elements in InlineArray literal, but got '3' +let x: InlineArray<2, Int> = [1, 2, 3] -func takesVector(_: Vector<2, Int>) {} +func takesInlineArray(_: InlineArray<2, Int>) {} -// error: expected '2' elements in vector literal, but got '3' -takesVector([1, 2, 3]) +// error: expected '2' elements in InlineArray literal, but got '3' +takesInlineArray([1, 2, 3]) ``` ### Initialization -In addition to literal initialization, `Vector` offers a few others forms of +In addition to literal initialization, `InlineArray` offers a few others forms of initialization: ```swift -extension Vector where Element: ~Copyable { - /// Initializes every element in this vector running the given closure value +extension InlineArray where Element: ~Copyable { + /// Initializes every element in this InlineArray running the given closure value /// that returns the element to emplace at the given index. /// /// This will call the closure `count` times, where `count` is the static - /// count of the vector, to initialize every element by passing the closure + /// count of the InlineArray, to initialize every element by passing the closure /// the index of the current element being initialized. The closure is allowed /// to throw an error at any point during initialization at which point the - /// vector will stop initialization, deinitialize every currently initialized + /// InlineArray will stop initialization, deinitialize every currently initialized /// element, and throw the given error back out to the caller. /// /// - Parameter next: A closure that returns an owned `Element` to emplace at /// the passed in index. - public init(with next: (Int) throws(E) -> Element) throws(E) + public init(_ next: (Int) throws(E) -> Element) throws(E) - /// Initializes every element in this vector by running the closure with the + /// Initializes every element in this InlineArray by running the closure with the /// previously initialized element. /// /// This will call the closure 'count' times, where 'count' is the static - /// count of the vector, to initialize every element by passing the closure + /// count of the InlineArray, to initialize every element by passing the closure /// an immutable borrow reference to the previously initialized element. The /// closure is allowed to throw an error at any point during initialization at - /// which point the vector will stop initialization, deinitialize every + /// which point the InlineArray will stop initialization, deinitialize every /// currently initialized element, and throw the given error back out to the /// caller. /// - /// - Parameter first: The first value to insert into the vector which will be + /// - Parameter first: The first value to insert into the InlineArray which will be /// passed to the closure as a borrow. /// - Parameter next: A closure that passes in an immutable borrow reference - /// of the previously initialized element of the vector + /// of the previously initialized element of the InlineArray /// which returns an owned `Element` instance to insert into - /// the vector. + /// the InlineArray. public init( first: consuming Element, next: (borrowing Element) throws(E) -> Element ) throws(E) } -extension Vector where Element: Copyable { - /// Initializes every element in this vector to a copy of the given value. +extension InlineArray where Element: Copyable { + /// Initializes every element in this InlineArray to a copy of the given value. /// - /// - Parameter value: The instance to initialize this vector with. + /// - Parameter value: The instance to initialize this InlineArray with. public init(repeating: Element) } ``` ### Deinitialization and consumption -Once a vector is no longer used, the compiler will implicitly destroy its value. +Once a InlineArray is no longer used, the compiler will implicitly destroy its value. This means that it will do an element by element deinitialization, releasing any class references or calling any `deinit`s on noncopyable elements. ### Generalized `Sequence` and `Collection` APIs -While we aren't conforming `Vector` to `Collection` (more information in future +While we aren't conforming `InlineArray` to `Collection` (more information in future directions), we do want to generalize a lot of APIs that will make this a usable collection type. ```swift -extension Vector where Element: ~Copyable { +extension InlineArray where Element: ~Copyable { public typealias Element = Element public typealias Index = Int @@ -339,70 +339,71 @@ extension Vector where Element: ~Copyable { ) public subscript(_ index: Int) -> Element + public subscript(unchecked index: Int) -> Element } ``` ## Source compatibility -`Vector` is a brand new type in the standard library, so source should still be +`InlineArray` is a brand new type in the standard library, so source should still be compatible. Given the name of this type however, we foresee this clashing with existing user -defined types named `Vector`. This isn't a particular issue though because the +defined types named `InlineArray`. This isn't a particular issue though because the standard library has special shadowing rules which prefer user defined types by -default. Which means in user code with a custom `Vector` type, that type will -always be preferred over the standard library's `Swift.Vector`. By always I +default. Which means in user code with a custom `InlineArray` type, that type will +always be preferred over the standard library's `Swift.InlineArray`. By always I truly mean _always_. Given the following two scenarios: ```swift // MyLib -public struct Vector { +public struct InlineArray { } -print(Vector.self) +print(InlineArray.self) -// error: generic type 'Vector' specialized with too many type parameters +// error: generic type 'InlineArray' specialized with too many type parameters // (got 2, but expected 1) -print(Vector<3, Int>.self) +print(InlineArray<3, Int>.self) ``` -Here, we're exercising the fact that this `MyLib.Vector` has a different generic -signature than `Swift.Vector`, but regardless of that we will prefer `MyLib`'s +Here, we're exercising the fact that this `MyLib.InlineArray` has a different generic +signature than `Swift.InlineArray`, but regardless of that we will prefer `MyLib`'s version even if we supply more generic arguments than it supports. ```swift // MyLib -public struct Vector { +public struct InlineArray { } // MyExecutable main.swift import MyLib -print(Vector.self) // OK +print(InlineArray.self) // OK -// error: generic type 'Vector' specialized with too many type parameters +// error: generic type 'InlineArray' specialized with too many type parameters // (got 2, but expected 1) -print(Vector<3, Int>.self) +print(InlineArray<3, Int>.self) // MyExecutable test.swift -// error: generic type 'Vector' specialized with too few type parameters +// error: generic type 'InlineArray' specialized with too few type parameters // (got 1, but expected 2) -print(Vector.self) +print(InlineArray.self) ``` -And here, we exercise that a module with its own `Vector`, like `MyLib`, will +And here, we exercise that a module with its own `InlineArray`, like `MyLib`, will always prefer its own definition within the module, but even for dependents -who import `MyLib` it will prefer `MyLib.Vector`. For files that don't -explicitly `MyLib`, it will prefer `Swift.Vector`. +who import `MyLib` it will prefer `MyLib.InlineArray`. For files that don't +explicitly `MyLib`, it will prefer `Swift.InlineArray`. ## ABI compatibility -`Vector` is a brand new type in the standard library, so ABI should still be +`InlineArray` is a brand new type in the standard library, so ABI should still be compatible. ## Implications on adoption @@ -424,14 +425,14 @@ were to ship say Swift X.Y with: ```swift @available(SwiftStdlib X.Y) -extension Vector: Equatable where Element: Equatable // & Element: Copyable +extension InlineArray: Equatable where Element: Equatable // & Element: Copyable ``` and later down the road in Swift X.(Y + 1): ```swift @available(SwiftStdlib X.Y) -extension Vector: Equatable where Element: ~Copyable & Equatable +extension InlineArray: Equatable where Element: ~Copyable & Equatable ``` Suddenly, this availability isn't quite right because the conformance that @@ -442,16 +443,16 @@ these conformances until they are fully generalized. ### `Sequence` and `Collection` Similarly, we aren't conforming to `Sequence` or `Collection` either. -While we could conform to these protocols when the element is copyable, `Vector` +While we could conform to these protocols when the element is copyable, `InlineArray` is unlike `Array` in that there are no copy-on-write semantics; it is eagerly copied. Conforming to these protocols would potentially open doors to lots of -implicit copies of the underlying vector instance which could be problematic +implicit copies of the underlying InlineArray instance which could be problematic given the prevalence of generic collection algorithms and slicing behavior. To avoid this potential performance pitfall, we're explicitly not opting into conforming this type to `Sequence` or `Collection`. We do plan to propose new protocols that look like `Sequence` and `Collection` -that avoid implicit copying making them suitable for types like `Vector` and +that avoid implicit copying making them suitable for types like `InlineArray` and containers of noncopyable elements. [SE-0437 Noncopyable Standard Library Primitives](0437-noncopyable-stdlib-primitives.md) goes into more depth about this rationale and mentions that creating new @@ -463,12 +464,12 @@ API we feel confident will be included in any future container protocol. Even if we find that to not be the case, they are still useful API outside of generic collection contexts in their own right. -Remember, one can still iterate a `Vector` instance with the usual `indices` -property (which is what noncopyable vector instances would have had to deal with +Remember, one can still iterate a `InlineArray` instance with the usual `indices` +property (which is what noncopyable InlineArray instances would have had to deal with regardless until new container protocols have been proposed): ```swift -let atomicInts: Vector<3, Atomic> = [Atomic(1), Atomic(2), Atomic(3)] +let atomicInts: InlineArray<3, Atomic> = [Atomic(1), Atomic(2), Atomic(3)] for i in atomicInts.indices { print(atomicInts[i].load(ordering: .relaxed)) @@ -480,7 +481,7 @@ for i in atomicInts.indices { With the recent proposal [SE-0447 Span: Safe Access to Contiguous Storage](0447-span-access-shared-contiguous-storage.md) who defines a safe abstraction over viewing contiguous storage, it would make -sense to define API on `Vector` to be able to get one of these `Span`s. However, +sense to define API on `InlineArray` to be able to get one of these `Span`s. However, the proposal states that: > We could provide `withSpan()` and `withBytes()` closure-taking functions as @@ -493,24 +494,24 @@ the proposal states that: > require lifetime annotations, as initializers do. We are deferring proposing > these extensions until the lifetime annotations are proposed. -All of which is exactly true for the current `Vector` type. We could propose a +All of which is exactly true for the current `InlineArray` type. We could propose a `withSpan` style API now, but it's unclear if that's what we truly want vs. a computed property that returns the span which requires lifetime annotation features. For now, we're deferring such API until a lifetime proposal is proposed and accepted. -### `ExpressibleByVectorLiteral` +### `ExpressibleByInlineArrayLiteral` -While the proposal does propose a literal initialization for `Vector` that +While the proposal does propose a literal initialization for `InlineArray` that doesn't use `ExpressibleByArrayLiteral`, we are intentionally not exposing some -`ExpressibleByVectorLiteral` or similar. It's unclear what this protocol would +`ExpressibleByInlineArrayLiteral` or similar. It's unclear what this protocol would look like because each design has a different semantic guarantee: ```swift -public protocol ExpressibleByVectorLiteral: ~Copyable { +public protocol ExpressibleByInlineArrayLiteral: ~Copyable { associatedtype Element: ~Copyable - init(vectorLiteral: consuming Vector) + init(InlineArrayLiteral: consuming InlineArray) } ``` @@ -518,46 +519,46 @@ This naive approach would satisfy a lot of types like `Array`, `Set`, some hypothetical future noncopyable array, etc. These types actually want a generic count and can allocate just enough space to hold all of those elements. -However, this shape doesn't quite work for `Vector` itself because initializing -a `Vector<4, Int>` should require that the literal has exactly 4 elements. Note +However, this shape doesn't quite work for `InlineArray` itself because initializing +a `InlineArray<4, Int>` should require that the literal has exactly 4 elements. Note that we wouldn't be able to impose a new constraint just for the conformer, so -`Vector` couldn't require that `N == count` and still have this witness the -requirement. Similarly, a `Pair` type could be vector initialized, but only if -the vector has exactly 2 elements. If we had the ability to define +`InlineArray` couldn't require that `N == count` and still have this witness the +requirement. Similarly, a `Pair` type could be InlineArray initialized, but only if +the InlineArray has exactly 2 elements. If we had the ability to define `associatedvalue`, then this makes the conformance pretty trivial for both of these types: ```swift -public protocol ExpressibleByVectorLiteral: ~Copyable { +public protocol ExpressibleByInlineArrayLiteral: ~Copyable { associatedtype Element: ~Copyable associatedvalue count: Int - init(vectorLiteral: consuming Vector) + init(InlineArrayLiteral: consuming InlineArray) } -extension Vector: ExpressibleByVectorLiteral { - init(vectorLiteral: consuming Vector) { ... } +extension InlineArray: ExpressibleByInlineArrayLiteral { + init(InlineArrayLiteral: consuming InlineArray) { ... } } -extension Pair: ExpressibleByVectorLiteral { - init(vectorLiteral: consuming Vector<2, Element>) { ... } +extension Pair: ExpressibleByInlineArrayLiteral { + init(InlineArrayLiteral: consuming InlineArray<2, Element>) { ... } } ``` But even with this design it's unsuitable for `Array` itself because it doesn't want a static count for the literal, it still wants it to be generic. -It would be nice to define something like this either on top of `Vector`, +It would be nice to define something like this either on top of `InlineArray`, parameter packs, or something else that would let us define statically the number of elements we need for literal initialization or be dynamic if we opt to. -### `InlineArray` and `SmallArray` +### `FixedCapacityArray` and `SmallArray` -In the same vein as this type, it may make sense to introduce some `InlineArray` +In the same vein as this type, it may make sense to introduce some `FixedCapacityArray` type which would support appending and removing elements given a fixed-capacity. ```swift -var numbers: InlineArray<4, Int> = [1, 2] +var numbers: FixedCapacityArray<4, Int> = [1, 2] print(numbers.capacity) // 4 print(numbers.count) // 2 numbers.append(3) @@ -568,28 +569,28 @@ numbers.append(5) // error: not enough space ``` This type is significantly different than the type we're proposing because -`Vector` defines a fixed-size meaning you cannot append or remove from it, but +`InlineArray` defines a fixed-size meaning you cannot append or remove from it, but it also requires that every single element is initialized. There must never be -an uninitialized element within a `Vector`, however for `InlineArray` this is +an uninitialized element within a `InlineArray`, however for `FixedCapacityArray` this is not true. It would act as a regular array with an initialized prefix and an uninitialized suffix, it would be inline allocated (stack allocated for locals, heap allocated if it's a class member, etc.), and it would not be growable. The difficulty in proposing such a type right now is that we have no way of -informing the compiler what parts of `InlineArray` are initialized and what +informing the compiler what parts of `FixedCapacityArray` are initialized and what parts are not. This is critical for copy operations, move operations, and destroy operations. Assuming that an uninitialized element is initialized and attempting to perform any of these operations on it may lead to runtime crashes which is definitely undesirable. -Once we have `InlineArray` and some hypothetical noncopyable heap allocated +Once we have `FixedCapacityArray` and some hypothetical noncopyable heap allocated array type (which [SE-0437 Noncopyable Standard Library Primitives](0437-noncopyable-stdlib-primitives.md) dons as `HypoArray` as a placeholder), it should be very trivial to define a `SmallArray` type similar to the one found in LLVM APIs `llvm::SmallVector`. ```swift public enum SmallArray: ~Copyable { - case small(InlineArray) + case small(FixedCapacityArray) case large(HypoArray) } ``` @@ -602,7 +603,7 @@ capacity and would fall back to a dynamic heap allocation. We feel that this type will become as fundamental as `Array` and `Dictionary` both of which have syntactic sugar for declaring a type of them, `[T]` for `Array` and `[K: V]` for `Dictionary`. It may make sense to define something -similar for `Vector`, however we leave that as a future direction as the +similar for `InlineArray`, however we leave that as a future direction as the spelling for such syntax is not critical to landing this type. It should be fairly trivial to propose such a syntax in the future either via a @@ -617,11 +618,11 @@ Some syntax suggestions: * `[T; N]` (from Rust) Note that it may make more sense to have the length appear before the type. I -discuss this more in depth in [Reorder the generic arguments](#reorder-the-generic-arguments-vectort-n-instead-of-vectorn-t). +discuss this more in depth in [Reorder the generic arguments](#reorder-the-generic-arguments-InlineArrayt-n-instead-of-InlineArrayn-t). ### C Interop changes -With the introduction of `Vector`, we have a unique opportunity to fix another +With the introduction of `InlineArray`, we have a unique opportunity to fix another pain point within the language with regards to C interop. Currently, the Swift compiler imports a C array of type `T[24]` as a tuple of `T` with 24 elements. Previously, this was really the only representation that the compiler could pick @@ -680,7 +681,7 @@ Having to resort to using very unsafe API to do anything useful with imported C arrays is not something a memory safe language like Swift should be in the business of. -Ideally we could migrate the importer from using tuples to this new `Vector` +Ideally we could migrate the importer from using tuples to this new `InlineArray` type, however that would be massively source breaking. A previous revision of this proposal proposed an _upcoming_ feature flag that modules can opt into, but this poses issues with the current importer implementation with regards to @@ -688,18 +689,37 @@ inlinable code. Another idea was to import struct fields with C array types twice, one with the existing name with a tuple type (as to not break source) and another with some -`Vector` suffix in the name with the `Vector` type. This works pretty well for +`InlineArray` suffix in the name with the `InlineArray` type. This works pretty well for struct fields and globals, but it leaves fields and functions who have pointers to C arrays in question as well (spelt `char (*x)[4]`). Do we import such functions twice using a similar method of giving it a different name? Such a solution would also incur a longer deprecation period to eventually having just -`Vector` be imported and no more tuples. +`InlineArray` be imported and no more tuples. We're holding off on any C interop changes here as there are still lots of open questions as to what the best path forward is. ## Alternatives considered +### Reorder the generic arguments (`InlineArray` instead of `InlineArray`) + +If we directly followed existing APIs from C++, then obviously the length should +follow the element type. However we realized that when reading this type aloud, +it's "a InlineArray of 3 integers" for example instead of "a InlineArray of integers of +size 3". It gets more interesting the more dimensions you add. +Consider an MxN matrix. In C, you'd write this as `T[N][M]` but index it as +`[m][n]`. We don't want to introduce that sort of confusion (which is a good +argument against `T[N]` as a potential syntax sugar for this type), so the +length being before the underlying element makes the most sense at least for any +potential sugared form. `[M * [N * T]]` would be indexed directly as it is spelt +out in the sugared form, `[m][n]`. In light of that, we wouldn't want the sugar +form to have a different ordering than the generic type itself leading us to +believe that the length must be before the element type. + +## Revisions + +Previously, this type was named `Vector`, but has since been renamed to `InlineArray`. + ### A name other than `Vector` For obvious reasons, we cannot name this type `Swift.Array` to match the @@ -739,21 +759,6 @@ the mathematical term of art. If there was any type we could add to the standard library whose name could be `Vector`, it must be this one. -### Reorder the generic arguments (`Vector` instead of `Vector`) - -If we directly followed existing APIs from C++, then obviously the length should -follow the element type. However we realized that when reading this type aloud, -it's "a vector of 3 integers" for example instead of "a vector of integers of -size 3". It gets more interesting the more dimensions you add. -Consider an MxN matrix. In C, you'd write this as `T[N][M]` but index it as -`[m][n]`. We don't want to introduce that sort of confusion (which is a good -argument against `T[N]` as a potential syntax sugar for this type), so the -length being before the underlying element makes the most sense at least for any -potential sugared form. `[M * [N * T]]` would be indexed directly as it is spelt -out in the sugared form, `[m][n]`. In light of that, we wouldn't want the sugar -form to have a different ordering than the generic type itself leading us to -believe that the length must be before the element type. - ## Acknowledgments I would like the thank the following people for helping in the design process From e8c98f0f12fd5b3c4d184944982149be22db503b Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 21 Jan 2025 13:09:11 -0800 Subject: [PATCH 044/505] Propose MutableSpan and MutableRawSpan --- proposals/nnnn-MutableSpan.md | 498 ++++++++++++++++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 proposals/nnnn-MutableSpan.md diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md new file mode 100644 index 0000000000..9627e80ca5 --- /dev/null +++ b/proposals/nnnn-MutableSpan.md @@ -0,0 +1,498 @@ +# MutableSpan and MutableRawSpan: delegate mutations of contiguous memory + +* Proposal: TBD +* Author: [Guillaume Lessard](https://github.com/glessard) +* Review Manager: TBD +* Status: **Pitch** +* Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) +* Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) +* Review: [Pitch](https://forums.swift.org/) + +[SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md +[SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md +[SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md +[PR-2305]: https://github.com/swiftlang/swift-evolution/pull/2305 +[SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md +[SE-0223]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0223-array-uninitialized-initializer.md +[SE-0176]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md + +## Introduction + +We recently [introduced][SE-0447] the `Span` and `RawSpan` types, providing read-only access to borrowed memory shared. This proposal adds mutations of exclusively-borrowed memory with `MutableSpan` and `MutableRawSpan`. + +## Motivation + +Many standard library container types can provide direct access to modify their internal representation. Up to now, it has only been possible to do so in an unsafe way. The standard library provides this unsafe functionality with closure-taking functions such as `withUnsafeMutableBufferPointer()` and `withContiguousMutableStorageIfAvailable()`. + +These functions have a few different drawbacks, most prominently their reliance on unsafe types, which makes them unpalatable in security-conscious environments. We continue addressing these issues with `MutableSpan` and `MutableRawSpan`, new non-copyable and non-escapable types that manage respectively mutations of typed and untyped memory. + +In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`. + +## Proposed solution +We previously introduced `Span` to provide shared read-only access to containers. A question can be raised as to whether this same type could be used for mutations. We cannot, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and it should be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled through a copyable type, since a copy of the value representing the access would violate exclusivity. We therefore need a type separate from `Span` in order to model mutations. + +#### MutableSpan + +`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan` relies on guarantees that it has exclusive access to the range of memory it represents, and that the memory it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. Like `Span`, `MutableSpan` performs bounds-checking on every access to preserve spatial safety. + +A `MutableSpan` provided by a container represents a mutation of that container, via an exclusive borrow. Mutations are implemented by mutating operations, which let the compiler statically enforce exclusivity. + +#### MutableRawSpan + +`MutableRawSpan` allows delegating mutations to memory representing possibly heterogeneously-typed values, such as memory intended for encoding. It makes the same safety guarantees as `MutableSpan`. A `MutableRawSpan` can be obtained from a `MutableSpan` whose `Element` is `BitwiseCopyable`. + +#### Extensions to standard library types + +The standard library will provide `mutableSpan` computed properties. These return lifetime-dependent `MutableSpan` instances, and represent a mutation of the instance that provided them. These computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. For example, + +```swift +func(_ array: inout Array) { + var ms = array.mutableSpan + modify(&ms) // call function that mutates a MutableSpan + // array.append(2) // attempt to modify `array` would be an error here + _ = consume ms // access to `array` via `ms` ends here + array.append(1) +} +``` + +These computed properties represent a case of lifetime relationships between two bindings that wasn't covered in [SE-0456][SE-0456]. There we defined lifetime relationships for computed property getters of non-escapable and copyable types (`~Escapable & Copyable`). We now need to define them for properties of non-escapable and non-copyable types (`~Escapable & ~Copyable`). A `~Escapable & ~Copyable` value borrows another binding; if this borrow is also a mutation then it is an exclusive borrow. The scope of the borrow, whether or not it is exclusive, extends until the last use of the dependent binding. + +## Detailed Design + +#### MutableSpan + +`MutableSpan` is a simple representation of a region of initialized memory. It is non-copyable in order to enforce exclusive access for mutations of its memory, as required by the law of exclusivity: + +````swift +@frozen +public struct MutableSpan: ~Copyable, ~Escapable { + internal var _start: UnsafeMutableRawPointer? + internal var _count: Int +} + +extension MutableSpan: @unchecked Sendable where Element: Sendable {} +```` + +We store a `UnsafeMutableRawPointer` value internally in order to explicitly support reinterpreted views of memory as containing different types of `BitwiseCopyable` elements. Note that the the optionality of the pointer does not affect usage of `MutableSpan`, since accesses are bounds-checked and the pointer is only dereferenced when the `MutableSpan` isn't empty, when the pointer cannot be `nil`. + +```swift +extension MutableSpan where Element: ~Copyable { + /// The number of initialized elements in this `MutableSpan`. + var count: Int { get } + + /// A Boolean value indicating whether the span is empty. + var isEmpty: Bool { get } + + /// The type that represents a position in a `MutableSpan`. + typealias Index = Int + + /// The range of indices valid for this `MutableSpan`. + var indices: Range { get } + + /// Accesses the element at the specified position. + subscript(_ index: Index) -> Element { borrowing read; mutate } + + /// Exchange the elements at the two given offsets + mutating func swapAt(_ i: Index, _ j: Index) +} +``` + +Like `Span` before it, `MutableSpan` does not conform to `Collection` or `MutableCollection`. These two protocols assume their conformers and elements are copyable, and as such are not compatible with a non-copyable type such as `MutableSpan`. A later proposal will consider generalized containers. + +The subscript uses a borrowing accessor for read-only element access, and a mutate accessor for element mutation. The read-only borrow is a read access to the entire `MutableSpan` for the duration of the access to the element. The `mutate` accessor is an exclusive access to the entire `MutableSpan` for the duration of the mutation of the element. + +`MutableSpan` uses offset-based indexing. The first element of a given span is always at offset 0, and its last element is always at position `count-1`. + +As a side-effect of not conforming to `Collection` or `Sequence`, `MutableSpan` is not directly supported by `for` loops at this time. It is, however, easy to use in a `for` loop via indexing: + +```swift +for i in myMutableSpan.indices { + mutatingFunction(&myMutableSpan[i]) +} +``` + +##### `MutableSpan` API: + +Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. + +```swift +extension MutableSpan where Element: ~Copyable { + @unsafe + subscript(unchecked position: Index) -> Element { borrowing read; mutate } + + @unsafe + mutating func swapAt(unchecked i: Index, unchecked j: Index) + + var storage: Span { borrowing get } +} +``` +##### Bulk updating of a `MutableSpan`'s elements: + +We include functions to perform bulk copies into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. + +```swift +extension MutableSpan { + mutating func update( + startingAt offset: Index = 0, + repeating repeatedValue: Element + ) + + mutating func update( + startingAt offset: Index = 0, + from source: S + ) -> (unwritten: S.Iterator, index: Index) where S.Element == Element + + mutating func update( + startingAt offset: Index = 0, + from elements: inout some IteratorProtocol + ) -> Index + + mutating func update( + startingAt offset: Index = 0, + fromContentsOf source: some Collection + ) -> Index + + mutating func update( + startingAt offset: Index = 0, + fromContentsOf source: Span + ) -> Index + + mutating func update( + startingAt offset: Index = 0, + fromContentsOf source: borrowing Self + ) -> Index +} + + mutating func moveUpdate( + startingAt offset: Index = 0, + fromContentsOf source: UnsafeMutableBufferPointer + ) -> Index +} + +extension MutableSpan { + mutating func moveUpdate( + startingAt offset: Index = 0, + fromContentsOf source: Slice> + ) -> Index +} +``` +##### Interoperability with unsafe code: + +```swift +extension MutableSpan where Element: ~Copyable { + func withUnsafeBufferPointer( + _ body: (_ buffer: UnsafeBufferPointer) throws(E) -> Result + ) throws(E) -> Result + + mutating func withUnsafeMutableBufferPointer( + _ body: (_ buffer: UnsafeMutableBufferPointer) throws(E) -> Result + ) throws(E) -> Result +} + +extension MutableSpan where Element: BitwiseCopyable { + func withUnsafeBytes( + _ body: (_ buffer: UnsafeRawBufferPointer) throws(E) -> Result + ) throws(E) -> Result + + mutating func withUnsafeMutableBytes( + _ body: (_ buffer: UnsafeMutableRawBufferPointer) throws(E) -> Result + ) throws(E) -> Result +} +``` +These functions use a closure to define the scope of validity of `buffer`, ensuring that the underlying `MutableSpan` and the binding it depends on both remain valid through the end of the closure. They have the same shape as the equivalents on `Array` because they fulfill the same function, namely to keep the underlying binding alive. + +#### MutableRawSpan + +`MutableRawSpan` is similar to `MutableSpan`, but reperesents untyped initialized bytes. `MutableRawSpan` specifically supports encoding and decoding applications. Its API supports `unsafeLoad(as:)` and `storeBytes(of: as:)`, as well as a variety of bulk copying operations. + +##### `MutableRawSpan` API: + +```swift +@frozen +public struct MutableRawSpan: ~Copyable, ~Escapable { + internal var _start: UnsafeMutableRawPointer? + internal var _count: Int +} + +extension MutableRawSpan: @unchecked Sendable +``` + +Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. + +```swift +extension MutableRawSpan { + /// The number of bytes in the span. + var byteCount: Int { get } + + /// A Boolean value indicating whether the span is empty. + var isEmpty: Bool { get } + + /// The range of valid byte offsets into this `RawSpan` + var byteOffsets: Range { get } +} + +``` + +##### Accessing and modifying the memory of a `MutableRawSpan`: + +The basic operations available on `RawSpan` are available for `MutableRawSpan`. These operations are not type-safe, in that the loaded value returned by the operation can be invalid, and violate type invariants. Some types have a property that makes the `unsafeLoad(as:)` function safe, but we don't have a way to [formally identify](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#SurjectiveBitPattern) such types at this time. + +```swift +extension MutableRawSpan { + @unsafe + func unsafeLoad( + fromByteOffset offset: Int = 0, as: T.Type + ) -> T + + @unsafe + func unsafeLoadUnaligned( + fromByteOffset offset: Int = 0, as: T.Type + ) -> T + + @unsafe + func unsafeLoad( + fromUncheckedByteOffset offset: Int, as: T.Type + ) -> T + + @unsafe + func unsafeLoadUnaligned( + fromUncheckedByteOffset offset: Int, as: T.Type + ) -> T +} +``` + +To these, `MutableRawSpan` adds functions to store the bytes of a `BitwiseCopyable` value: + +```swift +extension MutableRawSpan { + func storeBytes( + of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) + + @unsafe + func storeBytes( + of value: T, toUncheckedByteOffset offset: Int, as type: T.Type + ) +} +``` + +We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element. +```swift +extension MutableRawSpan { + mutating func update( + startingAt byteOffset: Int = 0, + from source: S + ) -> (unwritten: S.Iterator, byteOffset: Int) where S.Element: BitwiseCopyable + + mutating func update( + startingAt byteOffset: Int = 0, + from elements: inout some IteratorProtocol + ) -> Int + + mutating func update( + startingAt byteOffset: Int = 0, + fromContentsOf source: C + ) -> Int where C.Element: BitwiseCopyable + + mutating func update( + startingAt byteOffset: Int = 0, + fromContentsOf source: Span + ) -> Int + + mutating func update( + startingAt byteOffset: Int = 0, + fromContentsOf source: borrowing MutableSpan + ) -> Int + + mutating func update( + startingAt byteOffset: Int = 0, + fromContentsOf source: RawSpan + ) -> Int + + mutating func update( + startingAt byteOffset: Int = 0, + fromContentsOf source: borrowing MutableRawSpan + ) -> Int +} +``` + +##### Interoperability with unsafe code: + +```swift +extension MutableRawSpan { + func withUnsafeBytes( + _ body: (_ buffer: UnsafeRawBufferPointer) throws(E) -> Result + ) throws(E) -> Result + + mutating func withUnsafeMutableBytes( + _ body: (_ buffer: UnsafeMutableRawBufferPointer) throws(E) -> Result + ) throws(E) -> Result +} +``` +These functions use a closure to define the scope of validity of `buffer`, ensuring that the underlying `MutableSpan` and the binding it depends on both remain valid through the end of the closure. They have the same shape as the equivalents on `Array` because they fulfill the same purpose, namely to keep the underlying binding alive. + +##### Accessing and mutating the raw bytes of a `MutableSpan` + +```swift +extension MutableSpan where Element: BitwiseCopyable { + var mutableBytes: MutableRawSpan { mutating get } +} +``` + + + +#### Extensions to Standard Library types + +A `mutating` computed property getter defined on any type and returning a `~Escapable & ~Copyable` value establishes an exclusive borrowing lifetime relationship of the returned value on the callee's binding. As long as the returned value exists, then the callee's binding remains borrowed and cannot be accessed in any other way. + +A `nonmutating` computed property getter returning a `~Escapable & ~Copyable` value establishes a borrowing lifetime relationship, as if returning a `~Escapable & Copyable` value (see [SE-0456][SE-0456].) + +The standard library will provide `mutableSpan` computed properties. These return lifetime-dependent `MutableSpan` instances. These computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. + +```swift +extension Array { + var mutableSpan: MutableSpan { mutating get } +} + +extension ContiguousArray { + var mutableSpan: MutableSpan { mutating get } +} + +extension ArraySlice { + var mutableSpan: MutableSpan { mutating get } +} + +extension InlineArray { + var mutableSpan: MutableSpan { mutating get } +} + +extension CollectionOfOne { + var mutableSpan: MutableSpan { mutating get } +} +``` + + + +#### Extensions to unsafe buffer types + +We hope that `MutableSpan` and `MutableRawSpan` will become the standard ways to delegate mutations of shared contiguous memory in Swift. Many current API delegate mutations with closure-based functions that receive an `UnsafeMutableBufferPointer` parameter to do this. We will provide ways to unsafely obtain `MutableSpan` instances from `UnsafeMutableBufferPointer` and `MutableRawSpan` instances from `UnsafeMutableRawBufferPointer`, in order to bridge these unsafe types to newer, safer contexts. + +```swift +extension UnsafeMutableBufferPointer { + var mutableSpan: MutableSpan { get } +} + +extension UnsafeMutableRawBufferPointer { + var mutableBytes: MutableRawSpan { get } +} +``` + +These unsafe conversions returns a value whose lifetime is dependent on the _binding_ of the `UnsafeMutable[Raw]BufferPointer`. This dependency does not keep the underlying memory alive. As is usual where the `UnsafePointer` family of types is involved, the programmer must ensure the memory remains allocated while it is in use. Additionally, the following invariants must remain true for as long as the `MutableSpan` or `MutableRawSpan` value exists: + + - The underlying memory remains initialized. + - The underlying memory is not accessed through another means. + +Failure to maintain these invariants results in undefined behaviour. + +#### Extensions to `Foundation.Data` + +While the `swift-foundation` package and the `Foundation` framework are not governed by the Swift evolution process, `Data` is similar in use to standard library types, and the project acknowledges that it is desirable for it to have similar API when appropriate. Accordingly, we plan to propose the following additions to `Foundation.Data`: + +```swift +extension Foundation.Data { + // Mutate this `Data`'s bytes through a `MutableSpan` + var mutableSpan: MutableSpan { mutating get } + + // Mutate this `Data`'s bytes through a `MutableRawSpan` + var mutableBytes: MutableRawSpan { mutating get } +} +``` + +#### Performance + +The `mutableSpan` and `mutableBytes` properties should be performant and return their `MutableSpan` or `MutableRawSpan` with very little work, in O(1) time. In copy-on-write types, however, obtaining a `MutableSpan` is the start of the mutation, and if the backing buffer is not uniquely reference a copy must be made ahead of returning the `MutableSpan`. + +Note that `MutableSpan` incurs no special behaviour for bridged types, since mutations always require a defensive copy of data bridged from Objective-C data structures. + +## Source compatibility + +This proposal is additive and source-compatible with existing code. + +## ABI compatibility + +This proposal is additive and ABI-compatible with existing code. + +## Implications on adoption + +The additions described in this proposal require a new version of the Swift standard library and runtime. + +## Alternatives considered + +#### Adding `withMutableSpan()` closure-taking functions + +The `mutableSpan` and `mutableBytes` properties aim to be safe replacements for the `withUnsafeMutableBufferPointer()` and `withUnsafeMutableBytes()` closure-taking functions. We could consider `withMutableSpan()` and `withMutableBytes()` closure-taking functions that would provide a quicker migration away from the older unsafe functions. We do not believe the closure-taking functions are desirable in the long run. In the short run, there may be a desire to clearly mark the scope where a `MutableSpan` instance is used. The default method would be to explicitly consume a `MutableSpan` instance: + +```swift +var a = ContiguousArray(0..<8) +var span = a.mutableSpan +modify(&span) +_ = consume span +a.append(8) +``` + +During the evolution of Swift, we have learned that closure-based API are difficult to compose, especially with one another. They can also require alterations to support new language features. For example, the generalization of closure-taking API for non-copyable values as well as typed throws is ongoing; adding more closure-taking API may make future feature evolution more labor-intensive. By instead relying on returned values, whether from computed properties or functions, we build for **greater** composability. Use cases where this approach falls short should be reported as enhancement requests or bugs. + +#### Omitting extensions to `UnsafeBufferPointer` and related types + +We could omit the extensions to `UnsafeMutableBufferPointer` and related types, and rely instead of future `MutableSpan` and `MutableRawSpan` initializers. The initializers can have the advantage of being able to communicate semantics (somewhat) through their parameter labels. However, they also have a very different shape than the `storage` computed properties we are proposing for the safe types such as `Array`. We believe that the adding the same API on both safe and unsafe types is advantageous, even if the preconditions for the properties cannot be statically enforced. + +## Future directions + +Note: The future directions stated in [SE-0447](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#Directions) apply here as well. + +#### Initializing and returning `MutableSpan` instances + +`MutableSpan` represents a region of memory and, as such, must be initialized using an unsafe pointer. This is an unsafe operation which will typically be performed internally to a container's implementation. In order to bridge to safe code, these initializers require new annotations that indicate to the compiler how the newly-created `Span` can be used safely. + +These annotations have been [pitched][PR-2305-pitch] and, after revision, are expected to be pitched again soon. `MutableSpan` initializers using lifetime annotations will be proposed alongside the annotations themselves. + +#### Functions providing variants of `MutableRawSpan` to `MutableSpan` + +`MutableSpan`s representing subsets of consecutive elements could be extracted out of a larger `MutableSpan` with an API similar to the `extracting()` functions recently added to `UnsafeBufferPointer` in support of non-copyable elements: + +```swift +extension MutableSpan where Element: ~Copyable { + public mutating func extracting(_ bounds: Range) -> Self +} +``` + +These functions would require a lifetime dependency annotation. + +Similarly, a `MutableRawSpan` could provide a function to mutate a range of its bytes as a typed `MutableSpan`: + +```swift +extension MutableRawSpan { + @unsafe + public mutating func unsafeMutableView(as type: T.Type) -> MutableSpan +} +``` +We are subsetting functions that require lifetime annotations until such annotations are [proposed][PR-2305]. + +#### Splitting `MutableSpan` instances + +It is desirable to have a way to split a `MutableSpan` in multiple parts, for divide-and-conquer algorithms or other reasons: + +```swift +extension MutableSpan where Element: ~Copyable { + func split(at index: Index) -> (part1: Self, part2: Self) +} +``` + +Unfortunately, tuples do not support non-copyable values yet. We may be able to use the new `Vector`/`Slab`/`InlineArray` type proposed in [SE-0453][SE-0453], but destructuring its non-copyable elements remains a challenge. Solving this issue for `Span` as well as `MutableSpan` is a top priority. + +#### Delegated initialization with `OutputSpan` + +Some data structures can delegate initialization of parts of their owned memory. The standard library added the `Array` initializer `init(unsafeUninitializedCapacity:initializingWith:)` in [SE-0223][SE-0223]. This initializer relies on `UnsafeMutableBufferPointer` and correct usage of initialization primitives. We should present a simpler and safer model of initialization by leveraging non-copyability and non-escapability. + +## Acknowledgements + From 2f625f9cb3b54f2759850622059a937a16720ab0 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Fri, 7 Feb 2025 13:54:35 -0800 Subject: [PATCH 045/505] Edits, feedback responses --- proposals/nnnn-MutableSpan.md | 95 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index 9627e80ca5..70a76f6172 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -12,6 +12,7 @@ [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md [SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md [PR-2305]: https://github.com/swiftlang/swift-evolution/pull/2305 +[SE-0437]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md [SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md [SE-0223]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0223-array-uninitialized-initializer.md [SE-0176]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md @@ -29,13 +30,13 @@ These functions have a few different drawbacks, most prominently their reliance In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`. ## Proposed solution -We previously introduced `Span` to provide shared read-only access to containers. A question can be raised as to whether this same type could be used for mutations. We cannot, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and it should be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled through a copyable type, since a copy of the value representing the access would violate exclusivity. We therefore need a type separate from `Span` in order to model mutations. +We introduced `Span` to provide shared read-only access to containers. We cannot use `Span` to also model container mutations, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled with a copyable type, since a copy of the value representing the access would violate exclusivity by adding a second access. We therefore need a non-copyable type separate from `Span` in order to model mutations. #### MutableSpan -`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan` relies on guarantees that it has exclusive access to the range of memory it represents, and that the memory it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. Like `Span`, `MutableSpan` performs bounds-checking on every access to preserve spatial safety. +`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan` relies on guarantees that it has exclusive access to the range of memory it represents, and that the memory it represents will remain valid for the duration of the access. These provide data race safety and temporal safety. Like `Span`, `MutableSpan` performs bounds-checking on every access to preserve spatial safety. -A `MutableSpan` provided by a container represents a mutation of that container, via an exclusive borrow. Mutations are implemented by mutating operations, which let the compiler statically enforce exclusivity. +A `MutableSpan` provided by a container represents a mutation of that container, via an exclusive borrow. Mutations are implemented by mutating functions and subscripts, which let the compiler statically enforce exclusivity. #### MutableRawSpan @@ -55,7 +56,7 @@ func(_ array: inout Array) { } ``` -These computed properties represent a case of lifetime relationships between two bindings that wasn't covered in [SE-0456][SE-0456]. There we defined lifetime relationships for computed property getters of non-escapable and copyable types (`~Escapable & Copyable`). We now need to define them for properties of non-escapable and non-copyable types (`~Escapable & ~Copyable`). A `~Escapable & ~Copyable` value borrows another binding; if this borrow is also a mutation then it is an exclusive borrow. The scope of the borrow, whether or not it is exclusive, extends until the last use of the dependent binding. +These computed properties represent a case of lifetime relationships not covered in [SE-0456][SE-0456]. In SE-0456 we defined lifetime relationships for computed property getters of non-escapable and copyable types (`~Escapable & Copyable`). We propose defining them for properties of non-escapable and non-copyable types (`~Escapable & ~Copyable`). A `~Escapable & ~Copyable` value borrows another binding; if this borrow is also a mutation then it is an exclusive borrow. The scope of the borrow, whether or not it is exclusive, extends until the last use of the dependent binding. ## Detailed Design @@ -75,6 +76,8 @@ extension MutableSpan: @unchecked Sendable where Element: Sendable {} We store a `UnsafeMutableRawPointer` value internally in order to explicitly support reinterpreted views of memory as containing different types of `BitwiseCopyable` elements. Note that the the optionality of the pointer does not affect usage of `MutableSpan`, since accesses are bounds-checked and the pointer is only dereferenced when the `MutableSpan` isn't empty, when the pointer cannot be `nil`. +Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. + ```swift extension MutableSpan where Element: ~Copyable { /// The number of initialized elements in this `MutableSpan`. @@ -90,10 +93,14 @@ extension MutableSpan where Element: ~Copyable { var indices: Range { get } /// Accesses the element at the specified position. - subscript(_ index: Index) -> Element { borrowing read; mutate } + subscript(_ index: Index) -> Element { borrow; mutate } + // accessor syntax from accessors roadmap (https://forums.swift.org/t/76707) /// Exchange the elements at the two given offsets mutating func swapAt(_ i: Index, _ j: Index) + + /// Borrow the underlying memory for read-only access + var span: Span { borrowing get } } ``` @@ -111,24 +118,33 @@ for i in myMutableSpan.indices { } ``` -##### `MutableSpan` API: +##### Unchecked access to elements: -Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. +The `subscript` mentioned above always checks the bounds of the `MutableSpan` before allowing access to the memory, preventing out-of-bounds accesses. We also provide an unchecked variant of the `subscript` and of the `swapAt` function as an alternative for situations where bounds-checking is costly and has already been performed: ```swift extension MutableSpan where Element: ~Copyable { + /// Accesses the element at the specified `position`. + /// + /// This subscript does not validate `position`; this is an unsafe operation. + /// + /// - Parameter position: The offset of the element to access. `position` + /// must be greater or equal to zero, and less than `count`. @unsafe - subscript(unchecked position: Index) -> Element { borrowing read; mutate } + subscript(unchecked position: Index) -> Element { borrow; mutate } + /// Exchange the elements at the two given offsets + /// + /// This function does not validate `i` or `j`; this is an unsafe operation. @unsafe - mutating func swapAt(unchecked i: Index, unchecked j: Index) - - var storage: Span { borrowing get } + mutating func swapAt(unchecked i: Index, unchecked j: Index) } ``` ##### Bulk updating of a `MutableSpan`'s elements: -We include functions to perform bulk copies into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. +We include functions to perform bulk copies of elements into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. + +**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableSpan`. We could revive the option of using a `some RangeExpression` parameter, or we could use the return value of a `func extracting(_: some RangeExpression)` such as was [recently added][SE-0437] to `UnsafeBufferPointer`. The latter option in combination with `mutating` functions requires the use of intermediate bindings. This section may change in response to feedback and our investigations. ```swift extension MutableSpan { @@ -163,6 +179,7 @@ extension MutableSpan { ) -> Index } +extension MutableSpan where Element: ~Copyable { mutating func moveUpdate( startingAt offset: Index = 0, fromContentsOf source: UnsafeMutableBufferPointer @@ -203,7 +220,7 @@ These functions use a closure to define the scope of validity of `buffer`, ensur #### MutableRawSpan -`MutableRawSpan` is similar to `MutableSpan`, but reperesents untyped initialized bytes. `MutableRawSpan` specifically supports encoding and decoding applications. Its API supports `unsafeLoad(as:)` and `storeBytes(of: as:)`, as well as a variety of bulk copying operations. +`MutableRawSpan` is similar to `MutableSpan`, but represents untyped initialized bytes. `MutableRawSpan` specifically supports encoding and decoding applications. Its API supports `unsafeLoad(as:)` and `storeBytes(of: as:)`, as well as a variety of bulk copying operations. ##### `MutableRawSpan` API: @@ -230,12 +247,26 @@ extension MutableRawSpan { /// The range of valid byte offsets into this `RawSpan` var byteOffsets: Range { get } } - ``` ##### Accessing and modifying the memory of a `MutableRawSpan`: -The basic operations available on `RawSpan` are available for `MutableRawSpan`. These operations are not type-safe, in that the loaded value returned by the operation can be invalid, and violate type invariants. Some types have a property that makes the `unsafeLoad(as:)` function safe, but we don't have a way to [formally identify](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#SurjectiveBitPattern) such types at this time. +`MutableRawSpan` supports storing the bytes of a `BitwiseCopyable` value to its underlying memory: + +```swift +extension MutableRawSpan { + mutating func storeBytes( + of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) + + @unsafe + mutating func storeBytes( + of value: T, toUncheckedByteOffset offset: Int, as type: T.Type + ) +} +``` + +Additionally, the basic loading operations available on `RawSpan` are available for `MutableRawSpan`. These operations are not type-safe, in that the loaded value returned by the operation can be invalid, and violate type invariants. Some types have a property that makes the `unsafeLoad(as:)` function safe, but we don't have a way to [formally identify](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#SurjectiveBitPattern) such types at this time. ```swift extension MutableRawSpan { @@ -261,22 +292,10 @@ extension MutableRawSpan { } ``` -To these, `MutableRawSpan` adds functions to store the bytes of a `BitwiseCopyable` value: - -```swift -extension MutableRawSpan { - func storeBytes( - of value: T, toByteOffset offset: Int = 0, as type: T.Type - ) +We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element. - @unsafe - func storeBytes( - of value: T, toUncheckedByteOffset offset: Int, as type: T.Type - ) -} -``` +**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableRawSpan`. (See the note above for more details on the same considerations.) -We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element. ```swift extension MutableRawSpan { mutating func update( @@ -347,7 +366,7 @@ A `mutating` computed property getter defined on any type and returning a `~Esca A `nonmutating` computed property getter returning a `~Escapable & ~Copyable` value establishes a borrowing lifetime relationship, as if returning a `~Escapable & Copyable` value (see [SE-0456][SE-0456].) -The standard library will provide `mutableSpan` computed properties. These return lifetime-dependent `MutableSpan` instances. These computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. +The standard library will provide `mutating` computed properties providing lifetime-dependent `MutableSpan` instances. These `mutableSpan` computed properties are intended as the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. ```swift extension Array { @@ -371,8 +390,6 @@ extension CollectionOfOne { } ``` - - #### Extensions to unsafe buffer types We hope that `MutableSpan` and `MutableRawSpan` will become the standard ways to delegate mutations of shared contiguous memory in Swift. Many current API delegate mutations with closure-based functions that receive an `UnsafeMutableBufferPointer` parameter to do this. We will provide ways to unsafely obtain `MutableSpan` instances from `UnsafeMutableBufferPointer` and `MutableRawSpan` instances from `UnsafeMutableRawBufferPointer`, in order to bridge these unsafe types to newer, safer contexts. @@ -412,7 +429,7 @@ extension Foundation.Data { The `mutableSpan` and `mutableBytes` properties should be performant and return their `MutableSpan` or `MutableRawSpan` with very little work, in O(1) time. In copy-on-write types, however, obtaining a `MutableSpan` is the start of the mutation, and if the backing buffer is not uniquely reference a copy must be made ahead of returning the `MutableSpan`. -Note that `MutableSpan` incurs no special behaviour for bridged types, since mutations always require a defensive copy of data bridged from Objective-C data structures. +Note that `MutableSpan` incurs no special behaviour for bridged types, since mutable bindings always require a defensive copy of data bridged from Objective-C data structures. ## Source compatibility @@ -424,7 +441,7 @@ This proposal is additive and ABI-compatible with existing code. ## Implications on adoption -The additions described in this proposal require a new version of the Swift standard library and runtime. +The additions described in this proposal require a new version of the Swift standard library. ## Alternatives considered @@ -478,7 +495,7 @@ extension MutableRawSpan { ``` We are subsetting functions that require lifetime annotations until such annotations are [proposed][PR-2305]. -#### Splitting `MutableSpan` instances +#### Splitting `MutableSpan` instances – `MutableSpan` in divide-and-conquer algorithms It is desirable to have a way to split a `MutableSpan` in multiple parts, for divide-and-conquer algorithms or other reasons: @@ -488,11 +505,15 @@ extension MutableSpan where Element: ~Copyable { } ``` -Unfortunately, tuples do not support non-copyable values yet. We may be able to use the new `Vector`/`Slab`/`InlineArray` type proposed in [SE-0453][SE-0453], but destructuring its non-copyable elements remains a challenge. Solving this issue for `Span` as well as `MutableSpan` is a top priority. +Unfortunately, tuples do not support non-copyable values yet. We may be able to use `InlineArray` ([SE-0453][SE-0453]), or a bespoke type, but destructuring the non-copyable constituent part remains a challenge. Solving this issue for `Span` and `MutableSpan` is a top priority. + +#### Mutating algorithms + +Algorithms defined on `MutableCollection` such as `sort(by:)` and `partition(by:)` could be defined on `MutableSpan`. We believe we will be able to define these more generally once we have a generalized container protocol hierarchy. #### Delegated initialization with `OutputSpan` Some data structures can delegate initialization of parts of their owned memory. The standard library added the `Array` initializer `init(unsafeUninitializedCapacity:initializingWith:)` in [SE-0223][SE-0223]. This initializer relies on `UnsafeMutableBufferPointer` and correct usage of initialization primitives. We should present a simpler and safer model of initialization by leveraging non-copyability and non-escapability. -## Acknowledgements +We expect to propose an `OutputSpan` type to represent partially-initialized memory, and to support to the initialization of memory by appending to the initialized portion of the underlying storage. From 9923e61c2787efae8b509694ec9f92cb7e8e5f1e Mon Sep 17 00:00:00 2001 From: gangwoon Date: Mon, 10 Feb 2025 16:45:14 +0900 Subject: [PATCH 046/505] [SE-0430] Disallow borrowing sending --- proposals/0430-transferring-parameters-and-results.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/proposals/0430-transferring-parameters-and-results.md b/proposals/0430-transferring-parameters-and-results.md index 712847edbf..031685c0ee 100644 --- a/proposals/0430-transferring-parameters-and-results.md +++ b/proposals/0430-transferring-parameters-and-results.md @@ -390,18 +390,12 @@ the callee. Unlike `consuming` parameters, `sending` parameters do not have no-implicit-copying semantics. To opt into no-implicit-copying semantics or to change the default ownership -convention, `sending` may also be paired with an explicit `consuming` or -`borrowing` ownership modifier: +convention, `sending` may also be paired with an explicit `consuming` ownership modifier: ```swift func sendingConsuming(_ x: consuming sending T) { ... } -func sendingBorrowing(_ x: borrowing sending T) { ... } ``` -Note that an explicit `borrowing` annotation always implies no-implicit-copying, -so there is no way to change the default ownership convention of a -`sending` parameter without also opting into no-implicit-copying semantics. - ### Adoption in the Concurrency library There are several APIs in the concurrency library that send a parameter across From 356900ad58f726cdb2ce99d6ba50b5b0af681ccf Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 10 Feb 2025 07:50:18 -0800 Subject: [PATCH 047/505] Fix word salad --- proposals/nnnn-MutableSpan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index 70a76f6172..a76ddba350 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -19,7 +19,7 @@ ## Introduction -We recently [introduced][SE-0447] the `Span` and `RawSpan` types, providing read-only access to borrowed memory shared. This proposal adds mutations of exclusively-borrowed memory with `MutableSpan` and `MutableRawSpan`. +We recently [introduced][SE-0447] the `Span` and `RawSpan` types, providing shared read-only access to borrowed memory. This proposal adds helper types to delegate mutations of exclusively-borrowed memory: `MutableSpan` and `MutableRawSpan`. ## Motivation From 3d7202fc88a5bfc1e98c8ac912a7f8a00dc9fb4e Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 10 Feb 2025 08:59:55 -0800 Subject: [PATCH 048/505] Improve solution introduction --- proposals/nnnn-MutableSpan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index a76ddba350..f128749662 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -30,7 +30,7 @@ These functions have a few different drawbacks, most prominently their reliance In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`. ## Proposed solution -We introduced `Span` to provide shared read-only access to containers. We cannot use `Span` to also model container mutations, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled with a copyable type, since a copy of the value representing the access would violate exclusivity by adding a second access. We therefore need a non-copyable type separate from `Span` in order to model mutations. +We introduced `Span` to provide shared read-only access to containers. The natural next step is to provide a similar capability for mutable access. Mutability requires exclusive access, per Swift's [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Exclusive access cannot be modeled with a copyable type, since a copy would represent an additional access, in violation of the law of exclusivity. We therefore need a non-copyable type separate from `Span` in order to model mutations. #### MutableSpan From 495cf7dbe7d189f4d2480e2861a053210ef454ee Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 11 Feb 2025 14:21:20 -0700 Subject: [PATCH 049/505] Add UTF8Span proposal --- .../nnnn-utf8span-safe-utf8-processing.md | 900 ++++++++++++++++++ 1 file changed, 900 insertions(+) create mode 100644 proposals/nnnn-utf8span-safe-utf8-processing.md diff --git a/proposals/nnnn-utf8span-safe-utf8-processing.md b/proposals/nnnn-utf8span-safe-utf8-processing.md new file mode 100644 index 0000000000..e7984007cb --- /dev/null +++ b/proposals/nnnn-utf8span-safe-utf8-processing.md @@ -0,0 +1,900 @@ + + +# UTF8Span: Safe UTF-8 Processing Over Contiguous Bytes + +* Proposal: [SE-NNNN](nnnn-utf8-span.md) +* Authors: [Michael Ilseman](https://github.com/milseman), [Guillaume Lessard](https://github.com/glessard) +* Review Manager: TBD +* Status: **Awaiting review** +* Bug: rdar://48132971, rdar://96837923 +* Implementation: https://github.com/swiftlang/swift/pull/78531 +* Upcoming Feature Flag: +* Review: ([pitch 1](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([pitch 2](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) + + +## Introduction + +We introduce `UTF8Span` for efficient and safe Unicode processing over contiguous storage. `UTF8Span` is a memory safe non-escapable type [similar to `Span`](https://github.com/swiftlang/swift-evolution/pull/2307). + +Native `String`s are stored as validly-encoded UTF-8 bytes in an internal contiguous memory buffer. The standard library implements `String`'s API as internal methods which operate on top of this buffer, taking advantage of the validly-encoded invariant and specialized Unicode knowledge. We propose making this UTF-8 buffer and its methods public as API for more advanced libraries and developers. + +## Motivation + +Currently, if a developer wants to do `String`-like processing over UTF-8 bytes, they have to make an instance of `String`, which allocates a native storage class, copies all the bytes, and is reference counted. The developer would then need to operate within the new `String`'s views and map between `String.Index` and byte offsets in the original buffer. + +For example, if these bytes were part of a data structure, the developer would need to decide to either cache such a new `String` instance or recreate it on the fly. Caching more than doubles the size and adds caching complexity. Recreating it on the fly adds a linear time factor and class instance allocation/deallocation and potentially reference counting. + +Furthermore, `String` may not be fully available on tightly constrained platforms, especially those that cannot support allocations. Both `String` and `UTF8Span` have some API that require Unicode data tables and that might not be available on embedded (String via its conformance to `Comparable` and `Collection` depend on these data tables while `UTF8Span` has a couple of methods that will be unavailable). + +### UTF-8 validity and efficiency + +UTF-8 validation is a particularly common concern and the subject of a fair amount of [research](https://lemire.me/blog/2020/10/20/ridiculously-fast-unicode-utf-8-validation/). Once an input is known to be validly encoded UTF-8, subsequent operations such as decoding, grapheme breaking, comparison, etc., can be implemented much more efficiently under this assumption of validity. Swift's `String` type's native storage is guaranteed-valid-UTF8 for this reason. + +Failure to guarantee UTF-8 encoding validity creates security and safety concerns. With invalidly-encoded contents, memory safety would become more nuanced. An ill-formed leading byte can dictate a scalar length that is longer than the memory buffer. The buffer may have bounds associated with it, which differs from the bounds dictated by its contents. + +Additionally, a particular scalar value in valid UTF-8 has only one encoding, but invalid UTF-8 could have the same value encoded as an [overlong encoding](https://en.wikipedia.org/wiki/UTF-8#Overlong_encodings), which would compromise code that checks for the presence of a scalar value by looking at the encoded bytes (or that does a byte-wise comparison). + + +## Proposed solution + +We propose a non-escapable `UTF8Span` which exposes `String` functionality for validly-encoded UTF-8 code units in contiguous memory. We also propose rich API describing the kind and location of encoding errors. + +## Detailed design + +`UTF8Span` is a borrowed view into contiguous memory containing validly-encoded UTF-8 code units. + +```swift +@frozen +public struct UTF8Span: Copyable, ~Escapable { + **TODO**: This might end up being UnsafeRawPointer? like in Span + public var unsafeBaseAddress: UnsafeRawPointer + + /* + A bit-packed count and flags (such as isASCII) + + ╔═══════╦═════╦═════╦══════════╦═══════╗ + ║ b63 ║ b62 ║ b61 ║ b60:56 ║ b56:0 ║ + ╠═══════╬═════╬═════╬══════════╬═══════╣ + ║ ASCII ║ NFC ║ SSC ║ reserved ║ count ║ + ╚═══════╩═════╩═════╩══════════╩═══════╝ + + ASCII means the contents are all-ASCII (<0x7F). + NFC means contents are in normal form C for fast comparisons. + SSC means single-scalar Characters (i.e. grapheme clusters): every + `Character` holds only a single `Unicode.Scalar`. + */ + @usableFromInline + internal var _countAndFlags: UInt64 +} + +``` + + + +### UTF-8 validation + +We propose new API for identifying where and what kind of encoding errors are present in UTF-8 content. + +```swift +extension Unicode.UTF8 { + /** + + The kind and location of a UTF-8 encoding error. + + Valid UTF-8 is represented by this table: + + ╔════════════════════╦════════╦════════╦════════╦════════╗ + ║ Scalar value ║ Byte 0 ║ Byte 1 ║ Byte 2 ║ Byte 3 ║ + ╠════════════════════╬════════╬════════╬════════╬════════╣ + ║ U+0000..U+007F ║ 00..7F ║ ║ ║ ║ + ║ U+0080..U+07FF ║ C2..DF ║ 80..BF ║ ║ ║ + ║ U+0800..U+0FFF ║ E0 ║ A0..BF ║ 80..BF ║ ║ + ║ U+1000..U+CFFF ║ E1..EC ║ 80..BF ║ 80..BF ║ ║ + ║ U+D000..U+D7FF ║ ED ║ 80..9F ║ 80..BF ║ ║ + ║ U+E000..U+FFFF ║ EE..EF ║ 80..BF ║ 80..BF ║ ║ + ║ U+10000..U+3FFFF ║ F0 ║ 90..BF ║ 80..BF ║ 80..BF ║ + ║ U+40000..U+FFFFF ║ F1..F3 ║ 80..BF ║ 80..BF ║ 80..BF ║ + ║ U+100000..U+10FFFF ║ F4 ║ 80..8F ║ 80..BF ║ 80..BF ║ + ╚════════════════════╩════════╩════════╩════════╩════════╝ + + ### Classifying errors + + An *unexpected continuation* is when a continuation byte (`10xxxxxx`) occurs + in a position that should be the start of a new scalar value. Unexpected + continuations can often occur when the input contains arbitrary data + instead of textual content. An unexpected continuation at the start of + input might mean that the input was not correctly sliced along scalar + boundaries or that it does not contain UTF-8. + + A *truncated scalar* is a multi-byte sequence that is the start of a valid + multi-byte scalar but is cut off before ending correctly. A truncated + scalar at the end of the input might mean that only part of the entire + input was received. + + A *surrogate code point* (`U+D800..U+DFFF`) is invalid UTF-8. Surrogate + code points are used by UTF-16 to encode scalars in the supplementary + planes. Their presence may mean the input was encoded in a different 8-bit + encoding, such as CESU-8, WTF-8, or Java's Modified UTF-8. + + An *invalid non-surrogate code point* is any code point higher than + `U+10FFFF`. This can often occur when the input is arbitrary data instead + of textual content. + + An *overlong encoding* occurs when a scalar value that could have been + encoded using fewer bytes is encoded in a longer byte sequence. Overlong + encodings are invalid UTF-8 and can lead to security issues if not + correctly detected: + + - https://nvd.nist.gov/vuln/detail/CVE-2008-2938 + - https://nvd.nist.gov/vuln/detail/CVE-2000-0884 + + An overlong encoding of `NUL`, `0xC0 0x80`, is used in Java's Modified + UTF-8 but is invalid UTF-8. Overlong encoding errors often catch attempts + to bypass security measures. + + ### Reporting the range of the error + + The range of the error reported follows the *Maximal subpart of an + ill-formed subsequence* algorithm in which each error is either one byte + long or ends before the first byte that is disallowed. See "U+FFFD + Substitution of Maximal Subparts" in the Unicode Standard. Unicode started + recommending this algorithm in version 6 and is adopted by the W3C. + + The maximal subpart algorithm will produce a single multi-byte range for a + truncated scalar (a multi-byte sequence that is the start of a valid + multi-byte scalar but is cut off before ending correctly). For all other + errors (including overlong encodings, surrogates, and invalid code + points), it will produce an error per byte. + + Since overlong encodings, surrogates, and invalid code points are erroneous + by the second byte (at the latest), the above definition produces the same + ranges as defining such a sequence as a truncated scalar error followed by + unexpected continuation byte errors. The more semantically-rich + classification is reported. + + For example, a surrogate count point sequence `ED A0 80` will be reported + as three `.surrogateCodePointByte` errors rather than a `.truncatedScalar` + followed by two `.unexpectedContinuationByte` errors. + + Other commonly reported error ranges can be constructed from this result. + For example, PEP 383's error-per-byte can be constructed by mapping over + the reported range. Similarly, constructing a single error for the longest + invalid byte range can be constructed by joining adjacent error ranges. + + ╔═════════════════╦══════╦═════╦═════╦═════╦═════╦═════╦═════╦══════╗ + ║ ║ 61 ║ F1 ║ 80 ║ 80 ║ E1 ║ 80 ║ C2 ║ 62 ║ + ╠═════════════════╬══════╬═════╬═════╬═════╬═════╬═════╬═════╬══════╣ + ║ Longest range ║ U+61 ║ err ║ ║ ║ ║ ║ ║ U+62 ║ + ║ Maximal subpart ║ U+61 ║ err ║ ║ ║ err ║ ║ err ║ U+62 ║ + ║ Error per byte ║ U+61 ║ err ║ err ║ err ║ err ║ err ║ err ║ U+62 ║ + ╚═════════════════╩══════╩═════╩═════╩═════╩═════╩═════╩═════╩══════╝ + + */ + @frozen + public struct EncodingError: Error, Sendable, Hashable, Codable { + /// The kind of encoding error + public var kind: Unicode.UTF8.EncodingError.Kind + + /// The range of offsets into our input containing the error + public var range: Range + + @_alwaysEmitIntoClient + public init( + _ kind: Unicode.UTF8.EncodingError.Kind, + _ range: some RangeExpression + ) + + @_alwaysEmitIntoClient + public init(_ kind: Unicode.UTF8.EncodingError.Kind, at: Int) + } +} + +extension UTF8.EncodingError { + /// The kind of encoding error encountered during validation + @frozen + public struct Kind: Error, Sendable, Hashable, Codable, RawRepresentable { + public var rawValue: UInt8 + + @inlinable + public init(rawValue: UInt8) + + /// A continuation byte (`10xxxxxx`) outside of a multi-byte sequence + @_alwaysEmitIntoClient + public static var unexpectedContinuationByte: Self + + /// A byte in a surrogate code point (`U+D800..U+DFFF`) sequence + @_alwaysEmitIntoClient + public static var surrogateCodePointByte: Self + + /// A byte in an invalid, non-surrogate code point (`>U+10FFFF`) sequence + @_alwaysEmitIntoClient + public static var invalidNonSurrogateCodePointByte: Self + + /// A byte in an overlong encoding sequence + @_alwaysEmitIntoClient + public static var overlongEncodingByte: Self + + /// A multi-byte sequence that is the start of a valid multi-byte scalar + /// but is cut off before ending correctly + @_alwaysEmitIntoClient + public static var truncatedScalar: Self + } +} + +@_unavailableInEmbedded +extension UTF8.EncodingError.Kind: CustomStringConvertible { + public var description: String { get } +} + +@_unavailableInEmbedded +extension UTF8.EncodingError: CustomStringConvertible { + public var description: String { get } +} +``` + +**QUESTION**: It would be good to expose this functionality via a general purpose validation API. Question is do we want a `findFirstError` or `findAllErrors` style API, both? E.g.: + +```swift +extension UTF8 { + public static func checkForError( + _ s: some Sequence + ) -> some UTF8.EncodingError { + + ... or + + public static func checkForAllErrors( + _ s: some Sequence + ) -> some Sequence { +``` + + +### Creation and validation + +`UTF8Span` is validated at initialization time and encoding errors are diagnosed and thrown. + + +```swift + +extension UTF8Span { + @lifetime(codeUnits) + public init( + _validating codeUnits: consuming Span + ) throws(UTF8.EncodingError) { + + @lifetime(borrow start) + internal init( + _unsafeAssumingValidUTF8 start: borrowing UnsafeRawPointer, + _countAndFlags: UInt64 + ) +} +``` + +**NOTE**: The final status of underscores, annotations, etc., are pending things like [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17) and [Lifetime Dependencies](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865/140). + + +### Scalar processing + +We propose a `UTF8Span.ScalarIterator` type that can do scalar processing forwards and backwards. Note that `ScalarIterator` itself is non-escapable, and thus cannot conform to `IteratorProtocol`, etc. + +```swift +extension UTF8Span { + public func _makeScalarIterator() -> ScalarIterator + + /// Iterate the `Unicode.Scalar`s contents of a `UTF8Span`. + public struct ScalarIterator: ~Escapable { + public var codeUnits: UTF8Span + + /// The byte offset of the start of the next scalar. This is + /// always scalar-aligned. + public var currentCodeUnitOffset: Int { get } + + public init(_ codeUnits: UTF8Span) + + /// Decode and return the scalar starting at `currentCodeUnitOffset`. + /// After the function returns, `currentCodeUnitOffset` holds the + /// position at the end of the returned scalar, which is also the start + /// of the next scalar. + /// + /// Returns `nil` if at the end of the `UTF8Span`. + public mutating func next() -> Unicode.Scalar? + + /// Decode and return the scalar ending at `currentCodeUnitOffset`. After + /// the function returns, `currentCodeUnitOffset` holds the position at + /// the start of the returned scalar, which is also the end of the + /// previous scalar. + /// + /// Returns `nil` if at the start of the `UTF8Span`. + public mutating func previous() -> Unicode.Scalar? + + /// Advance `codeUnitOffset` to the end of the current scalar, without + /// decoding it. + /// + /// Returns the number of `Unicode.Scalar`s skipped over, which can be 0 + /// if at the end of the UTF8Span. + public mutating func skipForward() -> Int + + /// Advance `codeUnitOffset` to the end of `n` scalars, without decoding + /// them. + /// + /// Returns the number of `Unicode.Scalar`s skipped over, which can be + /// fewer than `n` if at the end of the UTF8Span. + public mutating func skipForward(by n: Int) -> Int + + /// Move `codeUnitOffset` to the start of the previous scalar, without + /// decoding it. + /// + /// Returns the number of `Unicode.Scalar`s skipped over, which can be 0 + /// if at the start of the UTF8Span. + public mutating func skipBack() -> Bool + + /// Move `codeUnitOffset` to the start of the previous `n` scalars, + /// without decoding them. + /// + /// Returns the number of `Unicode.Scalar`s skipped over, which can be + /// fewer than `n` if at the start of the UTF8Span. + public mutating func skipBack(by n: Int) -> Bool + + /// Reset to the nearest scalar-aligned code unit offset `<= i`. + /// + /// **TODO**: Example + public mutating func reset(roundingBackwardsFrom i: Int) + + /// Reset to the nearest scalar-aligned code unit offset `>= i`. + /// + /// **TODO**: Example + public mutating func reset(roundingForwardsFrom i: Int) + + /// Reset this iterator to code unit offset `i`, skipping _all_ safety + /// checks. + /// + /// Note: This is only for very specific, low-level use cases. If + /// `codeUnitOffset` is not properly scalar-aligned, this function can + /// result in undefined behavior when, e.g., `next()` is called. + /// + /// For example, this could be used by a regex engine to backtrack to a + /// known-valid previous position. + /// + public mutating func reset(uncheckedAssumingAlignedTo i: Int) + + /// Returns the UTF8Span containing all the content up to the iterator's + /// current position. + public func _prefix() -> UTF8Span + + /// Returns the UTF8Span containing all the content after the iterator's + /// current position. + public func _suffix() -> UTF8Span + } +} + +``` + +**QUESTION**: Is it worth also surfacing as `isScalarAligned` API on `UTF8Span` so it's a little easier to find and spell (as well as talk about in doc comments)? + + +### Character processing + +We similarly propose a `UTF8Span.CharacterIterator` type that can do grapheme-breaking forwards and backwards. + +The `CharacterIterator` assumes that the start and end of the `UTF8Span` is the start and end of content. + +Any scalar-aligned position is a valid place to start or reset the grapheme-breaking algorithm to, though you could get different `Character` output if if resetting to a position that isn't `Character`-aligned relative to the start of the `UTF8Span` (e.g. in the middle of a series of regional indicators). + + + +```swift +@_unavailableInEmbedded +extension UTF8Span { + public func _makeCharacterIterator() -> CharacterIterator + + /// Iterate the `Character` contents of a `UTF8Span`. + public struct CharacterIterator: ~Escapable { + public var codeUnits: UTF8Span + + /// The byte offset of the start of the next `Character`. This is + /// always scalar-aligned and `Character`-aligned. + public var currentCodeUnitOffset: Int { get } + + public init(_ span: UTF8Span) + + /// Return the `Character` starting at `currentCodeUnitOffset`. After the + /// function returns, `currentCodeUnitOffset` holds the position at the + /// end of the `Character`, which is also the start of the next + /// `Character`. + /// + /// Returns `nil` if at the end of the `UTF8Span`. + public mutating func next() -> Character? + + /// Return the `Character` ending at `currentCodeUnitOffset`. After the + /// function returns, `currentCodeUnitOffset` holds the position at the + /// start of the returned `Character`, which is also the end of the + /// previous `Character`. + /// + /// Returns `nil` if at the start of the `UTF8Span`. + public mutating func previous() -> Character? + + /// Advance `codeUnitOffset` to the end of the current `Character`, + /// without constructing it. + /// + /// Returns the number of `Character`s skipped over, which can be 0 + /// if at the end of the UTF8Span. + public mutating func skipForward() + + /// Advance `codeUnitOffset` to the end of `n` `Characters`, without + /// constructing them. + /// + /// Returns the number of `Character`s skipped over, which can be + /// fewer than `n` if at the end of the UTF8Span. + public mutating func skipForward(by n: Int) + + /// Move `codeUnitOffset` to the start of the previous `Character`, + /// without constructing it. + /// + /// Returns the number of `Character`s skipped over, which can be 0 + /// if at the start of the UTF8Span. + public mutating func skipBack() + + /// Move `codeUnitOffset` to the start of the previous `n` `Character`s, + /// without constructing them. + /// + /// Returns the number of `Character`s skipped over, which can be + /// fewer than `n` if at the start of the UTF8Span. + public mutating func skipBack(by n: Int) + + /// Reset to the nearest character-aligned position `<= i`. + public mutating func reset(roundingBackwardsFrom i: Int) + + /// Reset to the nearest character-aligned position `>= i`. + public mutating func reset(roundingForwardsFrom i: Int) + + /// Reset this iterator to code unit offset `i`, skipping _all_ safety + /// checks. + /// + /// Note: This is only for very specific, low-level use cases. If + /// `codeUnitOffset` is not properly scalar-aligned, this function can + /// result in undefined behavior when, e.g., `next()` is called. + /// + /// If `i` is scalar-aligned, but not `Character`-aligned, you may get + /// different results from running `Character` iteration. + /// + /// For example, this could be used by a regex engine to backtrack to a + /// known-valid previous position. + /// + public mutating func reset(uncheckedAssumingAlignedTo i: Int) + + /// Returns the UTF8Span containing all the content up to the iterator's + /// current position. + public func prefix() -> UTF8Span + + /// Returns the UTF8Span containing all the content after the iterator's + /// current position. + public func suffix() -> UTF8Span + } + +} +``` + +### Comparisons + +The content of a `UTF8Span` can be compared in a number of ways, including literally (byte semantics) and Unicode canonical equivalence. + +```swift +extension UTF8Span { + /// Whether this span has the same bytes as `other`. + @_alwaysEmitIntoClient + public func bytesEqual(to other: UTF8Span) -> Bool + + /// Whether this span has the same bytes as `other`. + @_alwaysEmitIntoClient + public func bytesEqual(to other: some Sequence) -> Bool + + /// Whether this span has the same `Unicode.Scalar`s as `other`. + @_alwaysEmitIntoClient + public func scalarsEqual( + to other: some Sequence + ) -> Bool + + /// Whether this span has the same `Character`s as `other`, using + /// `Character.==` (i.e. Unicode canonical equivalence). + @_unavailableInEmbedded + @_alwaysEmitIntoClient + public func charactersEqual( + to other: some Sequence + ) -> Bool +} +``` + +We also support literal (i.e. non-canonical) pattern matching against `StaticString`. + +```swift +extension UTF8Span { + static func ~=(_ lhs: UTF8Span, _ rhs: StaticString) -> Bool +} +``` + +#### Canonical equivalence and ordering + +`UTF8Span` can perform Unicode canonical equivalence checks (i.e. the semantics of `String.==` and `Character.==`). + +```swift +extension UTF8Span { + /// Whether `self` is equivalent to `other` under Unicode Canonical + /// Equivalence. + @_unavailableInEmbedded + public func isCanonicallyEquivalent( + to other: UTF8Span + ) -> Bool + + /// Whether `self` orders less than `other` under Unicode Canonical + /// Equivalence using normalized code-unit order (in NFC). + @_unavailableInEmbedded + public func isCanonicallyLessThan( + _ other: UTF8Span + ) -> Bool +} +``` + +#### Extracting sub-spans + +Slicing a `UTF8Span` is nuanced and depends on the caller's desired use. They can only be sliced at scalar-aligned code unit offsets or else it will break the valid-UTF8 invariant. Furthermore, if the caller desires consistent grapheme breaking behavior without externally managing grapheme breaking state, they must be sliced along `Character` boundaries. For this reason, we have exposed slicing as `prefix` and `suffix` operations on `UTF8Span`'s iterators instead of `Span`'s' `extracting` methods. + +### Queries + +`UTF8Span` checks at construction time and remembers whether its contents are all ASCII. Additional checks can be requested and remembered. + +```swift +extension UTF8Span { + /// Returns whether the validated contents were all-ASCII. This is checked at + /// initialization time and remembered. + @inlinable + public var isASCII: Bool { get } + + /// Returns whether the contents are known to be NFC. This is not + /// always checked at initialization time and is set by `checkForNFC`. + @inlinable + @_unavailableInEmbedded + public var isKnownNFC: Bool { get } + + /// Do a scan checking for whether the contents are in Normal Form C. + /// When the contents are in NFC, canonical equivalence checks are much + /// faster. + /// + /// `quickCheck` will check for a subset of NFC contents using the + /// NFCQuickCheck algorithm, which is faster than the full normalization + /// algorithm. However, it cannot detect all NFC contents. + /// + /// Updates the `isKnownNFC` bit. + @_unavailableInEmbedded + public mutating func checkForNFC( + quickCheck: Bool + ) -> Bool + + /// Returns whether every `Character` (i.e. grapheme cluster) + /// is known to be comprised of a single `Unicode.Scalar`. + /// + /// This is not always checked at initialization time. It is set by + /// `checkForSingleScalarCharacters`. + @_unavailableInEmbedded + @inlinable + public var isKnownSingleScalarCharacters: Bool { get } + + /// Do a scan, checking whether every `Character` (i.e. grapheme cluster) + /// is comprised of only a single `Unicode.Scalar`. When a span contains + /// only single-scalar characters, character operations are much faster. + /// + /// `quickCheck` will check for a subset of single-scalar character contents + /// using a faster algorithm than the full grapheme breaking algorithm. + /// However, it cannot detect all single-scalar `Character` contents. + /// + /// Updates the `isKnownSingleScalarCharacters` bit. + @_unavailableInEmbedded + public mutating func checkForSingleScalarCharacters( + quickCheck: Bool + ) -> Bool +} +``` + +**QUESTION**: There is an even quicker quick-check for NFC (checking if all scalars are `<0x300`, which covers extended latin characters). Should we expose that level as well? + +### `UTF8Span` from `String` + +We will add `utf8Span`-style properties to `String` and `Substring`, in line with however [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17) turns out. + + +### `Span`-like functionality + +A `UTF8Span` is similar to a `Span`, but with the valid-UTF8 invariant and additional information such as `isASCII`. We propose a way to get a `Span` from a `UTF8Span` as well as some methods directly on `UTF8Span`: + +``` +extension UTF8Span { + @_alwaysEmitIntoClient + public var isEmpty: Bool { get } + + @_alwaysEmitIntoClient + public var storage: Span { get } + + /// Calls a closure with a pointer to the viewed contiguous storage. + /// + /// The buffer pointer passed as an argument to `body` is valid only + /// during the execution of `withUnsafeBufferPointer(_:)`. + /// Do not store or return the pointer for later use. + /// + /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter + /// that points to the viewed contiguous storage. If `body` has + /// a return value, that value is also used as the return value + /// for the `withUnsafeBufferPointer(_:)` method. The closure's + /// parameter is valid only for the duration of its execution. + /// - Returns: The return value of the `body` closure parameter. + @_alwaysEmitIntoClient + borrowing public func withUnsafeBufferPointer< + E: Error, Result: ~Copyable & ~Escapable + >( + _ body: (_ buffer: borrowing UnsafeBufferPointer) throws(E) -> Result + ) throws(E) -> dependsOn(self) Result +} +``` + +### Getting a `String` from a `UTF8Span` + +**QUESTION**: We should make it easier than `String(decoding:as)` to make a `String` copy of the `UTF8Span`, especially since `UTF8Span` cannot conform to `Sequence` or `Collection`. This will form an ARC-managed copy and not something that will share the (ephemeral) storage. + +## Source compatibility + +This proposal is additive and source-compatible with existing code. + +## ABI compatibility + +This proposal is additive and ABI-compatible with existing code. + +## Implications on adoption + +The additions described in this proposal require a new version of the standard library and runtime. + +## Future directions + +### Streaming grapheme breaking + +Grapheme-breaking, which identifies where the boundaries between `Character`s are, is more complex than scalar decoding. Grapheme breaking can be ran from any scalar-aligned position, either with a given state from having processed previous scalars, or with a "fresh" state (as though that position were the start of new content). + +While the code units in a `UTF8Span` are always scalar-aligned (in order to be validly encoded), whether a span is grapheme-cluster aligned depends on its intended use. For example, `AttributedString` stores its content using rope-like storage, in which the entire content is a sequence of spans were each individual span is scalar-aligned but not necessarily grapheme-cluster aligned. + +A potential approach to exposing this functionality is to make the stdlib's `GraphemeBreakingState` public and define API for finding grapheme-breaks. + +```swift +extension Unicode { + public struct GraphemeBreakingState: Sendable, Equatable { + public init() + } +} +``` + +One approach is to add API to the grapheme breaking state so that the state can find the next break (while updating itself). Another is to pass grapheme breaking state to an iterator on UTF8Span, like below: + +```swift +extension UTF8Span { + public struct GraphemeBreakIterator: ~Escapable { + public var codeUnits: UTF8Span + public var currentCodeUnitOffset: Int + public var state: Unicode.GraphemeBreakingState + + public init(_ span: UTF8Span) + + public init(_ span: UTF8Span, using state: Unicode.GraphemeBreakingState) + + public mutating func next() -> Bool + + public mutating func previous() -> Bool + + + public mutating func skipForward() + + public mutating func skipForward(by n: Int) + + public mutating func skipBack() + + public mutating func skipBack(by n: Int) + + public mutating func reset( + roundingBackwardsFrom i: Int, using: Unicode.GraphemeBreakingState + ) + + public mutating func reset( + roundingForwardsFrom i: Int, using: Unicode.GraphemeBreakingState + ) + + public mutating func reset( + uncheckedAssumingAlignedTo i: Int, using: Unicode.GraphemeBreakingState + ) + + public func prefix() -> UTF8Span + public func suffix() -> UTF8Span + } +``` + + +### More alignments + +Future API could include word iterators (either [simple](https://www.unicode.org/reports/tr18/#Simple_Word_Boundaries) or [default](https://www.unicode.org/reports/tr18/#Default_Word_Boundaries)), line iterators, etc. + +### Normalization + +Future API could include checks for whether the content is in a particular normal form (not just NFC). + +### UnicodeScalarView and CharacterView + +Like `Span`, we are deferring adding any collection-like types to non-escapable `UTF8Span`. Future work could include adding view types that conform to a new `Container`-like protocol. + +For an example implementation of those see [the `UTFSpanViews.swift` test file](https://github.com/apple/swift-collections/pull/394). + +### More algorithms + +We propose equality checks (e.g. `scalarsEqual`), as those are incredibly common and useful operations. We have (tentatively) deferred other algorithms until non-escapable collections are figured out. + +However, we can add select high-value algorithms if motivated by the community. + +### More validation API + +Future work includes returning all the encoding errors found in a given input. + +```swift +extension UTF8 { + public static func checkAllErrors( + _ s: some Sequence + ) -> some Sequence +``` + +See [`_checkAllErrors` in `UTF8EncodingError.swift`](https://github.com/apple/swift-collections/pull/394). + +### Transcoded iterators, normalized iterators, case-folded iterators, etc + +We could provide lazily transcoded, normalized, case-folded, etc., iterators. If we do any of these for `UTF8Span`, we should consider adding equivalents views on `String`, `Substring`, etc. + +### Regex or regex-like support + +Future API additions would be to support `Regex`es on `UTF8Span`. We'd expose grapheme-level semantics, scalar-level semantics, and introduce byte-level semantics. + +Another future direction could be to add many routines corresponding to the underlying operations performed by the regex engine, which would be useful for parser-combinator libraries who wish to expose `String`'s model of Unicode by using the stdlib's accelerated implementation. + + +### Canonical Spaceships + +Should a `ComparisonResult` (or [spaceship](https://forums.swift.org/t/pitch-comparison-reform/5662)) be added to Swift, we could support that operation under canonical equivalence in a single pass rather than subsequent calls to `isCanonicallyEquivalent(to:)` and `isCanonicallyLessThan(_:)`. + + +### Exposing `String`'s storage class + +String's internal storage class is null-terminated valid UTF-8 (by substituting replacement characters) and implements range-replaceable operations along scalar boundaries. We could consider exposing the storage class itself, which might be useful for embedded platforms that don't have `String`. + +### Track other bits + +Future work include tracking whether the contents are NULL-terminated (useful for C bridging), whether the contents contain any newlines or only a single newline at the end (useful for accelerating Regex `.`), etc. + +### Putting more API on String + +`String` would also benefit from the query API, such as `isKnownNFC` and corresponding scan methods. Because a string may be a lazily-bridged instance of `NSString`, we don't always have the bits available to query or set, but this may become viable pending future improvements in bridging. + +### Generalize printing and logging facilities + +Many printing and logging protocols and facilities operate in terms of `String`. They could be generalized to work in terms of UTF-8 bytes instead, which is important for embedded. + +## Alternatives considered + +### Invalid start / end of input UTF-8 encoding errors + +Earlier prototypes had `.invalidStartOfInput` and `.invalidEndOfInput` UTF8 validation errors to communicate that the input was perhaps incomplete or not slices along scalar boundaries. In this scenario, `.invalidStartOfInput` is equivalent to `.unexpectedContinuation` with the range's lower bound equal to 0 and `.invalidEndOfInput` is equivalent to `.truncatedScalar` with the range's upper bound equal to `count`. + +This was rejected so as to not have two ways to encode the same error. There is no loss of information and `.unexpectedContinuation`/`.truncatedScalar` with ranges are more semantically precise. + +### An unsafe UTF8 Buffer Pointer type + +An [earlier pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715) proposed an unsafe version of `UTF8Span`. Now that we have `~Escapable`, a memory-safe `UTF8Span` is better. + +### Alternatives to Iterators + +#### Functions + +A previous version of this pitch had code unit offset taking API directly on UTF8Span instead of using iterators as proposed. This lead to a large number of unweildy API. For example, instead of: + +```swift +extension UTF8Span.ScalarIterator { + public mutating func next() -> Unicode.Scalar? { } +} +``` + +we had: + +```swift +extension UTF8Span { +/// Decode the `Unicode.Scalar` starting at `i`. Return it and the start of + /// the next scalar. + /// + /// `i` must be scalar-aligned. + @_alwaysEmitIntoClient + public func decodeNextScalar( + _ i: Int + ) -> (Unicode.Scalar, nextScalarStart: Int) + + /// Decode the `Unicode.Scalar` starting at `i`. Return it and the start of + /// the next scalar. + /// + /// `i` must be scalar-aligned. + /// + /// This function does not validate that `i` is within the span's bounds; + /// this is an unsafe operation. + @_alwaysEmitIntoClient + public func decodeNextScalar( + unchecked i: Int + ) -> (Unicode.Scalar, nextScalarStart: Int) + + /// Decode the `Unicode.Scalar` starting at `i`. Return it and the start of + /// the next scalar. + /// + /// `i` must be scalar-aligned. + /// + /// This function does not validate that `i` is within the span's bounds; + /// this is an unsafe operation. + /// + /// + /// This function does not validate that `i` is scalar-aligned; this is an + /// unsafe operation if `i` isn't. + @_alwaysEmitIntoClient + public func decodeNextScalar( + uncheckedAssumingAligned i: Int + ) -> (Unicode.Scalar, nextScalarStart: Int) +} +``` + +Every operation had `unchecked:` and `uncheckedAssumingAligned:` variants, which were needed to implement higher-performance constructs such as iterators and string processing features (including the `Regex` engine). + +This API made the caller manage the scalar-alignment invariant, while the iterator-style API proposed maintains this invariant internally, allowing it to use the most efficient implementation. + +Scalar-alignment can still be checked and managed by the caller through the `reset` API, which safely round forwards or backwards as needed. And, for high performance use cases where the caller knows that a given position is appropriately aligned already (for example, revisiting a prior point in a string during `Regex` processing), there's the `reset(uncheckedAssumingAlignedTo:)` API available. + +### Collections + +Because `Collection`s are `Escapable`, we cannot conform nested `View` types to `Collection`. + + +## Acknowledgments + +Karoy Lorentey, Karl, Geordie_J, and fclout, contributed to this proposal with their clarifying questions and discussions. + + + + + + + + + From 7eab91d2b1dacd993a94680a9eb9639aa728682b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 17:33:31 -0800 Subject: [PATCH 050/505] [SE-0458] Don't require declarations with unsafe signatures to be @unsafe This extra step of requiring @unsafe is mostly busywork. Rather, we infer @unsafe from unsafe types, and can later suppress false positives for actually-safe declarations by marking them @safe. --- proposals/0458-strict-memory-safety.md | 94 ++++++++++++-------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index c194e8dd49..c07036e48d 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -59,20 +59,13 @@ The `UnsafeBufferPointer` type will be marked with `@unsafe` in the Standard lib public struct UnsafeBufferPointer { ... } ``` -This indicates that use of this type is not memory-safe. Any declaration that has `UnsafeBufferPointer` as part of its type is also unsafe, and would produce a warning under this strict safety mode, e.g., +This indicates that use of this type is not memory-safe. Any declaration that has `UnsafeBufferPointer` as part of its type is implicitly `@unsafe`. ```swift -// warning: reference to unsafe generic struct 'UnsafePointer' +// note: implicitly @unsafe due to the use of the unsafe type UnsafePointer func sumIntBuffer(_ address: UnsafePointer?, _ count: Int) -> Int { ... } ``` -This warning can be suppressed by marking the function as `@unsafe`: - -```swift -@unsafe -func sumIntBuffer(_ address: UnsafePointer?, _ count: Int, _ start: Int) -> Int { ... } -``` - Users of this function that enable strict safety checking will see warnings when using it. For example: ```swift @@ -94,14 +87,13 @@ To suppress these warnings, the expressions involving unsafe code must be marked extension Array { func sum() -> Int { withUnsafeBufferPointer { buffer in - // warning: use of unsafe function 'sumIntBuffer' and unsafe property 'baseAddress' unsafe sumIntBuffer(buffer.baseAddress, buffer.count, 0) } } } ``` -The `unsafe` keyword here indicates the presence of unsafe code within that expression. As with `try` and `await`, it can cover multiple sources of unsafety within that expression: the call to `sumIntBuffer` is unsafe, as is the use of `buffer` and `buffer.baseAddress`, yet they are all covered by one `unsafe`. +The `unsafe` keyword here indicates the presence of unsafe code within that expression. As with `try` and `await`, it can cover multiple sources of unsafety within that expression: the call to `sumIntBuffer` is unsafe, as is the use of `buffer` and `buffer.baseAddress`, yet they are all covered by one `unsafe`. It is up to the authors of an unsafe API to document the conditions under which it is safe to use that API, and the user of that API to ensure that those conditions are met within the `unsafe` expression. Unlike `try`, `unsafe` doesn't propagate outward: we do *not* require that the `sum` function be marked `@unsafe` just because it has unsafe code in it. Similarly, the call to `withUnsafeBufferPointer` doesn't have to be marked as `unsafe` just because it has a closure that is unsafe. The programmer may choose to indicate that `sum` is unsafe, but the assumption is that unsafe behavior is properly encapsulated when using `unsafe` if the signature doesn't contain any unsafe types. @@ -123,7 +115,8 @@ The operation `UnsafeMutableBufferPointer.swapAt` swaps the values at the given ```swift extension UnsafeMutableBufferPointer { - @unsafe public func swapAt(_ i: Index, _ j: Index) { + /*implicitly @unsafe*/ + public func swapAt(_ i: Index, _ j: Index) { guard i != j else { return } precondition(i >= 0 && j >= 0) precondition(i < endIndex && j < endIndex) @@ -141,7 +134,7 @@ The `swapAt` implementation uses a mix of safe and unsafe code. The code marked * Performing pointer arithmetic on `baseAddress`: Swift cannot reason about the lifetime of that underlying pointer, nor whether the resulting pointer is still within the bounds of the allocation. * Moving and initializing the actual elements. The elements need to already be initialized. -The code itself has preconditions to ensure that the provided indices aren't out of bounds before performing the pointer arithmetic. However, there are other safety properties that cannot be checked with preconditions: that the memory associated with the pointer has been properly initialized, has a lifetime that spans the whole call, and is not being used simultaneously by any other part of the code. These safety properties are something that must be established by the *caller* of `swapAt`. Therefore, `swapAt` is marked `@unsafe` because callers of it need to reason about these properties. +The code itself has preconditions to ensure that the provided indices aren't out of bounds before performing the pointer arithmetic. However, there are other safety properties that cannot be checked with preconditions: that the memory associated with the pointer has been properly initialized, has a lifetime that spans the whole call, and is not being used simultaneously by any other part of the code. These safety properties are something that must be established by the *caller* of `swapAt`. Therefore, `swapAt` is considered `@unsafe` because callers of it need to reason about these properties. Because it's part of an unsafe type, it is implicitly `@unsafe`, although the author could choose to mark it as `@unsafe` explicitly. ### Incremental adoption @@ -150,17 +143,17 @@ The strict memory safety checking proposed here enforces a subset of Swift. Code * Strict concurrency checking, the focus of the Swift 6 language mode, required major changes to the type system, including the propagation of `Sendable` and the understanding of what code must be run on the main actor. These are global properties that don't permit local reasoning, or even local fixes, making the interoperability problem particularly hard. In contrast, strict safety checking has little or no effect on the type system, and unsafety can be encapsulated with `unsafe` expressions or ignored by a module that doesn't enable the checking. * [Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0337-support-incremental-migration-to-concurrency-checking.md) is a subset of Swift that works without a runtime. Like the proposed strictly-safe subset, code written in Embedded Swift will also work as regular Swift. Embedded Swift and the strict safety checking proposed here are orthogonal and can be composed to (for example) ensure that firmware written in Swift has no runtime and provides the best memory-safety guarantees. -A Swift module that adopts strict safety checking can address all of the resulting diagnostics by applying the `@unsafe` attribute and `unsafe` expression in the appropriate places, without changing any other code. This application of attributes can be automated through Fix-Its, making it possible to enable the mode and silence all diagnostics automatically. It would then be left to the programmer to audit those places that have used `unsafe` to encapsulate unsafe behavior, to ensure that they are indeed safe. Note that the strict safety checking does not by itself make the code more memory-safety: rather, it identifies those constructs that aren't safe, encouraging the use of safe alternatives and making it easier to audit for unsafe behavior. +A Swift module that adopts strict safety checking can address all of the resulting diagnostics by applying the `@unsafe` attribute and `unsafe` expression in the appropriate places, without changing any other code. This application of attributes can be automated through Fix-Its, making it possible to enable the mode and silence all diagnostics automatically. It would then be left to the programmer to audit those places that have used `unsafe` to encapsulate unsafe behavior, to ensure that they are indeed safe. Note that the strict safety checking does not by itself make the code more memory-safe: rather, it identifies those constructs that aren't safe, encouraging the use of safe alternatives and making it easier to audit for unsafe behavior. The introduction of the `@unsafe` attribute on a declaration has no effect on clients compiled without strict safety enabled. For clients that have enabled strict safety, they will start diagnosing uses of the newly-`@unsafe` API. However, these diagnostics are warnings with their own diagnostic group, so a client can ensure that they do not prevent the client from building. Therefore, modules can adopt strict safety checking at their own pace (or not) and clients of those modules are never "stuck" having to make major changes in response. ## Detailed design -This section describes how the primary proposed constructs, the `@unsafe` attribute and `unsafe` expression, interact with the strict type checking mode, and enumerates the places in the language, standard library, and compiler that introduce non-memory-safe code. +This section describes how the primary proposed constructs, the `@unsafe` attribute, `@safe` attribute, and `unsafe` expression, interact with the strict memory safety mode, and enumerates the places in the language, standard library, and compiler that introduce non-memory-safe code. ### `@unsafe` attribute -The `@unsafe` attribute can be applied to any declaration to indicate that use of that declaration can undermine memory safety. Any use of a declaration marked `@unsafe` will result in a warning. The closest analogue in the language today is `@available(*, deprecated)`, which has effectively no impact on the type system, yet any use of a deprecated declaration results in a warning. +The `@unsafe` attribute can be applied to any declaration to indicate that use of that declaration can undermine memory safety. Any use of an `@unsafe` declaration that isn't acknowledged in the source code (e.g., via the `unsafe` expression) will result in a warning. The closest analogue in the language today is `@available(*, deprecated)`, which has effectively no impact on the type system, yet any use of a deprecated declaration results in a warning. When a type is marked `@unsafe`, a declaration that uses that type in its interface is implicitly `@unsafe`. For example, consider a program containing three separate modules: @@ -170,7 +163,9 @@ When a type is marked `@unsafe`, a declaration that uses that type in its interf public struct DataWrapper { var buffer: UnsafeBufferPointer - public func checksum() -> Int32 { ... } + public func checksum() -> Int32 { + ... + } } // Module B @@ -191,12 +186,37 @@ extension MyType { } ``` -Module `A` defines a type, `DataWrapper`, that is `@unsafe`. It can be compiled with or without strict safety checking enabled, and is fine either way. +Module `A` defines a type, `DataWrapper` that stores an `UnsafeBufferPointer`, and is marked `@unsafe`. It can be compiled with or without strict safety checking enabled. If compiled with -Module `B` uses the `DataWrapper` type. If compiled without strict safety checking, there will be no diagnostics about memory safety. If compiled with strict safety checking, there will be a diagnostic about `wrapper` using an `@unsafe` type (`DataWrapper`) in its interface. This diagnostic can be ignored, but ideally the `wrapper` property will be marked as `@unsafe` (silencing the warning). +Module `B` uses the `DataWrapper` type. If compiled without strict safety checking, there will be no diagnostics about memory safety. The `wrapper` property is implicitly `@unsafe`, although the author may mark it as `@unsafe` explicitly if they choose to. If compiled with strict safety checking, the code will produce a warning because the storage of `MyType` involves an unsafe type (`DataWrapper`). This warning can be suppressed by either marking `MyType` as `@unsafe` (propagating unsafety) or `@safe` (`MyType` is safe to use). If left alone, it will be assumed to be safe. If module `C` enables strict memory safety, the use of `MyType` is considered safe (since it was not marked `@unsafe` and doesn't involve unsafe types in its interface). However, the access to `wrapper` will result in a diagnostic, because the type of `wrapper` involves an `@unsafe` type. This diagnostic will occur whether or not `wrapper` has been explicitly marked `@unsafe`. +### `unsafe` expression + +Any time there is executable code that makes use of unsafe constructs, the compiler will produce a diagnostic that indicates the use of those unsafe constructs unless it is within an `unsafe` expression. As noted in the previous section, use of the `wrapper` property (which is implicitly `@unsafe` due to the use of unsafe types) without an enclosing `unsafe` will produce a warning:: + +```swift +extension MyType { + public func checksum() -> Int32 {} + // warning: use of property `wrapper` with unsafe type `DataWrapper` + return wrapper.checksum() + } +} +``` + +To suppress the warning, introduce an `unsafe` prior to the expression involving the unsafe code: + +```swift +extension MyType { + public func checksum() -> Int32 {} + return unsafe wrapper.checksum() + } +} +``` + +The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`wrapper`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. + There are a few exemptions to the rule that any unsafe constructs within the signature require the declaration to be `@unsafe`: * Local variables involving unsafe types do not need to be marked with `@unsafe`. For example, the local variable `base` will have unsafe type `UnsafePointer?`, but does not require `@unsafe` because every *use* of this local variable will need to be marked using the `unsafe` expression described in the next section. @@ -218,7 +238,7 @@ There are a few exemptions to the rule that any unsafe constructs within the sig ### `@safe` attribute -Like the `@unsafe` attribute, the `@safe` attribute is used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is considered safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: +The `@safe` attribute is used on declarations whose signatures involve unsafe types but are, nonetheless, safe to use. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those certain operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: ```swift extension UnsafeBufferPointer { @@ -264,35 +284,6 @@ extension Array { } ``` -### `unsafe` expression - -When a declaration is marked `@unsafe`, it is free to use any other unsafe types as part of its interface. Any time there is executable code that makes use of unsafe constructs, that code must be within an `unsafe` expression or it will receive a diagnostic about uses of unsafe code. In the example from the previous section, `wrapper` can be marked as `@unsafe` to suppress diagnostics by explicitly propagating unsafety to their clients: - -```swift -// Module B -import A - -public struct MyType { - @unsafe public var wrapper: DataWrapper -} -``` - -However, the use of the `wrapper` property in module `C` will produce a diagnostic unless it is part of an `unsafe` expression, like this: - -```swift -// Module C -import A -import B - -extension MyType { - public func checksum() -> Int32 {} - return unsafe wrapper.checksum() - } -} -``` - -The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`wrapper`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. - ### Unsafe language constructs The following language constructs are always considered to be unsafe: @@ -740,7 +731,10 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh ## Revision history -* **Revision 2 (following first review)** +* **Revision 3 (following second review eextension)** + * Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe. + +* **Revision 2 (following first review extension)** * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. * Require types whose storage involves an unsafe type or conformance to be marked as `@safe` or `@unsafe`, much like other declarations that have unsafe types or conformances in their signature. * Add an Alternatives Considered section on prohibiting unsafe conformances and overrides. From 694d95ad1f3da2cef69f0d4ac44d7c722e722d0d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 22:17:33 -0800 Subject: [PATCH 051/505] SE-0459: Add handling of unsafe for for..in iteration --- proposals/0458-strict-memory-safety.md | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index c07036e48d..3de7b20fd8 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -411,6 +411,42 @@ func passUnsafe() { } ``` +### `for..in` loops + +Swift's `for..in` loops are effectively implemented as syntactic sugar over the `Sequence` and `IteratorProtocol` protocols, where the `for..in` creates a new iterator (with `Sequence.makeIterator()`) and then calls its `next()` operation for each loop iteration. If the conformances to `Sequence` are `IteratorProtocol` is `@unsafe`, the loop will introduce a warning: + +```swift +let someUnsafeBuffer: UnsafeBufferPointer = unsafe ... +for x in someBuffer { // warning: use of unsafe conformance of 'UnsafeBufferPointer' to 'Sequence' + // and someBuffer has unsafe type 'UnsafeBufferPointer' + // ... +} +``` + +Following the precedent set by [SE-0298](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0298-asyncsequence.md), which introduced effects in loops, the `unsafe` keyword that acknowledges unsafe behavior in the iteration will follow the `for`: + +```swift +let someUnsafeBuffer: UnsafeBufferPointer = unsafe ... +for unsafe x in someBuffer { // still warns that someBuffer has unsafe type 'UnsafeBufferPointer' + // ... +} +``` + +This may not be the only unsafe behavior in the `for..in` loop. For example, the expression that produces the sequence itself (via the reference to `someBuffer`) is also unsafe, so it needs to be acknowledged: + +```swift +let someUnsafeBuffer: UnsafeBufferPointer = unsafe ... +for unsafe x in unsafe someBuffer { + // ... +} +``` + +This repeated `unsafe` also occurs with the other effects: if an `async throws` function `getAsyncSequence()` produces an `AsyncSequence` whose iteration can throw, one will end up with two `try` and `await` keywords: + +```swift +for try await x in try await getAsyncSequence() { ... } +``` + ### Strict safety mode and escalatable warnings The strict memory safety mode can be enabled with the new compiler flag `-strict-memory-safety`. @@ -733,6 +769,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh * **Revision 3 (following second review eextension)** * Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe. + * Add `unsafe` for iteration via the `for..in` syntax. * **Revision 2 (following first review extension)** * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. From ee09e8a05a69fd5386581d49e1494f1eb58245d0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 22:47:03 -0800 Subject: [PATCH 052/505] Infer @unsafe on imported C structs/enums/classes/unions with pointers in them --- proposals/0458-strict-memory-safety.md | 61 ++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 3de7b20fd8..c2afa2b9f6 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -447,6 +447,66 @@ This repeated `unsafe` also occurs with the other effects: if an `async throws` for try await x in try await getAsyncSequence() { ... } ``` +### C(++) interoperability + +The C family of languages does not provide an equivalent to the strict safety mode described in this proposal, and unlike Swift, the defaults tend to be unsafe along all of the dimensions of memory safety. C(++) libriaries used within Swift can, therefore, introduce memory safety issues into the Swift code. + +The primary issue with memory safety in C(++) concerns the presence of pointers. C(++) pointers will generally be imported into Swift as an `Unsafe*Pointer` type of some form. For C functions (and C++ member functions), that means that a potentially unsafe API such as + +```swift +char *strstr(const char * haystack, const char *needle); +``` + +will be treated as implicitly `@unsafe` in Swift because its signature contains unsafe types: + +```swift +func strstr( + _ haystack: UnsafePointer?, + _ needle: UnsafePointer? +) -> UnsafeMutablePointer? +``` + +A C function that doesn't use pointer types, on the other hand, will implicitly be considered to be safe, because there are no unsafe types in its Swift signature. For example, the following would be considered safe: + +```swift +// int getchar(void); +func getchar() -> CInt +``` + +C and C++ also have user-defined types in the form of `struct`s, `enum`s, `union`s, and (in C++) `class`es. For such types, this proposal infers them to be `@unsafe` when their non-static data contains any C pointers or C types that are explicitly marked as unsafe. For example, a `Point` struct could be considered safe: + +```cpp +struct Point { + double x, y; +}; +``` + +but a `struct` with a pointer or C++ reference in it would be implicitly `@unsafe` in Swift: + +```swift +struct ListNode { + void *element; + struct ListNode *next; +}; +``` + +The C attribute `swift_attr` can be used to make specific declarations safe or unsafe, e.g., we could mark a C++ class that manages its internal pointer correctly as being safe, e.g., + +```cpp +class __attribute__((swift_attr("@safe"))) MyString { + char *data; + size_t length; + + MyString(const MyString &); + MyString(MyString &&); + MyString &operator=(const MyString&); + MyString &operator=(MyString&&); + ~MyString(); +}; +``` + +Note that C `enum`s will never be inferred to be `@unsafe` because they don't carry any values other than their underlying integral type, which is always a safe type. + ### Strict safety mode and escalatable warnings The strict memory safety mode can be enabled with the new compiler flag `-strict-memory-safety`. @@ -770,6 +830,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh * **Revision 3 (following second review eextension)** * Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe. * Add `unsafe` for iteration via the `for..in` syntax. + * Add C(++) interoperability section that infers `@unsafe` for C types that involve pointers. * **Revision 2 (following first review extension)** * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. From 2ffa2d4fc20fb5e839922fcb07c7d05c35e1b999 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 23:33:43 -0800 Subject: [PATCH 053/505] SE-0458: Restructure for improved readability The Detailed Design was becoming a grab-bag of sections, so give it more structure. First, we describe all of the sources of memory unsafety in Swift. Then, note the role of the @safe attribute. Finally, describe all of the ways in which one can acknowledge unsafety. One drive-by fix here is to document the unsafe conformances of the `UnsafeBufferPointer` family of types to the `Collection` protocol hierarchy. --- proposals/0458-strict-memory-safety.md | 327 ++++++++++++------------- 1 file changed, 151 insertions(+), 176 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index c2afa2b9f6..1a4cff2eed 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -151,90 +151,142 @@ The introduction of the `@unsafe` attribute on a declaration has no effect on cl This section describes how the primary proposed constructs, the `@unsafe` attribute, `@safe` attribute, and `unsafe` expression, interact with the strict memory safety mode, and enumerates the places in the language, standard library, and compiler that introduce non-memory-safe code. -### `@unsafe` attribute +### Sources of unsafety -The `@unsafe` attribute can be applied to any declaration to indicate that use of that declaration can undermine memory safety. Any use of an `@unsafe` declaration that isn't acknowledged in the source code (e.g., via the `unsafe` expression) will result in a warning. The closest analogue in the language today is `@available(*, deprecated)`, which has effectively no impact on the type system, yet any use of a deprecated declaration results in a warning. +There are a number of places in the language where one can introduce memory unsafety. This section enumerates the ways in which the language, library, and user code can introduce memory unsafety. -When a type is marked `@unsafe`, a declaration that uses that type in its interface is implicitly `@unsafe`. For example, consider a program containing three separate modules: +#### Unsafe language constructs + +The following language constructs are always considered to be unsafe: + +* `unowned(unsafe)`: Used to store a reference without maintaining its reference count. The safe counterpart, `unowned`, uses dynamic checking to ensure that the reference isn't accessed after the corresponding object has been released. The `unsafe` variant disables that dynamic checking. Uses of `unowned(unsafe)` entities are not memory-safe. +* `unsafeAddressor`, `unsafeMutableAddressor`: These accessors vend an unsafe pointer, and are therefore unsafe to declare. Other accessors (e.g., `get` and `set`) can provide safe alternatives. The accessors are considered to be part of the signature of the property or subscript they're associated with, making the property implicitly `@unsafe` unless explicitly marked `@safe`. +* `@exclusivity(unchecked)`: Used to remove dynamic exclusivity checks from a particular variable, which can mean that dynamic exclusivity violations go undetected at run time, causing a memory safety violation. Uses of `@exclusivity(unchecked)` entities are not memory-safe. + +The following language constructs are considered to be unsafe when strict concurrency checking is enabled (i.e., in the Swift 6 language mode): + +* `nonisolated(unsafe)`: Allows a property to be accessed from concurrent code without ensuring that such accesses are done so safely. Uses of `nonisolated(unsafe)` entities are not memory-safe. +* `@preconcurrency` imports: Suppresses diagnostics related to data race safety when they relate to specific imported modules, which can introduce thread safety issues. The `@preconcurrency` import will need to be annotated with `@unsafe` in the strict safety mode. + +#### `@unsafe` attribute + +The `@unsafe` attribute can be applied to any declaration to indicate that use of that declaration can undermine memory safety. Here are some examples: ```swift -// Module A @unsafe public struct DataWrapper { var buffer: UnsafeBufferPointer - - public func checksum() -> Int32 { - ... - } } -// Module B -import A +@unsafe +func writeToRegisterAt(integerAddress: Int, value: Int32) { ... } +``` -public struct MyType { - public var wrapper: DataWrapper -} +Uses of `DataWrapper` and `writeToRegisterAt` within executable code will be considered to be memory-unsafe. -// Module C -import A -import B +When a declaration uses unsafe types within its signature, it is implicitly considered to be `@unsafe`. The signature of a declaration is the interface that the declaration presents to clients, including the parameter and result types of functions, the type of properties, and any generic parameters and requirements. For example, a method on `DataWrapper` defined as follows: -extension MyType { - public func checksum() -> Int32 {} - return wrapper.checksum() +```swift +extension DataWrapper { + public func checksum() -> Int32 { + crc32(0, buffer.baseAddress, buffer.count) } } ``` -Module `A` defines a type, `DataWrapper` that stores an `UnsafeBufferPointer`, and is marked `@unsafe`. It can be compiled with or without strict safety checking enabled. If compiled with +will be implicitly `@unsafe` because the type of the implicit `self` parameter is `@unsafe`. -Module `B` uses the `DataWrapper` type. If compiled without strict safety checking, there will be no diagnostics about memory safety. The `wrapper` property is implicitly `@unsafe`, although the author may mark it as `@unsafe` explicitly if they choose to. If compiled with strict safety checking, the code will produce a warning because the storage of `MyType` involves an unsafe type (`DataWrapper`). This warning can be suppressed by either marking `MyType` as `@unsafe` (propagating unsafety) or `@safe` (`MyType` is safe to use). If left alone, it will be assumed to be safe. +Generally speaking, a declaration's signature is everything that isn't within the "body" of the definition that's enclosed in braces or following the `=` of a property. One notable exception to this is default arguments, because default arguments of functions are part of the implementation of a function, not its signature. For example, the following function does not have any unsafe types in its signature, even though the default argument for `value` involves unsafe code. That unsafe code is effectively part of the body of the function, so it follows the rules for `unsafe` expressions. -If module `C` enables strict memory safety, the use of `MyType` is considered safe (since it was not marked `@unsafe` and doesn't involve unsafe types in its interface). However, the access to `wrapper` will result in a diagnostic, because the type of `wrapper` involves an `@unsafe` type. This diagnostic will occur whether or not `wrapper` has been explicitly marked `@unsafe`. +```swift +func hasDefault(value: Int = unsafe getIntegerUnsafely()) { ... } +``` -### `unsafe` expression +#### Unsafe conformances -Any time there is executable code that makes use of unsafe constructs, the compiler will produce a diagnostic that indicates the use of those unsafe constructs unless it is within an `unsafe` expression. As noted in the previous section, use of the `wrapper` property (which is implicitly `@unsafe` due to the use of unsafe types) without an enclosing `unsafe` will produce a warning:: +A given type might implement a protocol in a manner that introduces unsafety, for example because the operations needed to satisfy protocol requirements cannot ensure that all uses through the protocol can maintain memory safety. For example, the `UnsafeBufferPointer` type conforms to the `Collection` protocol, but it cannot do so in a safe way because `UnsafeBufferPointer` does not provide the lifetime, bounds, or initialization safety that clients of the `Collection` protocol expect. Such conformances should be explicitly marked `@unsafe`, e.g., ```swift -extension MyType { - public func checksum() -> Int32 {} - // warning: use of property `wrapper` with unsafe type `DataWrapper` - return wrapper.checksum() - } -} +extension UnsafeBufferPointer: @unsafe Collection { ... } ``` -To suppress the warning, introduce an `unsafe` prior to the expression involving the unsafe code: +Unsafe conformances are similar to unsafe types in that their presence in a declaration's signature will make that declaration implicitly `@unsafe`. For example, the use of a collection algorithm such as `firstIndex(where:)` with an `UnsafeBufferPointer` will be considered unsafe because the conformance above is `@unsafe`. + +#### Unsafe standard library APIs + +Much of the identification of unsafe Swift code that becomes available with the strict memory safety mode is due to the identification of unsafe declarations within the standard library itself, and their propagation to other types that use them. In the standard library, the following functions and types would be marked `@unsafe` : + +* `Unsafe(Mutable)(Raw)(Buffer)Pointer`, `OpaquePointer`, `CVaListPointer`: These types provide neither lifetime nor bounds safety. Over time, Swift code is likely to move toward their safe replacements, such as `(Raw)Span`. +* `(Closed)Range.init(uncheckedBounds:)`: This operation makes it possible to create a range that doesn't satisfy invariants on which other bounds safety checking (e.g., in `Array.subscript`) relies. +* `Span.subscript(unchecked:)` : An unchecked subscript whose use can introduce bounds safety problems. +* `Unmanaged`: Wrapper over reference-counted types that explicitly disables reference counting, potentially introducing lifetime safety issues. +* `unsafeBitCast`: Allows type casts that are not known to be safe, which can introduce type safety problems. +* `unsafeDowncast`: An unchecked form of an `as!` cast that can introduce type safety problems. +* `Optional.unsafelyUnwrapped`: An unchecked form of the postfix `!` operation on optionals that can introduce various type, initialization, or lifetime safety problems when `nil` is interpreted as a typed value. +* `UnsafeContinuation`, `withUnsafe(Throwing)Continuation`: An unsafe form of `withChecked(Throwing)Continuation` that does not verify that the continuation is called exactly once, which can cause various safety problems. +* `withUnsafeCurrentTask` and `UnsafeCurrentTask`: The `UnsafeCurrentTask` type does not provide lifetime safety, and must only be used within the closure passed to `withUnsafeCurrentTask`. +* `UnownedSerialExecutor`: This type is intentionally not lifetime safe. It's primary use is the `unownedExecutor` property of the `Actor` protocol, which documents the lifetime assumptions of the `UnownedSerialExecutor` instance it produces. + +All of these APIs will be marked `@unsafe`. For standard library APIs that involve unsafe types, those that are safe to use will be marked `@safe` while those that require the user to maintain some aspect of safety will be marked `@unsafe`. Unless mentioned above, standard library APIs that do not have an unsafe type in their signature, but use unsafe constructs in their implementation, will be considered to be safe. + +There are also a number of unsafe conformances in the standard library: + +* `Unsafe(Mutable)(Raw)BufferPointer`: The conformances of these types to `Sequence` and the `Collection` protocol hierarchy are all `@unsafe`. +* `Unsafe(Mutable)(Raw)Pointer`: The conformances of these types to `Strideable` are `@unsafe`. + +#### Unsafe compiler flags + +There are a number of compiler flags that intentionally disable some safety-related checking. For each of these flags, the compiler will produce a diagnostic if they are used with strict memory safety: + +* `-Ounchecked`, which disables some checking in the standard library, including (for example) bounds checking on array accesses. +* `-enforce-exclusivity=unchecked` and `-enforce-exclusivity=none`, which disables exclusivity checking that is needed for memory safety. +* `-strict-concurrency=` for anything other than "complete", because the memory safety model requires strict concurrency to eliminate thread safety issues. +* `-disable-access-control`, which allows one to break invariants of a type that can lead to memory-safety issues, such as breaking the invariant of `Range` that the lower bound not exceed the upper bound. + +#### C(++) interoperability + +The C family of languages does not provide an equivalent to the strict safety mode described in this proposal, and unlike Swift, the defaults tend to be unsafe along all of the dimensions of memory safety. C(++) libriaries used within Swift can, therefore, introduce memory safety issues into the Swift code. + +The primary issue with memory safety in C(++) concerns the presence of pointers. C(++) pointers will generally be imported into Swift as an `Unsafe*Pointer` type of some form. For C functions (and C++ member functions), that means that a potentially unsafe API such as ```swift -extension MyType { - public func checksum() -> Int32 {} - return unsafe wrapper.checksum() - } -} +char *strstr(const char * haystack, const char *needle); ``` -The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`wrapper`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. +will be treated as implicitly `@unsafe` in Swift because its signature contains unsafe types: -There are a few exemptions to the rule that any unsafe constructs within the signature require the declaration to be `@unsafe`: +```swift +func strstr( + _ haystack: UnsafePointer?, + _ needle: UnsafePointer? +) -> UnsafeMutablePointer? +``` -* Local variables involving unsafe types do not need to be marked with `@unsafe`. For example, the local variable `base` will have unsafe type `UnsafePointer?`, but does not require `@unsafe` because every *use* of this local variable will need to be marked using the `unsafe` expression described in the next section. +A C function that doesn't use pointer types, on the other hand, will implicitly be considered to be safe, because there are no unsafe types in its Swift signature. For example, the following would be considered safe: - ```swift - func sum(array: [Int]) -> Int { - array.withUnsafeBufferPointer { buffer in - /*@unsafe is unnecessary here*/ let base = unsafe buffer.baseAddress - // ... - } - } - ``` +```swift +// int getchar(void); +func getchar() -> CInt +``` -* Default arguments of functions are part of the implementation of a function, not its signature. For example, the following function does not have any unsafe types in its signature, so it does not require `@unsafe`, even though the default argument for `value` involves unsafe code. That unsafe code is effectively part of the body of the function, so it follows the rules for `unsafe` expressions. +C and C++ also have user-defined types in the form of `struct`s, `enum`s, `union`s, and (in C++) `class`es. For such types, this proposal infers them to be `@unsafe` when their non-static data contains any C pointers or C types that are explicitly marked as unsafe. For example, a `Point` struct could be considered safe: - ```swift - func hasDefault(value: Int = unsafe getIntegerUnsafely()) { ... } - ``` +```cpp +struct Point { + double x, y; +}; +``` + +but a `struct` with a pointer or C++ reference in it would be implicitly `@unsafe` in Swift: + +```swift +struct ListNode { + void *element; + struct ListNode *next; +}; +``` + +Note that C `enum`s will never be inferred to be `@unsafe` because they don't carry any values other than their underlying integral type, which is always a safe type. ### `@safe` attribute @@ -284,48 +336,61 @@ extension Array { } ``` -### Unsafe language constructs +### Acknowledging unsafety -The following language constructs are always considered to be unsafe: +All of the features described above are available in Swift regardless of whether strict memory safety checking is enabled. When strict memory safety checking is enabled, each use of an unsafe construct of any form must be ackwnowledged in the source code with one of the forms below, which provides an in-source auditable indication of where memory unsafety issues can arise. The following section describes each of the features for acknowledging memory unsafety. -* `unowned(unsafe)`: Used to store a reference without maintaining its reference count. The safe counterpart, `unowned`, uses dynamic checking to ensure that the reference isn't accessed after the corresponding object has been released. The `unsafe` variant disables that dynamic checking. Uses of `unowned(unsafe)` entities are not memory-safe. -* `unsafeAddressor`, `unsafeMutableAddressor`: These accessors vend an unsafe pointer, and are therefore unsafe to declare. Other accessors (e.g., `get` and `set`) can provide safe alternatives. The accessors are considered to be part of the signature of the property or subscript they're associated with; the property should be marked either `@unsafe` or `@safe` to suppress the safety diagnostic on the declaration of an unsafe accessor. -* `@exclusivity(unchecked)`: Used to remove dynamic exclusivity checks from a particular variable, which can mean that dynamic exclusivity violations go undetected at run time, causing a memory safety violation. Uses of `@exclusivity(unchecked)` entities are not memory-safe. +#### `unsafe` expression -The following language constructs are considered to be unsafe when strict concurrency checking is enabled (i.e., in the Swift 6 language mode): +Any time there is executable code that makes use of unsafe constructs, the compiler will produce a diagnostic that indicates the use of those unsafe constructs unless it is within an `unsafe` expression. For example, consider the `DataWrapper` example from an earlier section: -* `nonisolated(unsafe)`: Allows a property to be accessed from concurrent code without ensuring that such accesses are done so safely. Uses of `nonisolated(unsafe)` entities are not memory-safe. -* `@preconcurrency` imports: Suppresses diagnostics related to data race safety when they relate to specific imported modules, which can introduce thread safety issues. The `@preconcurrency` import will need to be annotated with `@unsafe` in the strict safety mode. +```swift +public struct DataWrapper { + var buffer: UnsafeBufferPointer +} + +extension DataWrapper { + public func checksum() -> Int32 { + crc32(0, buffer.baseAddress, buffer.count) + } +} +``` -### Unsafe standard library APIs +The property `buffer` uses an unsafe type, `UnsafeBufferPointer`. When using that property in the implementation of `checksum`, the Swift compiler will produce a warning when strict memory safety checking is enabled: -In the standard library, the following functions and types would be marked `@unsafe` : +```swift +warning: expression uses unsafe constructs but is not marked with 'unsafe' +``` -* `Unsafe(Mutable)(Raw)(Buffer)Pointer`, `OpaquePointer`, `CVaListPointer`: These types provide neither lifetime nor bounds safety. Over time, Swift code is likely to move toward their safe replacements, such as `(Raw)Span`. -* `(Closed)Range.init(uncheckedBounds:)`: This operation makes it possible to create a range that doesn't satisfy invariants on which other bounds safety checking (e.g., in `Array.subscript`) relies. -* `Span.subscript(unchecked:)` : An unchecked subscript whose use can introduce bounds safety problems. -* `Unmanaged`: Wrapper over reference-counted types that explicitly disables reference counting, potentially introducing lifetime safety issues. -* `unsafeBitCast`: Allows type casts that are not known to be safe, which can introduce type safety problems. -* `unsafeDowncast`: An unchecked form of an `as!` cast that can introduce type safety problems. -* `Optional.unsafelyUnwrapped`: An unchecked form of the postfix `!` operation on optionals that can introduce various type, initialization, or lifetime safety problems when `nil` is interpreted as a typed value. -* `UnsafeContinuation`, `withUnsafe(Throwing)Continuation`: An unsafe form of `withChecked(Throwing)Continuation` that does not verify that the continuation is called exactly once, which can cause various safety problems. -* `withUnsafeCurrentTask` and `UnsafeCurrentTask`: The `UnsafeCurrentTask` type does not provide lifetime safety, and must only be used within the closure passed to `withUnsafeCurrentTask`. -* `UnownedSerialExecutor`: This type is intentionally not lifetime safe. It's primary use is the `unownedExecutor` property of the `Actor` protocol, which documents the lifetime assumptions of the `UnownedSerialExecutor` instance it produces. +This warning can be suppressed using the `unsafe` expression, as follows: -All of these APIs will be marked `@unsafe`. For standard library APIs that involve unsafe types, those that are safe to use will be marked `@safe` while those that require the user to maintain some aspect of safety will be marked `@unsafe`. Unless mentioned above, standard library APIs that do not have an unsafe type in their signature, but use unsafe constructs in their implementation, will be considered to be safe. +```swift +extension DataWrapper { + public func checksum() -> Int32 { + unsafe crc32(0, buffer.baseAddress, buffer.count) + } +} +``` -### Unsafe compiler flags +The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`buffer`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. -There are a number of compiler flags that intentionally disable some safety-related checking. For each of these flags, the compiler will produce a diagnostic if they are used with strict memory safety: +#### Types with unsafe storage -* `-Ounchecked`, which disables some checking in the standard library, including (for example) bounds checking on array accesses. -* `-enforce-exclusivity=unchecked` and `-enforce-exclusivity=none`, which disables exclusivity checking that is needed for memory safety. -* `-strict-concurrency=` for anything other than "complete", because the memory safety model requires strict concurrency to eliminate thread safety issues. -* `-disable-access-control`, which allows one to break invariants of a type that can lead to memory-safety issues, such as breaking the invariant of `Range` that the lower bound not exceed the upper bound. +Types that wrap unsafe types will often encapsulate the unsafe behavior to provide safe interfaces. However, this requires deliberate design and implementation, potentially involving adding specific preconditions. When strict safety checking is enabled, a type whose storage includes any unsafe types or conformances will be diagnosed as involving unsafe code. For example, the `DataWrapper` struct from the prior section -### Types with unsafe storage +```swift +public struct DataWrapper { + var buffer: UnsafeBufferPointer +} +``` + +contains storage of an unsafe type (`UnsafeBufferPointer`), so the Swift compiler will produce a warning when strict memory safety checking is enabled: + +```swift +warning: type `DataWrapper` that includes unsafe storage must be explicitly marked `@unsafe` or `@safe` +``` -Types that wrap unsafe types will often encapsulate the unsafe behavior to provide safe interfaces. However, this requires deliberate design and implementation, potentially involving adding specific preconditions. When strict safety checking is enabled, a type whose storage is unsafe will be diagnosed as involving unsafe code. This diagnostic can be suppressed by marking the type as `@safe` or `@unsafe`, in the same manner as any other declaration that has unsafe types or conformances in its signature: +As the warning implies, this diagnostic can be suppressed by marking the type as `@safe` or `@unsafe`. The `DataWrapper` type doesn't appear to provide safety over its storage, so it should likely be marked `@unsafe`. In contrast, one can wrap unsafe types to provide safe types. For example: ```swift // @safe is required to suppress a diagnostic about the 'buffer' property's use @@ -347,12 +412,14 @@ struct ImmortalBufferWrapper : Collection { } ``` +Much of the standard library is built up as safe abstractions over unsafe code, and it's expected that user code will do the same. + A type has unsafe storage if: * Any stored instance property (for `actor`, `class`, and `struct` types) or associated value (for cases of `enum` types) have a type that involves an unsafe type or conformance. * Any stored instance property uses one of the unsafe language features (such as `unowned(unsafe)`). -### Unsafe overrides +#### Unsafe overrides Overriding a safe method within an `@unsafe` one could introduce unsafety, so it will produce a diagnostic in the strict safety mode: @@ -377,41 +444,7 @@ class Sub: Super { The `@unsafe` annotation is at the class level because any use of the `Sub` type can now introduce unsafe behavior, and any indication of that unsafe behavior will be lost once that `Sub` is converted to a `Super` instance. -### Unsafe conformances - -Implementing a protocol requirement that is safe (and not part of an `@unsafe` protocol) within an `@unsafe` declaration introduces unsafety, so it will produce a diagnostic in the strict safety mode: - -```swift -protocol P { - func f() -} - -struct ConformsToP { } - -extension ConformsToP: P { - @unsafe func f() { } // warning: unsafe instance method 'f()' cannot satisfy safe requirement -} -``` - -To suppress this warning, one can place `@unsafe` on the conformance to `P` is supplied. This notes that the conformance itself is unsafe: - -```swift -extension ConformsToP: @unsafe P { - @unsafe func f() { } -} -``` - -Use of an `@unsafe` conformance for any reason (e.g., when that conformance is needed to call a generic function with a `ConformsToP` requirement) is diagnosed as an unsafe use, much like use of an `@unsafe` declaration. For example - -```swift -func acceptP(_: T.Type) { } - -func passUnsafe() { - acceptP(ConformsToP.self) // warning: use of @unsafe conformance of 'ConformsToP' to protocol 'P' -} -``` - -### `for..in` loops +#### `for..in` loops Swift's `for..in` loops are effectively implemented as syntactic sugar over the `Sequence` and `IteratorProtocol` protocols, where the `for..in` creates a new iterator (with `Sequence.makeIterator()`) and then calls its `next()` operation for each loop iteration. If the conformances to `Sequence` are `IteratorProtocol` is `@unsafe`, the loop will introduce a warning: @@ -447,66 +480,6 @@ This repeated `unsafe` also occurs with the other effects: if an `async throws` for try await x in try await getAsyncSequence() { ... } ``` -### C(++) interoperability - -The C family of languages does not provide an equivalent to the strict safety mode described in this proposal, and unlike Swift, the defaults tend to be unsafe along all of the dimensions of memory safety. C(++) libriaries used within Swift can, therefore, introduce memory safety issues into the Swift code. - -The primary issue with memory safety in C(++) concerns the presence of pointers. C(++) pointers will generally be imported into Swift as an `Unsafe*Pointer` type of some form. For C functions (and C++ member functions), that means that a potentially unsafe API such as - -```swift -char *strstr(const char * haystack, const char *needle); -``` - -will be treated as implicitly `@unsafe` in Swift because its signature contains unsafe types: - -```swift -func strstr( - _ haystack: UnsafePointer?, - _ needle: UnsafePointer? -) -> UnsafeMutablePointer? -``` - -A C function that doesn't use pointer types, on the other hand, will implicitly be considered to be safe, because there are no unsafe types in its Swift signature. For example, the following would be considered safe: - -```swift -// int getchar(void); -func getchar() -> CInt -``` - -C and C++ also have user-defined types in the form of `struct`s, `enum`s, `union`s, and (in C++) `class`es. For such types, this proposal infers them to be `@unsafe` when their non-static data contains any C pointers or C types that are explicitly marked as unsafe. For example, a `Point` struct could be considered safe: - -```cpp -struct Point { - double x, y; -}; -``` - -but a `struct` with a pointer or C++ reference in it would be implicitly `@unsafe` in Swift: - -```swift -struct ListNode { - void *element; - struct ListNode *next; -}; -``` - -The C attribute `swift_attr` can be used to make specific declarations safe or unsafe, e.g., we could mark a C++ class that manages its internal pointer correctly as being safe, e.g., - -```cpp -class __attribute__((swift_attr("@safe"))) MyString { - char *data; - size_t length; - - MyString(const MyString &); - MyString(MyString &&); - MyString &operator=(const MyString&); - MyString &operator=(MyString&&); - ~MyString(); -}; -``` - -Note that C `enum`s will never be inferred to be `@unsafe` because they don't carry any values other than their underlying integral type, which is always a safe type. - ### Strict safety mode and escalatable warnings The strict memory safety mode can be enabled with the new compiler flag `-strict-memory-safety`. @@ -831,6 +804,8 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh * Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe. * Add `unsafe` for iteration via the `for..in` syntax. * Add C(++) interoperability section that infers `@unsafe` for C types that involve pointers. + * Document the unsafe conformances of the `UnsafeBufferPointer` family of types to the `Collection` protocol hierarchy. + * Restructure detailed design to separate out "sources of unsafety" from "acknowledging unsafety". * **Revision 2 (following first review extension)** * Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe. From 682c8aca9ac946c004bc6b29a80d98b33670a340 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 23:38:25 -0800 Subject: [PATCH 054/505] SE-0458: Bring back discussion of unsafe witnesses and how to acknowledge them This was lost in my restructuring --- proposals/0458-strict-memory-safety.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 1a4cff2eed..bb249cd3ce 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -419,6 +419,30 @@ A type has unsafe storage if: * Any stored instance property (for `actor`, `class`, and `struct` types) or associated value (for cases of `enum` types) have a type that involves an unsafe type or conformance. * Any stored instance property uses one of the unsafe language features (such as `unowned(unsafe)`). +#### Unsafe witnesses + +When a type conforms to a given protocol, it must satisfy all of the requirements of that protocol. Part of this process is determining which declaration (called the *witness*) satisfies a given protocol requirement. If a particular witness is unsafe but the corresponding requirement is not safe, the compiler will produce a warning: + +```swift +protocol P { + func f() +} + +struct ConformsToP { } + +extension ConformsToP: P { + @unsafe func f() { } // warning: unsafe instance method 'f()' cannot satisfy safe requirement +} +``` + +This unsafety can be acknowledged by marking the conformance as `@unsafe`, e.g., + +```swift +extension ConformsToP: @unsafe P { + @unsafe func f() { } // okay, it's an unsafe conformance +} +``` + #### Unsafe overrides Overriding a safe method within an `@unsafe` one could introduce unsafety, so it will produce a diagnostic in the strict safety mode: From 48c09949709807271ed7ac4df1c77a0e8c8e5b93 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Feb 2025 23:44:45 -0800 Subject: [PATCH 055/505] SE-0458: Move the @safe attribute into the section on acknowledging unsafety --- proposals/0458-strict-memory-safety.md | 78 +++++++++++++------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index bb249cd3ce..5c4f45cc09 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -288,7 +288,45 @@ struct ListNode { Note that C `enum`s will never be inferred to be `@unsafe` because they don't carry any values other than their underlying integral type, which is always a safe type. -### `@safe` attribute +### Acknowledging unsafety + +All of the features described above are available in Swift regardless of whether strict memory safety checking is enabled. When strict memory safety checking is enabled, each use of an unsafe construct of any form must be ackwnowledged in the source code with one of the forms below, which provides an in-source auditable indication of where memory unsafety issues can arise. The following section describes each of the features for acknowledging memory unsafety. + +#### `unsafe` expression + +Any time there is executable code that makes use of unsafe constructs, the compiler will produce a diagnostic that indicates the use of those unsafe constructs unless it is within an `unsafe` expression. For example, consider the `DataWrapper` example from an earlier section: + +```swift +public struct DataWrapper { + var buffer: UnsafeBufferPointer +} + +extension DataWrapper { + public func checksum() -> Int32 { + crc32(0, buffer.baseAddress, buffer.count) + } +} +``` + +The property `buffer` uses an unsafe type, `UnsafeBufferPointer`. When using that property in the implementation of `checksum`, the Swift compiler will produce a warning when strict memory safety checking is enabled: + +```swift +warning: expression uses unsafe constructs but is not marked with 'unsafe' +``` + +This warning can be suppressed using the `unsafe` expression, as follows: + +```swift +extension DataWrapper { + public func checksum() -> Int32 { + unsafe crc32(0, buffer.baseAddress, buffer.count) + } +} +``` + +The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`buffer`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. + +#### `@safe` attribute The `@safe` attribute is used on declarations whose signatures involve unsafe types but are, nonetheless, safe to use. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those certain operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`: @@ -336,44 +374,6 @@ extension Array { } ``` -### Acknowledging unsafety - -All of the features described above are available in Swift regardless of whether strict memory safety checking is enabled. When strict memory safety checking is enabled, each use of an unsafe construct of any form must be ackwnowledged in the source code with one of the forms below, which provides an in-source auditable indication of where memory unsafety issues can arise. The following section describes each of the features for acknowledging memory unsafety. - -#### `unsafe` expression - -Any time there is executable code that makes use of unsafe constructs, the compiler will produce a diagnostic that indicates the use of those unsafe constructs unless it is within an `unsafe` expression. For example, consider the `DataWrapper` example from an earlier section: - -```swift -public struct DataWrapper { - var buffer: UnsafeBufferPointer -} - -extension DataWrapper { - public func checksum() -> Int32 { - crc32(0, buffer.baseAddress, buffer.count) - } -} -``` - -The property `buffer` uses an unsafe type, `UnsafeBufferPointer`. When using that property in the implementation of `checksum`, the Swift compiler will produce a warning when strict memory safety checking is enabled: - -```swift -warning: expression uses unsafe constructs but is not marked with 'unsafe' -``` - -This warning can be suppressed using the `unsafe` expression, as follows: - -```swift -extension DataWrapper { - public func checksum() -> Int32 { - unsafe crc32(0, buffer.baseAddress, buffer.count) - } -} -``` - -The `unsafe` expression is much like `try` and `await`, in that it acknowledges that unsafe constructs (`buffer`) are used within the subexpression but otherwise does not change the type. Unlike `try` and `await`, which require the enclosing context to handle throwing or be asynchronous, respectively, the `unsafe` expression does not imply any requirements about the enclosing block: it is purely a marker to indicate the presence of unsafe code, silencing a diagnostic. - #### Types with unsafe storage Types that wrap unsafe types will often encapsulate the unsafe behavior to provide safe interfaces. However, this requires deliberate design and implementation, potentially involving adding specific preconditions. When strict safety checking is enabled, a type whose storage includes any unsafe types or conformances will be diagnosed as involving unsafe code. For example, the `DataWrapper` struct from the prior section From 0d965868efd6c53f85ca7ecd6f7052d20ab2256f Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Wed, 12 Feb 2025 15:45:41 +0000 Subject: [PATCH 056/505] [SE-0453] `InlineArray` proposal is accepted --- proposals/0453-vector.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/0453-vector.md b/proposals/0453-vector.md index 9828b90203..7d143f7413 100644 --- a/proposals/0453-vector.md +++ b/proposals/0453-vector.md @@ -3,10 +3,10 @@ * Proposal: [SE-0453](0453-vector.md) * Authors: [Alejandro Alonso](https://github.com/Azoy) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active review (December 5...December 17, 2024)** +* Status: **Accepted** * Roadmap: [Approaches for fixed-size arrays](https://forums.swift.org/t/approaches-for-fixed-size-arrays/58894) * Implementation: [swiftlang/swift#76438](https://github.com/swiftlang/swift/pull/76438) -* Review: ([pitch](https://forums.swift.org/t/vector-a-fixed-size-array/75264)) ([review](https://forums.swift.org/t/se-0453-vector-a-fixed-size-array/76004)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0453-vector-a-fixed-size-array/76411)) ([second review](https://forums.swift.org/t/second-review-se-0453-vector-a-fixed-size-array/76412)) +* Review: ([pitch](https://forums.swift.org/t/vector-a-fixed-size-array/75264)) ([first review](https://forums.swift.org/t/se-0453-vector-a-fixed-size-array/76004)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0453-vector-a-fixed-size-array/76411)) ([second review](https://forums.swift.org/t/second-review-se-0453-vector-a-fixed-size-array/76412)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0453-inlinearray-formerly-vector-a-fixed-size-array/77678)) ## Introduction @@ -82,7 +82,7 @@ member it will be inline allocated on the heap with the rest of the properties. alone. ```swift -func complexAlgorithm() -> Int { +func complexAlgorithm() { // This is a stack allocation, no 'malloc's or reference counting here! let elements: InlineArray<4, Int> = [1, 2, 3, 4] @@ -215,10 +215,10 @@ func array(_: [T]) {} array([1, 2, 3]) // passes a Swift.Array array([1, 2, 3] as InlineArray<3, Int>) // error: 'InlineArray<3, Int>' is not convertible to 'Array' -func InlineArray(_: InlineArray<3, T>) {} +func inlineArray(_: InlineArray<3, T>) {} -InlineArray([1, 2, 3]) // passes a Swift.InlineArray -InlineArray([1, 2, 3] as [Int]) // error: 'Array' is not convertible to 'InlineArray<3, Int>' +inlineArray([1, 2, 3]) // passes a Swift.InlineArray +inlineArray([1, 2, 3] as [Int]) // error: 'Array' is not convertible to 'InlineArray<3, Int>' ``` I discuss later about a hypothetical `ExpressibleByInlineArrayLiteral` and the design @@ -276,7 +276,7 @@ extension InlineArray where Element: ~Copyable { /// Initializes every element in this InlineArray by running the closure with the /// previously initialized element. /// - /// This will call the closure 'count' times, where 'count' is the static + /// This will call the closure `count - 1` times, where `count` is the static /// count of the InlineArray, to initialize every element by passing the closure /// an immutable borrow reference to the previously initialized element. The /// closure is allowed to throw an error at any point during initialization at From 85e2171872f406de6b78f5b2f8b02ebfef8af474 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 12 Feb 2025 09:14:29 -0800 Subject: [PATCH 057/505] SE-0458: Fix typos --- proposals/0458-strict-memory-safety.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 5c4f45cc09..a56d0f2ce5 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -470,7 +470,7 @@ The `@unsafe` annotation is at the class level because any use of the `Sub` type #### `for..in` loops -Swift's `for..in` loops are effectively implemented as syntactic sugar over the `Sequence` and `IteratorProtocol` protocols, where the `for..in` creates a new iterator (with `Sequence.makeIterator()`) and then calls its `next()` operation for each loop iteration. If the conformances to `Sequence` are `IteratorProtocol` is `@unsafe`, the loop will introduce a warning: +Swift's `for..in` loops are effectively implemented as syntactic sugar over the `Sequence` and `IteratorProtocol` protocols, where the `for..in` creates a new iterator (with `Sequence.makeIterator()`) and then calls its `next()` operation for each loop iteration. If the conformances to `Sequence` or `IteratorProtocol` are `@unsafe`, the loop will introduce a warning: ```swift let someUnsafeBuffer: UnsafeBufferPointer = unsafe ... @@ -824,7 +824,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh ## Revision history -* **Revision 3 (following second review eextension)** +* **Revision 3 (following second review extension)** * Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe. * Add `unsafe` for iteration via the `for..in` syntax. * Add C(++) interoperability section that infers `@unsafe` for C types that involve pointers. From acff10f5d0c410da597de4e92e6641fa7bc177ed Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 12 Feb 2025 23:12:27 +0000 Subject: [PATCH 058/505] SE-0335: `any` syntax is not required in Swift 6 mode This information has become somewhat misleading because it didn't happen. `ExistentialAny` is scheduled for a post-Swift-6 language mode. --- proposals/0335-existential-any.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/proposals/0335-existential-any.md b/proposals/0335-existential-any.md index 8f12ca614e..eaf480380e 100644 --- a/proposals/0335-existential-any.md +++ b/proposals/0335-existential-any.md @@ -62,7 +62,7 @@ Despite these significant and often undesirable implications, existential types ## Proposed solution -I propose to make existential types syntactically explicit in the language using the `any` keyword. This proposal introduces the new syntax in the Swift 5 language mode, and this syntax should be required for existential types under the Swift 6 language mode. +I propose to make existential types syntactically explicit in the language using the `any` keyword. This proposal introduces the new syntax in the Swift 5 language mode, and this syntax should be required for existential types under a future language mode. In Swift 5, anywhere that an existential type can be used today, the `any` keyword can be used to explicitly denote an existential type: @@ -80,10 +80,10 @@ let pq1: P & Q = S() // 'P & Q' in this context is an existential type let pq2: any P & Q = S() // 'any P & Q' is an explicit existential type ``` -In Swift 6, existential types are required be explicitly spelled with `any`: +In a future language mode, existential types are required to be explicitly spelled with `any`: ```swift -// Swift 6 mode +// Future language mode protocol P {} protocol Q {} @@ -96,7 +96,7 @@ let pq1: P & Q = S() // error let pq2: any P & Q = S() // okay ``` -The Swift 6 behavior can be enabled in earlier language modes with the [upcoming feature flag](0362-piecemeal-future-features.md) `ExistentialAny`. +This behavior can be enabled in earlier language modes with the [upcoming feature flag](0362-piecemeal-future-features.md) `ExistentialAny`. ## Detailed design @@ -192,11 +192,9 @@ func generic(value: T) { ... } func generic(value: T) { ... } // error ``` -Once the `any` spelling is required under the Swift 6 language mode, a type alias to a plain protocol name is not a valid type witness for an associated type requirement; existential type witnesses must be explicit in the `typealias` with `any`: +Once the `any` spelling is required under a future language mode, a type alias to a plain protocol name is not a valid type witness for an associated type requirement; existential type witnesses must be explicit in the `typealias` with `any`: ```swift -// Swift 6 code - protocol P {} protocol Requirements { @@ -214,16 +212,16 @@ struct S2: Requirements { ## Source compatibility -Enforcing that existential types use the `any` keyword will require a source change. To ease the migration, I propose to start allowing existential types to be spelled with `any` with the Swift 5.6 compiler, and require existential types to be spelled with `any` under the Swift 6 language mode. The old existential type syntax will continue to be supported under the Swift 5 language mode, and the transition to the new syntax is mechanical, so it can be performed automatically by a migrator. +Enforcing that existential types use the `any` keyword will require a source change. To ease the migration, I propose to start allowing existential types to be spelled with `any` with the Swift 5.6 compiler, and require existential types to be spelled with `any` under a future language mode. The old existential type syntax will continue to be supported under the Swift 5 language mode, and the transition to the new syntax is mechanical, so it can be performed automatically by a migrator. -[SE-0309 Unlock existentials for all protocols](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0309-unlock-existential-types-for-all-protocols.md) enables more code to be written using existential types. To minimize the amount of new code written that will become invalid in Swift 6, I propose requiring `any` immediately for protocols with `Self` and associated type requirements. This introduces an inconsistency for protocols under the Swift 5 language mode, but this inconsistency already exists today (because you cannot use certain protocols as existential types at all), and the syntax difference serves two purposes: +[SE-0309 Unlock existentials for all protocols](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0309-unlock-existential-types-for-all-protocols.md) enables more code to be written using existential types. To minimize the amount of new code written that will become invalid under `ExistentialAny`, I propose requiring `any` immediately for protocols with `Self` and associated type requirements. This introduces an inconsistency for protocols under the Swift 5 language mode, but this inconsistency already exists today (because you cannot use certain protocols as existential types at all), and the syntax difference serves two purposes: 1. It saves programmers time in the long run by preventing them from writing new code that will become invalid later. -2. It communicates the existence of `any` and encourages programmers to start using it for other existential types before adopting Swift 6. +2. It communicates the existence of `any` and encourages programmers to start using it for other existential types before adopting `ExistentialAny`. -### Transitioning to `any` in Swift 6 +### Transitioning to `any` -The new `any` syntax will be staged in over several major Swift releases. In the release where `any` is introduced, the compiler will not emit any warnings for the lack of `any` on existential types. After `any` is introduced, warnings will be added to guide programmers toward the new syntax. Finally, these warnings can become errors, or [plain protocol names can be repurposed](#re-purposing-the-plain-protocol-name), in Swift 6. +The new `any` syntax will be staged in over several major Swift releases. In the release where `any` is introduced, the compiler will not emit diagnostics for the lack of `any` on existential types, save for the aforementioned cases. After `any` is introduced, warnings will be added to guide programmers toward the new syntax. Finally, a missing `any` will become an unconditional error, or [plain protocol names may be repurposed](#re-purposing-the-plain-protocol-name) — in Swift 6 or a later language mode. ## Effect on ABI stability From 7d2ae4e7d87682e6fcfa1095d24aa53ffd2aebac Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 29 Jan 2025 09:41:27 +0000 Subject: [PATCH 059/505] burp --- ...migration-tooling-for-upcoming-features.md | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 proposals/NNNN-migration-tooling-for-upcoming-features.md diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md new file mode 100644 index 0000000000..47097ba859 --- /dev/null +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -0,0 +1,335 @@ +# Adoption tooling for Swift features + +* Proposal: [SE-NNNN](NNNN-filename.md) +* Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) +* Review Manager: TBD +* Status: **Awaiting implementation** +* Implementation: TBD +* Review: TBD + +## Introduction + +The future we envision for Swift will take many more valiant evolutionary +decisions and major transformations with a proportional impact on its +expanding domains. + +Source-breaking changes to Swift were first staged behind the now obsolete +Swift 3 language mode. +Each successive major release has since included a correponding language mode, +using the previous language mode as the default to maximize source +compatibility. +For example, Swift 6 compilers operate in the Swift 5 language mode by default. +Users that are not ready to adopt the new default can still specify an earlier +language mode explicitly. +Once the time is right, old language modes together with the legacy behaviors +they manifest will be proposed to be deprecated. + +The cumulative source compatibility impact of the changes that were accreting +around a converging Swift 6 language mode gave rise to the +[Swift feature model][SE-0362], which enabled piecemeal adoption of individual +features as opposed to an entire language mode. +Upcoming features facilitated sooner adoption of improvements and drastically +reduced the pressures in our evolutionary model. + +This proposal centers seeks to improve the experience of adopting individual +features. +The proposition is that the growing complexity and diversification of Swift +calls for a flexible, integrated mechanism for supporting quality assistance +with feature adoption. +And that — in principle — comprehensive, code-aware assistance can be delivered +without breaking source and acted upon incrementally. + +## Motivation + +Whether you are adjusting code to follow new language rules or researching ways +to apply new functionality, adopting features can be a time-consuming endeavor +at the least. + +Some source-breaking language features are anticipated to generate hundreds +of targeted errors in sizable projects. +Occasionally, errors will also cascade down the dependecy graph or fall out +from changes in behavior without a clear indication of the precise cause or source of +the issue, requiring further investigation. +Developers are left to either resolve all of these errors or address a subset +and take the risk of switching the feature back off before they can resume +development and focus on other important tasks. + +### User Intent + +> [!CAUTION] +> TODO: No way for users to declare an intetion to adopt a feature + +### Automation + +Many existing and prospective upcoming features imply or implement simple and +consistent code modifications to facilitate the adoption process: + +* [`NonfrozenEnumExhaustivity`][SE-0192]: Restore exhaustivity with + `@unknown default:`. +* [`ConciseMagicFile`][SE-0274]: `#file` → `#filePath`. +* [`ForwardTrailingClosures`][SE-0286]: Disambiguate argument matching by + de-trailing closures and/or inlining default arguments. +* [`ExistentialAny`][SE-0335]: `P` → `any P`. +* [`ImplicitOpenExistentials`][SE-0352]: Suppress opening with `as any P` + coercions. +* [`BareSlashRegexLiterals`][SE-0354]: Disambiguate using parentheses, + e.g. `foo(/a, b/)` → `foo((/a), b/)`. +* [`DeprecateApplicationMain`][SE-0383]: `@UIApplicationMain` → `@main`, + `@NSApplicationMain` → `@main`. +* [`DisableOutwardActorInference`][SE-0401]: Specify global actor isolation + explicitly. +* [`InternalImportsByDefault`][SE-0409]: `import X` → `public import X`. +* [`GlobalConcurrency`][SE-0412]: + - Convert the global variable to a `let` (or) + - `@MainActor`-isolate it (or) + - Mark it with `nonisolated(unsafe)` +* [`MemberImportVisibility`][SE-0444]: Add explicit imports appropriately. +* [`InferSendableFromCaptures`][SE-0418]: Suppress inference with coercions + and type annotations. +* [Inherit isolation by default for async functions][async-inherit-isolation-pitch]: + Mark nonisolated functions with the proposed attribute. + +Feature + +Extending diagnostic metadata to include information that allows for +recognizing these diagnostics and distinguishing semantics-preserving fix-its +from alternative source changes would open up numerous opportunities for +higher-level tools — ranging from the Swift package manager to IDEs — to +implement powerful solutions for organizing, automating, and tuning code +migration processes. + +### Flexibility/Ergonomics + +> [!CAUTION] +> Still a draft. + +Although upcoming features should strive to facilitate code migration, + +language design principles may prevail over bespoke code migration solutions. +Some features, like [StrictConcurrency][SE-0337], inherently require user +intervetion + +Adjusting to new behaviors or language requirements can demand research, +careful consideration, coordinated efforts, and manual code refactorings, +sometimes on a case-by-case basis. + +Currently best solution is to implement custom staging solutions. This approach +has limited applications (why?). + +UPCOMING_FEATURE(DynamicActorIsolation, 423, 6) +UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6) +UPCOMING_FEATURE(StrictConcurrency, 0337, 6) +UPCOMING_FEATURE(IsolatedDefaultValues, 411, 6) +UPCOMING_FEATURE(RegionBasedIsolation, 414, 6) + +## Proposed solution + +Introduce the notion of a "adoption" mode for individual experimental and +upcoming features. +The core idea behind adoption mode is a declaration of intent that can be +leveraged to build holistic supportive adoption experiences for developers. +If enabling a feature communicates an intent to *enact* rules, adoption mode +communicates an intent to *adopt* them. +An immediate benefit of adoption mode is the capability to deliver source +modifications that can be applied to preserve or improve the behavior of +existing code whenever the feature provides for them. + +> [!NOTE] +> The subject of this proposal is an enhancement to the Swift feature model. +> Applications of adoption mode to existing features are beyond its scope. + +## Detailed design + +### Behavior + +The action of enabling a previously disabled source-breaking feature in adoption +mode per se must never produce compilation errors. +Additionally, this action will have no effect on the state of the feature if +it does not implement the mode. +A corresponding warning will be emitted in this case to avoid the false +impression that the impacted source code is compatible with the feature. + +> [!NOTE] +> Experimental features can be both additive and source-breaking. +> Upcoming features are necessarily source-breaking. + +adoption mode will deliver guidance in the shape of warnings, notes, remarks, +and fix-its, as and when appropriate. + +When implemented, adoption mode for upcoming features is expected to anticipate +and call out any behavioral differences that will result from enacting the +feature, coupling diagnostic messages with counteracting source-compatible +changes and helpful alternatives whenever possible. +Adoption mode cannot guarantee to provide exclusively source-compatible +modifications because the impact of a change on dependent source code is +generally unpredictable. +Neither can it promise to always offer fix-its in the first place for the +same reason in regards to user intention. + +### Interface + +#### Compiler + +The `-enable-*-feature` frontend and driver command line options will start +supporting an optional mode specifier with `adoption` as the only valid mode: + +``` +-enable-upcoming-feature [:] +-enable-experimental-feature [:] + + := adoption +``` + +For example: + +``` +-enable-upcoming-feature InternalImportsByDefault:adoption +``` + +In a series of either of these options applied to a given feature, only the +last option will be honored. +If an upcoming feature is both implied by the effective language mode and +enabled in adoption mode using either of the aforementioned options, the latter +will be disregarded. + +#### Swift package manager + +The [`SwiftSetting.enableUpcomingFeature`] and +[`SwiftSetting.enableExperimentalFeature`] methods from the +[`PackageDescription`](https://developer.apple.com/documentation/packagedescription) +library will be augmented with a `mode` parameter defaulted to match the +current behavior: + +```swift +extension SwiftSetting { + @available(_PackageDescription, introduced: 6.2) + public enum SwiftFeatureMode { + case adoption + case on + } +} +``` +```diff + public static func enableUpcomingFeature( + _ name: String, ++ mode: SwiftFeatureMode = .on, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting { ++ let argument = switch mode { ++ case .adoption: "\(name):adoption" ++ case .mode: name ++ } ++ + return SwiftSetting( +- name: "enableUpcomingFeature", value: [name], condition: condition) ++ name: "enableUpcomingFeature", value: [argument], condition: condition) + } +``` +```diff + public static func enableExperimentalFeature( + _ name: String, ++ mode: SwiftFeatureMode = .on, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting { ++ let argument = switch mode { ++ case .adoption: "\(name):adoption" ++ case .mode: name ++ } ++ + return SwiftSetting( +- name: "enableExperimentalFeature", value: [name], condition: condition) ++ name: "enableExperimentalFeature", value: [argument], condition: condition) + } +``` + +For example: + +``` +SwiftSetting.enableUpcomingFeature("InternalImportsByDefault", mode: .adoption) +``` + +### Diagnostics + +Diagnostics emitted in relation to a specific feature in adoption mode must +belong to a diagnostic group named after the feature. +There are several reasons why this will be useful: +* Future feature-oriented adoption tooling can use the group identifier to + filter out relevant diagnostics. +* IDEs and other diagnostic consumers can integrate group identifiers into + their interfaces to, well, group diagnostics, as well as to communicate + relationships between diagnostics and features. This can prove especially + handy when multiple features are simultaneously enabled in adoption mode. + +## Source compatibility + +This proposal does not affect language rules. The described changes to the API +surface are source-compatible. + +## ABI compatibility + +This proposal does not affect binary compatibility or binary interfaces. + +## Implications on adoption + +Demoting an enabled source-breaking feature to adoption mode may affect +behavior and is therefore a potentially source-breaking action. + +## Future directions + +### Augment diagnostic metadata + + + +### Support baseline features + +Adoption mode can be extrapolated to baseline features, such as `TypedThrows` +or [opaque parameter types][SE-0341], with an emphasis on actionable adoption +tips and otherwise unsolicited educational notes. +These additive features are hard-enabled in all language modes and become an +integral part of the language as soon as they ship. +Baseline feature identifiers are currently kept around for the sole purpose of +supporting [feature availability checks][feature-detection] in conditional +compilation blocks. + +### `swift adopt` + +The Swift package manager could implement an `adopt` subcommand with an +interactive command line interface similar to `git add --patch` for selecting +and applying fix-its ... + +## Alternatives considered + +### Naming + + + +## Acknowledgements + +This proposal was inspired by documents prepared by [Allan Shortlidge][Allan] +and [Holly Borla][Holly]. +Special thanks to Holly for her feedback throughout the draft stage. + + + +[Holly]: https://github.com/hborla +[Allan]: https://github.com/tshortli + +[SE-0192]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md +[SE-0274]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0274-magic-file.md +[SE-0286]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0286-forward-scan-trailing-closures.md +[SE-0296]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0296-async-await.md +[SE-0335]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0335-existential-any.md +[SE-0337]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0337-support-incremental-migration-to-concurrency-checking.md +[SE-0341]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0341-opaque-parameters.md +[SE-0352]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md +[SE-0354]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0354-regex-literals.md +[SE-0362]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md +[feature-detection]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md#feature-detection-in-source-code +[SE-0383]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0383-deprecate-uiapplicationmain-and-nsapplicationmain.md +[SE-0401]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0401-remove-property-wrapper-isolation.md +[SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md +[SE-0411]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0411-isolated-default-values.md +[SE-0412]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0412-strict-concurrency-for-global-variables.md +[SE-0418]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md +[SE-0444]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md +[async-inherit-isolation-pitch]: https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862 From dafb468cba8eee563e65860151211efffc5eb165 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 14 Feb 2025 21:36:14 +0000 Subject: [PATCH 060/505] burp --- proposals/NNNN-migration-tooling-for-upcoming-features.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index 47097ba859..67da10cf4f 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -24,12 +24,12 @@ language mode explicitly. Once the time is right, old language modes together with the legacy behaviors they manifest will be proposed to be deprecated. -The cumulative source compatibility impact of the changes that were accreting -around a converging Swift 6 language mode gave rise to the +In Swift 5.8, the cumulative source compatibility impact of a still converging +Swift 6 language mode gave rise to the [Swift feature model][SE-0362], which enabled piecemeal adoption of individual features as opposed to an entire language mode. -Upcoming features facilitated sooner adoption of improvements and drastically -reduced the pressures in our evolutionary model. +Among other things, upcoming features facilitated earlier adoption of +improvements and drastically reduced the pressures in our evolutionary model. This proposal centers seeks to improve the experience of adopting individual features. From a7ea7aed14bf4f7612f762020973c3d79988f2cd Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 14 Feb 2025 22:15:04 +0000 Subject: [PATCH 061/505] burp --- proposals/NNNN-migration-tooling-for-upcoming-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index 67da10cf4f..d748799ab7 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -62,7 +62,7 @@ development and focus on other important tasks. ### Automation Many existing and prospective upcoming features imply or implement simple and -consistent code modifications to facilitate the adoption process: +consistent code modifications to facilitate adoption processes: * [`NonfrozenEnumExhaustivity`][SE-0192]: Restore exhaustivity with `@unknown default:`. From 80fa27863bf2dd33eeb591b0317ee96a4198b354 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 14 Feb 2025 22:41:05 +0000 Subject: [PATCH 062/505] burp --- ...NNNN-migration-tooling-for-upcoming-features.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index d748799ab7..becd83f9b3 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -15,7 +15,7 @@ expanding domains. Source-breaking changes to Swift were first staged behind the now obsolete Swift 3 language mode. -Each successive major release has since included a correponding language mode, +Each successive major release has since included a corresponding language mode, using the previous language mode as the default to maximize source compatibility. For example, Swift 6 compilers operate in the Swift 5 language mode by default. @@ -31,7 +31,7 @@ features as opposed to an entire language mode. Among other things, upcoming features facilitated earlier adoption of improvements and drastically reduced the pressures in our evolutionary model. -This proposal centers seeks to improve the experience of adopting individual +This proposal seeks to improve the experience of adopting individual features. The proposition is that the growing complexity and diversification of Swift calls for a flexible, integrated mechanism for supporting quality assistance @@ -89,8 +89,6 @@ consistent code modifications to facilitate adoption processes: * [Inherit isolation by default for async functions][async-inherit-isolation-pitch]: Mark nonisolated functions with the proposed attribute. -Feature - Extending diagnostic metadata to include information that allows for recognizing these diagnostics and distinguishing semantics-preserving fix-its from alternative source changes would open up numerous opportunities for @@ -124,7 +122,7 @@ UPCOMING_FEATURE(RegionBasedIsolation, 414, 6) ## Proposed solution -Introduce the notion of a "adoption" mode for individual experimental and +Introduce the notion of an "adoption" mode for individual experimental and upcoming features. The core idea behind adoption mode is a declaration of intent that can be leveraged to build holistic supportive adoption experiences for developers. @@ -142,6 +140,9 @@ existing code whenever the feature provides for them. ### Behavior +Adoption mode should deliver guidance in the shape of warnings, notes, remarks, +and fix-its, as and when appropriate. + The action of enabling a previously disabled source-breaking feature in adoption mode per se must never produce compilation errors. Additionally, this action will have no effect on the state of the feature if @@ -153,9 +154,6 @@ impression that the impacted source code is compatible with the feature. > Experimental features can be both additive and source-breaking. > Upcoming features are necessarily source-breaking. -adoption mode will deliver guidance in the shape of warnings, notes, remarks, -and fix-its, as and when appropriate. - When implemented, adoption mode for upcoming features is expected to anticipate and call out any behavioral differences that will result from enacting the feature, coupling diagnostic messages with counteracting source-compatible From 8707bf78f6e11d029948ad880e8a6971c8bacd0d Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 14 Feb 2025 19:11:51 -0800 Subject: [PATCH 063/505] Editorial pass over the introduction section. --- ...migration-tooling-for-upcoming-features.md | 39 +++++-------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index becd83f9b3..32e254c6a9 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -9,35 +9,16 @@ ## Introduction -The future we envision for Swift will take many more valiant evolutionary -decisions and major transformations with a proportional impact on its -expanding domains. - -Source-breaking changes to Swift were first staged behind the now obsolete -Swift 3 language mode. -Each successive major release has since included a corresponding language mode, -using the previous language mode as the default to maximize source -compatibility. -For example, Swift 6 compilers operate in the Swift 5 language mode by default. -Users that are not ready to adopt the new default can still specify an earlier -language mode explicitly. -Once the time is right, old language modes together with the legacy behaviors -they manifest will be proposed to be deprecated. - -In Swift 5.8, the cumulative source compatibility impact of a still converging -Swift 6 language mode gave rise to the -[Swift feature model][SE-0362], which enabled piecemeal adoption of individual -features as opposed to an entire language mode. -Among other things, upcoming features facilitated earlier adoption of -improvements and drastically reduced the pressures in our evolutionary model. - -This proposal seeks to improve the experience of adopting individual -features. -The proposition is that the growing complexity and diversification of Swift -calls for a flexible, integrated mechanism for supporting quality assistance -with feature adoption. -And that — in principle — comprehensive, code-aware assistance can be delivered -without breaking source and acted upon incrementally. +In Swift 5.8 introduced [upcoming features][SE-0362], +which enabled piecemeal adoption of individual source incompatible +changes that are enabled by default in a new langauge mode. +Many upcoming features have a mechanical migration, meaning the compiler can +determine the exact source changes necessary to allow the code to compile under +the upcoming feature while preserving the behavior of the code. +This proposal seeks to improve the experience of enabling individual +upcoming features by providing tools that produce the necessary source code +changes automatically for a given set of upcoming features that a programmer +wants to enable. ## Motivation From 593a0699ef6589cae292223221f416060c5b8756 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 14 Feb 2025 20:03:42 -0800 Subject: [PATCH 064/505] Editorial pass over the automation section. --- ...migration-tooling-for-upcoming-features.md | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index 32e254c6a9..b816352c52 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -77,29 +77,14 @@ higher-level tools — ranging from the Swift package manager to IDEs — to implement powerful solutions for organizing, automating, and tuning code migration processes. -### Flexibility/Ergonomics +It's not always feasible for an upcoming feature to have a mechanical +migration path. For example, the following upcoming features require manual +migration: -> [!CAUTION] -> Still a draft. - -Although upcoming features should strive to facilitate code migration, - -language design principles may prevail over bespoke code migration solutions. -Some features, like [StrictConcurrency][SE-0337], inherently require user -intervetion - -Adjusting to new behaviors or language requirements can demand research, -careful consideration, coordinated efforts, and manual code refactorings, -sometimes on a case-by-case basis. - -Currently best solution is to implement custom staging solutions. This approach -has limited applications (why?). - -UPCOMING_FEATURE(DynamicActorIsolation, 423, 6) -UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6) -UPCOMING_FEATURE(StrictConcurrency, 0337, 6) -UPCOMING_FEATURE(IsolatedDefaultValues, 411, 6) -UPCOMING_FEATURE(RegionBasedIsolation, 414, 6) +* [`DynamicActorIsolation`][SE-0423] +* [`GlobalActorIsolatedTypesUsability`][SE-0434] +* [`StrictConcurrency`][SE-0337] +* [`IsolatedDefaultValues`][SE-0411] ## Proposed solution @@ -310,5 +295,7 @@ Special thanks to Holly for her feedback throughout the draft stage. [SE-0411]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0411-isolated-default-values.md [SE-0412]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0412-strict-concurrency-for-global-variables.md [SE-0418]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md +[SE-0423]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0423-dynamic-actor-isolation.md +[SE-0434]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0434-global-actor-isolated-types-usability.md [SE-0444]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md [async-inherit-isolation-pitch]: https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862 From 78fd5a2efb32b36df133c8112fffc683387b20b3 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 14 Feb 2025 20:08:45 -0800 Subject: [PATCH 065/505] Clarify that future proposals introducing upcoming features should include a migration. --- proposals/NNNN-migration-tooling-for-upcoming-features.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index b816352c52..7cd343e56f 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -98,9 +98,11 @@ An immediate benefit of adoption mode is the capability to deliver source modifications that can be applied to preserve or improve the behavior of existing code whenever the feature provides for them. -> [!NOTE] -> The subject of this proposal is an enhancement to the Swift feature model. -> Applications of adoption mode to existing features are beyond its scope. +This proposal will support the set of existing upcoming features that +have mechanical migrations, as described in the [Automation](#automation) +section. All future proposals that introduce new upcoming features should +include a mechanical migration via adoption mode in the Source compatibility +section of the proposal. ## Detailed design From 9bedf553f2806c6dbd764ed9b06a9de6dfe74a9c Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 17 Feb 2025 09:40:32 +0000 Subject: [PATCH 066/505] burp 0.9 --- ...migration-tooling-for-upcoming-features.md | 184 ++++++++++-------- 1 file changed, 106 insertions(+), 78 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index 7cd343e56f..d049330244 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -10,40 +10,48 @@ ## Introduction In Swift 5.8 introduced [upcoming features][SE-0362], -which enabled piecemeal adoption of individual source incompatible -changes that are enabled by default in a new langauge mode. +which enabled piecemeal adoption of individual source-incompatible changes that +are included in a language mode. Many upcoming features have a mechanical migration, meaning the compiler can -determine the exact source changes necessary to allow the code to compile under +determine the exact source changes necessary to allow the code to compile under the upcoming feature while preserving the behavior of the code. This proposal seeks to improve the experience of enabling individual -upcoming features by providing tools that produce the necessary source code -changes automatically for a given set of upcoming features that a programmer -wants to enable. +upcoming features by providing a mechanism for producing the necessary source +code changes automatically for a given set of upcoming features that a +programmer wants to enable. ## Motivation -Whether you are adjusting code to follow new language rules or researching ways -to apply new functionality, adopting features can be a time-consuming endeavor -at the least. - -Some source-breaking language features are anticipated to generate hundreds -of targeted errors in sizable projects. -Occasionally, errors will also cascade down the dependecy graph or fall out -from changes in behavior without a clear indication of the precise cause or source of -the issue, requiring further investigation. -Developers are left to either resolve all of these errors or address a subset -and take the risk of switching the feature back off before they can resume -development and focus on other important tasks. - -### User Intent - -> [!CAUTION] -> TODO: No way for users to declare an intetion to adopt a feature +Adopting certain features is a time-consuming endeavor at the least. +It is the responsibility of project maintainers to preserve source (and binary) +compatibility both internally and externally for library clients when enabling +an upcoming feature, which can be difficult or tedious without having tools to +help detect possibly inadvertent changes and perform monotonous migration +shenanigans for you. +*Our* responsibility is to make that an easier task for everybody. + +### User intent + +A primary limiting factor in how proactively and accurately the compiler can +assist developers with adopting a feature is a lack of comprehension of user +intent. +Is the developer expecting guidance on adopting an improvement? +All the compiler knows to do when a feature is enabled is to compile code +accordingly. +This suffices if a feature merely supplants an existing syntactical construct +or changes the behavior of existing code in strictly predictable ways because +Swift can infer the need to suggest a fix just from spotting certain code +patterns. + +Needless to say, not all upcoming features fall under these criteria (and not +all features are source-breaking in the first place). Consider +[`ConciseMagicFile`][SE-0274], which changes the meaning of an existing +literal. ### Automation Many existing and prospective upcoming features imply or implement simple and -consistent code modifications to facilitate adoption processes: +consistent source modifications to facilitate adoption: * [`NonfrozenEnumExhaustivity`][SE-0192]: Restore exhaustivity with `@unknown default:`. @@ -72,14 +80,15 @@ consistent code modifications to facilitate adoption processes: Extending diagnostic metadata to include information that allows for recognizing these diagnostics and distinguishing semantics-preserving fix-its -from alternative source changes would open up numerous opportunities for +from alternative source changes will open up numerous opportunities for higher-level tools — ranging from the Swift package manager to IDEs — to -implement powerful solutions for organizing, automating, and tuning code -migration processes. +implement powerful solutions for organizing, automating, and tuning feature +adoption processes. -It's not always feasible for an upcoming feature to have a mechanical -migration path. For example, the following upcoming features require manual -migration: +It is not always feasible or in line with language design principles for an +upcoming feature to have a mechanical migration path. +For example, the following upcoming features require manual migration to +preserve semantics: * [`DynamicActorIsolation`][SE-0423] * [`GlobalActorIsolatedTypesUsability`][SE-0434] @@ -91,7 +100,7 @@ migration: Introduce the notion of an "adoption" mode for individual experimental and upcoming features. The core idea behind adoption mode is a declaration of intent that can be -leveraged to build holistic supportive adoption experiences for developers. +leveraged to build better supportive adoption experiences for developers. If enabling a feature communicates an intent to *enact* rules, adoption mode communicates an intent to *adopt* them. An immediate benefit of adoption mode is the capability to deliver source @@ -100,21 +109,18 @@ existing code whenever the feature provides for them. This proposal will support the set of existing upcoming features that have mechanical migrations, as described in the [Automation](#automation) -section. All future proposals that introduce new upcoming features should -include a mechanical migration via adoption mode in the Source compatibility -section of the proposal. +section. +All future proposals that introduce a new upcoming feature and provide a +mechanical migration are expected to support adoption mode and detail its +behavior in the *Source compatibility* section of the proposal. ## Detailed design ### Behavior -Adoption mode should deliver guidance in the shape of warnings, notes, remarks, -and fix-its, as and when appropriate. - The action of enabling a previously disabled source-breaking feature in adoption -mode per se must never produce compilation errors. -Additionally, this action will have no effect on the state of the feature if -it does not implement the mode. +mode per se must not cause compilation errors . +Additionally, this action will have no effect if the mode is not supported. A corresponding warning will be emitted in this case to avoid the false impression that the impacted source code is compatible with the feature. @@ -122,15 +128,24 @@ impression that the impacted source code is compatible with the feature. > Experimental features can be both additive and source-breaking. > Upcoming features are necessarily source-breaking. -When implemented, adoption mode for upcoming features is expected to anticipate -and call out any behavioral differences that will result from enacting the -feature, coupling diagnostic messages with counteracting source-compatible -changes and helpful alternatives whenever possible. -Adoption mode cannot guarantee to provide exclusively source-compatible -modifications because the impact of a change on dependent source code is -generally unpredictable. -Neither can it promise to always offer fix-its in the first place for the -same reason in regards to user intention. +Adoption mode should deliver guidance in the shape of regular diagnostics. +For arbitrary upcoming features, adoption mode is expected to anticipate and +call out any compatibility issues that result from enacting the feature, +coupling diagnostic messages with counteracting compatible changes and helpful +alternatives whenever feasible. +Compatibility issues encompass both source and binary compatibility issues, +including behavioral changes. + +Note that adoption mode does not provide any new general guarantees in respect +to fix-its. +We cannot promise to offer exclusively compatible modifications. +Besides the impact of a change on dependent source code being generally +unpredictable, it can be reasonable to couple compatible fix-its with +potentially incompatible, albeit better, alternatives, as in `any P` → `some P`. +The same stands for provision of modifications — features might not have a +mechanical migration path, and the compiler remains inherently limited in the +extent to which it can make assumptions about what is helpful or best for the +programmer. ### Interface @@ -217,14 +232,10 @@ SwiftSetting.enableUpcomingFeature("InternalImportsByDefault", mode: .adoption) ### Diagnostics Diagnostics emitted in relation to a specific feature in adoption mode must -belong to a diagnostic group named after the feature. -There are several reasons why this will be useful: -* Future feature-oriented adoption tooling can use the group identifier to - filter out relevant diagnostics. -* IDEs and other diagnostic consumers can integrate group identifiers into - their interfaces to, well, group diagnostics, as well as to communicate - relationships between diagnostics and features. This can prove especially - handy when multiple features are simultaneously enabled in adoption mode. +belong to a diagnostic group named after the feature. The names of diagnostic +groups can be displayed along with diagnostic messages using +`-print-diagnostic-groups` and can be used to associate a message with a +particular feature. ## Source compatibility @@ -237,43 +248,59 @@ This proposal does not affect binary compatibility or binary interfaces. ## Implications on adoption -Demoting an enabled source-breaking feature to adoption mode may affect -behavior and is therefore a potentially source-breaking action. +Entering or exiting adoption mode may affect behavior and is therefore a +potentially source-breaking action. ## Future directions -### Augment diagnostic metadata - - - -### Support baseline features - -Adoption mode can be extrapolated to baseline features, such as `TypedThrows` -or [opaque parameter types][SE-0341], with an emphasis on actionable adoption -tips and otherwise unsolicited educational notes. -These additive features are hard-enabled in all language modes and become an -integral part of the language as soon as they ship. -Baseline feature identifiers are currently kept around for the sole purpose of -supporting [feature availability checks][feature-detection] in conditional -compilation blocks. +### Applications beyond migration + +Adoption mode can be extrapolated to additive features, such as +[typed `throws`][SE-0413] or [opaque parameter types][SE-0341], by providing +actionable adoption tips. +Additive features are hard-enabled and become an integral part of the language +as soon as they ship. +Many recent additive features are already integrated into the Swift feature +model and kept around for the sole purpose of supporting +[feature availability checks][feature-detection] in conditional compilation +blocks. + +Another potential direction for adoption mode is promotion of best practices. + +### Augmented diagnostic metadata + +The current serialization format for diagnostics does not include information +about diagnostic groups or whether a particular fix-it preserves semantics. +There are several reasons why this data is essential for future tools built +around adoption mode: +* The diagnostic group name can be used to, well, group diagnostics, as well as + to communicate relationships between diagnostics and features and filter out + relevant diagnostics. + This can prove especially handy when multiple features are simultaneously + enabled in adoption mode, or when similar diagnostic messages are caused by + distinct features. +* Fix-its that preserve semantics can be prioritized and auto-applied in + previews. ### `swift adopt` -The Swift package manager could implement an `adopt` subcommand with an -interactive command line interface similar to `git add --patch` for selecting -and applying fix-its ... +The Swift package manager could implement an `adopt` subcommand for interactive +review and application of adoption mode output for a given set of features, +with a command line interface similar to `git add --patch`. ## Alternatives considered ### Naming - +Perhaps the most intuitive alternative to "adoption" is "migration". We +settled on the former because there is no reason for this concept to be limited +to upcoming features or migrational changes. ## Acknowledgements This proposal was inspired by documents prepared by [Allan Shortlidge][Allan] and [Holly Borla][Holly]. -Special thanks to Holly for her feedback throughout the draft stage. +Special thanks to Holly for her guidance throughout the draft stage. @@ -295,6 +322,7 @@ Special thanks to Holly for her feedback throughout the draft stage. [SE-0401]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0401-remove-property-wrapper-isolation.md [SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md [SE-0411]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0411-isolated-default-values.md +[SE-0413]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md [SE-0412]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0412-strict-concurrency-for-global-variables.md [SE-0418]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md [SE-0423]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0423-dynamic-actor-isolation.md From 2c604947334c12e5e1fe20219dd09ab675151b46 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 17 Feb 2025 18:54:36 +0000 Subject: [PATCH 067/505] burp 0.10 --- ...NNN-migration-tooling-for-upcoming-features.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index d049330244..d922d37bbc 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -50,8 +50,8 @@ literal. ### Automation -Many existing and prospective upcoming features imply or implement simple and -consistent source modifications to facilitate adoption: +Many existing and prospective upcoming features come with simple and reliable +migration paths to facilitate adoption: * [`NonfrozenEnumExhaustivity`][SE-0192]: Restore exhaustivity with `@unknown default:`. @@ -119,7 +119,7 @@ behavior in the *Source compatibility* section of the proposal. ### Behavior The action of enabling a previously disabled source-breaking feature in adoption -mode per se must not cause compilation errors . +mode per se must not cause compilation errors. Additionally, this action will have no effect if the mode is not supported. A corresponding warning will be emitted in this case to avoid the false impression that the impacted source code is compatible with the feature. @@ -233,9 +233,8 @@ SwiftSetting.enableUpcomingFeature("InternalImportsByDefault", mode: .adoption) Diagnostics emitted in relation to a specific feature in adoption mode must belong to a diagnostic group named after the feature. The names of diagnostic -groups can be displayed along with diagnostic messages using -`-print-diagnostic-groups` and can be used to associate a message with a -particular feature. +groups can be displayed alongside diagnostic messages using +`-print-diagnostic-groups` and used to associate messages with features. ## Source compatibility @@ -271,8 +270,8 @@ Another potential direction for adoption mode is promotion of best practices. The current serialization format for diagnostics does not include information about diagnostic groups or whether a particular fix-it preserves semantics. -There are several reasons why this data is essential for future tools built -around adoption mode: +There are several reasons why this data can be valuable for users, and why it +is essential for future tools built around adoption mode: * The diagnostic group name can be used to, well, group diagnostics, as well as to communicate relationships between diagnostics and features and filter out relevant diagnostics. From 18300668513e01b4d1e35d5d9094de8299a847ca Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 17 Feb 2025 12:29:11 -0800 Subject: [PATCH 068/505] Use `DisableOutwardActorInference` in the example for the "User intent" section. --- ...NN-migration-tooling-for-upcoming-features.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index d922d37bbc..0b873eeeb9 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -45,8 +45,19 @@ patterns. Needless to say, not all upcoming features fall under these criteria (and not all features are source-breaking in the first place). Consider -[`ConciseMagicFile`][SE-0274], which changes the meaning of an existing -literal. +[`DisableOutwardActorInference`][SE-0401], which changes actor isolation +inference of a type that contains an actor-isolated property wrapper. There +is no way for the programmer to specify that they'd like compiler fix-its to +make the existing actor isolation inference explicit. If they enable the +upcoming feature, their code will simply behave differently. This was a +point of debate in the review of SE-0401, and the Language Steering Group +concluded that automatic migration tooling is the right way to address this +particular workflow, as [noted in the acceptance notes][SE-0401-acceptance: + +> the Language Steering Group believes that separate migration tooling to +> help programmers audit code whose behavior will change under Swift 6 mode +> would be beneficial for all upcoming features that can change behavior +> without necessarily emitting errors. ### Automation @@ -328,3 +339,4 @@ Special thanks to Holly for her guidance throughout the draft stage. [SE-0434]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0434-global-actor-isolated-types-usability.md [SE-0444]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md [async-inherit-isolation-pitch]: https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862 +[SE-0401-acceptance]: https://forums.swift.org/t/accepted-with-modifications-se-0401-remove-actor-isolation-inference-caused-by-property-wrappers/66241 From 7d62c544c66c21f55202c95e4751fe16c1a01961 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 17 Feb 2025 12:39:55 -0800 Subject: [PATCH 069/505] Move source incompatible changes to Future directions. --- ...migration-tooling-for-upcoming-features.md | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-migration-tooling-for-upcoming-features.md index 0b873eeeb9..8e1f49c734 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-migration-tooling-for-upcoming-features.md @@ -52,7 +52,7 @@ make the existing actor isolation inference explicit. If they enable the upcoming feature, their code will simply behave differently. This was a point of debate in the review of SE-0401, and the Language Steering Group concluded that automatic migration tooling is the right way to address this -particular workflow, as [noted in the acceptance notes][SE-0401-acceptance: +particular workflow, as [noted in the acceptance notes][SE-0401-acceptance]: > the Language Steering Group believes that separate migration tooling to > help programmers audit code whose behavior will change under Swift 6 mode @@ -127,18 +127,19 @@ behavior in the *Source compatibility* section of the proposal. ## Detailed design -### Behavior +Upcoming features that have mechanical migrations will support an adoption +mode, which is a a new mode of building a project that will produce compiler +warnings with attached fix-its that can be applied to preserve the behavior +of the code when the upcoming feature is enabled. Adoption mode must not +cause any new compiler errors, and the fix-its produced must preserve the +source compatibility and behavior of the code. -The action of enabling a previously disabled source-breaking feature in adoption -mode per se must not cause compilation errors. -Additionally, this action will have no effect if the mode is not supported. +Additionally, this action will have no effect if the mode is not supported +for a given upcoming feature, i,e. because the upcoming feature does not +have a mechanical migration. A corresponding warning will be emitted in this case to avoid the false impression that the impacted source code is compatible with the feature. -> [!NOTE] -> Experimental features can be both additive and source-breaking. -> Upcoming features are necessarily source-breaking. - Adoption mode should deliver guidance in the shape of regular diagnostics. For arbitrary upcoming features, adoption mode is expected to anticipate and call out any compatibility issues that result from enacting the feature, @@ -147,17 +148,6 @@ alternatives whenever feasible. Compatibility issues encompass both source and binary compatibility issues, including behavioral changes. -Note that adoption mode does not provide any new general guarantees in respect -to fix-its. -We cannot promise to offer exclusively compatible modifications. -Besides the impact of a change on dependent source code being generally -unpredictable, it can be reasonable to couple compatible fix-its with -potentially incompatible, albeit better, alternatives, as in `any P` → `some P`. -The same stands for provision of modifications — features might not have a -mechanical migration path, and the compiler remains inherently limited in the -extent to which it can make assumptions about what is helpful or best for the -programmer. - ### Interface #### Compiler @@ -263,6 +253,15 @@ potentially source-breaking action. ## Future directions +### Producing source incompatible fix-its + +For some upcoming features, a source change which alters the semantics of +the program is a more desirable approach to addressing an error that comes +from enabling an upcoming feature. For example, programmers might want to +replace cases of `any P` with `some P`. Adoption tooling could support the +option to produce source incompatible fix-its in cases where the compiler +can detect that a different behavior might be more beneficial. + ### Applications beyond migration Adoption mode can be extrapolated to additive features, such as From e3b0d36df9712c785d09ceb4a6f3bef6e7b528c9 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 12 Feb 2025 16:07:02 -0800 Subject: [PATCH 070/505] [SE-0456] amend proposal to rename properties to `span` --- proposals/0456-stdlib-span-properties.md | 58 ++++++++++++------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index fb2626ed0c..68a799b90c 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -46,9 +46,9 @@ func function() { ``` If we were to attempt using `b` again after the call to `modify(&a)`, the compiler would report an overlapping access error, due to attempting to mutate `a` (with `modify(&a)`) while it is already being accessed through `b`'s borrow. Note that the copyability of `B` means that it cannot represent a mutation of `A`; it therefore represents a non-exclusive borrowing relationship. -Given this, we propose to enable the definition of a borrowing relationship via a computed property. With this feature we then propose to add `storage` computed properties to standard library types that can share their internal typed storage, as well as `bytes` computed properties to those standard library types that can safely share their internal storage as untyped memory. +Given this, we propose to enable the definition of a borrowing relationship via a computed property. With this feature we then propose to add `span` computed properties to standard library types that can share access to their internal typed memory. When a `span` has `BitwiseCopyable` elements, it will have a `bytes` computed property to share a view of the memory it represents as untyped memory. -One of the purposes of `Span` is to provide a safer alternative to `UnsafeBufferPointer`. This proposal builds on it and allows us to rewrite code reliant on `withUnsafeBufferPointer()` to use `storage` properties instead. Eventually, code that requires access to contiguous memory can be rewritten to use `Span`, gaining better composability in the process. For example: +One of the purposes of `Span` is to provide a safer alternative to `UnsafeBufferPointer`. This proposal builds on it and allows us to rewrite code reliant on `withUnsafeBufferPointer()` to use `span` properties instead. Eventually, code that requires access to contiguous memory can be rewritten to use `Span`, gaining better composability in the process. For example: ```swift let result = try myArray.withUnsafeBufferPointer { buffer in @@ -63,7 +63,7 @@ let result = try myArray.withUnsafeBufferPointer { buffer in This closure-based call is difficult to evolve, such as making `result` have a non-copyable type, adding a concurrent task, or adding typed throws. An alternative based on a vended `Span` property would look like this: ```swift -let span = myArray.storage +let span = myArray.span let indices = findElements(span) var myResult = MyResult() for i in indices { @@ -87,47 +87,47 @@ By allowing the language to define lifetime dependencies in these limited ways, #### Extensions to Standard Library types -The standard library and Foundation will provide `storage` computed properties, returning lifetime-dependent `Span` instances. These computed properties are the safe and composable replacements for the existing `withUnsafeBufferPointer` closure-taking functions. +The standard library and Foundation will provide `span` computed properties, returning lifetime-dependent `Span` instances. These computed properties are the safe and composable replacements for the existing `withUnsafeBufferPointer` closure-taking functions. ```swift extension Array { /// Share this `Array`'s elements as a `Span` - var storage: Span { get } + var span: Span { get } } extension ArraySlice { /// Share this `Array`'s elements as a `Span` - var storage: Span { get } + var span: Span { get } } extension ContiguousArray { /// Share this `Array`'s elements as a `Span` - var storage: Span { get } + var span: Span { get } } extension String.UTF8View { /// Share this `UTF8View`'s code units as a `Span` - var storage: Span { get } + var span: Span { get } } extension Substring.UTF8View { /// Share this `UTF8View`'s code units as a `Span` - var storage: Span { get } + var span: Span { get } } extension CollectionOfOne { /// Share this `Collection`'s element as a `Span` - var storage: Span { get } + var span: Span { get } } extension SIMD_N_ { // where _N_ ∈ {2, 3, 4 ,8, 16, 32, 64} /// Share this vector's elements as a `Span` - var storage: Span { get } + var span: Span { get } } extension KeyValuePairs { /// Share this `Collection`'s elements as a `Span` - var storage: Span<(Key, Value)> { get } + var span: Span<(Key, Value)> { get } } ``` @@ -136,13 +136,13 @@ Conditionally to the acceptance of [`Vector`][SE-0453], we will also add the fol ```swift extension Vector where Element: ~Copyable { /// Share this vector's elements as a `Span` - var storage: Span { get } + var span: Span { get } } ``` #### Accessing the raw bytes of a `Span` -When a `Span`'s element is `BitwiseCopyable`, we allow viewing the underlying storage as raw bytes with `RawSpan`: +When a `Span`'s element is `BitwiseCopyable`, we allow viewing the underlying memory as raw bytes with `RawSpan`: ```swift extension Span where Element: BitwiseCopyable { @@ -160,12 +160,12 @@ We hope that `Span` and `RawSpan` will become the standard ways to access shared ```swift extension UnsafeBufferPointer { /// Unsafely view this buffer as a `Span` - var storage: Span { get } + var span: Span { get } } extension UnsafeMutableBufferPointer { /// Unsafely view this buffer as a `Span` - var storage: Span { get } + var span: Span { get } } extension UnsafeRawBufferPointer { @@ -193,22 +193,22 @@ While the `swift-foundation` package and the `Foundation` framework are not gove ```swift extension Foundation.Data { // Share this `Data`'s bytes as a `Span` - var storage: Span { get } + var span: Span { get } // Share this `Data`'s bytes as a `RawSpan` var bytes: RawSpan { get } } ``` -Unlike with the standard library types, we plan to have a `bytes` property on `Foundation.Data` directly. This type conceptually consists of untyped bytes, and `bytes` is likely to be the primary way to directly access its memory. As `Data`'s API presents its storage as a collection of `UInt8` elements, we provide both `bytes` and `storage`. Types similar to `Data` may choose to provide both typed and untyped `Span` properties. +Unlike with the standard library types, we plan to have a `bytes` property on `Foundation.Data` directly. This type conceptually consists of untyped bytes, and `bytes` is likely to be the primary way to directly access its memory. As `Data`'s API presents its storage as a collection of `UInt8` elements, we provide both `bytes` and `span`. Types similar to `Data` may choose to provide both typed and untyped `Span` properties. #### Performance -The `storage` and `bytes` properties should be performant and return their `Span` or `RawSpan` with very little work, in O(1) time. This is the case for all native standard library types. There is a performance wrinkle for bridged `Array` and `String` instances on Darwin-based platforms, where they can be bridged to Objective-C types that do not guarantee contiguous storage. In such cases the implementation will eagerly copy the underlying data to the native Swift form, and return a `Span` or `RawSpan` pointing to that copy. +The `span` and `bytes` properties should be performant and return their `Span` or `RawSpan` with very little work, in O(1) time. This is the case for all native standard library types. There is a performance wrinkle for bridged `Array` and `String` instances on Darwin-based platforms, where they can be bridged to Objective-C types that may not be represented in contiguous memory. In such cases the implementation will eagerly copy the underlying data to the native Swift form, and return a `Span` or `RawSpan` pointing to that copy. -This eager copy behaviour will be specific to the `storage` and `bytes` properties, and therefore the memory usage behaviour of existing unchanged code will remain the same. New code that adopts the `storage` and `bytes` properties will occasionally have higher memory usage due to the eager copies, but we believe this performance compromise is the right approach for the standard library. The alternative is to compromise the design for all platforms supported by Swift, and we consider that a non-starter. +This eager copy behaviour will be specific to the `span` and `bytes` properties, and therefore the memory usage behaviour of existing unchanged code will remain the same. New code that adopts the `span` and `bytes` properties will occasionally have higher memory usage due to the eager copies, but we believe this performance compromise is the right approach for the standard library. The alternative is to compromise the design for all platforms supported by Swift, and we consider that a non-starter. -As a result of the eager copy behaviour for bridged `String.UTF8View` and `Array` instances, the `storage` property for these types will have a documented performance characteristic of "amortized constant time performance." +As a result of the eager copy behaviour for bridged `String.UTF8View` and `Array` instances, the `span` property for these types will have a documented performance characteristic of "amortized constant time performance." ## Source compatibility @@ -226,10 +226,10 @@ The additions described in this proposal require a version of the Swift standard #### Adding `withSpan()` and `withBytes()` closure-taking functions -The `storage` and `bytes` properties aim to be safe replacements for the `withUnsafeBufferPointer()` and `withUnsafeBytes()` closure-taking functions. We could consider `withSpan()` and `withBytes()` closure-taking functions that would provide an quicker migration away from the older unsafe functions. We do not believe the closure-taking functions are desirable in the long run. In the short run, there may be a desire to clearly mark the scope where a `Span` instance is used. The default method would be to explicitly consume a `Span` instance: +The `span` and `bytes` properties aim to be safe replacements for the `withUnsafeBufferPointer()` and `withUnsafeBytes()` closure-taking functions. We could consider `withSpan()` and `withBytes()` closure-taking functions that would provide an quicker migration away from the older unsafe functions. We do not believe the closure-taking functions are desirable in the long run. In the short run, there may be a desire to clearly mark the scope where a `Span` instance is used. The default method would be to explicitly consume a `Span` instance: ```swift var a = ContiguousArray(0..<8) -var span = a.storage +var span = a.span read(span) _ = consume span a.append(8) @@ -239,7 +239,7 @@ In order to visually distinguish this lifetime, we could simply use a `do` block ```swift var a = ContiguousArray(0..<8) do { - let span = a.storage + let span = a.span read(span) } a.append(8) @@ -248,7 +248,7 @@ a.append(8) A more targeted solution may be a consuming function that takes a non-escaping closure: ```swift var a = ContiguousArray(0..<8) -var span = a.storage +var span = a.span consuming(span) { span in read(span) } @@ -257,9 +257,9 @@ a.append(8) During the evolution of Swift, we have learned that closure-based API are difficult to compose, especially with one another. They can also require alterations to support new language features. For example, the generalization of closure-taking API for non-copyable values as well as typed throws is ongoing; adding more closure-taking API may make future feature evolution more labor-intensive. By instead relying on returned values, whether from computed properties or functions, we build for greater composability. Use cases where this approach falls short should be reported as enhancement requests or bugs. -#### Giving the properties different names +#### Different naming for the properties -We chose the names `storage` and `bytes` because those reflect _what_ they represent. Another option would be to name the properties after _how_ they represent what they do, which would be `span` and `rawSpan`. It is possible the name `storage` would be deemed to clash too much with existing properties of types that would like to provide views of their internal storage with `Span`-providing properties. For example, the Standard Library's concrete `SIMD`-conforming types have a property `var _storage`. The current proposal means that making this property of `SIMD` types into public API would entail a name change more significant than simply removing its leading underscore. +We originally proposed the name `storage` for the `span` properties introduced here. That name seems to imply that the returned `Span` is the storage itself, rather than a view of the storage. That would be misleading for types that own their storage, especially those that delegate their storage to another type, such as a `ContiguousArray`. In such cases, it would make sense to have a `storage` property whose type is the type that implements the storage. #### Disallowing the definition of non-escapable properties of non-escapable types @@ -269,7 +269,7 @@ The original version of this pitch disallowed this. As a consequence, the `bytes #### Omitting extensions to `UnsafeBufferPointer` and related types -We could omit the extensions to `UnsafeBufferPointer` and related types, and rely instead of future `Span` and `RawSpan` initializers. The initializers can have the advantage of being able to communicate semantics (somewhat) through their parameter labels. However, they also have a very different shape than the `storage` computed properties we are proposing. We believe that the adding the same API on both safe and unsafe types is advantageous, even if the preconditions for the properties cannot be statically enforced. +We could omit the extensions to `UnsafeBufferPointer` and related types, and rely instead of future `Span` and `RawSpan` initializers. The initializers can have the advantage of being able to communicate semantics (somewhat) through their parameter labels. However, they also have a very different shape than the `span` computed properties we are proposing. We believe that the adding the same API on both safe and unsafe types is advantageous, even if the preconditions for the properties cannot be statically enforced. ## Future directions @@ -277,7 +277,7 @@ Note: The future directions stated in [SE-0447](https://github.com/swiftlang/swi #### Safe mutations with `MutableSpan` -Some data structures can delegate mutations of their owned memory. In the standard library the function `withMutableBufferPointer()` provides this functionality in an unsafe manner. We expect to add a `MutableSpan` type to support delegating mutations of initialized memory. Standard library types will then add a way to vend `MutableSpan` instances. This could be with a closure-taking `withMutableSpan()` function, or a new property, such as `var mutableStorage`. Note that a computed property providing mutable access needs to have a different name than the `storage` properties proposed here, because we cannot overload the return type of computed properties based on whether mutation is desired. +Some data structures can delegate mutations of their owned memory. In the standard library the function `withMutableBufferPointer()` provides this functionality in an unsafe manner. We expect to add a `MutableSpan` type to support delegating mutations of initialized memory. Standard library types will then add a way to vend `MutableSpan` instances. This could be with a closure-taking `withMutableSpan()` function, or a new property, such as `var mutableStorage`. Note that a computed property providing mutable access needs to have a different name than the `span` properties proposed here, because we cannot overload the return type of computed properties based on whether mutation is desired. #### A `ContiguousStorage` protocol From 7ac36f803fa9717560087bb068d6b39dcb6838c3 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 12 Feb 2025 16:09:14 -0800 Subject: [PATCH 071/505] [SE-0456] call `InlineArray` by its name --- proposals/0456-stdlib-span-properties.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index 68a799b90c..6461529d6e 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -131,11 +131,11 @@ extension KeyValuePairs { } ``` -Conditionally to the acceptance of [`Vector`][SE-0453], we will also add the following: +Following the acceptance of [`InlineArray`][SE-0453], we will also add the following: ```swift -extension Vector where Element: ~Copyable { - /// Share this vector's elements as a `Span` +extension InlineArray where Element: ~Copyable { + /// Share this `InlineArray`'s elements as a `Span` var span: Span { get } } ``` From 58dbf76a49dc0d09de9a57b67c4dcbe49c109568 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 12 Feb 2025 16:11:07 -0800 Subject: [PATCH 072/505] [SE-0456] amendment removing extensions to SIMD --- proposals/0456-stdlib-span-properties.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index 6461529d6e..c18fe06105 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -120,11 +120,6 @@ extension CollectionOfOne { var span: Span { get } } -extension SIMD_N_ { // where _N_ ∈ {2, 3, 4 ,8, 16, 32, 64} - /// Share this vector's elements as a `Span` - var span: Span { get } -} - extension KeyValuePairs { /// Share this `Collection`'s elements as a `Span` var span: Span<(Key, Value)> { get } @@ -289,6 +284,10 @@ Unfortunately, a major issue prevents us from proposing it at this time: the abi The other limitation stated in [SE-0447][SE-0447]'s section about `ContiguousStorage` is "the inability to declare a `_read` acessor as a protocol requirement." This proposal's addition to enable defining a borrowing relationship via a computed property is a solution to that, as long as we don't need to use a coroutine accessor to produce a `Span`. While allowing the return of `Span`s through coroutine accessors may be undesirable, whether it is undesirable is unclear until coroutine accessors are formalized in the language. +`span` properties on standard library SIMD types + +This proposal as reviewed included `span` properties for the standard library `SIMD` types. We are deferring this feature at the moment, since it is difficult to define these succinctly. The primary issue is that the `SIMD`-related protocols do not explicitly require contiguous memory; assuming that they are represented in contiguous memory fails with theoretically-possible examples. We could define the `span` property systematically for each concrete SIMD type in the standard library, but that would be very repetitive (and expensive from the point of view of code size.) We could also fix the SIMD protocols to require contiguous memory, enabling a succinct definition of their `span` property. Finally, we could also rely on converting `SIMD` types to `InlineArray`, and use the `span` property defined on `InlineArray`. + ## Acknowledgements Thanks to Ben Rimmington for suggesting that the `bytes` property should be on `Span` rather than on every type. From 5d306c96629efb3641f56d0f3567e58d4934dcec Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 17 Feb 2025 21:18:58 -0800 Subject: [PATCH 073/505] [SE-0456] Update Proposal Status --- proposals/0456-stdlib-span-properties.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index c18fe06105..aaeab8c600 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -3,12 +3,13 @@ * Proposal: [SE-0456](0456-stdlib-span-properties.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Active Review (January 15...28, 2024)** +* Status: **Accepted** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: [PR #78561](https://github.com/swiftlang/swift/pull/78561) -* Review: [Review](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233), [Pitch](https://forums.swift.org/t/76138) +* Review: [Pitch](https://forums.swift.org/t/76138), [Review](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233), [Acceptance](https://forums.swift.org/t/77684) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md + [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md [PR-2305]: https://github.com/swiftlang/swift-evolution/pull/2305 [SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md From 32b174c139b0d0930a1ee5205378bac86c6ccb45 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Tue, 18 Feb 2025 08:09:48 -0500 Subject: [PATCH 074/505] Mark SE-0443 as implemented in Swift 6.1. --- proposals/0443-warning-control-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0443-warning-control-flags.md b/proposals/0443-warning-control-flags.md index 1dcb5012fc..99562b689c 100644 --- a/proposals/0443-warning-control-flags.md +++ b/proposals/0443-warning-control-flags.md @@ -4,7 +4,7 @@ * Proposal: [SE-0443](0443-warning-control-flags.md) * Authors: [Doug Gregor](https://github.com/douggregor), [Dmitrii Galimzianov](https://github.com/DmT021) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Accepted** +* Status: **Implemented (Swift 6.1)** * Implementation: [apple/swift#74466](https://github.com/swiftlang/swift/pull/74466) * Review: ([pitch](https://forums.swift.org/t/warnings-as-errors-exceptions/72925)) ([review](https://forums.swift.org/t/se-0443-precise-control-flags-over-compiler-warnings/74116)) ([acceptance](https://forums.swift.org/t/accepted-se-0443-precise-control-flags-over-compiler-warnings/74377)) * Previous revisions: [1](https://github.com/swiftlang/swift-evolution/blob/57fe29d5d55edb85b14c153b7f4cbead6b6539eb/proposals/0443-warning-control-flags.md), [2](https://github.com/swiftlang/swift-evolution/blob/7b12899ad0d96002c793d33ef8109ec47c5d256f/proposals/0443-warning-control-flags.md) From 036815c53d796212eb25a53b328c35eb7bf6242c Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 17 Feb 2025 23:00:47 +0000 Subject: [PATCH 075/505] burp 1.0 --- ...NN-adoption-tooling-for-swift-features.md} | 157 ++++++++---------- 1 file changed, 70 insertions(+), 87 deletions(-) rename proposals/{NNNN-migration-tooling-for-upcoming-features.md => NNNN-adoption-tooling-for-swift-features.md} (67%) diff --git a/proposals/NNNN-migration-tooling-for-upcoming-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md similarity index 67% rename from proposals/NNNN-migration-tooling-for-upcoming-features.md rename to proposals/NNNN-adoption-tooling-for-swift-features.md index 8e1f49c734..c51aa9b38d 100644 --- a/proposals/NNNN-migration-tooling-for-upcoming-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -9,25 +9,23 @@ ## Introduction -In Swift 5.8 introduced [upcoming features][SE-0362], -which enabled piecemeal adoption of individual source-incompatible changes that -are included in a language mode. +Swift 5.8 introduced [upcoming features][SE-0362], which enabled piecemeal +adoption of individual source-incompatible changes that are included in a +language mode. Many upcoming features have a mechanical migration, meaning the compiler can determine the exact source changes necessary to allow the code to compile under the upcoming feature while preserving the behavior of the code. -This proposal seeks to improve the experience of enabling individual -upcoming features by providing a mechanism for producing the necessary source -code changes automatically for a given set of upcoming features that a -programmer wants to enable. +This proposal seeks to improve the experience of enabling individual Swift +features by providing an integrated mechanism for producing these source code +modifications automatically. ## Motivation -Adopting certain features is a time-consuming endeavor at the least. It is the responsibility of project maintainers to preserve source (and binary) -compatibility both internally and externally for library clients when enabling -an upcoming feature, which can be difficult or tedious without having tools to -help detect possibly inadvertent changes and perform monotonous migration -shenanigans for you. +compatibility both internally and for library clients when enabling an upcoming +feature, which can be difficult or tedious without having tools to help detect +possibly inadvertent changes or perform monotonous migration shenanigans for +you. *Our* responsibility is to make that an easier task for everybody. ### User intent @@ -38,21 +36,22 @@ intent. Is the developer expecting guidance on adopting an improvement? All the compiler knows to do when a feature is enabled is to compile code accordingly. -This suffices if a feature merely supplants an existing syntactical construct -or changes the behavior of existing code in strictly predictable ways because -Swift can infer the need to suggest a fix just from spotting certain code -patterns. +If an upcoming feature supplants an existing grammatical construct or +invalidates an existing behavior, the language rules alone suffice because +Swift can consistently infer the irrefutable need to diagnose certain code +patterns just by spotting them. Needless to say, not all upcoming features fall under these criteria (and not -all features are source-breaking in the first place). Consider -[`DisableOutwardActorInference`][SE-0401], which changes actor isolation -inference of a type that contains an actor-isolated property wrapper. There -is no way for the programmer to specify that they'd like compiler fix-its to -make the existing actor isolation inference explicit. If they enable the -upcoming feature, their code will simply behave differently. This was a -point of debate in the review of SE-0401, and the Language Steering Group -concluded that automatic migration tooling is the right way to address this -particular workflow, as [noted in the acceptance notes][SE-0401-acceptance]: +all features are source-breaking in the first place). +Consider [`DisableOutwardActorInference`][SE-0401], which changes actor +isolation inference rules with respect to wrapped properties. +There is no way for the programmer to specify that they'd like compiler fix-its +to make the existing actor isolation inference explicit. +If they enable the upcoming feature, their code will simply behave differently. +This was a point of debate in the review of [SE-0401], and the Language +Steering Group concluded that automatic migration tooling is the right way to +address this particular workflow, as +[noted in the acceptance notes][SE-0401-acceptance]: > the Language Steering Group believes that separate migration tooling to > help programmers audit code whose behavior will change under Swift 6 mode @@ -61,7 +60,7 @@ particular workflow, as [noted in the acceptance notes][SE-0401-acceptance]: ### Automation -Many existing and prospective upcoming features come with simple and reliable +Many existing and prospective upcoming features account for simple and reliable migration paths to facilitate adoption: * [`NonfrozenEnumExhaustivity`][SE-0192]: Restore exhaustivity with @@ -79,32 +78,17 @@ migration paths to facilitate adoption: * [`DisableOutwardActorInference`][SE-0401]: Specify global actor isolation explicitly. * [`InternalImportsByDefault`][SE-0409]: `import X` → `public import X`. -* [`GlobalConcurrency`][SE-0412]: - - Convert the global variable to a `let` (or) - - `@MainActor`-isolate it (or) - - Mark it with `nonisolated(unsafe)` +* [`GlobalConcurrency`][SE-0412]: Convert the global variable to a `let`, or + `@MainActor`-isolate it, or mark it with `nonisolated(unsafe)`. * [`MemberImportVisibility`][SE-0444]: Add explicit imports appropriately. * [`InferSendableFromCaptures`][SE-0418]: Suppress inference with coercions and type annotations. * [Inherit isolation by default for async functions][async-inherit-isolation-pitch]: Mark nonisolated functions with the proposed attribute. -Extending diagnostic metadata to include information that allows for -recognizing these diagnostics and distinguishing semantics-preserving fix-its -from alternative source changes will open up numerous opportunities for -higher-level tools — ranging from the Swift package manager to IDEs — to -implement powerful solutions for organizing, automating, and tuning feature -adoption processes. - -It is not always feasible or in line with language design principles for an -upcoming feature to have a mechanical migration path. -For example, the following upcoming features require manual migration to -preserve semantics: - -* [`DynamicActorIsolation`][SE-0423] -* [`GlobalActorIsolatedTypesUsability`][SE-0434] -* [`StrictConcurrency`][SE-0337] -* [`IsolatedDefaultValues`][SE-0411] +Application of these adjustments can be fully automated in favor of preserving +behavior, saving time for more important tasks, such as identifying, auditing, +and testing code where a change in behavior is preferable. ## Proposed solution @@ -115,39 +99,35 @@ leveraged to build better supportive adoption experiences for developers. If enabling a feature communicates an intent to *enact* rules, adoption mode communicates an intent to *adopt* them. An immediate benefit of adoption mode is the capability to deliver source -modifications that can be applied to preserve or improve the behavior of -existing code whenever the feature provides for them. +modifications that can be applied to preserve compatibility whenever a feature +provides for them. This proposal will support the set of existing upcoming features that have mechanical migrations, as described in the [Automation](#automation) section. -All future proposals that introduce a new upcoming feature and provide a -mechanical migration are expected to support adoption mode and detail its -behavior in the *Source compatibility* section of the proposal. +All future proposals that intend to introduce an upcoming feature and +provide for a mechanical migration should include an adoption mode and detail +its behavior alongside the migration paths in the *Source compatibility* +section. ## Detailed design Upcoming features that have mechanical migrations will support an adoption -mode, which is a a new mode of building a project that will produce compiler +mode, which is a new mode of building a project that will produce compiler warnings with attached fix-its that can be applied to preserve the behavior -of the code when the upcoming feature is enabled. Adoption mode must not -cause any new compiler errors, and the fix-its produced must preserve the -source compatibility and behavior of the code. +of the code once the upcoming feature is enacted. +The action of enabling a previously disabled upcoming feature in adoption +mode must not cause any new compiler errors or behavioral changes, and the +fix-its produced must preserve compatibility. +Compatibility here refers to both source and binary compatibility, as well as +to behavior. Additionally, this action will have no effect if the mode is not supported -for a given upcoming feature, i,e. because the upcoming feature does not +for a given upcoming feature, i.e., because the upcoming feature does not have a mechanical migration. A corresponding warning will be emitted in this case to avoid the false impression that the impacted source code is compatible with the feature. -Adoption mode should deliver guidance in the shape of regular diagnostics. -For arbitrary upcoming features, adoption mode is expected to anticipate and -call out any compatibility issues that result from enacting the feature, -coupling diagnostic messages with counteracting compatible changes and helpful -alternatives whenever feasible. -Compatibility issues encompass both source and binary compatibility issues, -including behavioral changes. - ### Interface #### Compiler @@ -233,14 +213,14 @@ SwiftSetting.enableUpcomingFeature("InternalImportsByDefault", mode: .adoption) ### Diagnostics Diagnostics emitted in relation to a specific feature in adoption mode must -belong to a diagnostic group named after the feature. The names of diagnostic -groups can be displayed alongside diagnostic messages using -`-print-diagnostic-groups` and used to associate messages with features. +belong to a diagnostic group named after the feature. +The names of diagnostic groups can be displayed alongside diagnostic messages +using `-print-diagnostic-groups` and used to associate messages with features. ## Source compatibility -This proposal does not affect language rules. The described changes to the API -surface are source-compatible. +This proposal does not affect language rules. +The described changes to the API surface are source-compatible. ## ABI compatibility @@ -248,21 +228,22 @@ This proposal does not affect binary compatibility or binary interfaces. ## Implications on adoption -Entering or exiting adoption mode may affect behavior and is therefore a +Entering or exiting adoption mode will affect behavior and is therefore a potentially source-breaking action. ## Future directions ### Producing source incompatible fix-its -For some upcoming features, a source change which alters the semantics of +For some features, a source change that alters the semantics of the program is a more desirable approach to addressing an error that comes -from enabling an upcoming feature. For example, programmers might want to -replace cases of `any P` with `some P`. Adoption tooling could support the -option to produce source incompatible fix-its in cases where the compiler -can detect that a different behavior might be more beneficial. +from enabling the feature. +For example, programmers might want to replace cases of `any P` with `some P`. +Adoption tooling could support the option to produce source incompatible +fix-its in cases where the compiler can detect that a different behavior might +be more beneficial. -### Applications beyond migration +### Applications beyond mechanical migration Adoption mode can be extrapolated to additive features, such as [typed `throws`][SE-0413] or [opaque parameter types][SE-0341], by providing @@ -270,9 +251,9 @@ actionable adoption tips. Additive features are hard-enabled and become an integral part of the language as soon as they ship. Many recent additive features are already integrated into the Swift feature -model and kept around for the sole purpose of supporting -[feature availability checks][feature-detection] in conditional compilation -blocks. +model, and their metadata is kept around either to support +[feature availability checks][SE-0362-feature-detection] in conditional +compilation blocks or because they started off as experimental features. Another potential direction for adoption mode is promotion of best practices. @@ -288,22 +269,24 @@ is essential for future tools built around adoption mode: This can prove especially handy when multiple features are simultaneously enabled in adoption mode, or when similar diagnostic messages are caused by distinct features. -* Fix-its that preserve semantics can be prioritized and auto-applied in - previews. +* Exposing the purpose of a fix-it can help developers make quicker decisions + when offered multiple fix-its. + Furthermore, tools can take advantage of this information by favoring and + auto-applying source-compatible fix-its. ### `swift adopt` The Swift package manager could implement an `adopt` subcommand for interactive review and application of adoption mode output for a given set of features, -with a command line interface similar to `git add --patch`. +with a command-line interface similar to `git add --patch`. ## Alternatives considered ### Naming -Perhaps the most intuitive alternative to "adoption" is "migration". We -settled on the former because there is no reason for this concept to be limited -to upcoming features or migrational changes. +Perhaps the most intuitive alternative to "adoption" is "migration". +We settled on the former because there is no reason for this concept to be +limited to upcoming features or migrational changes. ## Acknowledgements @@ -326,9 +309,10 @@ Special thanks to Holly for her guidance throughout the draft stage. [SE-0352]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md [SE-0354]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0354-regex-literals.md [SE-0362]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md -[feature-detection]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md#feature-detection-in-source-code +[SE-0362-feature-detection]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md#feature-detection-in-source-code [SE-0383]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0383-deprecate-uiapplicationmain-and-nsapplicationmain.md [SE-0401]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0401-remove-property-wrapper-isolation.md +[SE-0401-acceptance]: https://forums.swift.org/t/accepted-with-modifications-se-0401-remove-actor-isolation-inference-caused-by-property-wrappers/66241 [SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md [SE-0411]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0411-isolated-default-values.md [SE-0413]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md @@ -338,4 +322,3 @@ Special thanks to Holly for her guidance throughout the draft stage. [SE-0434]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0434-global-actor-isolated-types-usability.md [SE-0444]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md [async-inherit-isolation-pitch]: https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862 -[SE-0401-acceptance]: https://forums.swift.org/t/accepted-with-modifications-se-0401-remove-actor-isolation-inference-caused-by-property-wrappers/66241 From 945d93776cf44cefaa5e685ede0fa4fc96d460ab Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 18 Feb 2025 16:46:36 -0800 Subject: [PATCH 076/505] Add a vision for improving the approachability of data-race safety. (#2621) * Add a prospective vision for improving the approachability of data-race safety. * Specify approachability of data-race safety for programmers with other concurrent programming experience as an explicit goal of the vision document. * Clarify why diagnostics and documentation are not included in the vision document. * Minor clarifications and typo fixes. * Clarify how diagnostics are considered in the evolution process. * Add boilerplate re acceptance --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- visions/approachable-concurrency.md | 198 ++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 visions/approachable-concurrency.md diff --git a/visions/approachable-concurrency.md b/visions/approachable-concurrency.md new file mode 100644 index 0000000000..de8adefc75 --- /dev/null +++ b/visions/approachable-concurrency.md @@ -0,0 +1,198 @@ +# Improving the approachability of data-race safety + +[SE-0434]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0434-global-actor-isolated-types-usability.md + +> This document is an official feature [vision document](https://forums.swift.org/t/the-role-of-vision-documents-in-swift-evolution/62101). The Language Steering Group has endorsed the goals and basic approach laid out in this document. This endorsement is not a pre-approval of any of the concrete proposals that may come out of this document. All proposals will undergo normal evolution review, which may result in rejection or revision from how they appear in this document. + +## Introduction + +Swift's built-in support for concurrency has three goals: + +1. Extend memory safety guarantees to low-level data races. +2. Maintain progressive disclosure for non-concurrent code, and make basic use of concurrency simple and easy. +3. Make advanced uses of concurrency to improve performance natural to accomplish and reason about. + +The Swift 6 language mode provides a baseline of correctness that meets the first goal, but sometimes it comes at the cost of the second, and it can be frustrating to adopt. Now that we have a lot more user experience under our belt as a community, it’s reasonable to ask what we can do in the language to address that problem. This document lays out several potential paths for improving the usability of Swift 6, focusing on two primary use cases: + +1. Simple situations where programmers aren’t intending to use concurrency at all. +2. Adapting an existing code base that uses concurrency libraries which predate Swift's native concurrency model. + +While performance is not our immediate focus, it’s something we need to keep in mind during this exercise: we don’t want these usability wins to create pervasive regressions or to make it frustratingly difficult to achieve a high level of performance. + +A key tenet of our thinking in this vision is that we want to drastically reduce the number of explicit concurrency annotations necessary in projects that aren’t trying to leverage parallelism for performance. This is important for many kinds of programming, such as UI programming and scripts, where concurrency is often localized and large swathes of the code are generally expected to be constrained to the main actor. At the same time, we want to maintain a smooth path for experienced programmers to opt in to concurrency and maintain the safety of complete data-race checking. + +As we see it, there should be three phases on the progressive disclosure path for concurrency: + +1. **Write sequential, single-threaded code**. By default, programmers writing executable projects will write sequential code; there is no runtime parallelism, and therefore no data-race safety errors are surfaced to the programmer. +2. **Write asynchronous code without data-race safety errors**. When programmers need functionality that can suspend, they can start introducing basic uses of async/await. Programmers won’t have to confront data-race safety at this point, because they aren’t yet introducing parallelism into their code. This is an important distinction, because there are many library APIs that perform work asynchronously, but they don’t need to use the programmer’s shared mutable state from a concurrent task. In these cases, programmers don’t have to understand data-race safety just to call an async API. +3. **Introduce parallelism to improve performance.** When the programmer is ready to embrace concurrency to get better performance, they can explicitly offload work from the main actor to the cooperative thread pool, leverage tasks and structured concurrency, etc, all while relying on the compiler to prevent mistakes that risk a data race. + +## Mitigating false positive data-race safety errors in sequential code + +A lot of code is effectively “single-threaded”. For example, most executables, such as apps, command-line tools, and scripts, start running on the main actor and just stay there unless some part of the code actually does something concurrent (like creating a `Task`). If there isn’t any use of concurrency, the entire program will run sequentially, and there’s no risk of data races — every concurrency diagnostic is necessarily a false positive! It would be good to be able to take advantage of that in the language, both to avoid annoying programmers with unnecessary diagnostics and to reinforce progressive disclosure. Many people get into Swift by writing these kinds of programs, and if we can avoid needing to teach them about concurrency straight away, we’ll make the language much more approachable. + +Now, “If nothing in the program uses concurrency, suppress all the concurrency diagnostics” requires what compiler writers call a *whole-program analysis*, and rules like that tend not to work out well on multiple levels. For one, it would require the compiler to look at all of the code in the program all at once; this might be okay for small scripts, but it would scale poorly as the program got more complex. More importantly, it would make the first adoption of concurrency extremely painful: programmers would be hit by a tidal wave of errors in code they haven’t changed. And, of course, many libraries do use concurrency behind the scenes; importing even a single library like that would force concurrency-safety diagnostics everywhere. + +A better approach is to locally state our assumption that the sequential parts of the program are “single-threaded”. Rather than having to assume the possibility of concurrency, Swift would know that these parts of the code will all run sequentially, which it can use to prove that there aren’t any data races. There can still be concurrent parts of the program elsewhere, but Swift would stop them from accessing the single-threaded bits. Fortunately, this is something that Swift can already model quite well! + +### Single-threaded code and its challenges under Swift 6 + +The easiest and best way to model single-threaded code is with a global actor. Everything on a global actor runs sequentially, and code that isn’t isolated to that actor can’t access its data. All programs start running on the global actor `MainActor`, and if everything in the program is isolated to the main actor, there shouldn’t be any concurrency errors. + +Unfortunately, it’s not quite that simple right now. Writing a single-threaded program is surprisingly difficult under the Swift 6 language mode. This is because Swift 6 defaults to a presumption of concurrency: if a function or type is not annotated or inferred to be isolated, it is treated as non-isolated, meaning it can be used concurrently. This default often leads to conflicts with single-threaded code, producing false positive diagnostics in cases such as: + +* global and static variables, +* conformances of main-actor-isolated types to non-isolated protocols, +* class deinitializers, +* overrides of non-isolated superclass methods in a main-actor-isolated subclass, and +* calls to main-actor-isolated functions from the platform SDK. + +To see this, let’s explore the first of those cases in more detail. A mutable global variable (or an immutable one that stores a non-`Sendable` value) is only memory-safe if it’s used in a single-threaded way. If the whole program is single-threaded, there’s no problem, and the variable is always safe to use. But since Swift 6 presumes concurrency by default, it requires a variable like this to be explicitly isolated to a global actor, like `@MainActor`. A function that uses that variable is then also required to be statically isolated to `@MainActor`: + +```swift +class AudioManager { + @MainActor + static let shared = AudioManager() + + func playSound() { ... } +} + +class Model { + func play() { + AudioManager.shared.playSound() // error: Main actor-isolated static property 'shared' can not be referenced from a nonisolated context + } +} +``` + +And this in turn means that functions that call those functions must also be `@MainActor`, and so on until the `@MainActor` annotation has been laboriously propagated throughout the entire transitive tree of callers. Because main actor isolation is so common, many programmers have resorted to reflexively writing `@MainActor` everywhere, an onerous annotation burden that goes against Swift’s goals of making the simplest things easy. + +Because the default programming model presumes concurrency, it is also hard on programmers who haven’t yet learned about concurrent programming, because they are confronted with the concept of data-race safety and actor isolation too early simply by using these basic language features: + +```swift +class AudioManager { + static let shared = AudioManager() // error: Static property 'shared' is not concurrency-safe because non-'Sendable' type 'AudioManager' may have shared mutable state +} +``` + +Analogous problems arise with all the other kinds of false positives listed above. For example, when using values from generic code, the value’s type usually must conform to one or more protocols. However, actor-isolated types cannot easily conform to protocols that aren’t aware of that isolation: they can declare the conformance, but it’s often impossible to write a useful implementation because the value’s properties will not be available. This is exactly the same kind of conflict as with global variables, where we have generally single-threaded code but a presumption of concurrency from the protocol, except that *this* conflict usually can’t be solved with annotations at all — the only fixes are to change the protocol, avoid all the isolated storage, or dangerously assert (with `assumeIsolated`) that the method is only used dynamically from the right actor. + +### Allowing modules to default to being “single-threaded” + +We believe that the right solution to these problems is to allow code to opt in to being “single-threaded” by default, on a module-by-module basis. This would change the default isolation rule for unannotated code in the module: rather than being non-isolated, and therefore having to deal with the presumption of concurrency, the code would instead be implicitly isolated to `@MainActor`. Code imported from other modules would be unaffected by the current module’s choice of default. When the programmer really wants concurrency, they can request it explicitly by marking a function or type as `nonisolated` (which can be used on any declaration as of [SE-0449](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0449-nonisolated-for-global-actor-cutoff.md)), or they can define it in a module that doesn’t default to main-actor isolation. This doesn’t fundamentally change anything about Swift’s isolation model; it just flips the default, effectively creating a model in which code is single-threaded except where it explicitly requests concurrency. Modules that don’t want this could of course continue to use the current rules. + +Making a module be isolated to the main actor by default would directly fix several of the false positive problems listed above for single-threaded code. Global variables would default to being isolated to the main actor, avoiding the diagnostic when they’re declared. Functions in the module would also default to being isolated to the main actor, allowing them to freely use both those isolated global variables and any main-actor-isolated functions and variables imported from the platform SDK. Class overrides and protocol conformances aren’t quite so easy, but we think we can extend them in ways that allow a natural solution with main actor isolation. We’ll get to how later in this document. + +### Default concurrency rules for executable and library modules + +As mentioned above, executable targets tend to center around the main actor. Command-line tools and scripts all start on the main actor and continue to run there unless they explicitly do something that introduces concurrency. Similarly, most UI programs make heavy use of single-threaded UI frameworks that privilege the main actor. This kind of code would be greatly improved by adopting a single-threaded model by default. Furthermore, since many new Swift programmers find themselves first writing this kind of code, this would also be a significant improvement to Swift’s progressive disclosure: programmers writing code in this mode should not run into data-race safety issues and diagnostics until they intentionally introduce concurrency. We feel that this amounts to a compelling argument that executable targets should default to inferring main actor isolation. + +The same argument does not apply to libraries. Most library functions are meant to be usable from any context, and libraries usually avoid using any global or shared mutable state. Swift also already asks a little more of library authors in general; for example, access control is usually a more significant concern for library authors than for app developers. It would be reasonable for library targets to default to `nonisolated` the same way they do today in Swift 6. + +Specific libraries could still decide to default to the main actor, such as when they’re libraries of UI widgets, or if a library is used for code organization within an executable project. + +### Risks of a language dialect + +Adding a per-module setting to specify the default isolation would introduce a new permanent language dialect. In a sense, Swift adds a new language dialect whenever it adds an upcoming language feature flag, but these are seen as “temporary” because it’s expected that those features will eventually be rolled into a future language mode. Permanent language dialects can be problematic for a variety of reasons: + +* They can harm readability if readers have to know which dialect the code uses before they can understand the code. +* They can harm usability if programmers have to consciously program differently based on the dialect in use in the code or if code cannot be easily moved between projects using different dialects. +* They can harm tools such as IDEs if the tool has to know which dialect the code uses before it can work correctly; this is particularly challenging for code files that may be used in multiple dialects, such as a `.h` file in a C/C++/Objective-C IDE. +* When dialects are platform-dependent, they can harm portability and basic workflows (such as testing) if it is difficult to make the same code build as multiple dialects. + +Some of these problems do not seem to apply to this proposed dialect because it only affects the isolation of declarations. Most IDE services, such as syntax highlighting and code completion, do not need to know the isolation of the surrounding context. And there’s no good reason for a module to build with a different default isolation on different platforms, so the dialect does not seem to introduce any portability concerns. + +Readability does seem to be a fair concern. It is often useful to know what isolation a function will run under, and with this change, that would be dialect-specific. However, it is worth noting that the dynamic isolation of a function is already not always statically knowable because of the way that e.g. synchronous `nonisolated` functions inherit their callers’ isolation. And it would be reasonable for IDEs to be able to present isolation information for the current context: even without this dialect change, it is not always easy to understand how Swift’s isolation inference rules will apply to any particular declaration. + +Programmers will probably not consciously program differently under these different dialects, and the compiler should provide reasonable guidance if they make a mistake. Moving code from a single-threaded module to a nonisolated module might be somewhat more arduous, however. To some degree, this is inherent and arguably even good: the programmer may be moving this code in an effort to generalize it to work concurrently, and any new diagnostics represent real problems that the programmer didn’t have to deal with before this generalization. But when the programmer is not trying to generalize the code to use concurrency, this could be frustrating, and it might be good for IDEs to offer assistance, such as tools to make the single-threaded assumptions of a piece of code explicit. + +On balance, we feel that the costs of this particular dialect are modest and manageable. + +## Isolated conformances + +When checking a conformance to a protocol, Swift 6 often requires implementations to be nonisolated when the requirement is, including when the requirement is synchronous or the parameters are not Sendable. This makes it difficult to implement nonisolated protocols with any kind of isolated type: global-actor-isolated types, certainly, but also actors themselves. This restriction is very important when writing concurrent code, but it's a common source of false positives in single-threaded programs. Even worse, there's often no good solution to the problem: a correct implementation of the protocol for an isolated type usually requires access to the isolated data, and the only way to get that is to assert that the calling context is actually isolated, which completely subverts the static isolation safety that Swift 6 tries to provide. + +In many ways, isolation's interaction with protocol requirements is similar to its interaction with function values. In both situations, we have an abstract signature that doesn't express isolation by default, which Swift wants to interpret as an affirmative statement that the isolation of the implementation doesn't matter. Over the last few years, Swift has gradually added more ways to handle isolated function values: + +- A function value can have a type like `() -> Bool` that says it's not sendable. These functions can have any kind of isolation as long as it's the same as the current concurrency domain. Since the function can't be used from a different context, there's no need for it to spell out its isolation explicitly in its type; Swift just checks that the isolation actually matches whenever it makes a new non-`Sendable` function value. + +- A function value can have a type like `@MainActor () -> Bool` that says it's isolated to a specific global actor. These functions can either be non-isolated or isolated to that actor, and Swift just treats them as the latter unconditionally when calling them. + +- A function value can have a type like `@isolated(any) () -> Bool` that says it might be isolated to a specific actor that it carries around with it dynamically. These functions can be isolated to anything, and the caller has to be prepared to handle it. + +Each of these ideas also works with protocol conformances. If we know that we only intend to use a protocol conformance from the current concurrency domain, we don't really care whether the implementation requires some sort of isolation as long as the current context has that isolation. Similarly, if we know that the implementation of a protocol might be isolated to a specific global actor, we can handle that whenever we use the conformance exactly as if the protocol requirements were declared isolated to that actor. And we could even do that dynamically with a statically-unknown isolation, the same way Swift already does with `@isolated(any)` function values. + +The most important of these for our model of single-threaded code is to be able to express global-actor-isolated conformances. When a type is isolated to a global actor, its methods will be isolated by default. Normally, these methods would not be legal implementations of nonisolated protocol requirements. When Swift recognizes this, it can simply treat the conformance as isolated to that global actor. This is a kind of *isolated conformance*, which will be a new concept in the language. + +Now, an isolated conformance is less flexible than a nonisolated conformance. For example, generic types and functions from nonisolated modules (including all current declarations) will still be interpreted as requiring nonisolated conformances. This will mean that they can't be called with a type that only has an isolated conformance, but it will also allow them to freely use the conformance from any concurrency domain, the same way they can today. Generic types and functions in "single-threaded" modules will default to allowing conformances isolated to the module's default global actor. Since those functions will themselves be isolated to that global actor, they won't have any problem using those conformances. + +A generic function that can work with both isolated and nonisolated conformances should be able to declare that it can accept an isolated conformance. It would then be restricted to only use the conformance from the current concurrency domain, as if it were a sort of "non-sendable conformance". This is an important tool for generic libraries such as the standard library, many of which will never use conformances concurrently and so are fine with accepting isolated conformances. + +This design is still being developed, and there are a lot of details that will have to be figured out. Nonetheless, we are tentatively very excited about the potential for this feature to fix problems with how Swift's generics system interacts with isolated types, especially global-actor-isolated types. + +## Isolated subclasses and overrides + +To achieve data race safety, Swift 6 has to diagnose a variety of problems that are specific to classes: + +- The sendability of a class must match the sendability of its superclass[^1]. +- If a class is sendable and not isolated to a global actor, its stored properties must be sendable. +- If a class is isolated to a global actor, its superclass must either be non-isolated or isolated to the same global actor. +- An override must have the same isolation as the declaration it overrides. + +[^1]: There is a natural exception to this rule: a sendable class can have a non-sendable superclass if the superclass and all of its ancestors only have sendable stored properties. Currently, Swift only implements this exception for the exact class `NSObject`. + +All of these diagnostics are false positives in purely sequential programs. Fortunately, many of them don't apply to global-actor-isolated classes in the first place. The restriction that isolated classes can't inherit from classes isolated to a different global actor is very reasonable, but it's extremely unlikely to affect programmers in practice because they rarely use global actors other than the main actor at all. The only significant false positive here, then, is the restriction on overriding. + +[SE-0434][] changed the rules for global-actor-isolated classes to allow them to inherit from non-sendable classes; the subclass just remains non-sendable. Since the class is non-sendable and isolated to a global actor, it's tempting to say that override restrictions shouldn't be necessary for it: the object reference should only be usable on the global actor in the first place. This isn't quite true today, but we think we can revise SE-0434 to make it true by imposing restrictions on initializers in the subclass. This would be a small source break, but it would greatly improve the usability of these classes. + +Unfortunately, global-actor-isolated classes that inherit from nonisolated sendable classes can't benefit from the same idea. We can only see one way to make it safe to allow isolated overrides of non-isolated methods for these classes without a whole-program prohibition of concurrency: we would have to prevent any reference to the subclass from being converted to its sendable superclass type. This is feasible to implement, but we suspect it would be too restrictive to be widely useful; we can revisit this with more information. + +## Easing the introduction of basic async code + +[SE-0338](https://github.com/hborla/swift-evolution/blob/async-function-isolation/proposals/0338-clarify-execution-non-actor-async.md) specifies that nonisolated async functions never run on an actor's executor. This design decision was made to prevent unnecessary serialization and contention for the actor by switching off of the actor to run the nonisolated async function, and any new tasks it creates that inherit isolation. The actor is then free to make forward progress on other work. This behavior is especially important for preventing unexpected overhang on the main actor. + +Over time, we have learned that this design decision undermines progressive disclosure, because it prioritizes main actor responsiveness at the expense of making basic asynchronous code difficult to write. Always switching off of an actor to run a nonisolated async function imposes data-race safety errors on programmers when they call the API with non-sendable arguments from the main actor. + +Many library APIs have transitioned to using isolated parameters to ensure that an async API runs on the caller by default, because it’s a much easier default to work with in client code. + +The current execution semantics of async functions also impede programmer’s understanding of the concurrency model because there is a significant difference in what `nonisolated` means on synchronous and asynchronous functions. Nonisolated synchronous functions always run in the isolation domain of the caller, while nonisolated async functions always switch off of the caller's actor (if there is one). It's confusing that `nonisolated` does not have a consistent meaning when applied to functions, and the current behavior conflates the concept of actor isolation with the ability for a function to suspend. + +Changing the default execution semantics of nonisolated async functions to run wherever they are called better facilitates progressive disclosure of concurrency. This default allows functions to leverage suspension without forcing callers to cross an isolation boundary and imposing data-race safety checks on arguments and results. A lot of basic asynchronous code can be written correctly and efficiently with only the ability to suspend. When an async function needs to always run off of an actor, the API author can still specify that with a new `@execution(concurrent)` annotation on the function. This provides a better default for most cases while still maintaining the ease of specifying that an async function switches off of an actor to run. + +Many programmers have internalized the SE-0338 semantics, and making this change several years after SE-0338 was accepted creates an unfortunate intermediate state where it's difficult to understand the semantics of a nonisolated async function without understanding the build settings of the module you're writing code in. We can alleviate some of these consequences with a careful migration design. There are more details about migration in the [automatic migration](#automatic-migration) section of this document, and in the [source compatibility](https://github.com/hborla/swift-evolution/blob/async-function-isolation/proposals/NNNN-async-function-isolation.md#source-compatibility) section of the proposal for this change. + +This idea has already been pitched on the forums, and you can read the full proposal for it [here](https://github.com/hborla/swift-evolution/blob/async-function-isolation/proposals/NNNN-async-function-isolation.md). + +## Easing incremental migration to data-race safety + +Many programmers are not new to concurrency as a concept and have extensive experience with multi-threaded programming. However, the Swift 6 data-race safety model is a significant shift for programmers with experience using concurrency libraries that predate Swift's native concurrency features. Moreover, there are many existing, large codebases that were built on such libraries, and migrating these codebases to both leverage modern concurrency features and enable static data-race safety takes significant engineering effort. An explicit goal of improving the approachability of data-race safety is lessening the amount of effort it takes to enable data-race safety in existing codebases. + +### Bridging between synchronous and asynchronous code + +Introducing async/await into an existing codebase is difficult to do incrementally, because the language does not provide tools to bridge between synchronous and asynchronous code. Sometimes programmers can kick off a new unstructured task to perform the async work, and other times that is not suitable, e.g. because the synchronous code needs a result from the async operation. It’s also not always possible to propagate `async` throughout callers, because the function signature might be declared in a library dependency that you don’t own. + +Notably, using actors in programs that make heavy use of the main actor forces programmers to use async/await, because all interactions with an actor must be done asynchronously from outside the actor. This significantly restricts the utility of actors, especially in existing codebases. + +Other concurrency libraries like Dispatch provide a limited tool set to wait on asynchronous work, such as `DispatchQueue.asyncAndWait`. These tools come with serious tradeoffs, including tying up limited system resources and introducing the possibility for deadlocks, but they provide critical functionality that is sometimes necessary in a project. It’s important for programmers to have the ability to express this in the language, and because the language model allows actor re-entrancy and doesn’t have a strict FIFO guarantee for tasks enqueued on an actor, there’s opportunity to mitigate the risk of deadlocks that these tools come with. + +### Mitigating runtime assertions due to isolation mismatches + +[SE-0423: Dynamic actor isolation enforcement from non-strict-concurrency contexts](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0423-dynamic-actor-isolation.md) introduced dynamic actor isolation assertions that are injected by the compiler at the boundaries between data-race safe and unsafe code. This dynamic checking catches actor isolation violations in library dependencies that have not yet migrated to the Swift 6 language mode, and may have data-race safety issues in their implementation. These checks are effective at identifying missing `@Sendable` annotations, but they also make Swift 6 adoption painful for clients when they migrate before their dependencies. + +Some of these runtime crashes are false positives; the runtime checks are inserted based on the static isolation of the function, but the function might not access any mutable state that’s isolated to or derived from the actor. In these cases, the dynamic checks can simply be elided based on analysis of the function implementation. + +In other cases, the dynamic assertion indicates the presence of a runtime data race, because isolated state is being accessed from outside the actor. The correct way to resolve this data race is either to run the function on the actor, or change the function to eliminate access to actor-isolated state. There are two possible avenues for the language to aid programmers in resolving the data race: + +* Instead of directly calling the function in the wrong isolation domain, enqueue a job that calls the function on the actor. This only works if the function does not return a result. +* Use the import-as-async heuristic from [SE-0297: Concurrency Interoperability with Objective-C](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0297-concurrency-objc.md) to automatically import completion handlers of asynchronous functions as `@Sendable`, which will allow the compiler to diagnose access to actor-isolated state in completion handlers. + +## Automatic migration + +Unlike the Swift 6 migration, all language changes with source compatibility impact described in this vision can be automatically migrated to while preserving the semantics of existing code. The source incompatible portions of this vision will be gated behind [upcoming feature flags](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0362-piecemeal-future-features.md), which will be enabled by default in a future 6.x language mode, except for the per-module setting to infer main actor by default. + +Compiler tooling can automatically migrate existing projects when they choose to enable each of these upcoming features, either individually or as part of a future language mode migration. Programmers will be able to perform a “migration build” with one or more upcoming language features enabled, or with a specific language mode that enables a set of upcoming features, and be offered source code changes that would allow the compiler to build the project without errors and without changing semantics. + +## What’s not in this vision + +This vision does not cover existing pain points with task ordering and actor re-entrancy. These are important problems, but they are more prevalent in more advanced uses of concurrency and warrant a separate, dedicated exploration. + +Improving concurrency diagnostics and documentation is also not covered in this document. All language proposals should consider diagnostics to the extent that language design decisions prevent precise and actionable error messages. Beyond that, diagnostics and documentation changes are not governed by the Swift evolution process, because these changes don't have long-term source compatibility and ABI constraints, so gating improvements behind a heavy weight review process isn't necessary. However, diagnostics and documentation are an extremely important tool for making the concurrency model more approachable, and they will be included in the implementation effort behind this vision. From 24e26bb795a92c59b888153dc571b25213aa8431 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 19 Feb 2025 05:43:50 +0000 Subject: [PATCH 077/505] Add link to pitch --- proposals/NNNN-adoption-tooling-for-swift-features.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index c51aa9b38d..e3cce3289b 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -5,7 +5,7 @@ * Review Manager: TBD * Status: **Awaiting implementation** * Implementation: TBD -* Review: TBD +* Review: [pitch](https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936) ## Introduction @@ -294,7 +294,7 @@ This proposal was inspired by documents prepared by [Allan Shortlidge][Allan] and [Holly Borla][Holly]. Special thanks to Holly for her guidance throughout the draft stage. - + [Holly]: https://github.com/hborla [Allan]: https://github.com/tshortli From c6039af6146b466a121de35c17a1bf10c862ac8d Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 19 Feb 2025 06:09:32 +0000 Subject: [PATCH 078/505] Minor clarification for naming rationale --- proposals/NNNN-adoption-tooling-for-swift-features.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index e3cce3289b..e9a6b9d230 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -285,8 +285,8 @@ with a command-line interface similar to `git add --patch`. ### Naming Perhaps the most intuitive alternative to "adoption" is "migration". -We settled on the former because there is no reason for this concept to be -limited to upcoming features or migrational changes. +We settled on the former because there is no reason for this concept to remain +limited to upcoming features or mechanical migration. ## Acknowledgements From b41bec5425b4394fcc35ef90dc30b65f52da6d14 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 19 Feb 2025 17:12:46 +0900 Subject: [PATCH 079/505] Proposal: Task.startSynchronously --- ...k-start-synchronously-on-caller-context.md | 411 ++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 proposals/NNNN-task-start-synchronously-on-caller-context.md diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md new file mode 100644 index 0000000000..836873f954 --- /dev/null +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -0,0 +1,411 @@ +# Starting tasks synchronously from caller context + +* Proposal: [SE-NNNN](NNNN-filename.md) +* Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) +* Review Manager: TBD +* Status: **Awaiting implementation** +* Implementation: TODO +* Review: ... + +## Introduction + +Swift Concurrency's primary means of entering an asynchronous context is creating a Task (structured or unstructured), and from there onwards it is possible to call asynchronous functions, and execution of the current work may _suspend_. + +Entering the asynchronous context today incurs the creating and scheduling of a task to be executed at some later point in time. This initial delay may be wasteful for tasks which perform minimal or none (!) work at all. + +This initial delay may also be problematic for some situations where it is known that we are executing on the "right actor" however are *not* in an asynchronous function and therefore in order to call some different asynchronous function we must create a new task and introduce subtle timing differences as compared to just being able to call the target function–which may be isolated to the same actor we're calling from–immediately. + +## Motivation + +Today, the only way to enter an asynchronous execution context is to create a new task which then will be scheduled on the global concurrent executor or some specific actor the task is isolated to, and only once that task is scheduled execution of it may begin. + +This initial scheduling delay can be problematic in some situations where tight control over execution is required. While for most tasks the general semantics are a good choice–not risking overhang on the calling thread–we have found through experience that some UI or performance sensitive use-cases require a new kind of semantic: starting on the calling context, until a suspension occurs, and only then hopping off to another executor once the task is resumed from the suspension. + +This can be especially beneficial for tasks, which *may run to completion very quickly and without ever suspending.* + +A typical situation where this new API may be beneficial often shows up with @MainActor code, such as: + +```swift +@MainActor var thingsHappened: Int + +@MainActor func onThingHappened(context: Context) { + synchronousFunction() +} + +func asyncUpdateThingsHappenedCounter() async { + // for some reason this function MUST be async + thingsHappened += 1 +} + +func synchronousFunction() { + // we know this executes on the MainActor, and can assume so: + MainActor.assumeIsolated { + // we cannot call the asynchronous function asyncUpdateThingsHappenedCounter though! + } + + // Proposed API: + Task.startSynchronously { + // Now we CAN call the asynchronous function below: + await asyncUpdateThingsHappenedCounter() + } +} +``` + +The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation... it still would not allow us to call arbitrary async functions, as we are still in a synchronous context. + +The proposed `Task.startSynchronously` API forms an async context on the calling thread/task/executor, and therefore allows us to call into async code, at the risk of overhanging on the calling executor. So while this should be used sparingly, it allows entering an asynchronous context *synchronously*. + +## Proposed solution + +We propose the introduction of a new family of Task creation APIs, collectively called "start synchronously", which create a Task and use the calling thread to execute the task's "first synchronous section" right until the task suspends for the first time. + +After the suspension happens, execution yields back to an appropriate executor, and does not continue to use the caller's thread anymore. + +The canonical example for using this new API is using an unstructured task like this: + +```swift +func synchronous() { // synchronous function + // executor / thread: "T1" + let task: Task = Task.startSynchronously { + // executor / thread: "T1" + guard keepRunning() else { return } // synchronous call (1) + + // executor / thread: "T1" + await noSuspension() // potential suspension point #1 // (2) + + // executor / thread: "T1" + await suspend() // potential suspension point #2 // (3), suspend, (5) + // executor / thread: "other" + } + + // (4) continue execution + // executor / thread: "T1" +} +``` + +The task created by the `startSynchronously` function begins running immediately _on the calling executor (and thread)_ without any scheduling delay. This new task behaves generally the same as any other unstructured task, it gets a copy of the outer context's task locals, and uses the surrounding context's base priority as its base priority as well. + +Since the task started running immediately, we're able to perform some calls immediately inside it, and potentially return early. + +If a potential suspension point does not actually suspend, we still continue running on the calling context. For example, if potential suspension point `#1` did not suspend, we still continue running synchronously until we reach potential suspension point `#2` which for the sake of discussion let's say does suspend. At this point the calling thread continues executing the scope that created the unstructured task. + +> You can refer to the `(N)` numbers in the above snippet to follow the execution order of this example execution. Specifically, once the execution reaches (3) the calling thread stops executing the unstructured task, and continues executing at (4). Eventually, when the unstructured task is resumed, it gets woken up at (5) and continues running on some other executor and/or thread. + +## Detailed design + +We propose the introduction of a family of "start synchronously" task creation APIs. + +The most frequent use of this API is likely going to be the unstructured task one. This is because we are able to enter an asynchronous context from a synchronous function using it: + +```swift +extension Task { + + @discardableResult + public static func startSynchronously( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, + operation: sending @escaping async throws(Failure) -> Success, + ) -> Task + + @discardableResult + public static func startSynchronouslyDetached( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, + operation: sending @escaping async throws(Failure) -> Success, + ) -> Task +} +``` + +We also offer the same API for all kinds of task groups. These create child tasks, which participate in structured concurrency as one would expect of tasks created by task groups. + +```swift +extension (Throwing)TaskGroup { + + // Same add semantics as 'addTask'. + func startTaskSynchronously( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + ) + + // Same add semantics as 'addTaskUnlessCancelled'. + func startTaskSynchronouslyUnlessCancelled( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + ) +} + +extension (Throwing)DiscardingTaskGroup { + // Same add semantics as 'addTask'. + func startTaskSynchronously( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + ) + + // Same add semantics as 'addTaskUnlessCancelled'. + func startTaskSynchronouslyUnlessCancelled( + // SE-NNNN's proposed 'name: String? = nil' would be here + priority: TaskPriority? = nil, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + ) +} +``` + +The `startTaskSynchronously` mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled. + +### Isolation rules + +Due to the semantics of "starting on the caller context", the isolation rules of the closure passed to `startSynchronously` need to be carefully considered. + +For example, the following example would not be safe, as unlike `Task.init` the task does not actually immediately become isolated to the isolation of its closure: + +```swift +@MainActor var counter: Int = 0 + +func sayHello() { + Task { @MainActor in // ✅ ok + counter += 1 // we're isolated to the main actor immediately and may modify its state + } + + Task.startSynchronously { @MainActor in // ❌ unsafe, must be compile time error + counter += 1 // Not actually running on the main actor at this point (!) + } +} +``` + +The isolation rules for the `startSynchronously` family of APIs need to account for this synchronous "first part" of the execution. We propose the following set of rules to make this API concurrency-safe: + +- The operation closure is `sending`. +- The operation closure may only specify an isolation (e.g. `{ @MainActor in }`), if and only if already statically contained within the same isolation context. + +This allows for the following pattern, where we can enter an asynchronous task context, from a synchronous function, that is _known_ to be isolated to the main actor already: + +```swift +@MainActor var counter: Int = 0 + +func asyncUpdateCounter() async { counter += 1 } + +@MainActor +func sayHelloOnMain() { + Task.startSynchronously { @MainActor in // ✅ ok, caller isolation is also @MainActor + await asyncUpdateCounter() + } + + Task.startSynchronously { @OtherGlobalActor in // ❌ error: MainActor != OtherGlobalActor + await asyncUpdateCounter() + } +} +``` + +Task executors do not influence the static isolation properties of code, and thus have no impact on the isolation semantics of these APIs. In general, task executors are orthogonal to actor isolation, and while they can influence which actual executor a default actor or global async function would use to execute some piece of code they have no impact on isolation properties and therefore safety properties of a piece of code. + +### Interaction with `Actor/assumeIsolated` + +In [SE-0392: Custom Actor Executor](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md) we introduced the ability to dynamically recover isolation information using the `assumeIsolated` API. It can be used to dynamically recover the runtime information about whether we are executing on some specific actor. + +The `assumeIsolated` shares some ideas with `startSynchronously` however it is distinctly different. For example, while both APIs can effectively be used to "notice we are running on the expected actor, and therefore perform some work on its context". However, `assumeIsolated` does _not_ create a new asynchronous context, while `Task.startSynchronously` does: + +```swift +@MainActor +var state: Int = 0 + +@MainActor +func asyncMainActorMethod() async { } + +func synchronous() { + // assert that we are running "on" the MainActor, + // and therefore can access its isolated state: + MainActor.assumeIsolated { + num +=1 // ✅ ok + + await asyncMainActorMethod() // ❌ error: 'async' call in a function that does not support concurrency + } + +} +``` + +We can compose assumeIsolated with `startSynchronously` to ensure we synchronously start a task on the MainActor if we know we are already running on it, like this: + +```swift +func alwaysCalledFromMainActor() { // we know this because e.g. documentation, but the API wasn't annotated + MainActor.assumeIsolated { // @MainActor isolated + assert(num == 0) + Task.startSynchronously { @MainActor in + num +=1 // ✅ ok + assert(num == 1) // since we are guaranteed nothing else executed since the 'num == 0' assertion + + await asyncMainActorMethod() // ✅ ok + } + } +} +``` + +The synchronously started task will not suspend and context switch until any of the called async methods does. For example, we are guaranteed that there will be no interleaved code execution between the `assert(num == 0)` in our example, and the `num += 1` inside the synchronously started task. + +After the suspension point though, there may have been other tasks executed on the main actor, and we should check the value of `num` again. + +### Structured concurrency semantics + +Synchronously started tasks behave exactly the same as their fully asynchronous equivalents. + +In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual; + +The only difference in behavior is where these synchronously started tasks _begin_ their execution. + +## Source compatibility + +This proposal is purely additive, and does not cause any source compatibility issues. + +## ABI compatibility + +This proposal is purely ABI additive. + +## Alternatives considered + +### Dynamically asserting isolation correctness + +An important use case of this API is to support calling into an actor isolated context when in a synchronous function that is dynamically already running on that actor. This situation can occur both with instance actors and global actors, however the most commonly requested situation where this shows up is synchronous handler methods in existing frameworks, and which often may have had assumptions about the main thread, and did not yet annotate their API surface with @MainActor annotations. + +It would be possible to create a _dynamically asserting_ version of `Task.startSynchronously`, which does handle the happy path where indeed we "know" where we're going to be called quite well, but gives a *false sense of security* as it may crash at runtime, in the same way the `Actor/preconditionIsolated()` or `Actor/assumeIsolated` APIs do. We believe we should not add more such dynamically crashing APIs, but rather lean into the existing APIs and allow them compose well with any new APIs that should aim to complement them. + +The dynamically asserting version would be something like this: + +```swift +// Some Legacy API: documented to be invoked on main thread but NOT @MainActor annotated and NOT 'async' +func onSomethingHappenedAlwaysOnMainThread(something: Something) { + // we "know" we are on the MainActor, however this is a legacy API that is not an 'async' method + // so we cannot call any other async APIs unless we create a new task. + Task.startSynchronously { @MainActor in + await showThingy() + } +} + +func onSomethingHappenedSometimesOnMainThread(something: Something) { + // 💥 Must assert at runtime if not on main thread + Task.startSynchronously { @MainActor in + await showThingy() + } +} + +func showThingy() async { ... } +``` + +This implementation approach yields safe looking code which unfortunately may have to assert at runtime, rather than further improve the compile time safety properties of Swift Concurrency. + +> See *Future Directions: Dynamically "run synchronously if in right context, otherwise enqueue as usual"* for a future direction that would allow implementing somewhat related APIs in a more elegant and correct way. + +### Banning from use in async contexts (@available(*, noasync)) + +During earlier experiments with such API it was considered if this API should be restricted to only non-async contexts, by marking it `@available(*, noasync)` however it quickly became clear that this API also has specific benefits which can be used to ensure certain ordering of operations, which may be useful regardless if done from an asynchronous or synchronous context. + +## Future Directions + +### Partial not-sending closure semantics + +The isolation rules laid out in this proposal are slightly more conservative than necessary. + +Technically one could make use of the information that the part of the closure up until the first potential suspension point is definitely running synchronously, and therefore even access state that would not be able to be accessed even under region isolation analysis rules. + +We believe that most common situations will be handled well enough by region analysis, and sending closures, however this is a future direction that could be explored if it becomes more apparent that implementing these more complex semantics would be very beneficial. + +For example, such analysis could enable the following: + +```swift +actor Caplin { + var num: Int = 0 + + func check() { + Task.startSynchronously { + num += 1 // could be ok; we know we're synchronously executing on caller + + try await Task.sleep(for: .seconds(1)) + + num += 1 // not ok anymore; we're not on the caller context anymore + } + + num += 1 // always ok + } +} +``` + +### Dynamically "run synchronously if in right context, otherwise enqueue as usual" + +The proposed `startSynchronously` API is a tool to be used in performance and correctness work, and any "may sometimes run synchronously, it depends" is not a good solution to the task at hand. Because of that, we aim for this API to provide the _predictable_ behavior of running synchronously on the caller, without impacting the isolation, that can compose naturally with `assumeIsolated` that can recover dynamic into static isolation information. + +For example, we'll be able to build an API that composes the proposed `startSynchronously` with a not yet proposed but under investigation `Task/isIsolated(to: some Actor) -> Bool` API in order to offer an API that implements the semantics that some developers have been asking for a while: + +- if already dynamically isolated on the expected actor, run synchronously, +- if not, schedule a task to execute the same operation later. + +Using a combination of (a) `Task/startSynchronously`, (b) `Actor/assumeIsolated`, and some form of boolean returning the not yet proposed (c) `isIsolated` (which would be a `Bool` returning equivalent of `assumeIsolated`), we will be able to build such function by composing those more fundamental concurrency operations: + +```swift +func tryRunSynchronouslyOrAsynchronouslyOtherwise( + operation: sending @escaping @isolated(any) () async -> Success +) -> Task { + guard let actor = operation.isolation else { + // no specific isolation, just run async + return Task { try await operation() } + } + + if Task.__current.__isIsolated(to: actor) { // (c) !!! does not exist yet !!! + // we definitely are executing on 'actor' + return actor.assumeIsolated { // (b) guaranteed to not crash + // recovered static isolation information about 'actor' + // (a) use startSynchronously with specific actor isolation + return Task.runSynchronously { + [isolated actor] in // !! does not exist yet (closure isolation control) !! + try await operation() + } + } + } else { + // we are not isolated to 'actor' and therefore must schedule a normal unstructured task + return Task { try await operation() } + } +} +``` + +Or even better we could build the same API with structured concurrency: + +```swift +func tryRunSynchronouslyOrAsynchronouslyOtherwise( + operation: sending @escaping @isolated(any) () async throws -> Success +) async rethrows -> Success { /* same, but use TaskGroup inside */ } +``` + +### Expressing closure isolation tied to function parameter: `@isolated(to:)` + +The currently proposed API is working within the limitations of what is expressible in today's isolation model. It would be beneficial to be able to express the startSynchronously API if we could spell something like "this closure must be isolated to the same actor as the calling function" which would allow for the following code: + +```swift +@MainActor +func test() { + Task.startSynchronously { /* inferred to be @MainActor */ + num += 1 + } +} + +@MainActor var num = 0 +``` + +The way to spell this in an API could be something like this: + +```swift +public static func startSynchronously( + ... + isolation: isolated (any Actor)? = #isolation, + operation: @escaping @isolated(to: isolation) sending async throws(Failure) -> Success, +) -> Task +``` + +The introduction of a hypothetical `@isolated(to:)` paired with an `isolated` `#isolation` defaulted actor parameter, would allow us to express "the *operation* closure statically inherits the exact same isolation as is passed to the isolation parameter of the startSynchronously method". This naturally expresses the semantics that the startSynchronously is offering, and would allow to _stay_ on that isolation context after resuming from the first suspension inside the operation closure. + +Implementing this feature is a large task, and while very desirable we are not ready yet to commit to implementing it as part of this proposal. If and when this feature would become available, we would adopt it in the startSynchronously APIs. From f55ef578eab23f16c64c29501384ca05130daebe Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 19 Feb 2025 20:01:38 +0900 Subject: [PATCH 080/505] Update NNNN-task-start-synchronously-on-caller-context.md --- proposals/NNNN-task-start-synchronously-on-caller-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md index 836873f954..d467268e14 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -323,7 +323,7 @@ actor Caplin { var num: Int = 0 func check() { - Task.startSynchronously { + Task.startSynchronouslyDetached { num += 1 // could be ok; we know we're synchronously executing on caller try await Task.sleep(for: .seconds(1)) From 31ff6788affe981b60e76ca9b8661e6e3092e7cd Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 19 Feb 2025 18:45:34 +0000 Subject: [PATCH 081/505] Describe the behavior for specifying invalid mode --- proposals/NNNN-adoption-tooling-for-swift-features.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index e9a6b9d230..e68f1750b3 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -148,6 +148,9 @@ For example: -enable-upcoming-feature InternalImportsByDefault:adoption ``` +If the specified mode is invalid, the flag will be ignored, and a warning will +be emitted. This warning will belong to the `StrictLanguageFeatures` diagnostic +group. In a series of either of these options applied to a given feature, only the last option will be honored. If an upcoming feature is both implied by the effective language mode and From c1fc2b9ba4528df2bf9d0ee3faf9318ac93e1c4e Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 20 Feb 2025 07:52:16 -0800 Subject: [PATCH 082/505] Add a proposal to change the execution semantics of nonisolated async functions. (#2572) * WIP: Add a proposal for changing the execution semantics of nonisolated async functions. * Clarify why `@Sendable` function values can't inherit isolation. * Add an alternative considered for using `nonisolated` to control where an async function executes. * Various proposal clarifications. * Add a bit more detail to the ABI compatibility section. * Fill out the source compatibility section. * Fix a typo in a code example. * Proposal revisions. * Address feedback from the Language Steering Group. 1. Make it clear that in the end, `@execution(caller)` will rarely be explicit in source. 2. Simplify the function conversions section using a table, and clarify the rules for non-`@Sendable` function conversions. 3. Address alternative spellings for `@execution` in the alternatives considered section. * Remove a confusing line of reasoning. It's not very compelling anyway. * Editorial changes to the proposed solution. * Clarify that the import-as-async change is not gated behind the upcoming feature. * Assign SE-0461 --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- proposals/0461-async-function-isolation.md | 935 +++++++++++++++++++++ 1 file changed, 935 insertions(+) create mode 100644 proposals/0461-async-function-isolation.md diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md new file mode 100644 index 0000000000..bc2004e320 --- /dev/null +++ b/proposals/0461-async-function-isolation.md @@ -0,0 +1,935 @@ +# Run nonisolated async functions on the caller's actor by default + +* Proposal: [SE-0461](0461-async-function-isolation.md) +* Authors: [Holly Borla](https://github.com/hborla), [John McCall](https://github.com/rjmccall) +* Review Manager: [Xiaodi Wu](https://github.com/xwu) +* Status: **Active review (February 20...March 2, 2025)** +* Vision: [[Prospective Vision] Improving the approachability of data-race safety](https://forums.swift.org/t/prospective-vision-improving-the-approachability-of-data-race-safety/76183) +* Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` +* Upcoming Feature Flag: `AsyncCallerExecution` +* Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) +* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) + +## Introduction + +Swift's general philosophy is to prioritize safety and ease-of-use over +performance, while still providing tools to write more efficient code. The +current behavior of nonisolated async functions prioritizes main actor +responsiveness at the expense of usability. + +This proposal changes the behavior of nonisolated async functions to run on +the caller's actor by default, and introduces an explicit way to state that an +async function always switches off of an actor to run. + +## Table of Contents + +- [Motivation](#motivation) +- [Proposed solution](#proposed-solution) +- [Detailed design](#detailed-design) + - [The `@execution` attribute](#the-execution-attribute) + - [`@execution(caller)` functions](#executioncaller-functions) + - [`@execution(concurrent)` functions](#executionconcurrent-functions) + - [Task isolation inheritance](#task-isolation-inheritance) + - [`#isolation` macro expansion](#isolation-macro-expansion) + - [Isolation inference for closures](#isolation-inference-for-closures) + - [Function conversions](#function-conversions) + - [Executor switching](#executor-switching) + - [Import-as-async heuristic](#import-as-async-heuristic) +- [Source compatibility](#source-compatibility) +- [ABI compatibility](#abi-compatibility) +- [Implications on adoption](#implications-on-adoption) +- [Alternatives considered](#alternatives-considered) + - [Changing isolation inference behavior to implicitly capture isolated parameters](#changing-isolation-inference-behavior-to-implicitly-capture-isolated-parameters) + - [Use `nonisolated` instead of a separate `@execution(concurrent)` attribute](#use-nonisolated-instead-of-a-separate-executionconcurrent-attribute) + - [Don't introduce a type attribute for `@execution`](#dont-introduce-a-type-attribute-for-execution) +- [Revisions](#revisions) + +## Motivation + +[SE-0338: Clarify the Execution of Non-Actor-Isolated Async Functions][SE-0338] +specifies that nonisolated async functions never run on an actor's executor. +This design decision was made to prevent unnecessary serialization and +contention for the actor by switching off of the actor to run the nonisolated +async function, and any new tasks it creates that inherit isolation. The actor +is then free to make forward progress on other work. This behavior is +especially important for preventing unexpected overhang on the main actor. + +This decision has a number of unfortunate consequences. + +**`nonisolated` is difficult to understand.** There is a semantic difference +between the isolation behavior of nonisolated synchronous and asynchronous +functions; nonisolated synchronous functions always run on the caller's actor, +while nonisolated async functions always switch off of the caller's actor. This +means that sendable checking applies to arguments and results of nonisolated +async functions, but not nonisolated synchronous functions. + +For example: + +```swift +class NotSendable { + func performSync() { ... } + func performAsync() async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + x.performSync() // okay + + await x.performAsync() // error + } +} +``` + +The call to `performAsync` from the actor results in a data-race safety error +because the call leaves the actor to run the function. This frees up the actor +to run other tasks, but those tasks can access the non-`Sendable` value `x` +concurrently with the call to `performAsync`, which risks a data race. + +It's confusing that the two calls to methods on `NotSendable` have different +isolation behavior, because both methods are `nonisolated`. + +**Async functions that run on the caller's actor are difficult to express.** +It's possible to write an async function that does not leave an actor to run +using isolated parameters and the `#isolation` macro as a default argument: + +```swift +class NotSendable { + func performAsync( + isolation: isolated (any Actor)? = #isolation + ) async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + await x.performAsync() // okay + } +} +``` + +This resolves the data-race safety error because `performAsync` now runs on the +actor. However, this isn't an obvious solution, it's onerous boilerplate to +write, and the default argument is lost if the method is used in a higher-order +manner. + +**It's easy to write invalid async APIs.** If the `performAsync` method were in +a library that the programmer doesn't own, it's not possible to workaround the +data-race safety error without using unsafe opt outs. It's common for library +authors to mistakenly vend an API like this, because the data-race safety error +only manifests when calling the API from an actor. + +The concurrency library itself has made this mistake, and many of the async +APIs in the concurrency library have since transitioned to inheriting the +isolation of the caller using isolated parameters; see [SE-0421][SE-0421] for +an example. + +**It's difficult to write higher-order async APIs.** Consider the following +async API which provides a `with`-style method for acquiring a resource and +performing a scoped operation: + +```swift +public struct Resource { + internal init() {} + internal mutating func close() async {} +} + +public func withResource( + isolation: isolated (any Actor)? = #isolation, + _ body: (inout Resource) async -> Return +) async -> Return { + var resource = Resource() + let result = await body(&resource) + await resource.close() + return result +} +``` + +Despite `withResource` explicitly running on the caller's actor by default, +there's no way to specify that the async `body` function value should also run +in the same context. The compiler treats the async function parameter as +switching off of the actor to run, so it requires sendable checking on the +arguments and results. This particular example happens to pass a value in a +disconnected region to `body`, but passing an argument in the actor's region +would be invalid. In most cases, the call doesn't cross an isolation boundary +at runtime, because the function type is not `@Sendable`, so calling the API +from an actor-isolated context and passing a trailing closure will treat the +closure as isolated to the same actor. This sendable checking is often a source +of false positives that make higher-order async APIs extremely difficult to +write. The checking can't just be eliminated, because it's valid to pass a +nonisolated async function that will switch off the actor to run, which would +lead to a data race if actor-isolated state is passed to the `body` parameter. + +Moreover, the above explanation of isolation rules for async closures is +extremely difficult to understand; the default isolation rules are too +complicated. + +## Proposed solution + +This proposal changes the execution semantics of nonisolated async functions +to always run on the caller's actor by default. This means that nonisolated +functions will have consistent execution semantics by default, regardless of +whether the function is synchronous or asynchronous. + +This change makes the following example from the motivation section +valid, because the call to `x.performAsync()` does not cross an isolation +boundary: + +```swift +class NotSendable { + func performSync() { ... } + func performAsync() async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + x.performSync() // okay + + await x.performAsync() // okay + } +} +``` + +Changing the default execution semantics of async functions can change the +behavior of existing code, so the change is gated behind the +`AsyncCallerExecution` upcoming feature flag. To help stage in the new +behavior, a new `@execution` attribute can be used to explicitly specify the +execution semantics of an async function in any language mode. The +`@execution(concurrent)` attribute is an explicit spelling for the behavior of +async functions in language modes <= Swift 6, and the `@execution(caller)` +attribute is an explicit spelling for async functions that run on the caller's +actor. + +For example: + +```swift +class NotSendable { + func performSync() { ... } + + @execution(caller) + func performAsync() async { ... } + + @execution(concurrent) + func alwaysSwitch() async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + x.performSync() // okay + + await x.performAsync() // okay + + await x.alwaysSwitch() // error + } +} +``` + +`@execution(concurrent)` is the current default for nonisolated async +functions. `@execution(caller)` will become the default for async functions +when the `AsyncCallerExecution` upcoming feature is enabled. + +## Detailed design + +The sections below will explicitly use `@execution(concurrent)` and +`@execution(caller)` to demonstrate examples that will behave consistently +independent of upcoming features or language modes. However, note that the +end state under the `AsyncCallerExecution` upcoming feature will mean that +`@execution(caller)` is not necessary to explicitly write, and +`@execution(caller)` will likely be used sparingly because it has far +stricter data-race safety requirements. + +### The `@execution` attribute + +`@execution` is a declaration and type attribute that specifies the execution +semantics of an async function. `@execution` must be written with an argument +of either `caller` or `concurrent`. The details of each argument are specified +in the following sections. + +> _Naming rationale_: The term `concurrent` in `@execution(concurrent)` was +> chosen because the colloquial phrase "runs concurrently with actors" is a +> good way to describe the semantics of the function execution. Similarly, the +> async function can be described as running on the concurrent executor. + +Only (implicitly or explicitly) `nonisolated` functions can be marked with the +`@execution` attribute; it is an error to use the `@execution` attribute with +an isolation other than `nonisolated`, including global actors, isolated +parameters, and `@isolated(any)`. The `@execution` attribute can be used +together with `@Sendable` or `sending`. + +The `@execution` attribute is preserved in the type system so that the execution +semantics can be distinguished for function vales. + +The `@execution` attribute cannot be applied to synchronous functions. This is +an artificial limitation that could later be lifted if use cases arise. + +#### `@execution(caller)` functions + +Async functions annotated with `@execution(caller)` will always run on the +caller's actor: + +```swift +class NotSendable { + func performSync() { ... } + + @execution(caller) + func performAsync() async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + x.performSync() // okay + + await x.performAsync() // okay + } +} +``` + +In the above code, the call to `x.performAsync()` continues running on the +`self` actor instance. The code does not produce a data-race safety error, +because the `NotSendable` instance `x` does not leave the actor. + +This behavior is accomplished by implicitly passing an optional actor parameter +to the async function. The function will run on this actor's executor. See the +[Executor switching](#executor-switching) section for more details on why the +actor parameter is necessary. + +The type of an `@execution(caller)` function declaration is an +`@execution(caller)` function type. For example: + +```swift +class NotSendable { ... } + +func useAsValue(_ ns: NotSendable) async { ... } + +@MainActor let global: NotSendable = .init() + +@execution(caller) +func runOnActor(ns: NotSendable) async {} + +@MainActor +func callSendableClosure() async { + // the type of 'closure' is '@Sendable @execution(caller) (NotSendable) -> Void' + let closure = runOnActor(ns:) + + let ns = NotSendable() + await closure(ns) // okay + await closure(global) // okay +} + +callSendableClosure(useAsValue) +``` + +In the above code, the calls to `closure` from `callSendableClosure` run on the +main actor, because `closure` is `@execution(caller)` and `callSendableClosure` +is main actor isolated. + +#### `@execution(concurrent)` functions + +Async functions can be declared to always switch off of an actor to run using +the `@execution(concurrent)` attribute: + +```swift +struct S: Sendable { + @execution(concurrent) + func alwaysSwitch() async { ... } +} +``` + +The type of an `@execution(concurrent)` function declaration is an +`@execution(concurrent)` function type. Details on function conversions are +covered in a [later section](#function-conversions). + +When an `@execution(concurrent)` function is called from a context that can +run on an actor, including `@execution(caller)` functions or actor-isolated +functions, sendable checking is performed on the argument and result values. +Either the argument and result values must have a type that conforms to +`Sendable`, or the values must be in a disconnected region so they can be sent +outside of the actor: + +```swift +class NotSendable {} + +@execution(concurrent) +func alwaysSwitch(ns: NotSendable) async { ... } + +actor MyActor { + let ns: NotSendable = .init() + + func callConcurrent() async { + await alwaysSwitch(ns: ns) // error + + let disconnected = NotSendable() + await alwaysSwitch(ns: disconnected) // okay + } +} +``` + +### Task isolation inheritance + +Unstructured tasks created in nonisolated functions never run on an actor +unless explicitly specified. This behavior is consistent for all nonisolated +functions, including synchronous functions, `@execution(caller)` async +functions, and `@execution(concurrent)` async functions. + +For example: + +```swift +class NotSendable { + var value = 0 +} + +@execution(caller) +func createTask(ns: NotSendable) async { + Task { + // This task does not run on the same actor as `createTask` + + ns.value += 1 // error + } +} +``` + +Capturing `ns` in the unstructured task is an error, because the value can +be used concurrently between the caller of `createTask` and the newly +created task. + +This decision is deliberate to match the semantics of unstructured task +creation in nonisolated synchronous functions. Note that unstructured task +creation in methods with isolated parameters also do not inherit isolation +if the isolated parameter is not explicitly captured. + +### `#isolation` macro expansion + +Uses of the `#isolation` macro will expand to the implicit isolated parameter. +For example, the following program prints `Optional(Swift.MainActor)`: + +```swift +nonisolated func printIsolation() async { + let isolation = #isolation + print(isolation) +} + +@main +struct Program { + // implicitly isolated to @MainActor + static func main() async throws { + await printIsolation() + } +} +``` + +This behavior allows async function calls that use `#isolation` as a default +isolated argument to run on the same actor when called from an +`@execution(caller)` function. For example, the following code is valid because +the call to `explicitIsolationInheritance` does not cross an isolation +boundary: + +```swift +class NotSendable { ... } + +func explicitIsolationInheritance( + ns: NotSendable, + isolation: isolated (any Actor)? = #isolation +) async { ... } + +@execution(caller) +func printIsolation(ns: NotSendable) async { + await explicitIsolationInheritance(ns: ns) // okay +} +``` + +Note that this introduces a semantic difference compared to synchronous +nonisolated functions, where there is no implicit isolated parameter and +`#isolation` always expands to `nil`. For example, the following program prints +`nil`: + +```swift +func printIsolation() { + let isolation = #isolation + print(isolation) +} + +@main +struct Program { + // implicitly isolated to @MainActor + static func main() async throws { + printIsolation() + } +} +``` + +In an `@execution(concurrent)` function, the `#isolation` macro expands to +`nil`. + +### Isolation inference for closures + +Note that the rules in this section are not new with this proposal. However, +these rules have not been specified in any other proposal, and they are +necessary for understanding the execution semantics of async closures. + +The isolation of a closure can be explicitly specified with a type annotation +or in the closure signature. If no isolation is specified, the inferred +isolation for a closure depends on two factors: +1. The isolation of the context where the closure is formed. +2. Whether the contextual type of the closure is `@Sendable` or `sending`. + +If the contextual type of the closure is neither `@Sendable` nor `sending`, the +inferred isolation of the closure is the same as the enclosing context: + +```swift +class NotSendable { ... } + +@MainActor +func closureOnMain(ns: NotSendable) async { + let syncClosure: () -> Void = { + // inferred to be @MainActor-isolated + + // capturing main-actor state is okay + print(ns) + } + + // runs on the main actor + syncClosure() + + let asyncClosure: (NotSendable) async -> Void = { + // inferred to be @MainActor-isolated + + print($0) + } + + // runs on the main actor; + // passing main-actor state is okay + await asyncClosure(ns) +} +``` + +If the type of the closure is `@Sendable` or if the closure is passed to a +`sending` parameter, the closure is inferred to be `nonisolated`. + +The closure is also inferred to be `nonisolated` if the enclosing context +has an isolated parameter (including `self` in actor-isolated methods), and +the closure does not explicitly capture the isolated parameter. This is done to +avoid implicitly capturing values that are invisible to the programmer, because +this can lead to reference cycles. + +### Function conversions + +Function conversions can change isolation. You can think of this like a +closure with the new isolation that calls the original function, asynchronously +if necessary. For example, a function conversion from one global-actor-isolated +type to another can be conceptualized as an async closure that calls the +original function with `await`: + +```swift +@globalActor actor OtherActor { ... } + +func convert( + closure: @OtherActor () -> Void +) { + let mainActorFn: @MainActor () async -> Void = closure + + // The above conversion is the same as: + + let mainActorEquivalent: @MainActor () async -> Void = { + await closure() + } +} +``` + +A function conversion that crosses an isolation boundary must only +pass argument and result values that are `Sendable`; this is checked +at the point of the function conversion. For example, converting an +actor-isolated function type to a `nonisolated` function type requires +that the argument and result types conform to `Sendable`: + +```swift +class NotSendable {} +actor MyActor { + var ns = NotSendable() + + func getState() -> NotSendable { ns } +} + +func invalidResult(a: MyActor) async -> NotSendable { + let grabActorState: @execution(caller) () async -> NotSendable = a.getState // error + + return await grabActorState() +} +``` + +In the above code, the conversion from the actor-isolated method `getState` +to a `@execution(caller) nonisolated` function is invalid, because the +result type does not conform to `Sendable` and the result value could be +actor-isolated state. The `nonisolated` function can be called from +anywhere, which would allow access to actor state from outside the actor. + +Not all function conversions cross an isolation boundary, and function +conversions that don't can safely pass non-`Sendable` arguments and results. +For example, a `@execution(caller)` function type can always be converted to an +actor-isolated function type, because the `@execution(caller)` function will +simply run on the actor: + +```swift +class NotSendable {} + +@execution(caller) +nonisolated func performAsync(_ ns: NotSendable) async { ... } + +@MainActor +func convert(ns: NotSendable) async { + // Okay because 'performAsync' will run on the main actor + let runOnMain: @MainActor (NotSendable) async -> Void = performAsync + + await runOnMain(ns) +} +``` + +The following table enumerates each function conversion rule and specifies +which function conversions cross an isolation boundary. Function conversions +that cross an isolation boundary require `Sendable` argument and result types, +and the destination function type must be `async`. Note that the function +conversion rules for synchronous `nonisolated` functions and asynchronous +`@execution(caller) nonisolated` functions are the same; they are both +represented under the "Nonisolated" category in the table: + +| Old isolation | New isolation | Crosses Boundary | +|--------------------------|----------------------------|------------------| +| Nonisolated | Actor isolated | No | +| Nonisolated | `@isolated(any)` | No | +| Nonisolated | `@execution(concurrent)` | Yes | +| Actor isolated | Actor isolated | Yes | +| Actor isolated | `@isolated(any)` | No | +| Actor isolated | Nonisolated | Yes | +| Actor isolated | `@execution(concurrent)` | Yes | +| `@isolated(any)` | Actor isolated | Yes | +| `@isolated(any)` | Nonisolated | Yes | +| `@isolated(any)` | `@execution(concurrent)` | Yes | +| `@execution(concurrent)` | Actor isolated | Yes | +| `@execution(concurrent)` | `@isolated(any)` | No | +| `@execution(concurrent)` | Nonisolated | Yes | + +#### Non-`@Sendable` function conversions + +If a function type is not `@Sendable`, only one isolation domain can +reference the function at a time, and calls to the function may never +happen concurrently. These rules for non-`Sendable` types are enforced +through region isolation. When a non-`@Sendable` function is converted +to an actor-isolated function, the function value itself is merged into the +actor's region, along with any non-`Sendable` function captures: + +```swift +class NotSendable { + var value = 0 +} + +@execution(caller) +func convert(closure: () -> Void) async { + let ns = NotSendable() + let disconnectedClosure = { + ns.value += 1 + } + let valid: @MainActor () -> Void = disconnectedClosure // okay + await valid() + + let invalid: @MainActor () -> Void = closure // error + await invalid() +} +``` + +The function conversion for the `invalid` variable is an error because the +non-`Sendable` captures of `closure` could be used concurrently from the caller +of `convert` and the main actor. + +Converting a non-`@Sendable` function type to an actor-isolated one is invalid +if the original function must leave the actor in order to be called: + +```swift +@execution(caller) +func convert( + fn1: @escaping @execution(concurrent) () async -> Void, +) async { + let fn2: @MainActor () async -> Void = fn1 // error + + await withDiscardingTaskGroup { group in + group.addTask { await fn2() } + group.addTask { await fn2() } + } +} +``` + +In general, a conversion from an actor-isolated function type to a +`nonisolated` function type crosses an isolation boundary, because the +`nonisolated` function type can be called from an arbitrary isolation domain. +However, if the conversion happens on the actor, and the new function type is +not `@Sendable`, then the function must only be called from the actor. In this +case, the function conversion is allowed, and the resulting function value +is merged into the actor's region: + +```swift +class NotSendable {} + +@MainActor class C { + var ns: NotSendable + + func getState() -> NotSendable { ns } +} + +func call(_ closure: () -> NotSendable) -> NotSendable { + return closure() +} + +@MainActor func onMain(c: C) { + // 'result' is in the main actor's region + let result = call(c.getState) +} +``` + +### Executor switching + +Async functions switch executors in the implementation when entering the +function, and after any calls to other async functions. Note that synchronous +functions do not have the ability to switch executors. If a call to a +synchronous function crosses an isolation boundary, the call must happen in an +async context and the executor switch happens at the caller. + +`@execution(concurrent)` async functions switch to the generic executor, and +all other async functions switch to the isolated actor's executor. + +```swift +@MainActor func runOnMainExecutor() async { + // switch to main actor executor + + await runOnGenericExecutor() + + // switch to main actor executor +} + +@execution(concurrent) func runOnGenericExecutor() async { + // switch to generic executor + + await Task { @MainActor in + // switch to main actor executor + + ... + }.value + + // switch to generic executor +} +``` + +`@execution(caller)` functions will switch to the executor of the implicit +actor parameter passed from the caller instead of switching to the generic +executor: + +```swift +@MainActor func runOnMainExecutor() async { + // switch to main actor executor + ... +} + +class NotSendable { + var value = 0 +} + +actor MyActor { + let ns: NotSendable = .init() + + func callNonisolatedFunction() async { + await inheritIsolation(ns) + } +} + +nonisolated func inheritIsolation(_ ns: NotSendable) async { + // switch to isolated parameter's executor + + await runOnMainExecutor() + + // switch to isolated parameter's executor + + ns.value += 1 +} +``` + +For most calls, the switch upon entering the function will have no effect, +because it's already running on the executor of the actor parameter. + +A task executor preference can still be used to configure where a nonisolated +async function runs. However, if the nonisolated async function was called from +an actor with a custom executor, the task executor preference will not apply. +Otherwise, the code will risk a data-race, because the task executor preference +does not apply to actor-isolated methods with custom executors, and the +nonisolated async method can be passed mutable state from the actor. + +### Import-as-async heuristic + +Nonisolated functions imported from Objective-C that match the import-as-async +heuristic from [SE-0297: Concurrency Interoperability with Objective-C][SE-0297] +will implicitly be imported as `@execution(caller)`. Objective-C async +functions already have bespoke code generation that continues running on +the caller's actor to match the semantics of the original completion handler +function, so `@execution(caller)` already better matches the semantics of these +imported `async` functions. This change will eliminate many existing data-race +safety issues that happen when calling an async function on an Objective-C +class from the main actor. Because the only effect of this change is +eliminating concurrency diagnostics -- the runtime behavior of the code will +not change -- it will not be gated behind the upcoming feature. + +## Source compatibility + +This proposal changes the semantics of nonisolated async functions when the +upcoming feature flag is enabled. Without the upcoming feature flag, the default +for nonisolated async functions is `@execution(concurrent)`. When the upcoming +feature flag is enabled, the default for nonisolated async functions changes to +`@execution(caller)`. This applies to both function declarations and function +values that are nonisolated (either implicitly or explicitly). + +Changing the default execution semantics of nonisolated async functions has +minor source compatibility impact if the implementation calls an +`@execution(concurrent)` function and passes non-Sendable state in the actor's +region. In addition to the source compatibility impact, the change can also +regress performance of existing code if, for example, a specific async function +relied on running off of the main actor when called from the main actor to +maintain a responsive UI. + +To avoid breaking source compatibility or silently changing behavior of +existing code, this change must be gated behind an upcoming feature flag. +However, unlike most other changes gated behind upcoming feature flags, this +change allows writing code that is valid with and without the upcoming feature +flag, but means something different. Many programmers have internalized the +SE-0338 semantics, and making this change several years after SE-0338 was +accepted creates an unfortunate intermediate state where it's difficult to +understand the semantics of a nonisolated async function without understanding +the build settings of the module you're writing code in. To mitigate these +consequences, the compiler will emit warnings in all language modes +that do not enable this upcoming feature to prompt programmers to explicitly +specify the execution semantics of a nonisolated async function. + +Without the upcoming feature enabled, the compiler will warn if neither +attribute is specified on a nonisolated async function. With the +upcoming feature enabled, the default for a nonisolated async +function is `@execution(caller)`. Packages that must support older Swift tools +versions can use `#if hasAttribute(execution)` to silence the warning while +maintaining compatibility with tools versions back to Swift 5.8 when +`hasAttribute` was introduced: + +```swift +#if hasAttribute(execution) +@execution(concurrent) +#endif +public func myAsyncAPI() async { ... } +``` + +## ABI compatibility + +Adopting the semantics to run on the caller's actor for an existing nonisolated +async function is an ABI change, because the caller's actor must be passed as +a parameter. However, a number of APIs in the concurrency library have staged +in similar changes using isolated parameters and `#isolation`, and it may be +possible to offer tools to do this transformation automatically for resilient +libraries that want to adopt this behavior. + +For example, if a nonisolated async function is ABI-public and is available +earlier than a version of the Swift runtime that includes this change, the +compiler could emit two separate entry points for the function: + +```swift +@_alwaysEmitIntoClient +public func myAsyncFunc() async { + // original implementation +} + +@execution(concurrent) +@_silgen_name(...) // to preserve the original symbol name +@usableFromInline +internal func abi_myAsyncFunc() async { + // existing compiled code will continue to always run calls to this function + // on the generic executor. + await myAsyncFunc() +} +``` + +This transformation only works if the original function implementation +can be made inlinable. + +## Implications on adoption + +`@execution(caller)` functions must accept an implicit actor parameter. This +means that adding `@execution(caller)` to a function that is actor-isolated, or +changing a function from `@execution(concurrent)` to `@execution(caller)`, is +not a resilient change. + +## Alternatives considered + +### Changing isolation inference behavior to implicitly capture isolated parameters + +The current isolation inference behavior in contexts with isolated parameters +is often surprising with respect to data-race safety. However, this proposal +does not suggest changing the rules, because implicitly capturing an isolated +parameter can lead to silently causing new memory leaks in existing code. One +potential compromise is to keep the current isolation inference behavior, and +offer fix-its to capture the actor if there are any data-race safety errors +from capturing state in the actor's region. + +### Use `nonisolated` instead of a separate `@execution(concurrent)` attribute + +It's tempting to not introduce a new attribute to control where an async +function executes, and instead control this behavior with an explicit +`nonisolated` annotation. However, this approach falls short for the following +reasons: + +1. It does not accomplish the goal of having consistent semantics for + `nonisolated` by default, regardless of whether it's applied to synchronous + or async functions. +2. This approach cuts off the future direction of allowing + `@execution(concurrent)` on synchronous functions. + +### Use "isolation" terminology instead of "execution" + +One other possibility is to use isolation terminology instead of `@execution` +for the syntax. This direction does not accomplish goal 1. in the previous +section to have a consistent meaning for `nonisolated` across synchronous and +async functions. If the attribute were spelled `@isolated(caller)` and +`@isolated(concurrent)`, presumably that attribute would not work together with +`nonisolated`; it would instead be an alternative kind of actor isolation. + +Having `@execution(caller)` as an attribute that is used together with +`nonisolated` leads to a simpler programming model because after the upcoming +feature is enabled, programmers will simply write `nonisolated` on an `async` +function in the same way that `nonisolated` is applied to synchronous +functions. If we choose a different form of isolation like `@isolated(caller)`, +programmers have to learn a separate syntax for `async` functions that +accomplishes the same effect as a `nonisolated` synchronous function. + +### Don't introduce a type attribute for `@execution` + +There are a lot of existing type attributes for concurrency and it's +unfortunate to introduce another one. However, without `@execution` as a type +attribute, referencing nonisolated async functions unapplied is very restrictive, +because sendable checking would need to be performed at the point of the +function reference instead of when the function is called. + +## Revisions + +The proposal was revised with the following changes after the pitch discussion: + +* Gate the behavior change behind an `AsyncCallerExecution` upcoming feature + flag. +* Change the spelling of `@concurrent` to `@execution(concurrent)`, and add an + `@execution(caller)` attribute to allow expressing the new behavior this + proposal introduces when the upcoming feature flag is not enabled. +* Apply `@execution(caller)` to nonisolated async function types by default to + make the execution semantics consistent between async function declarations + and values. +* Change the terminology in the proposal to not use the "inherits isolation" + phrase. + +[SE-0297]: /proposals/0297-concurrency-objc.md +[SE-0338]: /proposals/0338-clarify-execution-non-actor-async.md +[SE-0421]: /proposals/0421-generalize-async-sequence.md From e56820b8eaeb5441ad4b0a4e0132eb501729f291 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Thu, 20 Feb 2025 11:04:47 -0500 Subject: [PATCH 083/505] Add link to review thread for SE-0461 (#2701) --- proposals/0461-async-function-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index bc2004e320..cdece7a616 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -8,7 +8,7 @@ * Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` * Upcoming Feature Flag: `AsyncCallerExecution` * Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) ## Introduction From 8ae57e809cfbe17a549fff127b006bf54cbecfdd Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Thu, 20 Feb 2025 23:32:34 +0000 Subject: [PATCH 084/505] Clarify diagnostic group for a proposed warning --- proposals/NNNN-adoption-tooling-for-swift-features.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index e68f1750b3..a7b69dd356 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -127,6 +127,7 @@ for a given upcoming feature, i.e., because the upcoming feature does not have a mechanical migration. A corresponding warning will be emitted in this case to avoid the false impression that the impacted source code is compatible with the feature. +This warning will belong to the diagnostic group `StrictLanguageFeatures`. ### Interface @@ -149,8 +150,8 @@ For example: ``` If the specified mode is invalid, the flag will be ignored, and a warning will -be emitted. This warning will belong to the `StrictLanguageFeatures` diagnostic -group. +be emitted. +This warning will belong to the diagnostic group `StrictLanguageFeatures`. In a series of either of these options applied to a given feature, only the last option will be honored. If an upcoming feature is both implied by the effective language mode and From 991e4c803e87360706175529ae7b28bba11e166a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 21 Feb 2025 08:38:22 +0900 Subject: [PATCH 085/505] Task Priority Escalation APIs (#2685) * Task Priority Escalation APIs * Update proposals/NNNN-task-priority-escalation-apis.md Co-authored-by: Franz Busch * Add better example, thanks to @dnadoba * remove the section explaining triggering * Apply suggestions from code review Co-authored-by: Jamie <2119834+jamieQ@users.noreply.github.com> * mark as implemented * Apply suggestions from code review * Task priority escalation is SE-0462 --------- Co-authored-by: Franz Busch Co-authored-by: Jamie <2119834+jamieQ@users.noreply.github.com> Co-authored-by: Frederick Kellison-Linn Co-authored-by: Freddy Kellison-Linn --- .../0462-task-priority-escalation-apis.md | 237 ++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 proposals/0462-task-priority-escalation-apis.md diff --git a/proposals/0462-task-priority-escalation-apis.md b/proposals/0462-task-priority-escalation-apis.md new file mode 100644 index 0000000000..a0ba3e47f1 --- /dev/null +++ b/proposals/0462-task-priority-escalation-apis.md @@ -0,0 +1,237 @@ +# Task Priority Escalation APIs + +* Proposal: [SE-0462](0462-task-priority-escalation-apis.md) +* Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) +* Review Manager: [Freddy Kellison-Linn](https://github.com/jumhyn) +* Status: **Active review (February 20...March 2, 2025)** +* Implementation: https://github.com/swiftlang/swift/pull/78625 +* Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) + +## Introduction + +A large part of Swift Concurrency is its Structured Concurrency model, in which tasks automatically form parent-child relationships, and inherit certain traits from their parent task. For example, a task started from a medium priority task, also starts on the medium priority, and not only that – if the parent task gets awaited on from a higher priority task, the parent's as well as all of its child tasks' task priority will be escalated in order to avoid priority inversion problems. + +This feature is automatic and works transparently for any structured task hierarchy. This proposal will discuss exposing user-facing APIs which can be used to participate in task priority escalation. + +## Motivation + +Generally developers can and should rely on the automatic task priority escalation happening transparently–at least for as long as all tasks necessary to escalate are created using structured concurrency primitives (task groups and `async let`). However, sometimes it is not possible to entirely avoid creating an unstructured task. + +One such example is the async sequence [`merge`](https://github.com/apple/swift-async-algorithms/blob/4c3ea81f81f0a25d0470188459c6d4bf20cf2f97/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Merge.md) operation from the [swift-async-algorithms](https://github.com/apple/swift-async-algorithms/) project where the implementation is forced to create an unstructured task for iterating the upstream sequences, which must outlive downstream calls. These libraries would like to participate in task priority escalation to boost the priority of the upstream consuming task, however today they lack the API to do so. + +```swift +// SIMPLIFIED EXAMPLE CODE +// Complete source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/Merge/MergeStorage.swift + +struct AsyncMergeSequenceIterator: AsyncIterator { + struct State { + var task: Task? // unstructured upstream consumer task + var buffer: Deque + var upstreamContinuations: [UnsafeContinuation] + var downstreamContinuation: UnsafeContinuation? + } + + let state = Mutex(State()) + + func next() async throws { + self.state.withLock { state in + if state.task == nil { + state.task = Task { + // Consume from the base iterators + // ... + } + } + } + + if let element = self.state.withLock { $0.buffer.popFirst() } { + return element + } else { + // We are handling cancellation here and need to handle task escalation here as well + try await withTaskCancellationHandler { + // HERE: need to handle priority escalation and boost `state.task` + try await withCheckedContinuation { cont in + self.state.withLock { $0.consumerContinuation = cont } + } + } onCancel: { + // trigger cancellation of tasks and fail continuations + } + } + } +} +``` + +The above example showcases a common pattern: often a continuation is paired with a Task used to complete it. Around the suspension on the continuation, waiting for it to be resumed, developers often install a task cancellation handler in order to potentially break out of potentially unbounded waiting for a continuation to be resumed. Around the same suspension (marked with `HERE` in the snippet above), we might want to insert a task priority escalation handler in order to priority boost the task that is used to resume the continuation. This can be important for correctness and performance of such operations, so we should find a way to offer these libraries a mechanism to participate in task priority handling. + +Another example of libraries which may want to reach for manual task priority escalation APIs are libraries which facilitate communication across process boundaries, and would like to react to priority escalation and propagate it to a different process. Relying on the built-in priority escalation mechanisms won't work, because they are necessarily in-process, so libraries like this need to be able to participate and be notified when priority escalation happens, and also be able to efficiently cause the escalation inside the other process. + +## Proposed solution + +In order to address the above use-cases, we propose to add a pair of APIs: to react to priority escalation happening within a block of code, and an API to _cause_ a priority escalation without resorting to trickery by creating new tasks whose only purpose is to escalate the priority of some other task: + +```swift +enum State { + case initialized + case task(Task) + case priority(TaskPriority) +} +let m: Mutex = .init(.initialized) + +await withTaskPriorityEscalationHandler { + await withCheckedContinuation { cc in + let task = Task { cc.resume() } + + let newPriority: TaskPriority? = state.withLock { state -> TaskPriority? in + defer { state = .task(task) } + switch state { + case .initialized: + return nil + case .task: + preconditionFailure("unreachable") + case .priority(let priority): + return priority + } + } + // priority was escalated just before we stored the task in the mutex + if let newPriority { + Task.escalatePriority(task, to: newPriority) + } + } onPriorityEscalated: { newPriority in + state.withLock { state in + switch state { + case .initialized, .priority: + // priority was escalated just before we managed to store the task in the mutex + state = .priority(newPriority) + case .task(let task): + Task.escalatePriority(task, to: newPriority) + } + } + } +} +``` + +The above snippet handles edge various ordering situations, including the task escalation happening after +the time the handler is registered but _before_ we managed to create and store the task. + +In general, task escalation remains a slightly racy affair, we could always observe an escalation "too late" for it to matter, +and have any meaningful effect on the work's execution, however this API and associated patterns handle most situations which +we care about in practice. + +## Detailed design + +We propose the addition of a task priority escalation handler, similar to task cancellation handlers already present in the concurrency library: + +```swift +public func withTaskPriorityEscalationHandler( + operation: () async throws(E) -> T, + onPriorityEscalated handler: @Sendable (TaskPriority) -> Void, + isolation: isolated (any Actor)? = #isolation +) async throws(E) -> T +``` + +The shape of this API is similar to the `withTaskCancellationHandler` API present since initial Swift Concurrency release, however–unlike a cancellation handler–the `onPriorityEscalated` callback may be triggered multiple times. The `TaskPriority` passed to the handler is the "new priority" the surrounding task was escalated to. + +It is guaranteed that priority is ever only increasing, as Swift Concurrency does not allow for a task priority to ever be lowered after it has been escalated. If attempts are made to escalate the task priority from multiple other threads to the same priority, the handler will only trigger once. However if priority is escalated to a high and then even higher priority, the handler may be invoked twice. + +Task escalation handlers are inherently racy, and may sometimes miss an escalation, for example if it happened immediately before the handler was installed, like this: + +```swift +// priority: low +// priority: high! +await withTaskPriorityEscalationHandler { + await work() +} onPriorityEscalated: { newPriority in // may not be triggered if ->high escalation happened before handler was installed + // do something +} +``` + +This is inherent to the nature of priority escalation and even with this behavior, we believe handlers are a worthy addition. One could also check for the `Task.currentPriority` and match it against our expectations inside the `operation` wrapped by the `withTaskPriorityEscalationHandler` if that could be useful to then perform the operation at an already _immediately_ heightened priority. + +Escalation handlers work with any existing task kind (child, unstructured, unstructured detached), and trigger at every level of the hierarchy in an "outside in" order: + +```swift +let t = Task { + await withTaskPriorityEscalationHandler { + await withTaskGroup { group in + group.addTask { + await withTaskPriorityEscalationHandler { + try? await Task.sleep(for: .seconds(1)) + } onPriorityEscalated: { newPriority in print("inner: \(newPriority)") } + } + } + } onPriorityEscalated: { newPriority in print("outer: \(newPriority)") } +} + +// escalate t -> high +// "outer: high" +// "inner: high" +``` + +The API can also be freely composed with `withTaskCancellationHandler` or there may even be multiple task escalation handlers registered on the same task (but in different pieces of the code). + +### Manually propagating priority escalation + +While generally developers should not rely on manual task escalation handling, this API also does introduce a manual way to escalate a task's priority. Primarily this should be used in combination with a task escalation handler to _propagate_ an escalation to an _unstructured task_ which otherwise would miss reacting to the escalation. + +The `escalatePriority` API is offered as a static method on `Task` in order to slightly hide it away from using it accidentally by stumbling upon it if it were directly declared as a member method of a Task. + +```swift +extension Task { + public static func escalatePriority(of task: Task, to newPriority: TaskPriority) +} + +extension UnsafeCurrentTask { + public static func escalatePriority(of task: UnsafeCurrentTask, to newPriority: TaskPriority) +} +``` + +It is possible to escalate both a `Task` and `UnsafeCurrentTask`, however great care must be taken to not attempt to escalate an unsafe task handle if the task has already been destroyed. The `Task` accepting API is always safe. + +Currently it is not possible to escalate a specific child task (created by `async let` or a task group) because those do not return task handles. We are interested in exposing task handles to child tasks in the future, and this design could then be easily amended to gain API to support such child task handles as well. + +## Source compatibility + +This proposal is purely additive, and does not cause any source compatibility issues. + +## ABI compatibility + +This proposal is purely ABI additive. + +## Alternatives considered + +### New Continuation APIs + +We did consider if offering a new kind of continuation might be easier to work with for developers. One shape this might take is: + +```swift +struct State { + var cc = CheckedContinuation? + var task: Task? +} +let C: Mutex + +await withCheckedContinuation2 { cc in + // ... + C.withLock { $0.cc = cc } + + let t = Task { + C.withLock { + $0.cc?.resume() // maybe we'd need to add 'tryResume' + } + } + C.withLock { $0.task = t } +} onCancel: { cc in + // remember the cc can only be resumed once; we'd need to offer 'tryResume' + cc.resume(throwing: CancellationError()) +} onPriorityEscalated: { cc, newPriority in + print("new priority: \(newPriority)") + C.withLock { Task.escalatePriority($0.task, to: newPriority) } +} +``` + +While at first this looks promising, we did not really remove much of the complexity -- careful locking is still necessary, and passing the continuation into the closures only makes it more error prone than not since it has become easier to accidentally multi-resume a continuation. This also does not compose well, and would only be offered around continuations, even if not all use-cases must necessarily suspend on a continuation to benefit from the priority escalation handling. + +Overall, this seems like a tightly knit API that changes current idioms of `with...Handler ` without really saving us from the inherent complexity of these handlers being invoked concurrently, and limiting the usefulness of those handlers to just "around a continuation" which may not always be the case. + +### Acknowledgements + +We'd like to thank John McCall, David Nadoba for their input on the APIs during early reviews. From 1dc6904e6b1ea5091111a7687344afae586e82bc Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Thu, 20 Feb 2025 18:43:34 -0500 Subject: [PATCH 086/505] Add review link to SE-0462 (#2702) --- proposals/0462-task-priority-escalation-apis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0462-task-priority-escalation-apis.md b/proposals/0462-task-priority-escalation-apis.md index a0ba3e47f1..aa2a883f17 100644 --- a/proposals/0462-task-priority-escalation-apis.md +++ b/proposals/0462-task-priority-escalation-apis.md @@ -5,7 +5,7 @@ * Review Manager: [Freddy Kellison-Linn](https://github.com/jumhyn) * Status: **Active review (February 20...March 2, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/78625 -* Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) +* Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) ([review](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997)) ## Introduction From 24b8954a946eb8e93f625ac9627326fe2e35d3f4 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Sat, 22 Feb 2025 23:53:44 +0900 Subject: [PATCH 087/505] [SE-0462] Add a few missing "of:" in code examples (#2704) --- proposals/0462-task-priority-escalation-apis.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/0462-task-priority-escalation-apis.md b/proposals/0462-task-priority-escalation-apis.md index aa2a883f17..1f270b4150 100644 --- a/proposals/0462-task-priority-escalation-apis.md +++ b/proposals/0462-task-priority-escalation-apis.md @@ -93,7 +93,7 @@ await withTaskPriorityEscalationHandler { } // priority was escalated just before we stored the task in the mutex if let newPriority { - Task.escalatePriority(task, to: newPriority) + Task.escalatePriority(of: task, to: newPriority) } } onPriorityEscalated: { newPriority in state.withLock { state in @@ -102,7 +102,7 @@ await withTaskPriorityEscalationHandler { // priority was escalated just before we managed to store the task in the mutex state = .priority(newPriority) case .task(let task): - Task.escalatePriority(task, to: newPriority) + Task.escalatePriority(of: task, to: newPriority) } } } @@ -172,7 +172,7 @@ The API can also be freely composed with `withTaskCancellationHandler` or there While generally developers should not rely on manual task escalation handling, this API also does introduce a manual way to escalate a task's priority. Primarily this should be used in combination with a task escalation handler to _propagate_ an escalation to an _unstructured task_ which otherwise would miss reacting to the escalation. -The `escalatePriority` API is offered as a static method on `Task` in order to slightly hide it away from using it accidentally by stumbling upon it if it were directly declared as a member method of a Task. +The `escalatePriority(of:to:)` API is offered as a static method on `Task` in order to slightly hide it away from using it accidentally by stumbling upon it if it were directly declared as a member method of a Task. ```swift extension Task { @@ -224,7 +224,7 @@ await withCheckedContinuation2 { cc in cc.resume(throwing: CancellationError()) } onPriorityEscalated: { cc, newPriority in print("new priority: \(newPriority)") - C.withLock { Task.escalatePriority($0.task, to: newPriority) } + C.withLock { Task.escalatePriority(of: $0.task, to: newPriority) } } ``` @@ -234,4 +234,4 @@ Overall, this seems like a tightly knit API that changes current idioms of `with ### Acknowledgements -We'd like to thank John McCall, David Nadoba for their input on the APIs during early reviews. +I'd like to thank John McCall, David Nadoba for their input on the APIs during early reviews. From f9000ffb95c6f7a309ab03ee7bf937639b3924e5 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 22 Feb 2025 10:22:33 -0800 Subject: [PATCH 088/505] [SE-0461] Proposal clarifications based on early review discussion. (#2703) * [SE-0461] Proposal clarifications based on early review discussion. * [SE-0461] Fix the vision document link. --- proposals/0461-async-function-isolation.md | 51 +++++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index cdece7a616..86655481cf 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -4,7 +4,7 @@ * Authors: [Holly Borla](https://github.com/hborla), [John McCall](https://github.com/rjmccall) * Review Manager: [Xiaodi Wu](https://github.com/xwu) * Status: **Active review (February 20...March 2, 2025)** -* Vision: [[Prospective Vision] Improving the approachability of data-race safety](https://forums.swift.org/t/prospective-vision-improving-the-approachability-of-data-race-safety/76183) +* Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` * Upcoming Feature Flag: `AsyncCallerExecution` * Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) @@ -41,6 +41,8 @@ async function always switches off of an actor to run. - [Alternatives considered](#alternatives-considered) - [Changing isolation inference behavior to implicitly capture isolated parameters](#changing-isolation-inference-behavior-to-implicitly-capture-isolated-parameters) - [Use `nonisolated` instead of a separate `@execution(concurrent)` attribute](#use-nonisolated-instead-of-a-separate-executionconcurrent-attribute) + - [Use "isolation" terminology instead of "execution"](#use-isolation-terminology-instead-of-execution) + - [Deprecate `nonisolated`](#deprecate-nonisolated) - [Don't introduce a type attribute for `@execution`](#dont-introduce-a-type-attribute-for-execution) - [Revisions](#revisions) @@ -241,7 +243,7 @@ The sections below will explicitly use `@execution(concurrent)` and independent of upcoming features or language modes. However, note that the end state under the `AsyncCallerExecution` upcoming feature will mean that `@execution(caller)` is not necessary to explicitly write, and -`@execution(caller)` will likely be used sparingly because it has far +`@execution(concurrent)` will likely be used sparingly because it has far stricter data-race safety requirements. ### The `@execution` attribute @@ -259,8 +261,26 @@ in the following sections. Only (implicitly or explicitly) `nonisolated` functions can be marked with the `@execution` attribute; it is an error to use the `@execution` attribute with an isolation other than `nonisolated`, including global actors, isolated -parameters, and `@isolated(any)`. The `@execution` attribute can be used -together with `@Sendable` or `sending`. +parameters, and `@isolated(any)`: + +```swift +actor MyActor { + var value = 0 + + // error: '@execution(caller)' can only be used with 'nonisolated' methods + @execution(caller) + func isolatedToSelf() async { + value += 1 + } + + @execution(caller) + nonisolated func canRunAnywhere() async { + // cannot access 'value' or other actor-isolated state + } +} +``` + +The `@execution` attribute can be used together with `@Sendable` or `sending`. The `@execution` attribute is preserved in the type system so that the execution semantics can be distinguished for function vales. @@ -892,12 +912,15 @@ reasons: ### Use "isolation" terminology instead of "execution" -One other possibility is to use isolation terminology instead of `@execution` -for the syntax. This direction does not accomplish goal 1. in the previous +Another possibility is to use isolation terminology instead of `@execution` +for the syntax. This direction does not accomplish the goal of having a section to have a consistent meaning for `nonisolated` across synchronous and async functions. If the attribute were spelled `@isolated(caller)` and `@isolated(concurrent)`, presumably that attribute would not work together with `nonisolated`; it would instead be an alternative kind of actor isolation. +`@isolated(concurrent)` also doesn't make much sense because the concurrent +executor does not provide isolation at all - isolation is only provided by +actors and tasks. Having `@execution(caller)` as an attribute that is used together with `nonisolated` leads to a simpler programming model because after the upcoming @@ -907,6 +930,22 @@ functions. If we choose a different form of isolation like `@isolated(caller)`, programmers have to learn a separate syntax for `async` functions that accomplishes the same effect as a `nonisolated` synchronous function. +### Deprecate `nonisolated` + +Going in the oppose direction, this proposal could effectively deprecate +`nonisolated` and allow you to use `@execution(caller)` everywhere that +`nonisolated` is currently supported, including synchronous methods, stored +properties, type declarations, and extensions. This direction was not chosen +for the following reasons: + +1. This would lead to much more code churn than the current proposal. Part of + the goal of this proposal is to minimize the change to only what is absolutely + necessary to solve the major usability problem with async functions on + non-`Sendable` types, because it's painful both to transition code and to + re-learn parts of the model that have already been internalized. +2. `nonisolated` is nicer to write than `@execution(caller)`, + `@isolated(caller)`, or any other alternative attribute + argument syntax. + ### Don't introduce a type attribute for `@execution` There are a lot of existing type attributes for concurrency and it's From 07baa567d2fb40e7e95bd9aebbaac3beec19ece3 Mon Sep 17 00:00:00 2001 From: tokizuoh Date: Sun, 23 Feb 2025 15:58:56 +0900 Subject: [PATCH 089/505] Replace newlines with `
` in Mermaid flowchart --- process.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/process.md b/process.md index 241b684b78..d38eeec80e 100644 --- a/process.md +++ b/process.md @@ -162,13 +162,13 @@ flowchart LR %% %% Nodes: - 1{{"Awaiting\nreview"}} - 2{{"Scheduled\nfor review"}} - 3{"Active\nreview"} - 4["Returned\nfor revision"] + 1{{"Awaiting
review"}} + 2{{"Scheduled
for review"}} + 3{"Active
review"} + 4["Returned
for revision"] 5(["Withdrawn"]) 6(["Rejected"]) - 7_8["Accepted\n(with revisions)"] + 7_8["Accepted
(with revisions)"] 9[["Previewing"]] 10(["Implemented"]) From ed0867b58af8190b43ce24b7170e9bcb0c762cae Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Mon, 24 Feb 2025 08:36:53 -0800 Subject: [PATCH 090/505] Update 0371-isolated-synchronous-deinit.md (#2707) Per forum thread https://forums.swift.org/t/isolated-deinit-not-in-swift-6-1/78055, the deinit is in Swift 6.2, didn't make it into the cut for Swift 6.1 --- proposals/0371-isolated-synchronous-deinit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0371-isolated-synchronous-deinit.md b/proposals/0371-isolated-synchronous-deinit.md index d860b1178f..00b88aca31 100644 --- a/proposals/0371-isolated-synchronous-deinit.md +++ b/proposals/0371-isolated-synchronous-deinit.md @@ -3,7 +3,7 @@ * Proposal: [SE-0371](0371-isolated-synchronous-deinit.md) * Author: [Mykola Pokhylets](https://github.com/nickolas-pohilets) * Review Manager: [Frederick Kellison-Linn](https://github.com/jumhyn) -* Status: **Implemented (Swift 6.1)** +* Status: **Implemented (Swift 6.2)** * Implementation: [apple/swift#60057](https://github.com/apple/swift/pull/60057) * Review: ([first pitch](https://forums.swift.org/t/isolated-synchronous-deinit/58177)) ([first review](https://forums.swift.org/t/se-0371-isolated-synchronous-deinit/59754)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0371-isolated-synchronous-deinit/60060)) ([discussion](https://forums.swift.org/t/isolated-synchronous-deinit-2/62565)) ([second pitch](https://forums.swift.org/t/pitch-2-se-0371-isolated-async-deinit/64836)) ([sub-pitch](https://forums.swift.org/t/sub-pitch-task-local-values-in-isolated-synchronous-deinit-and-async-deinit/70060)) ([second review](https://forums.swift.org/t/second-review-se-0371-isolated-synchronous-deinit/73406)) ([accepted with modifications](https://forums.swift.org/t/accepted-with-modifications-se-0371-isolated-synchronous-deinit/74042)) From ea5b8fa5236cff0a990932e9d4106ee0353d880d Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 24 Feb 2025 18:44:09 -0500 Subject: [PATCH 091/505] Slight editorial fixes --- proposals/0456-stdlib-span-properties.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index aaeab8c600..178da8f82b 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -6,10 +6,9 @@ * Status: **Accepted** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: [PR #78561](https://github.com/swiftlang/swift/pull/78561) -* Review: [Pitch](https://forums.swift.org/t/76138), [Review](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233), [Acceptance](https://forums.swift.org/t/77684) +* Review: ([pitch](https://forums.swift.org/t/76138)) ([review](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233)) ([acceptance](https://forums.swift.org/t/77684)) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md - [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md [PR-2305]: https://github.com/swiftlang/swift-evolution/pull/2305 [SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md From c023f344af885734bdbe853d489647882e1ebd93 Mon Sep 17 00:00:00 2001 From: shiz <35151927+stzn@users.noreply.github.com> Date: Tue, 25 Feb 2025 08:50:48 +0900 Subject: [PATCH 092/505] Fix an invalid syntax (#2706) --- proposals/0461-async-function-isolation.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index 86655481cf..aecc52bea4 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -327,8 +327,6 @@ The type of an `@execution(caller)` function declaration is an ```swift class NotSendable { ... } -func useAsValue(_ ns: NotSendable) async { ... } - @MainActor let global: NotSendable = .init() @execution(caller) @@ -344,7 +342,7 @@ func callSendableClosure() async { await closure(global) // okay } -callSendableClosure(useAsValue) +callSendableClosure() ``` In the above code, the calls to `closure` from `callSendableClosure` run on the From f30047248257f74ac8a4aae61a6dd5c04ef3b519 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Tue, 25 Feb 2025 01:46:13 +0000 Subject: [PATCH 093/505] replace term RLP with EDSL --- ...environment-dependent-shared-libraries.md} | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) rename proposals/{NNNN-replaceable-library-plugins.md => NNNN-environment-dependent-shared-libraries.md} (63%) diff --git a/proposals/NNNN-replaceable-library-plugins.md b/proposals/NNNN-environment-dependent-shared-libraries.md similarity index 63% rename from proposals/NNNN-replaceable-library-plugins.md rename to proposals/NNNN-environment-dependent-shared-libraries.md index 35f2d9e1c3..e7a0569ab5 100644 --- a/proposals/NNNN-replaceable-library-plugins.md +++ b/proposals/NNNN-environment-dependent-shared-libraries.md @@ -1,6 +1,6 @@ -# Replaceable Library Plugins +# Environment Dependent Shared Libraries -* Proposal: [SE-NNNN](NNNN-replaceable-library-plugins.md) +* Proposal: [SE-NNNN](NNNN-environment-dependent-shared-libraries.md) * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) @@ -8,7 +8,7 @@ ## Introduction -SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Replaceable Library Plugins**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Replaceable Library Plugins through the existing `.artifactbundle` format. +SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Environment Dependent Shared Libraries**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Environment Dependent Shared Libraries through the existing `.artifactbundle` format. Swift-evolution thread: [Discussion thread](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605) @@ -29,13 +29,13 @@ While macOS has Dynamic Library support through XCFrameworks, on Linux we curren On Linux, there are a lot of obstacles to having fully general support for Dynamic Libraries. Swift is not ABI stable on Linux, and Linux itself is not a single platform but a wide range of similar platforms that provide few binary compatibility guarantees. This means it is pretty much impossible for a public Swift library to vend precompiled binaries that will Just Work for everyone, and we are not going to try to solve that problem in this proposal. -Instead, we will focus on **Replaceable Library Plugins** (RLPs). We choose this term to emphasize the distinction between our use case and fully general Dynamic Libraries. +Instead, we will focus on **Environment Dependent Shared Libraries** (EDSLs). We choose this term to emphasize the distinction between our use case and fully general Dynamic Libraries. ### Organization-Defined Platforms (ODPs) -Unlike fully general Dynamic Libraries, you would distribute Replaceable Library Plugins strictly for internal consumption within an organization, or to a small set of paying clients. +Unlike fully general Dynamic Libraries, you would distribute Environment Dependent Shared Libraries strictly for internal consumption within an organization, or to a small set of paying clients. -The organization that distributes an RLP is responsible for defining what exactly constitutes a “platform” for their purposes. An Organization-Defined Platform (ODP) is not necessarily an operating system or architecture, or even a specific distribution of an operating system. A trivial example of two ODPs might be: +The organization that distributes an EDSL is responsible for defining what exactly constitutes a “platform” for their purposes. An Organization-Defined Platform (ODP) is not necessarily an operating system or architecture, or even a specific distribution of an operating system. A trivial example of two ODPs might be: 1. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift` 2. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift-runtime` @@ -44,13 +44,13 @@ Concepts like Platform Triples are not sufficient to describe an ODP. Even thoug Organizations add and remove ODPs as needed, and trying to define a global registry of all possible ODPs is a non-goal. -To keep things simple, we identify ODPs by the URL of the Artifact Bundle that contains the RLP. +To keep things simple, we identify ODPs by the URL of the Artifact Bundle that contains the EDSL. -### Creating RLPs +### Creating EDSLs -To compile an RLP, you just need to build an ordinary SwiftPM library product with the `-enable-library-evolution` flag. This requires no modifications to SwiftPM. +To compile an EDSL, you just need to build an ordinary SwiftPM library product with the `-enable-library-evolution` flag. This requires no modifications to SwiftPM. -You would package an RLP as an `.artifactbundle` just as you would an executable, with the following differences: +You would package an EDSL as an `.artifactbundle` just as you would an executable, with the following differences: - The `info.json` must have `schemaVersion` set to `1.2` or higher. - The artifact type must be `library`, a new enum case introduced in this proposal. @@ -59,21 +59,21 @@ You would package an RLP as an `.artifactbundle` just as you would an executable Because SwiftPM is not (and cannot be) aware of a particular organization’s ODPs, this enforces the requirement that each ODP must have its own Artifact Bundle. -The organization that distributes the RLP is responsible for upholding ABI stability guarantees, including the exact Swift compiler and runtime versions needed to safely consume the RLP. +The organization that distributes the EDSL is responsible for upholding ABI stability guarantees, including the exact Swift compiler and runtime versions needed to safely consume the EDSL. -### Consuming RLPs +### Consuming EDSLs -To consume an RLP, you would add a `binaryTarget` to your `Package.swift` manifest, just as you would for an executable. Because ODPs are identified by the URL of the Artifact Bundle, there are no new fields in the `PackageDescription` API. +To consume an EDSL, you would add a `binaryTarget` to your `Package.swift` manifest, just as you would for an executable. Because ODPs are identified by the URL of the Artifact Bundle, there are no new fields in the `PackageDescription` API. -We expect that the logic for selecting the correct RLP for a given ODP would live within the `Package.swift` file, that it would be highly organization-specific, and that it would be manipulated using existing means such as environment variables. +We expect that the logic for selecting the correct EDSL for a given ODP would live within the `Package.swift` file, that it would be highly organization-specific, and that it would be manipulated using existing means such as environment variables. -### Deploying RLPs +### Deploying EDSLs -Deploying RLPs does not involve SwiftPM or Artifact Bundles at all. You would deploy an RLP by copying the latest binaries to the appropriate `@rpath` location on each machine in your fleet. The `@rpath` location is part of the ODP definition, and is not modeled by SwiftPM. +Deploying EDSLs does not involve SwiftPM or Artifact Bundles at all. You would deploy an EDSL by copying the latest binaries to the appropriate `@rpath` location on each machine in your fleet. The `@rpath` location is part of the ODP definition, and is not modeled by SwiftPM. -Some organizations might choose to forgo the `@rpath` mechanism entirely and simply install the RLPs in a system-wide location. +Some organizations might choose to forgo the `@rpath` mechanism entirely and simply install the EDSLs in a system-wide location. ## Detailed design @@ -110,7 +110,7 @@ Below is an example of an `info.json` file for an Artifact Bundle containing a s } ``` -The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. An RLP Artifact Bundle can contain multiple libraries at the top level. +The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. An EDSL Artifact Bundle can contain multiple libraries at the top level. Below is an example of the layout of an Artifact Bundle containing a single library called `MyLibrary`. Only the `info.json` must appear at the root of the Artifact Bundle; all other files can appear at whatever paths are defined in the `info.json`, as long as they are within the Artifact Bundle. @@ -122,12 +122,12 @@ Below is an example of the layout of an Artifact Bundle containing a single libr 📝 info.json ``` -A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. RLPs will be supported on macOS, although we expect this will be an exceedingly rare use case. +A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. EDSLs will be supported on macOS, although we expect this will be an exceedingly rare use case. ## Security -RLPs are not intended for public distribution, and are not subject to the same security concerns as public libraries. Organizations that distribute RLPs are responsible for ensuring that the RLPs are safe to consume. +EDSLs are not intended for public distribution, and are not subject to the same security concerns as public libraries. Organizations that distribute EDSLs are responsible for ensuring that the EDSLs are safe to consume. ## Impact on existing packages @@ -143,11 +143,11 @@ SwiftPM currently uses Platform Triples to select among artifact variants when c We could extend Platform Triples to model ODPs, but this would privilege a narrow set of predefined deployment architectures, and if you wanted to add a new ODP, you would have to modify SwiftPM to teach it to recognize the new ODP. -### Supporting multiple variants of an RLP in the same Artifact Bundle +### Supporting multiple variants of an EDSL in the same Artifact Bundle -We could allow an Artifact Bundle to contain multiple variants of an RLP, but we would still need to support a way to identify those variants, which in practice makes SwiftPM aware of ODPs. +We could allow an Artifact Bundle to contain multiple variants of an EDSL, but we would still need to support a way to identify those variants, which in practice makes SwiftPM aware of ODPs. -We also don’t see much value in this feature, as you would probably package and upload RLPs using one CI/CD workflow per ODP anyway. Combining artifacts would require some kind of synchronization mechanism to await all pipelines before fetching and merging bundles. +We also don’t see much value in this feature, as you would probably package and upload EDSLs using one CI/CD workflow per ODP anyway. Combining artifacts would require some kind of synchronization mechanism to await all pipelines before fetching and merging bundles. One benefit of merging bundles would be that it reduces the number of checksums you need to keep track of, but we expect that most organizations will have a very small number of ODPs, with new ODPs continously phasing out old ODPs. From 09b508acf14bf56f0e3a35f170bf1a320b6afdc5 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 25 Feb 2025 10:37:39 -0700 Subject: [PATCH 094/505] Update UTF8Span --- .../nnnn-utf8span-safe-utf8-processing.md | 347 ++++++++---------- 1 file changed, 148 insertions(+), 199 deletions(-) diff --git a/proposals/nnnn-utf8span-safe-utf8-processing.md b/proposals/nnnn-utf8span-safe-utf8-processing.md index e7984007cb..30a7816eac 100644 --- a/proposals/nnnn-utf8span-safe-utf8-processing.md +++ b/proposals/nnnn-utf8span-safe-utf8-processing.md @@ -1,5 +1,3 @@ - - # UTF8Span: Safe UTF-8 Processing Over Contiguous Bytes * Proposal: [SE-NNNN](nnnn-utf8-span.md) @@ -24,7 +22,7 @@ Currently, if a developer wants to do `String`-like processing over UTF-8 bytes, For example, if these bytes were part of a data structure, the developer would need to decide to either cache such a new `String` instance or recreate it on the fly. Caching more than doubles the size and adds caching complexity. Recreating it on the fly adds a linear time factor and class instance allocation/deallocation and potentially reference counting. -Furthermore, `String` may not be fully available on tightly constrained platforms, especially those that cannot support allocations. Both `String` and `UTF8Span` have some API that require Unicode data tables and that might not be available on embedded (String via its conformance to `Comparable` and `Collection` depend on these data tables while `UTF8Span` has a couple of methods that will be unavailable). +Furthermore, `String` may not be available on tightly constrained platforms, such as those that cannot support allocations. Both `String` and `UTF8Span` have some API that require Unicode data tables and that might not be available on embedded (String via its conformance to `Comparable` and `Collection` depend on these data tables while `UTF8Span` has a couple of methods that will be unavailable). ### UTF-8 validity and efficiency @@ -46,17 +44,17 @@ We propose a non-escapable `UTF8Span` which exposes `String` functionality for v ```swift @frozen public struct UTF8Span: Copyable, ~Escapable { - **TODO**: This might end up being UnsafeRawPointer? like in Span - public var unsafeBaseAddress: UnsafeRawPointer + @usableFromInline + internal var _unsafeBaseAddress: UnsafeRawPointer? /* A bit-packed count and flags (such as isASCII) - ╔═══════╦═════╦═════╦══════════╦═══════╗ - ║ b63 ║ b62 ║ b61 ║ b60:56 ║ b56:0 ║ - ╠═══════╬═════╬═════╬══════════╬═══════╣ - ║ ASCII ║ NFC ║ SSC ║ reserved ║ count ║ - ╚═══════╩═════╩═════╩══════════╩═══════╝ + ╔═══════╦═════╦══════════╦═══════╗ + ║ b63 ║ b62 ║ b61:56 ║ b56:0 ║ + ╠═══════╬═════╬══════════╬═══════╣ + ║ ASCII ║ NFC ║ reserved ║ count ║ + ╚═══════╩═════╩══════════╩═══════╝ ASCII means the contents are all-ASCII (<0x7F). NFC means contents are in normal form C for fast comparisons. @@ -69,21 +67,6 @@ public struct UTF8Span: Copyable, ~Escapable { ``` - - ### UTF-8 validation We propose new API for identifying where and what kind of encoding errors are present in UTF-8 content. @@ -191,13 +174,11 @@ extension Unicode.UTF8 { /// The range of offsets into our input containing the error public var range: Range - @_alwaysEmitIntoClient public init( _ kind: Unicode.UTF8.EncodingError.Kind, _ range: some RangeExpression ) - @_alwaysEmitIntoClient public init(_ kind: Unicode.UTF8.EncodingError.Kind, at: Int) } } @@ -208,59 +189,35 @@ extension UTF8.EncodingError { public struct Kind: Error, Sendable, Hashable, Codable, RawRepresentable { public var rawValue: UInt8 - @inlinable public init(rawValue: UInt8) /// A continuation byte (`10xxxxxx`) outside of a multi-byte sequence - @_alwaysEmitIntoClient public static var unexpectedContinuationByte: Self /// A byte in a surrogate code point (`U+D800..U+DFFF`) sequence - @_alwaysEmitIntoClient public static var surrogateCodePointByte: Self /// A byte in an invalid, non-surrogate code point (`>U+10FFFF`) sequence - @_alwaysEmitIntoClient public static var invalidNonSurrogateCodePointByte: Self /// A byte in an overlong encoding sequence - @_alwaysEmitIntoClient public static var overlongEncodingByte: Self /// A multi-byte sequence that is the start of a valid multi-byte scalar /// but is cut off before ending correctly - @_alwaysEmitIntoClient public static var truncatedScalar: Self } } -@_unavailableInEmbedded extension UTF8.EncodingError.Kind: CustomStringConvertible { public var description: String { get } } -@_unavailableInEmbedded extension UTF8.EncodingError: CustomStringConvertible { public var description: String { get } } ``` -**QUESTION**: It would be good to expose this functionality via a general purpose validation API. Question is do we want a `findFirstError` or `findAllErrors` style API, both? E.g.: - -```swift -extension UTF8 { - public static func checkForError( - _ s: some Sequence - ) -> some UTF8.EncodingError { - - ... or - - public static func checkForAllErrors( - _ s: some Sequence - ) -> some Sequence { -``` - - ### Creation and validation `UTF8Span` is validated at initialization time and encoding errors are diagnosed and thrown. @@ -269,37 +226,34 @@ extension UTF8 { ```swift extension UTF8Span { - @lifetime(codeUnits) - public init( - _validating codeUnits: consuming Span - ) throws(UTF8.EncodingError) { - - @lifetime(borrow start) - internal init( - _unsafeAssumingValidUTF8 start: borrowing UnsafeRawPointer, - _countAndFlags: UInt64 - ) + /// Creates a UTF8Span containing `codeUnits`. Validates that the input is + /// valid UTF-8, otherwise throws an error. + /// + /// The resulting UTF8Span has the same lifetime constraints as `codeUnits`. + public init(validating codeUnits: Span) throws(UTF8.EncodingError) } ``` -**NOTE**: The final status of underscores, annotations, etc., are pending things like [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17) and [Lifetime Dependencies](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865/140). - - ### Scalar processing -We propose a `UTF8Span.ScalarIterator` type that can do scalar processing forwards and backwards. Note that `ScalarIterator` itself is non-escapable, and thus cannot conform to `IteratorProtocol`, etc. +We propose a `UTF8Span.UnicodeScalarIterator` type that can do scalar processing forwards and backwards. Note that `UnicodeScalarIterator` itself is non-escapable, and thus cannot conform to `IteratorProtocol`, etc. ```swift extension UTF8Span { - public func _makeScalarIterator() -> ScalarIterator + /// Returns an iterator that will decode the code units into + /// `Unicode.Scalar`s. + /// + /// The resulting iterator has the same lifetime constraints as `self`. + public func makeUnicodeScalarIterator() -> UnicodeScalarIterator - /// Iterate the `Unicode.Scalar`s contents of a `UTF8Span`. - public struct ScalarIterator: ~Escapable { - public var codeUnits: UTF8Span + /// Iterate the `Unicode.Scalar`s contents of a `UTF8Span`. + @frozen + public struct UnicodeScalarIterator: ~Escapable { + public let codeUnits: UTF8Span /// The byte offset of the start of the next scalar. This is /// always scalar-aligned. - public var currentCodeUnitOffset: Int { get } + public var currentCodeUnitOffset: Int { get private(set) } public init(_ codeUnits: UTF8Span) @@ -348,17 +302,13 @@ extension UTF8Span { public mutating func skipBack(by n: Int) -> Bool /// Reset to the nearest scalar-aligned code unit offset `<= i`. - /// - /// **TODO**: Example public mutating func reset(roundingBackwardsFrom i: Int) /// Reset to the nearest scalar-aligned code unit offset `>= i`. - /// - /// **TODO**: Example public mutating func reset(roundingForwardsFrom i: Int) /// Reset this iterator to code unit offset `i`, skipping _all_ safety - /// checks. + /// checks (including bounds checks). /// /// Note: This is only for very specific, low-level use cases. If /// `codeUnitOffset` is not properly scalar-aligned, this function can @@ -371,18 +321,20 @@ extension UTF8Span { /// Returns the UTF8Span containing all the content up to the iterator's /// current position. - public func _prefix() -> UTF8Span + /// + /// The resultant `UTF8Span` has the same lifetime constraints as `self`. + public func prefix() -> UTF8Span /// Returns the UTF8Span containing all the content after the iterator's /// current position. - public func _suffix() -> UTF8Span + /// + /// The resultant `UTF8Span` has the same lifetime constraints as `self`. + public func suffix() -> UTF8Span } } ``` -**QUESTION**: Is it worth also surfacing as `isScalarAligned` API on `UTF8Span` so it's a little easier to find and spell (as well as talk about in doc comments)? - ### Character processing @@ -392,39 +344,22 @@ The `CharacterIterator` assumes that the start and end of the `UTF8Span` is the Any scalar-aligned position is a valid place to start or reset the grapheme-breaking algorithm to, though you could get different `Character` output if if resetting to a position that isn't `Character`-aligned relative to the start of the `UTF8Span` (e.g. in the middle of a series of regional indicators). - - ```swift -@_unavailableInEmbedded + extension UTF8Span { - public func _makeCharacterIterator() -> CharacterIterator + /// Returns an iterator that will construct `Character`s from the underlying + /// UTF-8 content. + /// + /// The resulting iterator has the same lifetime constraints as `self`. + public func makeCharacterIterator() -> CharacterIterator /// Iterate the `Character` contents of a `UTF8Span`. public struct CharacterIterator: ~Escapable { - public var codeUnits: UTF8Span + public let codeUnits: UTF8Span /// The byte offset of the start of the next `Character`. This is /// always scalar-aligned and `Character`-aligned. - public var currentCodeUnitOffset: Int { get } + public var currentCodeUnitOffset: Int { get private(set) } public init(_ span: UTF8Span) @@ -449,28 +384,28 @@ extension UTF8Span { /// /// Returns the number of `Character`s skipped over, which can be 0 /// if at the end of the UTF8Span. - public mutating func skipForward() + public mutating func skipForward() -> Int /// Advance `codeUnitOffset` to the end of `n` `Characters`, without /// constructing them. /// /// Returns the number of `Character`s skipped over, which can be /// fewer than `n` if at the end of the UTF8Span. - public mutating func skipForward(by n: Int) + public mutating func skipForward(by n: Int) -> Int /// Move `codeUnitOffset` to the start of the previous `Character`, /// without constructing it. /// /// Returns the number of `Character`s skipped over, which can be 0 /// if at the start of the UTF8Span. - public mutating func skipBack() + public mutating func skipBack() -> Int /// Move `codeUnitOffset` to the start of the previous `n` `Character`s, /// without constructing them. /// /// Returns the number of `Character`s skipped over, which can be /// fewer than `n` if at the start of the UTF8Span. - public mutating func skipBack(by n: Int) + public mutating func skipBack(by n: Int) -> Int /// Reset to the nearest character-aligned position `<= i`. public mutating func reset(roundingBackwardsFrom i: Int) @@ -479,7 +414,7 @@ extension UTF8Span { public mutating func reset(roundingForwardsFrom i: Int) /// Reset this iterator to code unit offset `i`, skipping _all_ safety - /// checks. + /// checks (including bounds checks). /// /// Note: This is only for very specific, low-level use cases. If /// `codeUnitOffset` is not properly scalar-aligned, this function can @@ -495,13 +430,16 @@ extension UTF8Span { /// Returns the UTF8Span containing all the content up to the iterator's /// current position. + /// + /// The resultant `UTF8Span` has the same lifetime constraints as `self`. public func prefix() -> UTF8Span /// Returns the UTF8Span containing all the content after the iterator's /// current position. + /// + /// The resultant `UTF8Span` has the same lifetime constraints as `self`. public func suffix() -> UTF8Span } - } ``` @@ -512,23 +450,18 @@ The content of a `UTF8Span` can be compared in a number of ways, including liter ```swift extension UTF8Span { /// Whether this span has the same bytes as `other`. - @_alwaysEmitIntoClient public func bytesEqual(to other: UTF8Span) -> Bool /// Whether this span has the same bytes as `other`. - @_alwaysEmitIntoClient public func bytesEqual(to other: some Sequence) -> Bool /// Whether this span has the same `Unicode.Scalar`s as `other`. - @_alwaysEmitIntoClient public func scalarsEqual( to other: some Sequence ) -> Bool /// Whether this span has the same `Character`s as `other`, using /// `Character.==` (i.e. Unicode canonical equivalence). - @_unavailableInEmbedded - @_alwaysEmitIntoClient public func charactersEqual( to other: some Sequence ) -> Bool @@ -551,14 +484,12 @@ extension UTF8Span { extension UTF8Span { /// Whether `self` is equivalent to `other` under Unicode Canonical /// Equivalence. - @_unavailableInEmbedded public func isCanonicallyEquivalent( to other: UTF8Span ) -> Bool /// Whether `self` orders less than `other` under Unicode Canonical /// Equivalence using normalized code-unit order (in NFC). - @_unavailableInEmbedded public func isCanonicallyLessThan( _ other: UTF8Span ) -> Bool @@ -575,15 +506,27 @@ Slicing a `UTF8Span` is nuanced and depends on the caller's desired use. They ca ```swift extension UTF8Span { - /// Returns whether the validated contents were all-ASCII. This is checked at - /// initialization time and remembered. - @inlinable - public var isASCII: Bool { get } + /// Returns whether contents are known to be all-ASCII. A return value of + /// `true` means that all code units are ASCII. A return value of `false` + /// means there _may_ be non-ASCII content. + /// + /// ASCII-ness is checked and remembered during UTF-8 validation, so this + /// is often equivalent to is-ASCII, but there are some situations where + /// we might return `false` even when the content happens to be all-ASCII. + /// + /// For example, a UTF-8 span generated from a `String` that at some point + /// contained non-ASCII content would report false for `isKnownASCII`, even + /// if that String had subsequent mutation operations that removed any + /// non-ASCII content. + public var isKnownASCII: Bool { get } + + /// Do a scan checking for whether the contents are all-ASCII. + /// + /// Updates the `isKnownASCII` bit if contents are all-ASCII. + public mutating func checkForASCII() -> Bool /// Returns whether the contents are known to be NFC. This is not /// always checked at initialization time and is set by `checkForNFC`. - @inlinable - @_unavailableInEmbedded public var isKnownNFC: Bool { get } /// Do a scan checking for whether the contents are in Normal Form C. @@ -595,41 +538,24 @@ extension UTF8Span { /// algorithm. However, it cannot detect all NFC contents. /// /// Updates the `isKnownNFC` bit. - @_unavailableInEmbedded public mutating func checkForNFC( quickCheck: Bool ) -> Bool - - /// Returns whether every `Character` (i.e. grapheme cluster) - /// is known to be comprised of a single `Unicode.Scalar`. - /// - /// This is not always checked at initialization time. It is set by - /// `checkForSingleScalarCharacters`. - @_unavailableInEmbedded - @inlinable - public var isKnownSingleScalarCharacters: Bool { get } - - /// Do a scan, checking whether every `Character` (i.e. grapheme cluster) - /// is comprised of only a single `Unicode.Scalar`. When a span contains - /// only single-scalar characters, character operations are much faster. - /// - /// `quickCheck` will check for a subset of single-scalar character contents - /// using a faster algorithm than the full grapheme breaking algorithm. - /// However, it cannot detect all single-scalar `Character` contents. - /// - /// Updates the `isKnownSingleScalarCharacters` bit. - @_unavailableInEmbedded - public mutating func checkForSingleScalarCharacters( - quickCheck: Bool - ) -> Bool } ``` -**QUESTION**: There is an even quicker quick-check for NFC (checking if all scalars are `<0x300`, which covers extended latin characters). Should we expose that level as well? - ### `UTF8Span` from `String` -We will add `utf8Span`-style properties to `String` and `Substring`, in line with however [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17) turns out. +We propose adding `utf8Span` properties to `String` and `Substring`, in line with [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17): + +```swift +extension String { + public var utf8Span: UTF8Span { borrowing get } +} +extension Substring { + public var utf8Span: UTF8Span { borrowing get } +} +``` ### `Span`-like functionality @@ -638,37 +564,12 @@ A `UTF8Span` is similar to a `Span`, but with the valid-UTF8 invariant an ``` extension UTF8Span { - @_alwaysEmitIntoClient public var isEmpty: Bool { get } - @_alwaysEmitIntoClient - public var storage: Span { get } - - /// Calls a closure with a pointer to the viewed contiguous storage. - /// - /// The buffer pointer passed as an argument to `body` is valid only - /// during the execution of `withUnsafeBufferPointer(_:)`. - /// Do not store or return the pointer for later use. - /// - /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter - /// that points to the viewed contiguous storage. If `body` has - /// a return value, that value is also used as the return value - /// for the `withUnsafeBufferPointer(_:)` method. The closure's - /// parameter is valid only for the duration of its execution. - /// - Returns: The return value of the `body` closure parameter. - @_alwaysEmitIntoClient - borrowing public func withUnsafeBufferPointer< - E: Error, Result: ~Copyable & ~Escapable - >( - _ body: (_ buffer: borrowing UnsafeBufferPointer) throws(E) -> Result - ) throws(E) -> dependsOn(self) Result + public var span: Span { get } } ``` -### Getting a `String` from a `UTF8Span` - -**QUESTION**: We should make it easier than `String(decoding:as)` to make a `String` copy of the `UTF8Span`, especially since `UTF8Span` cannot conform to `Sequence` or `Collection`. This will form an ARC-managed copy and not something that will share the (ephemeral) storage. - ## Source compatibility This proposal is additive and source-compatible with existing code. @@ -743,19 +644,28 @@ extension UTF8Span { ``` -### More alignments + +### More alignments and alignment queries Future API could include word iterators (either [simple](https://www.unicode.org/reports/tr18/#Simple_Word_Boundaries) or [default](https://www.unicode.org/reports/tr18/#Default_Word_Boundaries)), line iterators, etc. +Similarly, we could add API directly to `UTF8Span` for testing whether a given code unit offset is suitably aligned (including scalar or grapheme-cluster alignment checks). + +### Creating `String` copies + +We could add an initializer to `String` that makes an owned copy of a `UTF8Span`'s contents. Such an initializer can skip UTF-8 validation. + +Alternatively, we could defer adding anything until more of the `Container` protocol story is clear. + ### Normalization Future API could include checks for whether the content is in a particular normal form (not just NFC). ### UnicodeScalarView and CharacterView -Like `Span`, we are deferring adding any collection-like types to non-escapable `UTF8Span`. Future work could include adding view types that conform to a new `Container`-like protocol. +Like `Span`, we are deferring adding any collection-like types to non-escapable `UTF8Span`. Future work could include adding view types that conform to a new `Container`-like protocol. -For an example implementation of those see [the `UTFSpanViews.swift` test file](https://github.com/apple/swift-collections/pull/394). +See "Alternatives Considered" below for more rationale on not adding `Collection`-like API in this proposal. ### More algorithms @@ -765,16 +675,24 @@ However, we can add select high-value algorithms if motivated by the community. ### More validation API -Future work includes returning all the encoding errors found in a given input. +Future API could include a way to find and classify UTF-8 encoding errors in arbitrary byte sequences, beyond just `Span`. + +We could propose something like: ```swift extension UTF8 { - public static func checkAllErrors( + public static func findFirstError( + _ s: some Sequence + ) -> UTF8.EncodingError? + + public static func findAllErrors( _ s: some Sequence - ) -> some Sequence + ) -> some Sequence? ``` -See [`_checkAllErrors` in `UTF8EncodingError.swift`](https://github.com/apple/swift-collections/pull/394). +We are leaving this as future work. It also might be better formulated in line with a segemented-storage `Container`-like protocol instead of `some Sequence`. + +For now, developers can validate UTF-8 and diagnose the location and type of error using `UTF8Span`'s validating initializer, which takes a `Span`. This is similar to how developers do UTF-8 validation [in Rust](https://doc.rust-lang.org/std/str/fn.from_utf8.html). ### Transcoded iterators, normalized iterators, case-folded iterators, etc @@ -786,16 +704,6 @@ Future API additions would be to support `Regex`es on `UTF8Span`. We'd expose gr Another future direction could be to add many routines corresponding to the underlying operations performed by the regex engine, which would be useful for parser-combinator libraries who wish to expose `String`'s model of Unicode by using the stdlib's accelerated implementation. - -### Canonical Spaceships - -Should a `ComparisonResult` (or [spaceship](https://forums.swift.org/t/pitch-comparison-reform/5662)) be added to Swift, we could support that operation under canonical equivalence in a single pass rather than subsequent calls to `isCanonicallyEquivalent(to:)` and `isCanonicallyLessThan(_:)`. - - -### Exposing `String`'s storage class - -String's internal storage class is null-terminated valid UTF-8 (by substituting replacement characters) and implements range-replaceable operations along scalar boundaries. We could consider exposing the storage class itself, which might be useful for embedded platforms that don't have `String`. - ### Track other bits Future work include tracking whether the contents are NULL-terminated (useful for C bridging), whether the contents contain any newlines or only a single newline at the end (useful for accelerating Regex `.`), etc. @@ -827,7 +735,7 @@ An [earlier pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe A previous version of this pitch had code unit offset taking API directly on UTF8Span instead of using iterators as proposed. This lead to a large number of unweildy API. For example, instead of: ```swift -extension UTF8Span.ScalarIterator { +extension UTF8Span.UnicodeScalarIterator { public mutating func next() -> Unicode.Scalar? { } } ``` @@ -840,7 +748,6 @@ extension UTF8Span { /// the next scalar. /// /// `i` must be scalar-aligned. - @_alwaysEmitIntoClient public func decodeNextScalar( _ i: Int ) -> (Unicode.Scalar, nextScalarStart: Int) @@ -852,7 +759,6 @@ extension UTF8Span { /// /// This function does not validate that `i` is within the span's bounds; /// this is an unsafe operation. - @_alwaysEmitIntoClient public func decodeNextScalar( unchecked i: Int ) -> (Unicode.Scalar, nextScalarStart: Int) @@ -868,7 +774,6 @@ extension UTF8Span { /// /// This function does not validate that `i` is scalar-aligned; this is an /// unsafe operation if `i` isn't. - @_alwaysEmitIntoClient public func decodeNextScalar( uncheckedAssumingAligned i: Int ) -> (Unicode.Scalar, nextScalarStart: Int) @@ -881,20 +786,64 @@ This API made the caller manage the scalar-alignment invariant, while the iterat Scalar-alignment can still be checked and managed by the caller through the `reset` API, which safely round forwards or backwards as needed. And, for high performance use cases where the caller knows that a given position is appropriately aligned already (for example, revisiting a prior point in a string during `Regex` processing), there's the `reset(uncheckedAssumingAlignedTo:)` API available. -### Collections +#### View Collections + +Another forumulation of these operations could be to provide a collection-like API phrased in terms of indices. Because `Collection`s are `Escapable`, we cannot conform nested `View` types to `Collection` so these would not benefit from any `Collection`-generic code, algorithms, etc. + +A benefit of such `Collection`-like views is that it could help serve as adapter code for migration. Existing `Collection`-generic algorithms and methods could be converted to support `UTF8Span` via copy-paste-edit. That is, a developer could interact with `UTF8Span` ala: + +```swift +// view: UTF8Span.UnicodeScalarView +var curIdx = view.startIndex +while curIdx < view.endIndex { + let scalar = view[curIdx] + foo(scalar) + view.formIndex(after: &curIndex) +} +``` + +in addition to the iterator approach of: + +```swift +// iter: UTF8Span.UnicodeScalarIterator (or UTF8Span.UnicodeScalarView.Iterator) +while let scalar = iter.next() { + foo(scalar) +} +``` + +However, the iterator-based approach is the more efficient and direct way to work with a `UTF8Span`. Even if we had `Collection`-like API, we'd still implement a custom iterator type and advocate its use as the best way to interact with `UTF8Span`. The question is whether or not, for a given `FooIterator` we should additionally provide a `FooView`, `FooView.Index`, `FooView.SubSequence`, (possibly) `FooView.Slice`, etc. + +Idiomatic `Collection`-style interfaces support index interchange, even if "support" means reliably crashing after a dynamic check. Any idiomatic index-based interface would need to dynamically check for correct alignment in case the received index was derived from a different span. (There is a whole design space around smart indices and their tradeoffs, discussed in a [lengthy appendix](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#appendix-index-and-slicing-design-considerations) in the Span proposal). -Because `Collection`s are `Escapable`, we cannot conform nested `View` types to `Collection`. +This means that `UTF8Span.UnicodeScalarView.subscript` would have to check for scalar alignment of its given index, as it does not know whether it originally produced the passed index or not. Similarly, `index(after:)`, `index(before:)`, `index(_:offsetBy:)`, etc., would make these checks on every call. +If we want to give the developer access to efficient formulations of index-style interfaces, we'd additionally propose `uncheckedAssumingAligned:` variants of nearly every method: `subscript(uncheckedAssumingAligned i:)`, `index(uncheckedAssumingAlignedAfter:)`, `index(uncheckedAssumingAlignedBefore:)`, `index(uncheckedAssumingAligned:offsetBy:)`, etc.. This also undermines the value of having an adapter to existing code patterns. + +If we do provide view adapter code, the API could look a little different in that `UnicodeScalarIterator` is called `UnicodeScalarView.Iterator`, `prefix/suffix` are slicing, and the `reset()` functionality is expressed by slicing the view before creating an iterator. However, this would also have the effect of scattering the efficient API use pattern across multiple types, intermingled with inefficient or ill-advised adaptor interfaces which have the more idiomatic names. + +Finally, in the future there will likely be some kind of `Container` protocol for types that can vend segments of contiguous storage. In our case, the segment type is `UTF8Span`, while the element is decoded from the underlying UTF-8. It's likely easier and more straightforward to retrofit or deprecate a single `UnicodeScalarIterator` type than a collection of types interrelated to each other. ## Acknowledgments Karoy Lorentey, Karl, Geordie_J, and fclout, contributed to this proposal with their clarifying questions and discussions. + From 2f08c1dde9f802378d2d5d3e36018541e7934e05 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 25 Feb 2025 19:44:06 -0500 Subject: [PATCH 095/505] Accept SE-0458 --- proposals/0458-strict-memory-safety.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index a56d0f2ce5..c3bb3fdaa1 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -3,12 +3,12 @@ * Proposal: [SE-0458](0458-strict-memory-safety.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active Review (January 17th...February 11th, 2025)** +* Status: **Accepted** * Feature name: `StrictMemorySafety` -* Vision: [Opt-in Strict Memory Safety Checking (Prospective)](https://github.com/swiftlang/swift-evolution/pull/2581) +* Vision: [Optional Strict Memory Safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/memory-safety.md) * Implementation: On main with experimental feature flags `AllowUnsafeAttribute` and `WarnUnsafe` -* Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/f2cab4ddc3381d1dc7a970e813ed29e27b5ae43f/proposals/0458-strict-memory-safety.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) ([mid-review revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/33)) +* Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/f2cab4ddc3381d1dc7a970e813ed29e27b5ae43f/proposals/0458-strict-memory-safety.md) [2](https://github.com/swiftlang/swift-evolution/blob/9d180aea291c6b430bcc816ce12ef0174ec0237b/proposals/0458-strict-memory-safety.md) +* Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) ([first revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/33)) ([second revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/51)) ([acceptance](https://forums.swift.org/t/accepted-se-0458-opt-in-strict-memory-safety-checking/78116)) ## Introduction From fac1b44c903e4dbf434ffc60e8004aa07837abfe Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 15 Feb 2025 14:08:29 -0800 Subject: [PATCH 096/505] Add a proposal for importing Objective-C completion handler parameters as `@Sendable`. --- .../NNNN-sendable-completion-handlers.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 proposals/NNNN-sendable-completion-handlers.md diff --git a/proposals/NNNN-sendable-completion-handlers.md b/proposals/NNNN-sendable-completion-handlers.md new file mode 100644 index 0000000000..17d45006f1 --- /dev/null +++ b/proposals/NNNN-sendable-completion-handlers.md @@ -0,0 +1,77 @@ +# Import Objective-C completion handler parameters as `@Sendable` + +* Proposal: [SE-NNNN](NNNN-sendable-completion-handlers.md) +* Authors: [Holly Borla](https://github.com/hborla) +* Review Manager: TBD +* Status: **Awaiting review** +* Vision: [[Prospective Vision] Improving the approachability of data-race safety](https://forums.swift.org/t/prospective-vision-improving-the-approachability-of-data-race-safety/76183) +* Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` +* Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) + +## Introduction + +This proposal changes the Objective-C importing rules such that completion handler parameters are `@Sendable` by default. + +## Motivation + +Swift's data-race safety model requires function declarations to codify their concurrency invariants in the function signature with annotations. The `@Sendable` annotation indicates that closure parameters are passed over an isolation boundary before they're called. A missing `@Sendable` annotation in a library has negative effects on clients who call the function; the caller can unknowingly introduce data races, and [SE-0423: Dynamic actor isolation enforcement from non-strict-concurrency contexts][SE-0423] injects runtime assertions for non-`Sendable` closure parameters that are passed into libraries that don't have data-race safety checking. This means that a missing `@Sendable` annotation can lead to a runtime crash for any code that calls the API from an actor isolated context, which is extremely painful for projects that are migrating to the Swift 6 language mode. + +There's a large category of APIs with closure parameters that can be automatically identified as `@Sendable` functions, even if the annotation is missing: Objective-C methods with completion handler parameters. `@Sendable` is nearly always the right default for Objective-C completion handlers, and [programmers have already been searching for an automatic way for completion handlers to be `@Sendable` by default when auditing Clang headers](https://forums.swift.org/t/clang-sendability-audit-for-closures/75557). + +## Proposed solution + +I propose automatically importing completion handler parameters from Objective-C methods as `@Sendable` functions. + +## Detailed design + +If an imported method has an async variant (as described in [SE-0297: Concurrency Interoperability with Objective-C][SE-0297]) and the method is (implicitly or explicitly) `nonisolated`, the original method will be imported with a `@Sendable` annotation on its completion handler parameter. + +For example, given the following Objective-C method signature: + +```objc +- (void)performOperation:(NSString * _Nonnull)operation + completionHandler:(void (^ _Nullable)(NSString * _Nullable, NSError * _Nullable))completionHandler; +``` + +Swift will import the method with `@Sendable` on the `completionHandler` parameter: + +```swift +@preconcurrency +func perform( + operation: String, + completionHandler: @Sendable @escaping ((String?, Error?) -> Void)? +) +``` + +When calling the `perform` method from a Swift actor, the inference rules that allow non-`Sendable` closures to be isolated to the context they're formed in will no longer apply. The closure will be inferred as `nonisolated`, and warnings will be produced if any mutable state in the actor's region is accessed from the closure. Note that all APIs imported from C/C++/Objective-C are automatically `@preconcurrency`, so data-race safety violations are only ever warnings, even in the Swift 6 language mode. + +### Completion handlers of global actor isolated functions + +Functions that are isolated to a global actor will not have completion handlers imported as `@Sendable`. Main actor isolated functions with completion handlers that are always called on the main actor is a very common Objective-C pattern, and this carve out will eliminate false positive warnings in the cases where the main actor annotation is missing on the completion handler parameter. This carve out will not add any new dynamic assertions. + +### Opting out of `@Sendable` completion handlers + +If a completion handler does not cross an isolation boundary before it's called, the parameter can be annotated in the header with the `@nonSendable` attribute using `__attribute__((swift_attr(“@nonSendable”)))`. The `@nonSendable` attribute is only for Clang header annotations; it is not meant to be used from Swift code. + +## Source compatibility + +This change has no effect in language modes prior to Swift 6 when using minimal concurrency checking, and it only introduces warnings when using complete concurrency checking, even in the Swift 6 language mode. Declarations imported from C/C++/Objective-C are implicitly `@preconcurrency`, which makes all data-race safety violations warnings. + +## ABI compatibility + +This proposal has no impact on existing ABI. + +## Alternatives considered + +### Import completion handlers as `sending` instead of `@Sendable` + +The choice to import completion handlers as `@Sendable` instead of `sending` is pragmatic - the experimental `SendableCompletionHandlers` implementation has existed since 2021 and has been extensively tested for source compatibility. Similarly, `@Sendable` has been explicitly adopted in Objective-C frameworks for several years, and source compatibility issues resulting from corner cases in the compiler implementation that were intolerable to `@Sendable` mismatches have shaken out over time. `sending` is still a relatively new parameter attribute, it has not been adopted as extensively as `@Sendable`, and it does not support downgrading diagnostics in the Swift 6 language mode when combined with `@preconcurrency`. The pain caused by the dynamic actor isolation runtime assertions is enough that it's worth solving this problem now conservatively using `@Sendable`. + +Changing this proposal later to use `sending` instead will pose source compatibility issues, because it would become invalid to have a protocol requirement that is imported with a `sending` completion handler and implement the requirement with a `@Sendable` completion handler. The same source compatibility issue exists for overridden class methods. If programmers want to take advantage of region isolation, the recommended path is to modernize the code using `async`/`await`. + +## Acknowledgments + +Thank you to Becca Royal-Gordon for implementing the `SendableCompletionHandlers` experimental feature, and thank you to Pavel Yaskevich for consistently fixing compiler bugs where the implementation was intolerant to `@Sendable` mismatches. + +[SE-0297]: /proposals/0297-concurrency-objc.md +[SE-0423]: /proposals/0423-dynamic-actor-isolation.md From f42ebc0a0a0c6cfd1908bedbf9c6898bbbe11960 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 26 Feb 2025 13:24:16 -0800 Subject: [PATCH 097/505] Add a revision history section. --- proposals/NNNN-sendable-completion-handlers.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proposals/NNNN-sendable-completion-handlers.md b/proposals/NNNN-sendable-completion-handlers.md index 17d45006f1..9a9fb08a34 100644 --- a/proposals/NNNN-sendable-completion-handlers.md +++ b/proposals/NNNN-sendable-completion-handlers.md @@ -75,3 +75,9 @@ Thank you to Becca Royal-Gordon for implementing the `SendableCompletionHandlers [SE-0297]: /proposals/0297-concurrency-objc.md [SE-0423]: /proposals/0423-dynamic-actor-isolation.md + +## Revisions + +The proposal was revised with the following changes after the pitch discussion: + +* Add a carve out where global actor isolated functions are still imported with non-`Sendable` completion handlers. From 180e96f7699918de37cc55e49833361823c524bd Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Feb 2025 00:12:40 -0800 Subject: [PATCH 098/505] SE-0458 "Opt-in Strict Memory Safety Checking" is implemented (#2711) --- proposals/0458-strict-memory-safety.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index c3bb3fdaa1..24854d310b 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -3,10 +3,9 @@ * Proposal: [SE-0458](0458-strict-memory-safety.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Feature name: `StrictMemorySafety` * Vision: [Optional Strict Memory Safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/memory-safety.md) -* Implementation: On main with experimental feature flags `AllowUnsafeAttribute` and `WarnUnsafe` * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/f2cab4ddc3381d1dc7a970e813ed29e27b5ae43f/proposals/0458-strict-memory-safety.md) [2](https://github.com/swiftlang/swift-evolution/blob/9d180aea291c6b430bcc816ce12ef0174ec0237b/proposals/0458-strict-memory-safety.md) * Review: ([pitch](https://forums.swift.org/t/pitch-opt-in-strict-memory-safety-checking/76689)) ([review](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274)) ([first revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/33)) ([second revision](https://forums.swift.org/t/se-0458-opt-in-strict-memory-safety-checking/77274/51)) ([acceptance](https://forums.swift.org/t/accepted-se-0458-opt-in-strict-memory-safety-checking/78116)) @@ -421,7 +420,7 @@ A type has unsafe storage if: #### Unsafe witnesses -When a type conforms to a given protocol, it must satisfy all of the requirements of that protocol. Part of this process is determining which declaration (called the *witness*) satisfies a given protocol requirement. If a particular witness is unsafe but the corresponding requirement is not safe, the compiler will produce a warning: +When a type conforms to a given protocol, it must satisfy all of the requirements of that protocol. Part of this process is determining which declaration (called the *witness*) satisfies a given protocol requirement. If a particular witness is unsafe but the corresponding requirement is safe, the compiler will produce a warning: ```swift protocol P { From 6ba97a33931a9574ce97446a11df7e8aa3496854 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 27 Feb 2025 16:29:59 -0500 Subject: [PATCH 099/505] Assign SE-0463 to the sendable completion handlers proposal and put it in review --- ...n-handlers.md => 0463-sendable-completion-handlers.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{NNNN-sendable-completion-handlers.md => 0463-sendable-completion-handlers.md} (95%) diff --git a/proposals/NNNN-sendable-completion-handlers.md b/proposals/0463-sendable-completion-handlers.md similarity index 95% rename from proposals/NNNN-sendable-completion-handlers.md rename to proposals/0463-sendable-completion-handlers.md index 9a9fb08a34..8aafcfdca9 100644 --- a/proposals/NNNN-sendable-completion-handlers.md +++ b/proposals/0463-sendable-completion-handlers.md @@ -1,10 +1,10 @@ # Import Objective-C completion handler parameters as `@Sendable` -* Proposal: [SE-NNNN](NNNN-sendable-completion-handlers.md) +* Proposal: [SE-0463](0463-sendable-completion-handlers.md) * Authors: [Holly Borla](https://github.com/hborla) -* Review Manager: TBD -* Status: **Awaiting review** -* Vision: [[Prospective Vision] Improving the approachability of data-race safety](https://forums.swift.org/t/prospective-vision-improving-the-approachability-of-data-race-safety/76183) +* Review Manager: [John McCall](https://github.com/rjmccall) +* Status: **Active Review (Feburary 27th...March 10th, 2025)** +* Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` * Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) From a3727f80254bf0e1660b164270a3e284d6c3b3b4 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 27 Feb 2025 16:34:57 -0500 Subject: [PATCH 100/505] Link SE-0463 to its review thread --- proposals/0463-sendable-completion-handlers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0463-sendable-completion-handlers.md b/proposals/0463-sendable-completion-handlers.md index 8aafcfdca9..8211413d0b 100644 --- a/proposals/0463-sendable-completion-handlers.md +++ b/proposals/0463-sendable-completion-handlers.md @@ -6,7 +6,7 @@ * Status: **Active Review (Feburary 27th...March 10th, 2025)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` -* Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) +* Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) ([review](https://forums.swift.org/t/se-0463-import-objective-c-completion-handler-parameters-as-sendable/78169)) ## Introduction From f2b428c31393da20b09a7770ac9d0ad4c91f3753 Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Thu, 27 Feb 2025 22:22:22 +0000 Subject: [PATCH 101/505] [SE-0463] Fix sendable-completion-handlers status --- proposals/0463-sendable-completion-handlers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0463-sendable-completion-handlers.md b/proposals/0463-sendable-completion-handlers.md index 8211413d0b..3200e21039 100644 --- a/proposals/0463-sendable-completion-handlers.md +++ b/proposals/0463-sendable-completion-handlers.md @@ -3,7 +3,7 @@ * Proposal: [SE-0463](0463-sendable-completion-handlers.md) * Authors: [Holly Borla](https://github.com/hborla) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active Review (Feburary 27th...March 10th, 2025)** +* Status: **Active Review (February 27th...March 10th, 2025)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` * Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) ([review](https://forums.swift.org/t/se-0463-import-objective-c-completion-handler-parameters-as-sendable/78169)) From e62f7dadc3627c018f8b18aa97e2875ff11375a6 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 27 Feb 2025 16:24:33 -0800 Subject: [PATCH 102/505] [SE-0458] Rename diagnostic group from Unsafe to StrictMemorySafety (#2714) This is more self-explanatory and lines up with the feature name. Specific diagnostic group names are non-normative, so I feel okay changing this :) --- proposals/0458-strict-memory-safety.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index 24854d310b..b9ce0f6221 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -43,7 +43,7 @@ For example, Swift solves null references with optional types. Statically, Swift This proposal introduces an opt-in strict memory safety checking mode that identifies all uses of unsafe behavior within the given module. There are several parts to this change: -* A compiler flag `-strict-memory-safety` that enables warnings for all uses of unsafe constructs within a given module. All warnings will be in the diagnostic group `Unsafe`, enabling precise control over memory-safety-related warnings per [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md). When strict memory safety is enabled, the `StrictMemorySafety` feature will be set: `#if hasFeature(StrictMemorySafety)` can be used to detect when Swift code is being compiled in this mode. +* A compiler flag `-strict-memory-safety` that enables warnings for all uses of unsafe constructs within a given module. All warnings will be in the diagnostic group `StrictMemorySafety`, enabling precise control over memory-safety-related warnings per [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md). When strict memory safety is enabled, the `StrictMemorySafety` feature will be set: `#if hasFeature(StrictMemorySafety)` can be used to detect when Swift code is being compiled in this mode. * An attribute `@unsafe` that indicates that a declaration is unsafe to use. Such declarations may use unsafe constructs within their signatures. * A corresponding attribute `@safe` that indicates that a declaration whose signature contains unsafe constructs is actually safe to use. For example, the `withUnsafeBufferPointer` method on `Array` has an unsafe type in its signature (`self`), but is actually safe to use because it handles safety for the unsafe buffer pointer it vends to its closure argument. The closure itself will need to handle the unsafety when using that unsafe buffer pointer. * An `unsafe` expression that marks any use of unsafe constructs in an expression, much like `try` and `await`. @@ -507,7 +507,7 @@ for try await x in try await getAsyncSequence() { ... } The strict memory safety mode can be enabled with the new compiler flag `-strict-memory-safety`. -All of the memory-safety diagnostics produced by the strict memory safety mode will be warnings. These warnings be in the group `Unsafe` (possibly organized into subgroups) so that one can choose to escalate them to errors or keep them as warnings using the compiler flags introduced in [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md). For example, one can choose to enable the mode and make memory-safety issues errors using: +All of the memory-safety diagnostics produced by the strict memory safety mode will be warnings. These warnings be in the group `StrictMemorySafety` (possibly organized into subgroups) so that one can choose to escalate them to errors or keep them as warnings using the compiler flags introduced in [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md). For example, one can choose to enable the mode and make memory-safety issues errors using: ``` swiftc -strict-memory-safety -Werror Unsafe From 720735324854811854ee5175dfe34276239039a7 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 28 Feb 2025 19:05:53 -0600 Subject: [PATCH 103/505] Add a proposal template for Swift Testing (#2709) * Add a proposal template for Swift Testing * Update URL template for "Previous revision" link * Switch to /proposals/testing subdirectory --- .../0000-swift-testing-template.md | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 proposal-templates/0000-swift-testing-template.md diff --git a/proposal-templates/0000-swift-testing-template.md b/proposal-templates/0000-swift-testing-template.md new file mode 100644 index 0000000000..2ea8c57572 --- /dev/null +++ b/proposal-templates/0000-swift-testing-template.md @@ -0,0 +1,184 @@ +# Swift Testing Feature name + +* Proposal: [SWT-NNNN](NNNN-filename.md) +* Authors: [Author 1](https://github.com/author1), [Author 2](https://github.com/author2) +* Status: **Awaiting implementation** or **Awaiting review** +* Bug: _if applicable_ [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/issues/NNNNN) +* Implementation: [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/pull/NNNNN) +* Previous Proposal: _if applicable_ [SWT-XXXX](XXXX-filename.md) +* Previous Revision: _if applicable_ [1](https://github.com/swiftlang/swift-evolution/blob/...commit-ID.../proposals/testing/NNNN-filename.md) +* Review: ([pitch](https://forums.swift.org/...)) + +When filling out this template, you should delete or replace all of the text +except for the section headers and the header fields above. For example, you +should delete everything from this paragraph down to the Introduction section +below. + +As a proposal author, you should fill out all of the header fields. Delete any +header fields marked _if applicable_ that are not applicable to your proposal. + +When sharing a link to the proposal while it is still a PR, be sure to share a +live link to the proposal, not an exact commit, so that readers will always see +the latest version when you make changes. On GitHub, you can find this link by +browsing the PR branch: from the PR page, click the "username wants to merge ... +from username:my-branch-name" link and find the proposal file in that branch. + +`Status` should reflect the current implementation status while the proposal is +still a PR. The proposal cannot be reviewed until an implementation is available, +but early readers should see the correct status. + +`Bug` should be used when this proposal is fixing a bug with significant +discussion in the bug report. It is not necessary to link bugs that do not +contain significant discussion or that merely duplicate discussion linked +somewhere else. Do not link bugs from private bug trackers. + +`Implementation` should link to the PR(s) implementing the feature. If the +proposal has not been implemented yet, or if it simply codifies existing +behavior, just say that. If the implementation has already been committed to the +main branch (as an experimental feature or SPI), mention that. If the +implementation is spread across multiple PRs, just link to the most important +ones. + +`Previous Proposal` should be used when there is a specific line of succession +between this proposal and another proposal. For example, this proposal might +have been removed from a previous proposal so that it can be reviewed separately, +or this proposal might supersede a previous proposal in some way that was felt +to exceed the scope of a "revision". Include text briefly explaining the +relationship, such as "Supersedes SWT-1234" or "Extracted from SWT-01234". If +possible, link to a post explaining the relationship, such as a review decision +that asked for part of the proposal to be split off. Otherwise, you can just +link to the previous proposal. + +`Previous Revision` should be added after a major substantive revision of a +proposal that has undergone review. It links to the previously reviewed revision. +It is not necessary to add or update this field after minor editorial changes. + +`Review` is a history of all discussion threads about this proposal, in +chronological order. Use these standardized link names: `pitch` `review` +`revision` `acceptance` `rejection`. If there are multiple such threads, spell +the ordinal out: `first pitch` `second review` etc. + +## Introduction + +A short description of what the feature is. Try to keep it to a single-paragraph +"elevator pitch" so the reader understands what problem this proposal is +addressing. + +## Motivation + +Describe the problems that this proposal seeks to address. If the problem is +that some common pattern is currently hard to express, show how one can +currently get a similar effect and describe its drawbacks. If it's completely +new functionality that cannot be emulated, motivate why this new functionality +would help Swift developers test their code more effectively. + +## Proposed solution + +Describe your solution to the problem. Provide examples and describe how they +work. Show how your solution is better than current workarounds: is it cleaner, +safer, or more efficient? + +This section doesn't have to be comprehensive. Focus on the most important parts +of the proposal and make arguments about why the proposal is better than the +status quo. + +## Detailed design + +Describe the design of the solution in detail. If it includes new API, show the +full API and its documentation comments detailing what it does. If it involves +new macro logic, describe the behavior changes and include a succinct example of +the additions or modifications to the macro expansion code. The detail in this +section should be sufficient for someone who is *not* one of the authors to be +able to reasonably implement the feature. + +## Source compatibility + +Describe the impact of this proposal on source compatibility. As a general rule, +all else being equal, test code that worked in previous releases of the testing +library should work in new releases. That means both that it should continue to +build and that it should continue to behave dynamically the same as it did +before. + +This is not an absolute guarantee, and the testing library administrators will +consider intentional compatibility breaks if their negative impact can be shown +to be small and the current behavior is causing substantial problems in practice. + +For proposals that affect testing library API, consider the impact on existing +clients. If clients provide a similar API, will type-checking find the right one? +If the feature overloads an existing API, is it problematic that existing users +of that API might start resolving to the new API? + +## Integration with supporting tools + +In this section, describe how this proposal affects tools which integrate with +the testing library. Some features depend on supporting tools gaining awareness +of the new feature for users to realize new benefits. Other features do not +strictly require integration but bring improvement opportunities which are worth +considering. Use this section to discuss any impact on tools. + +This section does need not to include details of how this proposal may be +integrated with _specific_ tools, but it should consider the general ways that +tools might support this feature and note any accompanying SPI intended for +tools which are included in the implementation. Note that tools may evolve +independently and have differing release schedules than the testing library, so +special care should be taken to ensure compatibility across versions according +to the needs of each tool. + +## Future directions + +Describe any interesting proposals that could build on this proposal in the +future. This is especially important when these future directions inform the +design of the proposal, for example by making sure an interface meant for tools +integration can be extended to include additional information. + +The rest of the proposal should generally not talk about future directions +except by referring to this section. It is important not to confuse reviewers +about what is covered by this specific proposal. If there's a larger vision that +needs to be explained in order to understand this proposal, consider starting a +discussion thread on the forums to capture your broader thoughts. + +Avoid making affirmative statements in this section, such as "we will" or even +"we should". Describe the proposals neutrally as possibilities to be considered +in the future. + +Consider whether any of these future directions should really just be part of +the current proposal. It's important to make focused, self-contained proposals +that can be incrementally implemented and reviewed, but it's also good when +proposals feel "complete" rather than leaving significant gaps in their design. +An an example from the Swift project, when +[SE-0193](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0193-cross-module-inlining-and-specialization.md) +introduced the `@inlinable` attribute, it also included the `@usableFromInline` +attribute so that declarations used in inlinable functions didn't have to be +`public`. This was a relatively small addition to the proposal which avoided +creating a serious usability problem for many adopters of `@inlinable`. + +## Alternatives considered + +Describe alternative approaches to addressing the same problem. This is an +important part of most proposal documents. Reviewers are often familiar with +other approaches prior to review and may have reasons to prefer them. This +section is your first opportunity to try to convince them that your approach is +the right one, and even if you don't fully succeed, you can help set the terms +of the conversation and make the review a much more productive exchange of ideas. + +You should be fair about other proposals, but you do not have to be neutral; +after all, you are specifically proposing something else. Describe any +advantages these alternatives might have, but also be sure to explain the +disadvantages that led you to prefer the approach in this proposal. + +You should update this section during the pitch phase to discuss any +particularly interesting alternatives raised by the community. You do not need +to list every idea raised during the pitch, just the ones you think raise points +that are worth discussing. Of course, if you decide the alternative is more +compelling than what's in the current proposal, you should change the main +proposal; be sure to then discuss your previous proposal in this section and +explain why the new idea is better. + +## Acknowledgments + +If significant changes or improvements suggested by members of the community +were incorporated into the proposal as it developed, take a moment here to thank +them for their contributions. This is a collaborative process, and everyone's +input should receive recognition! + +Generally, you should not acknowledge anyone who is listed as a co-author. From 49347edac6069bd7efb23f5427ca07c8fa0a18bf Mon Sep 17 00:00:00 2001 From: shiz <35151927+stzn@users.noreply.github.com> Date: Mon, 3 Mar 2025 07:32:04 +0900 Subject: [PATCH 104/505] Fix invalid URLs (#2715) --- visions/approachable-concurrency.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/visions/approachable-concurrency.md b/visions/approachable-concurrency.md index de8adefc75..25e6e6b725 100644 --- a/visions/approachable-concurrency.md +++ b/visions/approachable-concurrency.md @@ -158,9 +158,9 @@ The current execution semantics of async functions also impede programmer’s un Changing the default execution semantics of nonisolated async functions to run wherever they are called better facilitates progressive disclosure of concurrency. This default allows functions to leverage suspension without forcing callers to cross an isolation boundary and imposing data-race safety checks on arguments and results. A lot of basic asynchronous code can be written correctly and efficiently with only the ability to suspend. When an async function needs to always run off of an actor, the API author can still specify that with a new `@execution(concurrent)` annotation on the function. This provides a better default for most cases while still maintaining the ease of specifying that an async function switches off of an actor to run. -Many programmers have internalized the SE-0338 semantics, and making this change several years after SE-0338 was accepted creates an unfortunate intermediate state where it's difficult to understand the semantics of a nonisolated async function without understanding the build settings of the module you're writing code in. We can alleviate some of these consequences with a careful migration design. There are more details about migration in the [automatic migration](#automatic-migration) section of this document, and in the [source compatibility](https://github.com/hborla/swift-evolution/blob/async-function-isolation/proposals/NNNN-async-function-isolation.md#source-compatibility) section of the proposal for this change. +Many programmers have internalized the SE-0338 semantics, and making this change several years after SE-0338 was accepted creates an unfortunate intermediate state where it's difficult to understand the semantics of a nonisolated async function without understanding the build settings of the module you're writing code in. We can alleviate some of these consequences with a careful migration design. There are more details about migration in the [automatic migration](#automatic-migration) section of this document, and in the [source compatibility](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0461-async-function-isolation.md#source-compatibility) section of the proposal for this change. -This idea has already been pitched on the forums, and you can read the full proposal for it [here](https://github.com/hborla/swift-evolution/blob/async-function-isolation/proposals/NNNN-async-function-isolation.md). +This idea has already been pitched on the forums, and you can read the full proposal for it [here](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0461-async-function-isolation.md). ## Easing incremental migration to data-race safety From 6cc9f5f00c395fae37dd6bf430812fb5b0fb4e88 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 3 Mar 2025 15:24:47 +0900 Subject: [PATCH 105/505] initial isIsolated revision --- proposals/NNNN-SerialExecutor-isIsolated.md | 195 ++++++++++++++++++++ proposals/nnnn-is-isolated-flow.graffle | Bin 0 -> 157991 bytes proposals/nnnn-is-isolated-flow.png | Bin 0 -> 74137 bytes 3 files changed, 195 insertions(+) create mode 100644 proposals/NNNN-SerialExecutor-isIsolated.md create mode 100644 proposals/nnnn-is-isolated-flow.graffle create mode 100644 proposals/nnnn-is-isolated-flow.png diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md new file mode 100644 index 0000000000..6961770056 --- /dev/null +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -0,0 +1,195 @@ +# Improved Custom SerialExecutor isolation checking for Concurrency Runtime + +* Proposal: [SE-NNNN](...) +* Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) +* Review Manager: +* Status: **WIP** +* Review: TODO + +## Introduction + +In [SE-0424: Custom isolation checking for SerialExecutor](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0424-custom-isolation-checking-for-serialexecutor.md) we introduced a way for custom executors implementing the `SerialExecutor` protocol to assert and and assume the static isolation if the dynamic check succeeded. This proposal extends these capabilities, allowing custom executors to not only "check and crash if assumption was wrong", but also check and act on the result of the check. + +## Motivation + +The previously ([SE-0424](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0424-custom-isolation-checking-for-serialexecutor.md)) introduced family of `Actor/assertIsolated()`, `Actor/preconditionIsolated()` and `Actor/assumeIsolated(operation:)` all rely on the `SerialExecutor/checkIsolated()` API which was introduced in the same proposal. + +These APIs all follow the "*pass or crash*" pattern. Where the crash is caused in order to prevent an incorrect assumption about isolation resulting in unsafe concurrent access to some isolated state. This is frequently used by methods which are "known to be called" on some specific actor to recover the dynamic (known at runtime) isolation information, into its static equivalent and therefore safely access some isolated state, like in this example: + +```swift +@MainActor +var counter: Int = num + +protocol P { + // Always called by the main actor, + // yet protocol author forgot to annotate the method or protocol using @MainActor + func actuallyWeKnowForSureThisIsCalledFromTheMainActor() +} + +struct Impl: P { + func actuallyWeKnowForSureThisIsCalledFromTheMainActor() { + MainActor.assumeIsolated { // we know this is safe here + counter += 1 + } + } +} + +@MainActor +func call(p: some P) { + p.actuallyWeKnowForSureThisIsCalledFromTheMainActor() +} +``` + +This works fine for many situations, however some libraries may need to be more careful when rolling out strict concurrency checks like these, and instead of crashing may want to choose to issue warnings before they adopt a mode that enforces correct use. + +Currently all APIs available are using the `checkIsolated()` API which must crash if called from a context not managed by the serial executor it is invoked on. This method is often implemented using `dispatchPrecondition()` when the serial executor is backed using `Dispatch` or custom `fatalError()` messages otherwise: + +```swift +final class ExampleExecutor: SerialExecutor { + func checkIsolated() { + dispatchPrecondition(condition: .onQueue(self.queue)) + } +} +``` + +This approach is better than not being able to participate in the checks at all (i.e. this API allows for advanced thread/queue sharing between actor and non-actor code), but it has two severe limitations: + +- the crash **messages** offered by these `checkIsolated()` crashes **are often sub-optimal** and confusing + - messages often don't include crucial information about which actor/executor the calling context was _actually_ executing on. Offering only "expected [...]" messages, leading to hard to debug crashes. +- it is **impossible** for the Swift runtime to offer **isolation violation warnings** + - because the Swift runtime _must_ call into a custom executor to verify its isolation, the "pass or crash" method will crash, rather than inform the runtime that a violation ocured and we should warn about it. + +Today, it is not possible for the Swift runtime to issue _warnings_ if something is detected to be on not the expected executor, but somehow we'd still like to continue without crashing the application. + +And for existing situations when `assumeIsolated()` is called and _should_ crash, by using this new API the Swift runtime will be able to provide _more informative_ messages, including all available context about the execution environment. + +## Proposed solution + +We propose to introduce a new `isIsolatingCurrentContext` protocol requirement to the `SerialExecutor` protocol: + +```swift +protocol SerialExecutor { + + /// May be called by the Swift runtime before `checkIsolated()` + /// in order to check for isolation violations at runtime, + /// and potentially issue isolation warnings. + /// + /// [...] + func isIsolatingCurrentContext() -> Bool + + // existing API, since SE-0424 + @available(SwiftStdlib 6.0, *) + func checkIsolated() // must crash if run on a context not managed by this serial executor + + // ... +} + +extension SerialExecutor { + /// Default implementation for backwards compatibility. + func isIsolatingCurrentContext() -> Bool { false } +} +``` + +The Swift runtime is free to call the `isIsolated` function whenever it wants to verify if the current context is apropriately isolated by some serial executor. + +In most cases implementing this new API is preferable to implementing `checkIsolated()`, as the Swift runtime is able to offer more detailed error messages when when an isolation failure detected by a call to `isIsolatingCurrentContext()` is detected. + +## Detailed design + +The newly proposed `isIsolatingCurrentContext()` function participates in the previously established runtime isolation checking flow, and happens _before_ any calls to `checkIsolated()` are attempted. The following diagram explains the order of calls issued by the runtime to dynamically verify an isolation when e.g. `assumeIsolated()` is called: + +![diagram illustrating which method is called when](/Users/ktoso/code/swift-evolution/proposals/nnnn-is-isolated-flow.png) + + + +There are a lot of conditions here and availability of certain features also impacts this decision flow, so it is best to refer to the diagram for detailed analysis of every situation. However the most typical situation involves executing on a task, which has a potentially different executor than the `expected` one. In such situation the runtime will: + +- check for the existence of a "current" task, +- (fast path) if a task is present: + - compare the current task's serial executor it is isolated to (if any) with the expected serial executor, + +- :new: if **`isIsolatingCurrentContext`** **is available** on the `expected` executor: + - invoke `isIsolatingCurrentContext` + - ✅ if it returned true: pass the check. + - :x: if it returned false: fail the check. + - The runtime will **not** proceed to call `checkIsolated` after `isIsolated` is invoked! + +- if **`isIsolatingCurrentContext`** is **not available** on the expected executor, but **`checkIsolated`** **is available**: + - invoke `expected.checkIsolated` which will crash :x: or pass :white_check_mark: depending on its internal checking. +- if neither `checkIsolated` or `isIsolatingCurrentContext` are available, + - :x: crash with a best effort message. + + +This proposal specifically adds the "if `isIsolatingCurrentContext` is available" branch into the existing logic for confirming the isolation expectation. + +If `isIsolatingCurrentContext` is available, effectively it replaces `checkIsolated` because it does offer a sub-par error message experience and is not able to offer a warning if Swift would be asked to check the isolation but not crash upon discovering a violation. + +### Enabling `isIsolatingCurrentContext` checking mode + +Similar as complex equality in `SerialExecutors` this feature must be opted into by flagging it when the `UnownedSerialExecutor` value is returned from a serial executor's `asUnownedSerialExecutor()`. + +Previously this was done by signalling the feature in the `UnownedSerialExecutor` initializer like this: + +```swift +// Existing API +public func asUnownedSerialExecutor() -> UnownedSerialExecutor { + UnownedSerialExecutor(complexEquality: self) +} +``` + +Which enables the following `isSameExclusiveExecutionContext` check, which can only be used when a "current" executor is present, and cannot be used when running code outside of a Swift concurren ytask (!): + +```swift +// Existing API +public func isSameExclusiveExecutionContext(other: NaiveQueueExecutor) -> Bool { + other.secretIdentifier == self.secretIdentifier +} +``` + +In order to enable the the runtime to call into the `isIsolatingCurrentContext` the `UnownedSerialExecutor` **must** be constructed as follows: + +```swift +public func asUnownedSerialExecutor() -> UnownedSerialExecutor { + UnownedSerialExecutor(hasIsIsolatingCurrentContext: self) +} +``` + +This sets a flag inside the internal executor reference which makes the swift runtime call into the new `isIsolatingCurrentContext` function, rather than the other versions of isolation checking. In many ways this API is the most general of them all, and generally preferable _if_ your executor is using some kind of mechanism to track the "current" context that the Swift concurrency runtime cannot know about, e.g. like thread local values inside threads managed by your executor. + +### Compatibility strategy for custom SerialExecutor authors + +New executor implementations should prioritize implementing `isIsolatingCurrentContext` when available, using an appropriate `#if swift(>=...)` check to ensure compatibility. Otherwise, they should fall back to implementing the crashing version of this API: `checkIsolated()`. + +While the relationship between `isIsolatingCurrentContext` and `checkIsolated` is not ideal, the boolean-returning version was previously not possible to implement due to runtime restrictions which we have manage to resolve, and thus would like to introduce the better API and better user-experience. + +For authors of custom serial executors, adopting this feature is an incremental process and they can adopt it at their own pace, properly guarding the new feature with necessary availability guards. This feature requires a new version of the Swift concurrency runtime which is aware of this new mode and therefore able to call into the new checking function, therefore libraries should implement and adopt it, however it will only manifest itself when the code is used with a new enough concurrency runtime + +As a result, this change should cause little to no disruption to Swift concurrency users, while providing an improved error reporting experience if using executors which adopt this feature. + +## Source Compatibility + +This proposal is source compatible, a default implementation of the new protocol requirement is introduced along with it, allowing existing `SerialExecutors` to compile without changes. + +## Binary Compatibility + +This proposal is ABI additive, and does not cause any binary incompatibility risks. + +## Future directions + +### Expose `isIsolated` on (Distributed)Actor and MainActor? + +We are _not_ including new public API on Actor types because of concerns of this function being abused. + +If we determine that there are significant good use-cases for this method to be exposed, we might reconsider this position. + +## Alternatives considered + +### Somehow change `checkIsolated` to return a bool value + +This would be ideal, however also problematic since changing a protocol requirements signature would be ABI breaking. + +It would be ideal if this method could have been bool returning initially, but due to some restrictions back then it would not have been implementable the to what concurrency integrations were available to Swift. + +### Deprecate `checkIsolated`? + +In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. diff --git a/proposals/nnnn-is-isolated-flow.graffle b/proposals/nnnn-is-isolated-flow.graffle new file mode 100644 index 0000000000000000000000000000000000000000..198985bdb668652be7d77f816ff2c55966e98bce GIT binary patch literal 157991 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

    C+cO*h>h&R{e3J^ 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 literal 0 HcmV?d00001 From 323232889ad803a3631df7f13894354e2a711ee9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 3 Mar 2025 17:14:40 +0900 Subject: [PATCH 106/505] fix hardcoded path from desktop editor --- proposals/NNNN-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 6961770056..7bd3e6e375 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -98,7 +98,7 @@ In most cases implementing this new API is preferable to implementing `checkIsol The newly proposed `isIsolatingCurrentContext()` function participates in the previously established runtime isolation checking flow, and happens _before_ any calls to `checkIsolated()` are attempted. The following diagram explains the order of calls issued by the runtime to dynamically verify an isolation when e.g. `assumeIsolated()` is called: -![diagram illustrating which method is called when](/Users/ktoso/code/swift-evolution/proposals/nnnn-is-isolated-flow.png) +![diagram illustrating which method is called when](nnnn-is-isolated-flow.png) From ccc62e9b6dea0f357a8fa4729e7e8c38169cfb6c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 3 Mar 2025 17:21:57 +0900 Subject: [PATCH 107/505] update images --- proposals/nnnn-is-isolated-flow.graffle | Bin 157991 -> 158389 bytes proposals/nnnn-is-isolated-flow.png | Bin 74137 -> 75953 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/proposals/nnnn-is-isolated-flow.graffle b/proposals/nnnn-is-isolated-flow.graffle index 198985bdb668652be7d77f816ff2c55966e98bce..cfe1fc4d456e8156a6bdda297874bcbaae83c397 100644 GIT binary patch delta 125435 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 E08^@Vz5oCK delta 125009 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�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 SOs8AmpS+C9qvD6gum1-)9r!T- literal 74137 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

    C+cO*h>h&R{e3J^ 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 From d9a5748948ae5ff7469541a069fa77b97109bd5c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 3 Mar 2025 19:44:38 +0900 Subject: [PATCH 108/505] Update NNNN-SerialExecutor-isIsolated.md Co-authored-by: Mykola (Nickolas) Pokhylets --- proposals/NNNN-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 7bd3e6e375..1d8d5bac1d 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -137,7 +137,7 @@ public func asUnownedSerialExecutor() -> UnownedSerialExecutor { } ``` -Which enables the following `isSameExclusiveExecutionContext` check, which can only be used when a "current" executor is present, and cannot be used when running code outside of a Swift concurren ytask (!): +Which enables the following `isSameExclusiveExecutionContext` check, which can only be used when a "current" executor is present, and cannot be used when running code outside of a Swift concurrency task (!): ```swift // Existing API From 6a4af1f9c74fe291afa0d7d92f0e84aaad49a7fe Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 3 Mar 2025 19:44:48 +0900 Subject: [PATCH 109/505] Update NNNN-SerialExecutor-isIsolated.md Co-authored-by: Volodymyr Myroniuk --- proposals/NNNN-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 1d8d5bac1d..e60b53a5ae 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -146,7 +146,7 @@ public func isSameExclusiveExecutionContext(other: NaiveQueueExecutor) -> Bool { } ``` -In order to enable the the runtime to call into the `isIsolatingCurrentContext` the `UnownedSerialExecutor` **must** be constructed as follows: +In order to enable the runtime to call into the `isIsolatingCurrentContext` the `UnownedSerialExecutor` **must** be constructed as follows: ```swift public func asUnownedSerialExecutor() -> UnownedSerialExecutor { From 47118c37500420e8efb26db4bae6f1fafcefc750 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 3 Mar 2025 12:43:54 -0700 Subject: [PATCH 110/505] Newests updates to drop ABI annotations --- .../nnnn-utf8span-safe-utf8-processing.md | 59 +++---------------- 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/proposals/nnnn-utf8span-safe-utf8-processing.md b/proposals/nnnn-utf8span-safe-utf8-processing.md index 30a7816eac..26308fcadf 100644 --- a/proposals/nnnn-utf8span-safe-utf8-processing.md +++ b/proposals/nnnn-utf8span-safe-utf8-processing.md @@ -42,31 +42,11 @@ We propose a non-escapable `UTF8Span` which exposes `String` functionality for v `UTF8Span` is a borrowed view into contiguous memory containing validly-encoded UTF-8 code units. ```swift -@frozen -public struct UTF8Span: Copyable, ~Escapable { - @usableFromInline - internal var _unsafeBaseAddress: UnsafeRawPointer? - - /* - A bit-packed count and flags (such as isASCII) - - ╔═══════╦═════╦══════════╦═══════╗ - ║ b63 ║ b62 ║ b61:56 ║ b56:0 ║ - ╠═══════╬═════╬══════════╬═══════╣ - ║ ASCII ║ NFC ║ reserved ║ count ║ - ╚═══════╩═════╩══════════╩═══════╝ - - ASCII means the contents are all-ASCII (<0x7F). - NFC means contents are in normal form C for fast comparisons. - SSC means single-scalar Characters (i.e. grapheme clusters): every - `Character` holds only a single `Unicode.Scalar`. - */ - @usableFromInline - internal var _countAndFlags: UInt64 -} - +public struct UTF8Span: Copyable, ~Escapable, BitwiseCopyable {} ``` +`UTF8Span` is a trivial struct and is 2 words in size on 64-bit platforms. + ### UTF-8 validation We propose new API for identifying where and what kind of encoding errors are present in UTF-8 content. @@ -166,7 +146,6 @@ extension Unicode.UTF8 { ╚═════════════════╩══════╩═════╩═════╩═════╩═════╩═════╩═════╩══════╝ */ - @frozen public struct EncodingError: Error, Sendable, Hashable, Codable { /// The kind of encoding error public var kind: Unicode.UTF8.EncodingError.Kind @@ -185,7 +164,6 @@ extension Unicode.UTF8 { extension UTF8.EncodingError { /// The kind of encoding error encountered during validation - @frozen public struct Kind: Error, Sendable, Hashable, Codable, RawRepresentable { public var rawValue: UInt8 @@ -247,7 +225,6 @@ extension UTF8Span { public func makeUnicodeScalarIterator() -> UnicodeScalarIterator /// Iterate the `Unicode.Scalar`s contents of a `UTF8Span`. - @frozen public struct UnicodeScalarIterator: ~Escapable { public let codeUnits: UTF8Span @@ -292,14 +269,14 @@ extension UTF8Span { /// /// Returns the number of `Unicode.Scalar`s skipped over, which can be 0 /// if at the start of the UTF8Span. - public mutating func skipBack() -> Bool + public mutating func skipBack() -> Int /// Move `codeUnitOffset` to the start of the previous `n` scalars, /// without decoding them. /// /// Returns the number of `Unicode.Scalar`s skipped over, which can be /// fewer than `n` if at the start of the UTF8Span. - public mutating func skipBack(by n: Int) -> Bool + public mutating func skipBack(by n: Int) -> Int /// Reset to the nearest scalar-aligned code unit offset `<= i`. public mutating func reset(roundingBackwardsFrom i: Int) @@ -335,14 +312,13 @@ extension UTF8Span { ``` - ### Character processing We similarly propose a `UTF8Span.CharacterIterator` type that can do grapheme-breaking forwards and backwards. The `CharacterIterator` assumes that the start and end of the `UTF8Span` is the start and end of content. -Any scalar-aligned position is a valid place to start or reset the grapheme-breaking algorithm to, though you could get different `Character` output if if resetting to a position that isn't `Character`-aligned relative to the start of the `UTF8Span` (e.g. in the middle of a series of regional indicators). +Any scalar-aligned position is a valid place to start or reset the grapheme-breaking algorithm to, though you could get different `Character` output if resetting to a position that isn't `Character`-aligned relative to the start of the `UTF8Span` (e.g. in the middle of a series of regional indicators). ```swift @@ -357,8 +333,9 @@ extension UTF8Span { public struct CharacterIterator: ~Escapable { public let codeUnits: UTF8Span - /// The byte offset of the start of the next `Character`. This is - /// always scalar-aligned and `Character`-aligned. + /// The byte offset of the start of the next `Character`. This is always + /// scalar-aligned. It is always `Character`-aligned relative to the last + /// call to `reset` (or the start of the span if not called). public var currentCodeUnitOffset: Int { get private(set) } public init(_ span: UTF8Span) @@ -827,23 +804,5 @@ Finally, in the future there will likely be some kind of `Container` protocol fo Karoy Lorentey, Karl, Geordie_J, and fclout, contributed to this proposal with their clarifying questions and discussions. - From 72751e7161c0c48dd1028200e912a821ede40a68 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 3 Mar 2025 11:59:31 -0800 Subject: [PATCH 111/505] [SE-0447] Mark as implemented. (#2717) --- proposals/0447-span-access-shared-contiguous-storage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0447-span-access-shared-contiguous-storage.md b/proposals/0447-span-access-shared-contiguous-storage.md index a196781226..95d5c8346b 100644 --- a/proposals/0447-span-access-shared-contiguous-storage.md +++ b/proposals/0447-span-access-shared-contiguous-storage.md @@ -3,11 +3,11 @@ * Proposal: [SE-0447](0447-span-access-shared-contiguous-storage.md) * Authors: [Guillaume Lessard](https://github.com/glessard), [Michael Ilseman](https://github.com/milseman), [Andrew Trick](https://github.com/atrick) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Bug: rdar://48132971, rdar://96837923 -* Implementation: https://github.com/swiftlang/swift/pull/76406 -* Review: ([pitch 1](https://forums.swift.org/t/69888))([pitch 2](https://forums.swift.org/t/72745))([review](https://forums.swift.org/t/se-0447-span-safe-access-to-contiguous-storage/74676))([acceptance](https://forums.swift.org/t/accepted-se-0447-span-safe-access-to-contiguous-storage/75508)) +* Implementation: [apple/swift#76406](https://github.com/swiftlang/swift/pull/76406) +* Review: ([Pitch 1](https://forums.swift.org/t/69888))([Pitch 2](https://forums.swift.org/t/72745))([Review](https://forums.swift.org/t/se-0447-span-safe-access-to-contiguous-storage/74676))([Acceptance](https://forums.swift.org/t/accepted-se-0447-span-safe-access-to-contiguous-storage/75508)) ## Introduction From 40c77c613013283a35b514a1e8833c73af46d490 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 16:20:04 -0500 Subject: [PATCH 112/505] Proposal to add exit tests to Swift Testing This PR adds the draft proposal for Exit Tests in Swift Testing. --- proposals/testing/NNNN-exit-tests.md | 787 +++++++++++++++++++++++++++ 1 file changed, 787 insertions(+) create mode 100644 proposals/testing/NNNN-exit-tests.md diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/NNNN-exit-tests.md new file mode 100644 index 0000000000..06f740d63e --- /dev/null +++ b/proposals/testing/NNNN-exit-tests.md @@ -0,0 +1,787 @@ +# Exit tests + +* Proposal: [SWT-NNNN](NNNN-exit-tests.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Awaiting review** +* Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) +* Implementation: [apple/swift-testing#307](https://github.com/apple/swift-testing/pull/307) +* Review: ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) + +## Introduction + +One of the first enhancement requests we received for Swift Testing was the +ability to test for precondition failures and other critical failures that +terminate the current process when they occur. This feature is also frequently +requested for XCTest. With Swift Testing, we have the opportunity to build such +a feature in an ergonomic way. + +> [!NOTE] +> This feature has various names in the relevant literature, e.g. "exit tests", +> "death tests", "death assertions", "termination tests", etc. We consistently +> use the term "exit tests" to refer to them. + +## Motivation + +Imagine a function, implemented in a package, that includes a precondition: + +```swift +func eat(_ taco: consuming Taco) { + precondition(taco.isDelicious, "Tasty tacos only!") + ... +} +``` + +Today, a test author can write unit tests for this function, but there is no way +to make sure that the function rejects a taco whose `isDelicious` property is +`false` because a test that passes such a taco as input will crash (correctly!) +when it calls `precondition()`. + +An exit test allows testing this sort of functionality. The mechanism by which +an exit test is implemented varies between testing libraries and languages, but +a common implementation involves spawning a new process, performing the work +there, and checking that the spawned process ultimately terminates with a +particular (possibly platform-specific) exit status. + +Adding exit tests to Swift Testing would allow an entirely new class of tests +and would improve code coverage for existing test targets that adopt them. + +## Proposed solution + +This proposal introduces new overloads of the `#expect()` and `#require()` +macros that take, as an argument, a closure to be executed in a child process. +When called, these macros spawn a new process using the relevant +platform-specific interface (`posix_spawn()`, `CreateProcessW()`, etc.), call +the closure from within that process, and suspend the caller until that process +terminates. The exit status of the process is then compared against a known +value passed to the macro, allowing the test to pass or fail as appropriate. + +The function from earlier can then be tested using either of the new +overloads: + +```swift +await #expect(exitsWith: .failure) { + var taco = Taco() + taco.isDelicious = false + eat(taco) // should trigger a precondition failure and process termination +} +``` + +## Detailed design + +### New expectations + +We will introduce the following new overloads of `#expect()` and `#require()` to +the testing library: + +```swift +/// Check that an expression causes the process to terminate in a given fashion. +/// +/// - Parameters: +/// - expectedExitCondition: The expected exit condition. +/// - observedValues: An array of key paths representing results from within +/// the exit test that should be observed and returned by this macro. The +/// ``ExitTest/Result/statusAtExit`` property is always returned. +/// - comment: A comment describing the expectation. +/// - sourceLocation: The source location to which recorded expectations and +/// issues should be attributed. +/// - expression: The expression to be evaluated. +/// +/// - Returns: If the exit test passed, an instance of ``ExitTest/Result`` +/// describing the state of the exit test when it exited. If the exit test +/// fails, the result is `nil`. +/// +/// Use this overload of `#expect()` when an expression will cause the current +/// process to terminate and the nature of that termination will determine if +/// the test passes or fails. For example, to test that calling `fatalError()` +/// causes a process to terminate: +/// +/// await #expect(exitsWith: .failure) { +/// fatalError() +/// } +/// +/// - Note: A call to this expectation macro is called an "exit test." +/// +/// ## How exit tests are run +/// +/// When an exit test is performed at runtime, the testing library starts a new +/// process with the same executable as the current process. The current task is +/// then suspended (as with `await`) and waits for the child process to +/// terminate. `expression` is not called in the parent process. +/// +/// Meanwhile, in the child process, `expression` is called directly. To ensure +/// a clean environment for execution, it is not called within the context of +/// the original test. If `expression` does not terminate the child process, the +/// process is terminated automatically as if the main function of the child +/// process were allowed to return naturally. If an error is thrown from +/// `expression`, it is handed as if the error were thrown from `main()` and the +/// process is terminated. +/// +/// Once the child process terminates, the parent process resumes and compares +/// its exit status against `expectedExitCondition`. If they match, the exit +/// test has passed; otherwise, it has failed and an issue is recorded. +/// +/// ## Child process output +/// +/// By default, the child process is configured without a standard output or +/// standard error stream. If your test needs to review the content of either of +/// these streams, you can pass its key path in the `observedValues` argument: +/// +/// let result = await #expect( +/// exitsWith: .failure, +/// observing: [\.standardOutputContent] +/// ) { +/// print("Goodbye, world!") +/// fatalError() +/// } +/// if let result { +/// #expect(result.standardOutputContent.contains(UInt8(ascii: "G"))) +/// } +/// +/// - Note: The content of the standard output and standard error streams may +/// contain any arbitrary sequence of bytes, including sequences that are not +/// valid UTF-8 and cannot be decoded by [`String.init(cString:)`](https://developer.apple.com/documentation/swift/string/init(cstring:)-6kr8s). +/// These streams are globally accessible within the child process, and any +/// code running in an exit test may write to it including the operating +/// system and any third-party dependencies you have declared in your package. +/// +/// The actual exit condition of the child process is always reported by the +/// testing library even if you do not specify it in `observedValues`. +/// +/// ## Runtime constraints +/// +/// Exit tests cannot capture any state originating in the parent process or +/// from the enclosing lexical context. For example, the following exit test +/// will fail to compile because it captures an argument to the enclosing +/// parameterized test: +/// +/// @Test(arguments: 100 ..< 200) +/// func sellIceCreamCones(count: Int) async { +/// await #expect(exitsWith: .failure) { +/// precondition( +/// count < 10, // ERROR: A C function pointer cannot be formed from a +/// // closure that captures context +/// "Too many ice cream cones" +/// ) +/// } +/// } +/// +/// An exit test cannot run within another exit test. +#if SWT_NO_EXIT_TESTS +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +@discardableResult +@freestanding(expression) public macro expect( + exitsWith expectedExitCondition: ExitTest.Condition, + observing observedValues: [any PartialKeyPath & Sendable] = [], + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: @convention(thin) () async throws -> Void +) -> ExitTest.Result? = #externalMacro(module: "TestingMacros", type: "ExitTestExpectMacro") + +/// Check that an expression causes the process to terminate in a given fashion +/// and throw an error if it did not. +/// +/// [...] +#if SWT_NO_EXIT_TESTS +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +@discardableResult +@freestanding(expression) public macro require( + exitsWith expectedExitCondition: ExitTest.Condition, + observing observedValues: [any PartialKeyPath & Sendable] = [], + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: @convention(thin) () async throws -> Void +) -> ExitTest.Result = #externalMacro(module: "TestingMacros", type: "ExitTestRequireMacro") +``` + +> [!NOTE] +> These interfaces are currently implemented and available on **macOS**, +> **Linux**, **FreeBSD**, **OpenBSD**, and **Windows**. If a platform does not +> support exit tests (generally because it does not support spawning or awaiting +> child processes), then we define `SWT_NO_EXIT_TESTS` when we build it. +> +> `SWT_NO_EXIT_TESTS` is not defined during test target builds. + +### Representing an exit test in Swift + +A new type, `ExitTest`, represents an exit test: + +```swift +/// A type describing an exit test. +/// +/// Instances of this type describe exit tests you create using the +/// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or +/// ``require(exitsWith:observing:_:sourceLocation:performing:)`` macro. You +/// don't usually need to interact directly with an instance of this type. +#if SWT_NO_EXIT_TESTS +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +public struct ExitTest: Sendable, ~Copyable { + /// The exit test that is running in the current process, if any. + /// + /// If the current process was created to run an exit test, the value of this + /// property describes that exit test. If this process is the parent process + /// of an exit test, or if no exit test is currently running, the value of + /// this property is `nil`. + /// + /// The value of this property is constant across all tasks in the current + /// process. + public static var current: ExitTest? { get } +} +``` + +### Exit conditions + +These macros take an argument of the new type `ExitTest.Condition`. This type +describes how the child process is expected to have exited: + +- With a specific exit code (as passed to the C standard function `exit()` or a + platform-specific equivalent); +- With a specific signal (on platforms that support signal handling[^winsig]); +- With any successful status; or +- With any failure status. + +[^winsig]: Windows nominally supports signal handling as it is part of the C + standard, but not to the degree that signals are supported by POSIX-like or + UNIX-derived operating systems. Swift Testing makes a "best effort" to emulate + signal-handling support on Windows. See [this](https://forums.swift.org/t/swift-on-windows-question-about-signals-and-exceptions/76640/2) + Swift forum message for more information. + +The type is declared as: + +```swift +#if SWT_NO_EXIT_TESTS +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +extension ExitTest { + /// The possible conditions under which an exit test will complete. + /// + /// Values of this type are used to describe the conditions under which an + /// exit test is expected to pass or fail by passing them to + /// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or + /// ``require(exitsWith:observing:_:sourceLocation:performing:)``. + /// + /// ## Topics + /// + /// ### Successful exit conditions + /// + /// - ``success`` + /// + /// ### Failing exit conditions + /// + /// - ``failure`` + /// - ``exitCode(_:)`` + /// - ``signal(_:)`` + public struct Condition: Sendable { + /// A condition that matches when a process terminates successfully with exit + /// code `EXIT_SUCCESS`. + /// + /// The C programming language defines two [standard exit codes](https://en.cppreference.com/w/c/program/EXIT_status), + /// `EXIT_SUCCESS` and `EXIT_FAILURE` as well as `0` (as a synonym for + /// `EXIT_SUCCESS`.) + public static var success: Self { get } + + /// A condition that matches when a process terminates abnormally with any + /// exit code other than `EXIT_SUCCESS` or with any signal. + public static var failure: Self { get } + + public init(_ statusAtExit: StatusAtExit) + + /// Creates a condition that matches when a process terminates with a given + /// exit code. + /// + /// - Parameters: + /// - exitCode: The exit code yielded by the process. + /// + /// The C programming language defines two [standard exit codes](https://en.cppreference.com/w/c/program/EXIT_status), + /// `EXIT_SUCCESS` and `EXIT_FAILURE`. Platforms may additionally define their + /// own non-standard exit codes: + /// + /// | Platform | Header | + /// |-|-| + /// | macOS | [``](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/_Exit.3.html), [``](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysexits.3.html) | + /// | Linux | [``](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `` | + /// | FreeBSD | [``](https://man.freebsd.org/cgi/man.cgi?exit(3)), [``](https://man.freebsd.org/cgi/man.cgi?sysexits(3)) | + /// | OpenBSD | [``](https://man.openbsd.org/exit.3), [``](https://man.openbsd.org/sysexits.3) | + /// | Windows | [``](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure) | + /// + /// On macOS, FreeBSD, OpenBSD, and Windows, the full exit code reported by + /// the process is yielded to the parent process. Linux and other POSIX-like + /// systems may only reliably report the low unsigned 8 bits (0–255) of + /// the exit code. + public static func exitCode(_ exitCode: CInt) -> Self + + /// Creates a condition that matches when a process terminates with a given + /// signal. + /// + /// - Parameters: + /// - signal: The signal that terminated the process. + /// + /// The C programming language defines a number of [standard signals](https://en.cppreference.com/w/c/program/SIG_types). + /// Platforms may additionally define their own non-standard signal codes: + /// + /// | Platform | Header | + /// |-|-| + /// | macOS | [``](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/signal.3.html) | + /// | Linux | [``](https://sourceware.org/glibc/manual/latest/html_node/Standard-Signals.html) | + /// | FreeBSD | [``](https://man.freebsd.org/cgi/man.cgi?signal(3)) | + /// | OpenBSD | [``](https://man.openbsd.org/signal.3) | + /// | Windows | [``](https://learn.microsoft.com/en-us/cpp/c-runtime-library/signal-constants) | + public static func signal(_ signal: CInt) -> Self + } +} +``` + +### Exit status + +The set of possible status codes reported by the child process are represented +by the `StatusAtExit` enumeration: + +```swift +/// An enumeration describing possible status a process will yield on exit. +/// +/// You can convert an instance of this type to an instance of +/// ``ExitTest/Condition`` using ``ExitTest/Condition/init(_:)``. That value +/// can then be used to describe the condition under which an exit test is +/// expected to pass or fail by passing it to +/// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or +/// ``require(exitsWith:observing:_:sourceLocation:performing:)``. +#if SWT_NO_PROCESS_SPAWNING +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +public enum StatusAtExit: Sendable { + /// The process terminated with the given exit code. + /// + /// [...] + case exitCode(_ exitCode: CInt) + + /// The process terminated with the given signal. + /// + /// [...] + case signal(_ signal: CInt) +} +``` + +### Exit test results + +These macros return an instance of the new type `ExitTest.Result`. This type +describes the results of the process including its reported exit condition and +the contents of its standard output and standard error streams, if requested. + +```swift +#if SWT_NO_EXIT_TESTS +@available(*, unavailable, message: "Exit tests are not available on this platform.") +#endif +extension ExitTest { + /// A type representing the result of an exit test after it has exited and + /// returned control to the calling test function. + /// + /// Both ``expect(exitsWith:observing:_:sourceLocation:performing:)`` and + /// ``require(exitsWith:observing:_:sourceLocation:performing:)`` return + /// instances of this type. + public struct Result: Sendable { + /// The status of the process hosting the exit test at the time it exits. + /// + /// When the exit test passes, the value of this property is equal to the + /// exit status reported by the process that hosted the exit test. + public var statusAtExit: StatusAtExit { get set } + + /// All bytes written to the standard output stream of the exit test before + /// it exited. + /// + /// The value of this property may contain any arbitrary sequence of bytes, + /// including sequences that are not valid UTF-8 and cannot be decoded by + /// [`String.init(cString:)`](https://developer.apple.com/documentation/swift/string/init(cstring:)-6kr8s). + /// Consider using [`String.init(validatingCString:)`](https://developer.apple.com/documentation/swift/string/init(validatingcstring:)-992vo) + /// instead. + /// + /// When checking the value of this property, keep in mind that the standard + /// output stream is globally accessible, and any code running in an exit + /// test may write to it including including the operating system and any + /// third-party dependencies you have declared in your package. Rather than + /// comparing the value of this property with [`==`](https://developer.apple.com/documentation/swift/array/==(_:_:)), + /// use [`contains(_:)`](https://developer.apple.com/documentation/swift/collection/contains(_:)) + /// to check if expected output is present. + /// + /// To enable gathering output from the standard output stream during an + /// exit test, pass `\.standardOutputContent` in the `observedValues` + /// argument of ``expect(exitsWith:observing:_:sourceLocation:performing:)`` + /// or ``require(exitsWith:observing:_:sourceLocation:performing:)``. + /// + /// If you did not request standard output content when running an exit test, + /// the value of this property is the empty array. + public var standardOutputContent: [UInt8] { get set } + + /// All bytes written to the standard error stream of the exit test before + /// it exited. + /// + /// [...] + public var standardErrorContent: [UInt8] { get set } + } +} +``` + +### Usage + +These macros can be used within a test function: + +```swift +@Test func `We only eat delicious tacos`() async { + await #expect(exitsWith: .failure) { + var taco = Taco() + taco.isDelicious = false + eat(taco) + } +} +``` + +Given the definition of `eat(_:)` above, this test can be expected to hit a +precondition failure and crash the process; because `.failure` was the specified +exit condition, this is treated as a successful test. + +It is often interesting to examine what is written to the standard output and +standard error streams by code running in an exit test. Callers can request that +either or both stream be captured and included in the result of the call to +`#expect(exitsWith:)` or `#require(exitsWith:)`. Capturing these streams can be +a memory-intensive operation, so the caller must explicitly opt in: + +```swift +@Test func `We only eat delicious tacos`() async throws { + let result = try await #require(exitsWith: .failure, observing: [\.standardErrorContent])) { ... } + #expect(result.standardOutputContent.contains("ERROR: This taco tastes terrible!".utf8) +} +``` + +There are some constraints on valid exit tests: + +1. Because exit tests are run in child processes, they cannot capture any state + from the calling context (hence their body closures are `@convention(thin)` + or `@convention(c)`.) See the **Future directions** for further discussion. +1. Exit tests cannot recursively invoke other exit tests; this is a constraint + that could potentially be lifted in the future, but it would be technically + complex to do so. + +If a Swift Testing issue such as an expectation failure occurs while running an +exit test, it is reported to the parent process and to the user as if it +happened locally. If an error is thrown from an exit test and not caught, it +behaves the same way a Swift program would if an error were thrown from its +`main()` function (that is, the program terminates abnormally.) + +## Source compatibility + +This is a new interface that is unlikely to collide with any existing +client-provided interfaces. The typical Swift disambiguation tools can be used +if needed. + +## Integration with supporting tools + +SPI is provided to allow testing environments other than Swift Package Manager +to detect and run exit tests: + +```swift +@_spi(ForToolsIntegrationOnly) +extension ExitTest { + /// A type whose instances uniquely identify instances of ``ExitTest``. + public struct ID: Sendable, Equatable, Codable { /* ... */ } + + /// A value that uniquely identifies this instance. + public var id: ID { get set } + + /// Key paths representing results from within this exit test that should be + /// observed and returned to the caller. + /// + /// The testing library sets this property to match what was passed by the + /// developer to the `#expect(exitsWith:)` or `#require(exitsWith:)` macro. + /// If you are implementing an exit test handler, you can check the value of + /// this property to determine what information you need to preserve from your + /// child process. + /// + /// The value of this property always includes ``ExitTest/Result/statusAtExit`` + /// even if the test author does not specify it. + /// + /// Within a child process running an exit test, the value of this property is + /// otherwise unspecified. + public var observedValues: [any PartialKeyPath & Sendable] { get set } + + /// Call the exit test in the current process. + /// + /// This function invokes the closure originally passed to + /// `#expect(exitsWith:)` _in the current process_. That closure is expected + /// to terminate the process; if it does not, the testing library will + /// terminate the process as if its `main()` function returned naturally. + public consuming func callAsFunction() async -> Never + + /// Find the exit test function at the given source location. + /// + /// - Parameters: + /// - id: The unique identifier of the exit test to find. + /// + /// - Returns: The specified exit test function, or `nil` if no such exit test + /// could be found. + public static func find(identifiedBy id: ExitTest.ID) -> Self? + + /// A handler that is invoked when an exit test starts. + /// + /// - Parameters: + /// - exitTest: The exit test that is starting. + /// + /// - Returns: The result of the exit test including the condition under which + /// it exited. + /// + /// - Throws: Any error that prevents the normal invocation or execution of + /// the exit test. + /// + /// This handler is invoked when an exit test (i.e. a call to either + /// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or + /// ``require(exitsWith:observing:_:sourceLocation:performing:)``) is started. + /// The handler is responsible for initializing a new child environment + /// (typically a child process) and running the exit test identified by + /// `sourceLocation` there. + /// + /// In the child environment, you can find the exit test again by calling + /// ``ExitTest/find(at:)`` and can run it by calling + /// ``ExitTest/callAsFunction()``. + /// + /// The parent environment should suspend until the results of the exit test + /// are available or the child environment is otherwise terminated. The parent + /// environment is then responsible for interpreting those results and + /// recording any issues that occur. + public typealias Handler = @Sendable (_ exitTest: borrowing ExitTest) async throws -> ExitTest.Result +} + +@_spi(ForToolsIntegrationOnly) +extension Configuration { + /// A handler that is invoked when an exit test starts. + /// + /// For an explanation of how this property is used, see ``ExitTest/Handler``. + /// + /// When using the `swift test` command from Swift Package Manager, this + /// property is pre-configured. Otherwise, the default value of this property + /// records an issue indicating that it has not been configured. + public var exitTestHandler: ExitTest.Handler { get set } +} +``` + +Any tools that use `swift build --build-tests`, `swift test`, or equivalent to +compile executables for testing will inherit the functionality provided for +`swift test` and do not need to implement their own exit test handlers. Tools +that directly compile test targets or otherwise do not leverage Swift Package +Manager will need to provide an implementation. + +## Future directions + +### Support for iOS, WASI, etc. + +The need for exit tests on other platforms is just as strong as it is on the +supported platforms (macOS, Linux, FreeBSD/OpenBSD, and Windows). These +platforms do not support spawning new processes, so a different mechanism for +running exit tests would be needed. + +Android _does_ have `posix_spawn()` and related API and may be able to use the +same implementation as Linux. Android support is an ongoing area of research for +Swift Testing's core team. + +### Recursive exit tests + +The technical constraints preventing recursive exit test invocation can be +resolved if there is a need to do so. However, we don't anticipate that this +constraint will be a serious issue for developers. + +### Support for passing state + +Arbitrary state is necessarily not preserved between the parent and child +processes, but there is little to prevent us from adding a variadic `arguments:` +argument and passing values whose types conform to `Codable`. + +The blocker right now is that there is no type information during macro +expansion, meaning that the testing library can emit the glue code to _encode_ +arguments, but does not know what types to use when _decoding_ those arguments. +If generic types were made available during macro expansion via the macro +expansion context, then it would be possible to synthesize the correct logic. + +Alternatively, if the language gained something akin to C++'s `decltype()`, we +could leverage closures' capture list syntax. Subjectively, capture lists ought +to be somewhat intuitive for developers in this context: + +```swift +let (lettuce, cheese, crema) = taco.addToppings() +await #expect(exitsWith: .failure) { [taco, plant = lettuce, cheese, crema] in + try taco.removeToppings(plant, cheese, crema) +} +``` + +### More nuanced support for throwing errors from exit test bodies + +Currently, if an error is thrown from an exit test without being caught, the +test behaves the same way a program does when an error is thrown from an +explicit or implicit `main() throws` function: the process terminates abnormally +and control returns to the test function that is awaiting the exit test: + +```swift +await #expect(exitsWith: .failure) { + throw TacoError.noTacosFound +} +``` + +If the test function is expecting `.failure`, this means the test passes. +Although this behavior is consistent with modelling an exit test as an +independent program (i.e. the exit test acts like its own `main()` function), it +may be surprising to test authors who aren't thinking about error handling. In +the future, we may want to offer a compile-time diagnostic if an error is thrown +from an exit test body without being caught, or offer a distinct exit condition +(i.e. `.errorNotCaught(_ error: Error & Codable)`) for these uncaught errors. +For error types that conform to `Codable`, we could offer rethrowing behavior, +but this is not possible for error types that cannot be sent across process +boundaries. + +### Exit-testing customized processes + +The current model of exit tests is that they run in approximately the same +environment as the test process by spawning a copy of the executable under test. +There is a very real use case for allowing testing other processes and +inspecting their output. In the future, we could provide API to spawn a process +with particular arguments and environment variables, then inspect its exit +condition and standard output/error streams: + +```swift +let result = try await #require( + executableAt: "/usr/bin/swift", + passing: ["build", "--package-path", ...], + environment: [:], + exitsWith: .success +) +#expect(result.standardOutputContent.contains("Build went well!").utf8) +``` + +We could also investigate explicitly integrating with [`Foundation.Process`](https://developer.apple.com/documentation/foundation/process) +or the proposed [`Foundation.Subprocess`](https://github.com/swiftlang/swift-foundation/blob/main/Proposals/0007-swift-subprocess.md) +as an alternative: + +```swift +let process = Process() +process.executableURL = URL(filePath: "/usr/bin/swift", directoryHint: .notDirectory) +process.arguments = ["build", "--package-path", ...] +let result = try await #require(process, exitsWith: .success) +#expect(result.standardOutputContent.contains("Build went well!").utf8) +``` + +## Alternatives considered + +- Doing nothing. + +- Marking exit tests using a trait rather than a new `#expect()` overload: + + ```swift + @Test(.exits(with: .failure)) + func `We only eat delicious tacos`() { + var taco = Taco() + taco.isDelicious = false + eat(taco) + } + ``` + + This syntax would require separate test functions for each exit test, while + reusing the same function for relatively concise tests may be preferable. + + It would also potentially conflict with parameterized tests, as it is not + possible to pass arbitrary parameters to the child process. It would be + necessary to teach the testing library's macro target about the + `.exits(with:)` trait so that it could produce a diagnostic when used with a + parameterized test function. + +- Inferring exit tests from test functions that return `Never`: + + ```swift + @Test func `No seafood for me, thanks!`() -> Never { + var taco = Taco() + taco.toppings.append(.shrimp) + eat(taco) + fatalError("Should not have eaten that!") + } + ``` + + There's a certain synergy in inferring that a test function that returns + `Never` must necessarily be a crasher and should be handled out of process. + However, this forces the test author to add a call to `fatalError()` or + similar in the event that the code under test does _not_ terminate, and there + is no obvious way to express that a specific exit code, signal, or other + condition is expected (as opposed to just "it exited".) + + We might want to support that sort of inference in the future (i.e. "don't run + this test in-process because it will terminate the test run"), but without + also inferring success or failure from the process' exit status. + +- Naming the macro something else such as: + + - `#exits(with:_:)`; + - `#exits(because:_:)`; + - `#expect(exitsBecause:_:)`; + - `#expect(terminatesBecause:_:)`; etc. + + While "with" is normally avoided in symbol names in Swift, it sometimes really + is the best preposition for the job. "Because", "due to", and others don't + sound "right" when the entire expression is read out loud. For example, you + probably wouldn't say "exits due to success" in English. + +- Combining `StatusAtExit` and `ExitTest.Condition` into a single type: + + ```swift + enum ExitCondition { + case failure // any failure + case exitCode(CInt) + case signal(CInt) + } + ``` + + This simplified the set of types used for exit tests, but made comparing two + exit conditions complicated and necessitated a `==` operator that did not + satisfy the requirements of the `Equatable` protocol. + +- Naming `StatusAtExit` something else such as: + + - `ExitStatus`, which could be too easily confusable with exit _codes_ such as + `EXIT_SUCCESS`; + - `ProcessStatus`, but we don't say "process" in our API surface elsewhere; + - `Status`, which is too generic, + - `ExitReason`, but "status" is a more widely-used term of art for this + concept; or + - `terminationStatus` (which Foundation to represent approximately the same + concept), but we don't use "termination" in Swift Testing's API anywhere. + + I settled on `StatusAtExit` because it was distinct and makes it clear that it + represents the status of a process _at exit time_. `ExitStatus` could be + interpreted as the status of the exit itself, i.e.: + + ```swift + enum ExitStatus { + case running + case suspended + case exiting + case exited + } + ``` + +- Changing the implementation of `precondition()`, `fatalError()`, etc. in the + standard library so that they do not terminate the current process while + testing, thus removing the need to spawn a child process for an exit test. + + Most of the functions in this family return `Never`, and changing their return + types would be ABI-breaking (as well as a pessimization in production code.) + Even if we did modify these functions in the Swift standard library, other + ways to terminate the process exist and would not be covered: + + - Calling the C standard function `exit()`; + - Throwing an uncaught Objective-C or C++ exception; + - Sending a signal to the process; or + - Misusing memory (e.g. trying to dereference a null pointer.) + + Modifying the C or C++ standard library, or modifying the Objective-C runtime, + would be well beyond the scope of this proposal. + +## Acknowledgments + +Many thanks to the XCTest and Swift Testing team. Thanks to @compnerd for his +help with the Windows implementation. Thanks to my colleagues Coops, +Danny N., David R., Drew Y., and Robert K. at Apple for +their help with the nuances of crash reporting on macOS. From b2a77d6128d38765d4d0bc7a7e25f6678e0a6c41 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 16:33:06 -0500 Subject: [PATCH 113/505] Proposal to add attachments to Swift Testing This PR adds the draft proposal for attachments in Swift Testing. --- proposals/testing/NNNN-attachments.md | 436 ++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 proposals/testing/NNNN-attachments.md diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md new file mode 100644 index 0000000000..ce3d5efdeb --- /dev/null +++ b/proposals/testing/NNNN-attachments.md @@ -0,0 +1,436 @@ +# Attachments + +* Proposal: [SWT-NNNN](NNNN-attachments.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Awaiting review** +* Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) +* Implementation: [swiftlang/swift-testing#796](https://github.com/swiftlang/swift-testing/pull/796) +* Review: ([pitch](https://forums.swift.org/...)) + +## Introduction + +Test authors frequently need to include out-of-band data with tests that can be +used to diagnose issues when a test fails. This proposal introduces a new API +called "attachments" (analogous to the same-named feature in XCTest) as well as +the infrastructure necessary to create new attachments and handle them in tools +like VS Code. + +## Motivation + +When a test fails, especially in a remote environment like CI, it can often be +difficult to determine what exactly has gone wrong. Data that was produced +during the test can be useful, but there is currently no mechanism in Swift +Testing to output arbitrary data other than via `stdout`/`stderr` or via an +artificially-generated issue. A dedicated interface for attaching arbitrary +information to a test would allow test authors to gather relevant information +from a test in a structured way. + +## Proposed solution + +We propose introducing a new type to Swift Testing, `Attachment`, that represents +some arbitrary "attachment" to associate with a test. Along with `Attachment`, +we will introduce a new protocol, `Attachable`, to which types can conform to +indicate they can be attached to a test. + +Default conformances to `Attachable` will be provided for standard library types +that can reasonably be attached. We will also introduce a **cross-import overlay** +with Foundation—that is, a tertiary module that is automatically imported when +a test target imports both Foundation _and_ Swift Testing—that includes +additional conformances for Foundation types such as `Data` and `URL` and +provides support for attaching values that also conform to `Encodable` or +`NSSecureCoding`. + +## Detailed design + +The `Attachment` type is defined as follows: + +```swift +/// A type describing values that can be attached to the output of a test run +/// and inspected later by the user. +/// +/// Attachments are included in test reports in Xcode or written to disk when +/// tests are run at the command line. To create an attachment, you need a value +/// of some type that conforms to ``Attachable``. Initialize an instance of +/// ``Attachment`` with that value and, optionally, a preferred filename to use +/// when writing to disk. +public struct Attachment: ~Copyable where AttachableValue: Attachable & ~Copyable { + /// A filename to use when writing this attachment to a test report or to a + /// file on disk. + /// + /// The value of this property is used as a hint to the testing library. The + /// testing library may substitute a different filename as needed. If the + /// value of this property has not been explicitly set, the testing library + /// will attempt to generate its own value. + public var preferredName: String { get } + + /// The value of this attachment. + public var attachableValue: AttachableValue { get } + + /// Initialize an instance of this type that encloses the given attachable + /// value. + /// + /// - Parameters: + /// - attachableValue: The value that will be attached to the output of the + /// test run. + /// - preferredName: The preferred name of the attachment when writing it to + /// a test report or to disk. If `nil`, the testing library attempts to + /// derive a reasonable filename for the attached value. + /// - sourceLocation: The source location of the call to this initializer. + /// This value is used when recording issues associated with the + /// attachment. + public init( + _ attachableValue: consuming AttachableValue, + named preferredName: String? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) + + /// Attach this instance to the current test. + /// + /// - Parameters: + /// - sourceLocation: The source location of the call to this function. + /// + /// When attaching a value of a type that does not conform to both + /// [`Sendable`](https://developer.apple.com/documentation/swift/sendable) and + /// [`Copyable`](https://developer.apple.com/documentation/swift/copyable), + /// the testing library encodes it as data immediately. If the value cannot be + /// encoded and an error is thrown, that error is recorded as an issue in the + /// current test and the attachment is not written to the test report or to + /// disk. + /// + /// An attachment can only be attached once. + public consuming func attach(sourceLocation: SourceLocation = #_sourceLocation) + + /// Call a function and pass a buffer representing the value of this + /// instance's ``attachableValue-2tnj5`` property to it. + /// + /// - Parameters: + /// - body: A function to call. A temporary buffer containing a data + /// representation of this instance is passed to it. + /// + /// - Returns: Whatever is returned by `body`. + /// + /// - Throws: Whatever is thrown by `body`, or any error that prevented the + /// creation of the buffer. + /// + /// The testing library uses this function when writing an attachment to a + /// test report or to a file on disk. This function calls the + /// ``Attachable/withUnsafeBytes(for:_:)`` function on this attachment's + /// ``attachableValue-2tnj5`` property. + @inlinable public borrowing func withUnsafeBytes( + _ body: (UnsafeRawBufferPointer) throws -> R + ) throws -> R +} + +extension Attachment: Copyable where AttachableValue: Copyable {} +extension Attachment: Sendable where AttachableValue: Sendable {} +``` + +With `Attachment` comes `Attachable`, a protocol to which "attachable values" +conform: + +```swift +/// A protocol describing a type that can be attached to a test report or +/// written to disk when a test is run. +/// +/// To attach an attachable value to a test report or test run output, use it to +/// initialize a new instance of ``Attachment``, then call +/// ``Attachment/attach(sourceLocation:)``. An attachment can only be attached +/// once. +/// +/// The testing library provides default conformances to this protocol for a +/// variety of standard library types. Most user-defined types do not need to +/// conform to this protocol. +/// +/// A type should conform to this protocol if it can be represented as a +/// sequence of bytes that would be diagnostically useful if a test fails. If a +/// type cannot conform directly to this protocol (such as a non-final class or +/// a type declared in a third-party module), you can create a container type +/// that conforms to ``AttachableContainer`` to act as a proxy. +public protocol Attachable: ~Copyable { + /// An estimate of the number of bytes of memory needed to store this value as + /// an attachment. + /// + /// The testing library uses this property to determine if an attachment + /// should be held in memory or should be immediately persisted to storage. + /// Larger attachments are more likely to be persisted, but the algorithm the + /// testing library uses is an implementation detail and is subject to change. + /// + /// The value of this property is approximately equal to the number of bytes + /// that will actually be needed, or `nil` if the value cannot be computed + /// efficiently. The default implementation of this property returns `nil`. + /// + /// - Complexity: O(1) unless `Self` conforms to `Collection`, in which case + /// up to O(_n_) where _n_ is the length of the collection. + var estimatedAttachmentByteCount: Int? { get } + + /// Call a function and pass a buffer representing this instance to it. + /// + /// - Parameters: + /// - attachment: The attachment that is requesting a buffer (that is, the + /// attachment containing this instance.) + /// - body: A function to call. A temporary buffer containing a data + /// representation of this instance is passed to it. + /// + /// - Returns: Whatever is returned by `body`. + /// + /// - Throws: Whatever is thrown by `body`, or any error that prevented the + /// creation of the buffer. + /// + /// The testing library uses this function when writing an attachment to a + /// test report or to a file on disk. The format of the buffer is + /// implementation-defined, but should be "idiomatic" for this type: for + /// example, if this type represents an image, it would be appropriate for + /// the buffer to contain an image in PNG format, JPEG format, etc., but it + /// would not be idiomatic for the buffer to contain a textual description of + /// the image. + borrowing func withUnsafeBytes(for attachment: borrowing Attachment, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R + + /// Generate a preferred name for the given attachment. + /// + /// - Parameters: + /// - attachment: The attachment that needs to be named. + /// - suggestedName: A suggested name to use as the basis of the preferred + /// name. This string was provided by the developer when they initialized + /// `attachment`. + /// + /// - Returns: The preferred name for `attachment`. + /// + /// The testing library uses this function to determine the best name to use + /// when adding `attachment` to a test report or persisting it to storage. The + /// default implementation of this function returns `suggestedName` without + /// any changes. + borrowing func preferredName(for attachment: borrowing Attachment, basedOn suggestedName: String) -> String +} +``` + +Default conformances to `Attachable` are provided for: + +- `Array`, `ContiguousArray`, and `ArraySlice` +- `String` and `Substring` +- `Data` (if Foundation is also imported) + +Default _implementations_ are provided for types when they conform to +`Attachable` and either `Encodable` or `NSSecureCoding` (or both.) To use these +conformances, Foundation must be imported because `JSONEncoder` and +`PropertyListEncoder` are members of Foundation, not the Swift standard library. + +Some types cannot conform directly to `Attachable` because they require +additional information to encode correctly, or because they are not directly +`Sendable` or `Copyable`. A second protocol, `AttachableContainer`, is provided +that refines `Attachable`: + +```swift +/// A protocol describing a type that can be attached to a test report or +/// written to disk when a test is run and which contains another value that it +/// stands in for. +/// +/// To attach an attachable value to a test report or test run output, use it to +/// initialize a new instance of ``Attachment``, then call +/// ``Attachment/attach(sourceLocation:)``. An attachment can only be attached +/// once. +/// +/// A type can conform to this protocol if it represents another type that +/// cannot directly conform to ``Attachable``, such as a non-final class or a +/// type declared in a third-party module. +public protocol AttachableContainer: Attachable, ~Copyable { + /// The type of the attachable value represented by this type. + associatedtype AttachableValue + + /// The attachable value represented by this instance. + var attachableValue: AttachableValue { get } +} + +extension Attachment where AttachableValue: AttachableContainer & ~Copyable { + /// The value of this attachment. + /// + /// When the attachable value's type conforms to ``AttachableContainer``, the + /// value of this property equals the container's underlying attachable value. + /// To access the attachable value as an instance of `T` (where `T` conforms + /// to ``AttachableContainer``), specify the type explicitly: + /// + /// ```swift + /// let attachableValue = attachment.attachableValue as T + /// ``` + public var attachableValue: AttachableValue.AttachableValue { get } +} +``` + +The cross-import overlay with Foundation also provides the following convenience +interface for attaching the contents of a file or directory on disk: + +```swift +extension Attachment where AttachableValue == _AttachableURLContainer { + /// Initialize an instance of this type with the contents of the given URL. + /// + /// - Parameters: + /// - url: The URL containing the attachment's data. + /// - preferredName: The preferred name of the attachment when writing it to + /// a test report or to disk. If `nil`, the name of the attachment is + /// derived from the last path component of `url`. + /// - sourceLocation: The source location of the call to this initializer. + /// This value is used when recording issues associated with the + /// attachment. + /// + /// - Throws: Any error that occurs attempting to read from `url`. + public init( + contentsOf url: URL, + named preferredName: String? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) async throws +} +``` + +`_AttachableURLContainer` is a type that conforms to `AttachableContainer` and +encloses the URL and corresponding mapped data. As an implementation detail, it +is omitted from this proposal for brevity. + +## Source compatibility + +This proposal is additive and has no impact on existing code. + +## Integration with supporting tools + +We will add a new command-line argument to the `swift test` command in Swift +Package Manager: + +```sh +--attachments-path Path where attachments should be saved. +``` + +If specified, an attachment will be written to that path when its `attach()` +method is called. If not specified, attachments are not saved to disk. Tools +that indirectly use Swift Testing through `swift test` can specify a path (e.g. +to a directory created inside the system's temporary directory), then move or +delete the created files as needed. + +The JSON event stream ABI will be amended correspondingly: + +```diff +--- a/Documentation/ABI/JSON.md ++++ b/Documentation/ABI/JSON.md + ::= { + "kind": , + "instant": , ; when the event occurred + ["issue": ,] ; the recorded issue (if "kind" is "issueRecorded") ++ ["attachment": ,] ; the attachment (if kind is "valueAttached") + "messages": , + ["testID": ,] + } + + ::= "runStarted" | "testStarted" | "testCaseStarted" | + "issueRecorded" | "testCaseEnded" | "testEnded" | "testSkipped" | +- "runEnded" ; additional event kinds may be added in the future ++ "runEnded" | "valueAttached"; additional event kinds may be added in the future + ++ ::= { ++ "path": , ; the absolute path to the attachment on disk ++} +``` + +As these changes are additive only, the JSON schema version does not need to be +incremented to support them. We are separately planning to increment the JSON +schema version to support other features; these changes will apply to the newer +version too. + +## Future directions + +- Attachment lifetime management: XCTest's attachments allow for specifying a + "lifetime", with two lifetimes currently available: + + ```objc + typedef NS_ENUM(NSInteger, XCTAttachmentLifetime) { + XCTAttachmentLifetimeKeepAlways = 0, + XCTAttachmentLifetimeDeleteOnSuccess = 1 + }; + ``` + + If a test passes, it is probably not necessary to keep its attachments saved + to disk. The exact "shape" this feature should take in Swift Testing is not + yet clear. + +- Image attachments: it is often useful to be able to attach images to tests, + however there is no cross-platform solution for this functionality. An + experimental implementation that allows attaching an instance of `CGImage` (on + Apple platforms) is available in Swift Testing's repository and shows what it + might look like for us to provide this functionality. + +- Additional conformances for types in other modules: in order to keep Swift + Testing's dependency graph as small as possible, we cannot link it to + arbitrary packages such as (for example) swift-collections even if it would be + useful to do so. That means we can't directly provide conformances to + `Attachable` for types in those modules. Adding additional cross-import + overlays would allow us to provide those conformances when both Swift Testing + and those packages are imported at the same time. + + This functionality may require changes in Swift Package Manager that are + beyond the scope of this proposal. + +- Adopting `RawSpan` instead of `UnsafeRawBufferPointer`: `RawSpan` represents a + safer alternative to `UnsafeRawBufferPointer`, but it is not yet available + everywhere we'd need it in the standard library, and our minimum deployment + targets on Apple's platforms do not allow us to require the use of `RawSpan` + (as no shipping version of Apple's platforms includes it.) + +- Adding an associated `Metadata` type to `Attachable` allowing for inclusion of + arbitrary out-of-band data to attachments: we see several uses for such a + feature: + + - Fine-grained control of the serialization format used for `Encodable` types; + - Metrics (scaling factor, rotation, etc.) for images; and + - Compression algorithms to use for attached files and directories. + + The exact shape of this interface needs further consideration, but it could be + added in the future without disrupting the interface we are proposing here. + [swiftlang/swift-testing#824](https://github.com/swiftlang/swift-testing/pull/824) + includes an experimental implementation of this feature. + +## Alternatives considered + +- Doing nothing: there's sufficient demand for this feature that we know we want + to address it. + +- Reusing the existing `XCTAttachment` API from XCTest: while this would + _probably_ have saved me a lot of typing, `XCTAttachment` is an Objective-C + class and is only available on Apple's platforms. The open-source + swift-corelibs-xctest package does not include it or an equivalent interface. + As well, this would create a dependency on XCTest in Swift Testing that does + not currently exist. + +- Implementing `Attachment` as a non-generic type and eagerly serializing + non-sendable or move-only attachable values: an earlier implementation did + exactly this, but it forced us to include an existential box in `Attachment` + to store the attachable value, and that would preclude ever supporting + attachments in Embedded Swift. + +- Having `Attachment` take a byte buffer rather than an attachable value, or + having it take a closure that returns a byte buffer: this would just raise the + problem of attaching arbitrary values up to the test author's layer, and that + would no doubt produce a lot of duplicate implementations of "turn this value + into a byte buffer" while also worsening the interface's ergonomics. + +- Adding a `var contentType: UTType { get set }` property to `Attachment` or to + `Attachable`: `XCTAttachment` lets you specify a Uniform Type Identifier that + tells Xcode the type of data. Uniform Type Identifiers are proprietary and not + available on Linux or Windows, and adding that property would force us to also + add a public dependency on the `UniformTypeIdentifiers` framework and, + indirectly, on Foundation, which would prevent Foundation from authoring tests + using Swift Testing in the future due to the resulting circular dependency. + + We considered using a MIME type instead, but there is no portable mechanism + for turning a MIME type into a path extension, which is ultimately what we + need when writing an attachment to persistent storage. + + Instead, `Attachable` includes the function `preferredName(for:basedOn:)` that + allows an implementation (such as that of `Encodable & Attachable`) to add a + path extension to the filename specified by the test author if needed. + +## Acknowledgments + +Thanks to Stuart Montgomery and Brian Croom for goading me into finally writing +this proposal! + +Thanks to Wil Addario-Turner for his feedback, in particular around `UTType` and +MIME type support. + +Thanks to Honza Dvorsky for his earlier work on attachments in XCTest and his +ideas on how to improve Swift Testing's implementation. From 54569d464d785c596b3f5b92739fa61a50cd8155 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 16:56:57 -0500 Subject: [PATCH 114/505] Update prefix --- proposals/testing/NNNN-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index ce3d5efdeb..ae4b08fedd 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -1,6 +1,6 @@ # Attachments -* Proposal: [SWT-NNNN](NNNN-attachments.md) +* Proposal: [ST-NNNN](NNNN-attachments.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Status: **Awaiting review** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) From 7e9a4fd8986a877e694b680aad023649b04ec881 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 16:57:41 -0500 Subject: [PATCH 115/505] Update prefix --- proposals/testing/NNNN-exit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/NNNN-exit-tests.md index 06f740d63e..b273fab3f3 100644 --- a/proposals/testing/NNNN-exit-tests.md +++ b/proposals/testing/NNNN-exit-tests.md @@ -1,6 +1,6 @@ # Exit tests -* Proposal: [SWT-NNNN](NNNN-exit-tests.md) +* Proposal: [ST-NNNN](NNNN-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Status: **Awaiting review** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) From f08054cb6fa2bd5a4ac21942fe1a514df827780d Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 17:09:47 -0500 Subject: [PATCH 116/505] Update implementation link to point to the PR that promotes exit tests to API --- proposals/testing/NNNN-exit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/NNNN-exit-tests.md index b273fab3f3..76a4edff3a 100644 --- a/proposals/testing/NNNN-exit-tests.md +++ b/proposals/testing/NNNN-exit-tests.md @@ -4,7 +4,7 @@ * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Status: **Awaiting review** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) -* Implementation: [apple/swift-testing#307](https://github.com/apple/swift-testing/pull/307) +* Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) * Review: ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction From a9c639f1262e63cffd9378d8157b4698c74928ae Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 17:10:23 -0500 Subject: [PATCH 117/505] Update implementation link to point to the PR that promotes attachments to API --- proposals/testing/NNNN-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index ae4b08fedd..26aecfcca5 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -4,7 +4,7 @@ * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Status: **Awaiting review** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) -* Implementation: [swiftlang/swift-testing#796](https://github.com/swiftlang/swift-testing/pull/796) +* Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) * Review: ([pitch](https://forums.swift.org/...)) ## Introduction From 63a0034f61eb6b027215198d304905b7ddcbc6b9 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 3 Mar 2025 17:11:31 -0500 Subject: [PATCH 118/505] Add pitch URL --- proposals/testing/NNNN-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index 26aecfcca5..02c02f5610 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -5,7 +5,7 @@ * Status: **Awaiting review** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) -* Review: ([pitch](https://forums.swift.org/...)) +* Review: ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) ## Introduction From b4daebfb4bab5a6b6f9620a0f093773cd060526b Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 4 Mar 2025 15:05:58 +0900 Subject: [PATCH 119/505] link to partial implementation --- proposals/NNNN-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md index d467268e14..068be78c57 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -3,8 +3,8 @@ * Proposal: [SE-NNNN](NNNN-filename.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: TBD -* Status: **Awaiting implementation** -* Implementation: TODO +* Status: **Partially implemented on `main`** +* Implementation: [TODO](https://github.com/swiftlang/swift/pull/79608) * Review: ... ## Introduction From 59b9d9c51cc87eec61d515f6a7e3438a8e5ce8d9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 4 Mar 2025 15:06:49 +0900 Subject: [PATCH 120/505] edit filename in text --- proposals/NNNN-task-start-synchronously-on-caller-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md index 068be78c57..ccb621e83f 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -1,6 +1,6 @@ # Starting tasks synchronously from caller context -* Proposal: [SE-NNNN](NNNN-filename.md) +* Proposal: [SE-NNNN](NNNN-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: TBD * Status: **Partially implemented on `main`** From 041c19eabe56028eba40e9a719e8fe37b161b8f6 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 4 Mar 2025 10:10:31 -0500 Subject: [PATCH 121/505] fix typo --- proposals/testing/NNNN-exit-tests.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/NNNN-exit-tests.md index 76a4edff3a..c822fd90fb 100644 --- a/proposals/testing/NNNN-exit-tests.md +++ b/proposals/testing/NNNN-exit-tests.md @@ -448,8 +448,12 @@ a memory-intensive operation, so the caller must explicitly opt in: ```swift @Test func `We only eat delicious tacos`() async throws { - let result = try await #require(exitsWith: .failure, observing: [\.standardErrorContent])) { ... } - #expect(result.standardOutputContent.contains("ERROR: This taco tastes terrible!".utf8) + let result = try await #require( + exitsWith: .failure, + observing: [\.standardErrorContent]) + ) { ... } + let stdout = result.standardOutputContent + #expect(stdout.contains("ERROR: This taco tastes terrible!".utf8)) } ``` From 8c709f14c7a103c0419676440bcb697e9f0fc445 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 4 Mar 2025 09:14:14 -0600 Subject: [PATCH 122/505] Import existing, already-implemented Swift Testing proposals (#2721) * Import existing, already-implemented Swift Testing proposals * Update relative link --- .../0000-swift-testing-template.md | 6 +- proposals/testing/0001-refactor-bug-inits.md | 173 ++++++ proposals/testing/0002-json-abi.md | 428 +++++++++++++++ .../testing/0003-make-serialized-trait-api.md | 156 ++++++ ...ranularity-of-test-time-limit-durations.md | 207 +++++++ .../testing/0005-ranged-confirmations.md | 191 +++++++ .../0006-return-errors-from-expect-throws.md | 272 +++++++++ proposals/testing/0007-test-scoping-traits.md | 515 ++++++++++++++++++ 8 files changed, 1945 insertions(+), 3 deletions(-) create mode 100644 proposals/testing/0001-refactor-bug-inits.md create mode 100644 proposals/testing/0002-json-abi.md create mode 100644 proposals/testing/0003-make-serialized-trait-api.md create mode 100644 proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md create mode 100644 proposals/testing/0005-ranged-confirmations.md create mode 100644 proposals/testing/0006-return-errors-from-expect-throws.md create mode 100644 proposals/testing/0007-test-scoping-traits.md diff --git a/proposal-templates/0000-swift-testing-template.md b/proposal-templates/0000-swift-testing-template.md index 2ea8c57572..9e0377961e 100644 --- a/proposal-templates/0000-swift-testing-template.md +++ b/proposal-templates/0000-swift-testing-template.md @@ -1,11 +1,11 @@ # Swift Testing Feature name -* Proposal: [SWT-NNNN](NNNN-filename.md) +* Proposal: [ST-NNNN](NNNN-filename.md) * Authors: [Author 1](https://github.com/author1), [Author 2](https://github.com/author2) * Status: **Awaiting implementation** or **Awaiting review** * Bug: _if applicable_ [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/issues/NNNNN) * Implementation: [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/pull/NNNNN) -* Previous Proposal: _if applicable_ [SWT-XXXX](XXXX-filename.md) +* Previous Proposal: _if applicable_ [ST-XXXX](XXXX-filename.md) * Previous Revision: _if applicable_ [1](https://github.com/swiftlang/swift-evolution/blob/...commit-ID.../proposals/testing/NNNN-filename.md) * Review: ([pitch](https://forums.swift.org/...)) @@ -44,7 +44,7 @@ between this proposal and another proposal. For example, this proposal might have been removed from a previous proposal so that it can be reviewed separately, or this proposal might supersede a previous proposal in some way that was felt to exceed the scope of a "revision". Include text briefly explaining the -relationship, such as "Supersedes SWT-1234" or "Extracted from SWT-01234". If +relationship, such as "Supersedes ST-1234" or "Extracted from ST-01234". If possible, link to a post explaining the relationship, such as a review decision that asked for part of the proposal to be split off. Otherwise, you can just link to the previous proposal. diff --git a/proposals/testing/0001-refactor-bug-inits.md b/proposals/testing/0001-refactor-bug-inits.md new file mode 100644 index 0000000000..385047be48 --- /dev/null +++ b/proposals/testing/0001-refactor-bug-inits.md @@ -0,0 +1,173 @@ +# Dedicated `.bug()` functions for URLs and IDs + +* Proposal: [ST-0001](0001-refactor-bug-inits.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Implemented (Swift 6.0)** +* Implementation: [swiftlang/swift-testing#401](https://github.com/swiftlang/swift-testing/pull/401) +* Review: ([pitch](https://forums.swift.org/t/pitch-dedicated-bug-functions-for-urls-and-ids/71842)), ([acceptance](https://forums.swift.org/t/swt-0001-dedicated-bug-functions-for-urls-and-ids/71842/2)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0001](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0001-refactor-bug-inits.md). + +## Introduction + +One of the features of swift-testing is a test traits system that allows +associating metadata with a test suite or test function. One trait in +particular, `.bug()`, has the potential for integration with development tools +but needs some refinement before integration would be practical. + +## Motivation + +A test author can associate a bug (AKA issue, problem, ticket, etc.) with a test +using the `.bug()` trait, to which they pass an "identifier" for the bug. The +swift-testing team's intent here was that a test author would pass the unique +identifier of the bug in the test author's preferred bug-tracking system (e.g. +GitHub Issues, Bugzilla, etc.) and that any tooling built around this trait +would be able to infer where the bug was located and how to view it. + +It became clear immediately that a generic system for looking up bugs by unique +identifier in an arbitrary and unspecified database wouldn't be a workable +solution. So we modified the description of `.bug()` to explain that, if the +identifier passed to it was a valid URL, then it would be "interpreted" as a URL +and that tools could be designed to open that URL as needed. + +This design change then placed the burden of parsing each `.bug()` trait and +potentially mapping it to a URL on tools. swift-testing itself avoids linking to +or using Foundation API such as `URL`, so checking for a valid URL inside the +testing library was not feasible either. + +## Proposed solution + +To solve the underlying problem and allow test authors to specify a URL when +available, or just an opaque identifier otherwise, we propose splitting the +`.bug()` function up into two overloads: + +- The first overload takes a URL string and additional optional metadata; +- The second overload takes a bug identifier as an opaque string or integer and, + optionally, a URL string. + +Test authors are then free to specify any combination of URL and opaque +identifier depending on the information they have available and their specific +needs. Tools authors are free to consume either or both of these properties and +present them where appropriate. + +## Detailed design + +The `Bug` trait type and `.bug()` trait factory function shall be refactored +thusly: + +```swift +/// A type representing a bug report tracked by a test. +/// +/// To add this trait to a test, use one of the following functions: +/// +/// - ``Trait/bug(_:_:)`` +/// - ``Trait/bug(_:id:_:)-10yf5`` +/// - ``Trait/bug(_:id:_:)-3vtpl`` +public struct Bug: TestTrait, SuiteTrait, Equatable, Hashable, Codable { + /// A URL linking to more information about the bug, if available. + /// + /// The value of this property represents a URL conforming to + /// [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). + public var url: String? + + /// A unique identifier in this bug's associated bug-tracking system, if + /// available. + /// + /// For more information on how the testing library interprets bug + /// identifiers, see . + public var id: String? + + /// The human-readable title of the bug, if specified by the test author. + public var title: Comment? +} + +extension Trait where Self == Bug { + /// Construct a bug to track with a test. + /// + /// - Parameters: + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. + /// + /// - Returns: An instance of ``Bug`` representing the specified bug. + public static func bug(_ url: _const String, _ title: Comment? = nil) -> Self + + /// Construct a bug to track with a test. + /// + /// - Parameters: + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - id: The unique identifier of this bug in its associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. + /// + /// - Returns: An instance of ``Bug`` representing the specified bug. + public static func bug(_ url: _const String? = nil, id: some Numeric, _ title: Comment? = nil) -> Self + + /// Construct a bug to track with a test. + /// + /// - Parameters: + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - id: The unique identifier of this bug in its associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. + /// + /// - Returns: An instance of ``Bug`` representing the specified bug. + public static func bug(_ url: _const String? = nil, id: _const String, _ title: Comment? = nil) -> Self +} +``` + +The `@Test` and `@Suite` macros have already been modified so that they perform +basic validation of a URL string passed as input and emit a diagnostic if the +URL string appears malformed. + +## Source compatibility + +This change is expected to be source-breaking for test authors who have already +adopted the existing `.bug()` functions. This change is source-breaking for code +that directly refers to these functions by their signatures. This change is +source-breaking for code that uses the `identifier` property of the `Bug` type +or expects it to contain a URL. + +## Integration with supporting tools + +Tools that integrate with swift-testing and provide lists of tests or record +results after tests have run can use the `Bug` trait on tests to present +relevant identifiers and/or URLs to users. + +Tools that use the experimental event stream output feature of the testing +library will need a JSON schema for bug traits on tests. This work is tracked in +a separate upcoming proposal. + +## Alternatives considered + +- Inferring whether or not a bug identifier was a URL by parsing it at runtime + in tools. As discussed above, this option would require every tool that + integrates with swift-testing to provide its own URL-parsing logic. + +- Using different argument labels (e.g. the label `url` for the URL argument + and/or no label for the `id` argument.) We felt that URLs, which are + recognizable by their general structure, did not need labels. At least one + argument must have a label to avoid ambiguous resolution of the `.bug()` + function at compile time. + +- Inferring whether or not a bug identifier was a URL by parsing it at compile- + time or at runtime using `Foundation.URL` or libcurl. swift-testing actively + avoids linking to Foundation if at all possible, and libcurl would be a + platform-specific solution (Windows doesn't ship with libcurl, but does have + `InternetCrackUrlW()` whose parsing engine differs.) We also run the risk of + inappropriately interpreting some arbitrary bug identifier as a URL when it is + not meant to be parsed that way. + +- Removing the `.bug()` trait. We see this particular trait as having strong + potential for integration with tools and for use by test authors; removing it + because we can't reliably parse URLs would be unfortunate. + +## Acknowledgments + +Thanks to the swift-testing team and managers for their contributions! Thanks to +our community for the initial feedback around this feature. diff --git a/proposals/testing/0002-json-abi.md b/proposals/testing/0002-json-abi.md new file mode 100644 index 0000000000..e13bb1ad37 --- /dev/null +++ b/proposals/testing/0002-json-abi.md @@ -0,0 +1,428 @@ +# A stable JSON-based ABI for tools integration + +* Proposal: [ST-0002](0002-json-abi.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Implemented (Swift 6.0)** +* Implementation: [swiftlang/swift-testing#383](https://github.com/swiftlang/swift-testing/pull/383), + [swiftlang/swift-testing#402](https://github.com/swiftlang/swift-testing/pull/402) +* Review: ([pitch](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627)), ([acceptance](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627/4)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0002](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0002-json-abi.md). + +## Introduction + +One of the core components of Swift Testing is its ability to interoperate with +Xcode 16, VS Code, and other tools. Swift Testing has been fully open-sourced +across all platforms supported by Swift, and can be added as a package +dependency (or—eventually—linked from the Swift toolchain.) + +## Motivation + +Because Swift Testing may be used in various forms, and because integration with +various tools is critical to its success, we need it to have a stable interface +that can be used regardless of how it's been added to a package. There are a few +patterns in particular we know we need to support: + +- An IDE (e.g. Xcode 16) that builds and links its own copy of Swift Testing: + the copy used by the IDE might be the same as the copy that tests use, in + which case interoperation is trivial, but it may also be distinct if the tests + use Swift Testing as a package dependency. + + In the case of Xcode 16, Swift Testing is built as a framework much like + XCTest and is automatically linked by test targets in an Xcode project or + Swift package, but if the test target specifies a package dependency on Swift + Testing, that dependency will take priority when the test code is compiled. + +- An IDE (e.g. VS Code) that does _not_ link directly to Swift Testing (and + perhaps, as with VS Code, cannot because it is not natively compiled): such an + IDE needs a way to configure and invoke test code and then to read events back + as they occur, but cannot touch the Swift symbols used by the tests. + + In the case of VS Code, because it is implemented using TypeScript, it is not + able to directly link to Swift Testing or other Swift libraries. In order for + it to interpret events from a test run like "test started" or "issue + recorded", it needs to receive those events in a format it can understand. + +Tools integration is important to the success of Swift Testing. The more tools +provide integrations for it, the more likely developers are to adopt it. The +more developers adopt, the more tests are written. And the more tests are +written, the better our lives as software engineers will be. + +## Proposed solution + +We propose defining and implementing a stable ABI for using Swift Testing that +can be reliably adopted by various IDEs and other tools. There are two aspects +of this ABI we need to implement: + +- A stable entry point function that can be resolved dynamically at runtime (on + platforms with dynamic loaders such as Darwin, Linux, and Windows.) This + function needs a signature that will not change over time and which will take + input and pass back asynchronous output in a format that a wide variety of + tools will be able to interpret (whether they are written in Swift or not.) + + This function should be implemented in Swift as it is expected to be used by + code that can call into Swift, but which cannot rely on the specific binary + minutiae of a given copy of Swift Testing. + +- A stable format for input that can be passed to the entry point function and + which can also be passed at the command line; and a stable format for output + that can be consumed by tools to interpret test results. + + Some tools cannot directly link to Swift code and must instead rely on + command-line invocations of `swift test`. These tools will be able to pass + their test configuration and options as an argument in the stable format and + will be able to receive event information in the same stable format via a + dedicated channel such as a file or named pipe. + +> [!NOTE] +> This document proposes defining a stable format for input and output, but only +> actually defines the JSON schema for _output_. We intend to define the schema +> for input in a subsequent proposal. +> +> In the interim, early adopters can encode an instance of Swift Testing's +> `__CommandLineArguments_v0` type using `JSONEncoder`. + +## Detailed design + +We propose defining the stable input and output format using JSON as it is +widely supported across platforms and languages. The proposed JSON schema for +output is defined [here](https://github.com/swiftlang/swift-testing/blob/main/Documentation/ABI/JSON.md). + +### Example output + +The proposed schema is a sequence of JSON objects written to an event handler or +file stream. When a test run starts, Swift Testing first emits a sequence of +JSON objects representing each test that is part of the planned run. For +example, this is the JSON representation of Swift Testing's own `canGetStdout()` +test function: + +```json +{ + "kind": "test", + "payload": { + "displayName": "Can get stdout", + "id": "TestingTests.FileHandleTests/canGetStdout()/FileHandleTests.swift:33:4", + "isParameterized": false, + "kind": "function", + "name": "canGetStdout()", + "sourceLocation": { + "column": 4, + "fileID": "TestingTests/FileHandleTests.swift", + "line": 33 + } + }, + "version": 0 +} +``` + +A tool that is observing this data stream can build a map or dictionary of test +IDs to comprehensive test details if needed. Once all tests in the planned run +have been written out, testing begins. Swift Testing writes a sequence of JSON +objects representing various events such as "test started" or "issue recorded". +For example, here is an abridged sequence of events generated for a test that +records a failed expectation: + +```json +{ + "kind": "event", + "payload": { + "instant": { + "absolute": 266418.545786299, + "since1970": 1718302639.76747 + }, + "kind": "testStarted", + "messages": [ + { + "symbol": "default", + "text": "Test \"Can get stdout\" started." + } + ], + "testID": "TestingTests.FileHandleTests/canGetStdout()/FileHandleTests.swift:33:4" + }, + "version": 0 +} + +{ + "kind": "event", + "payload": { + "instant": { + "absolute": 266636.524236724, + "since1970": 1718302857.74857 + }, + "issue": { + "isKnown": false, + "sourceLocation": { + "column": 7, + "fileID": "TestingTests/FileHandleTests.swift", + "line": 29 + } + }, + "kind": "issueRecorded", + "messages": [ + { + "symbol": "fail", + "text": "Expectation failed: (EOF → -1) == (feof(fileHandle) → 0)" + } + ], + "testID": "TestingTests.FileHandleTests/canGetStdout()/FileHandleTests.swift:33:4" + }, + "version": 0 +} + +{ + "kind": "event", + "payload": { + "instant": { + "absolute": 266636.524741106, + "since1970": 1718302857.74908 + }, + "kind": "testEnded", + "messages": [ + { + "symbol": "fail", + "text": "Test \"Can get stdout\" failed after 0.001 seconds with 1 issue." + } + ], + "testID": "TestingTests.FileHandleTests/canGetStdout()/FileHandleTests.swift:33:4" + }, + "version": 0 +} +``` + +Each event includes zero or more "messages" that Swift Testing intends to +present to the user. These messages contain human-readable text as well as +abstractly-specified symbols that correspond to the output written to the +standard error stream of the test process. Tools can opt to present these +messages in whatever ways are appropriate for their interfaces. + +### Invoking from the command line + +When invoking `swift test`, we propose adding three new arguments to Swift +Package Manager: + +| Argument | Value Type | Description | +|---|:-:|---| +| `--configuration-path` | File system path | Specifies a path to a file, named pipe, etc. containing test configuration/options. | +| `--event-stream-output-path` | File system path | Specifies a path to a file, named pipe, etc. to which output should be written. | +| `--event-stream-version` | Integer | Specifies the version of the stable JSON schema to use for output. | + +The process for adding arguments to Swift Package Manager is separate from the +process for Swift Testing API changes, so the names of these arguments are +speculative and are subject to change as part of the Swift Package Manager +review process. + +If `--configuration-path` is specified, Swift Testing will open it for reading +and attempt to decode its contents as JSON. If `--event-stream-output-path` is +specified, Swift Testing will open it for writing and will write a sequence of +[JSON Lines](https://jsonlines.org) to it representing the data and events +produced by the test run. `--event-stream-version` determines the stable schema +used for output; pass `0` to match the schema proposed in this document. + +> [!NOTE] +> If `--event-stream-output-path` is specified but `--event-stream-version` is +> not, the format _currently_ used is based on direct JSON encodings of the +> internal Swift structures used by Swift Testing. This format is necessary to +> support Xcode 16 Beta 1. In the future, the default value of this argument +> will be assumed to equal the newest available JSON schema version (`0` as of +> this document's acceptance, i.e. the JSON schema will match what we are +> proposing here until a new schema supersedes it.) +> +> Tools authors that rely on the JSON schema are strongly advised to specify a +> version rather than relying on this behavior to avoid breaking changes in the +> future. + +On platforms that support them, callers can use a named pipe with +`--event-stream-output-path` to get live results back from the test run rather +than needing to wait until the file is closed by the test process. Named pipes +can be created on Darwin or Linux with the POSIX [`mkfifo()`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mkfifo.2.html) +function or on Windows with the [`CreateNamedPipe()`](https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createnamedpipew) +function. + +If `--configuration-path` is specified in addition to explicit command-line +options like `--no-parallel`, the explicit command-line options take priority. + +### Invoking from Swift + +Tools that can link to and call Swift directly have the option of instantiating +the tools-only SPI type `Runner`, however this is only possible if the tools and +the test target link to the exact same copy of Swift Testing. To support tools +that may link to a different copy (intentionally or otherwise), we propose +adding an exported symbol to the Swift Testing library with the following Swift +signature: + +```swift +@_spi(ForToolsIntegrationOnly) +public enum ABIv0 { + /* ... */ + + /// The type of the entry point to the testing library used by tools that want + /// to remain version-agnostic regarding the testing library. + /// + /// - Parameters: + /// - configurationJSON: A buffer to memory representing the test + /// configuration and options. If `nil`, a new instance is synthesized + /// from the command-line arguments to the current process. + /// - recordHandler: A JSON record handler to which is passed a buffer to + /// memory representing each record as described in `ABI/JSON.md`. + /// + /// - Returns: Whether or not the test run finished successfully. + /// + /// - Throws: Any error that occurred prior to running tests. Errors that are + /// thrown while tests are running are handled by the testing library. + public typealias EntryPoint = @convention(thin) @Sendable ( + _ configurationJSON: UnsafeRawBufferPointer?, + _ recordHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void + ) async throws -> Bool + + /// The entry point to the testing library used by tools that want to remain + /// version-agnostic regarding the testing library. + /// + /// The value of this property is a Swift function that can be used by tools + /// that do not link directly to the testing library and wish to invoke tests + /// in a binary that has been loaded into the current process. The value of + /// this property is accessible from C and C++ as a function with name + /// `"swt_abiv0_getEntryPoint"` and can be dynamically looked up at runtime + /// using `dlsym()` or a platform equivalent. + /// + /// The value of this property can be thought of as equivalent to + /// `swift test --event-stream-output-path` except that, instead of streaming + /// JSON records to a named pipe or file, it streams them to an in-process + /// callback. + public static var entryPoint: EntryPoint { get } +} +``` + +The inputs and outputs to this function are typed as `UnsafeRawBufferPointer` +rather than `Data` because the latter is part of Foundation, and adding a public +dependency on a Foundation type would make it very difficult for Foundation to +adopt Swift Testing. It is a goal of the Swift Testing team to keep our Swift +dependency list as small as possible. + +### Invoking from C or C++ + +We expect most tools that need to make use of this entry point will not be able +to directly link to the exported Swift symbol and will instead need to look it +up at runtime using a platform-specific interface such as [`dlsym()`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html) +or [`GetProcAddress()`](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress). +The `ABIv0.entryPoint` property's getter will be exported to C and C++ as: + +```c++ +extern "C" const void *_Nonnull swt_abiv0_getEntryPoint(void); +``` + +The value returned from this C function is a direct representation of the value +of `ABIv0.entryPoint` and can be cast back to its Swift function type using +[`unsafeBitCast(_:to:)`](https://developer.apple.com/documentation/swift/unsafebitcast%28_%3Ato%3A%29). + +On platforms where data-pointer-to-function-pointer conversion is disallowed per +the C standard, this operation is unsupported. See §6.3.2.3 and §J.5.7 of +[the C standard](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf). + +> [!NOTE] +> Swift Testing is statically linked into the main executable when it is +> included as a package dependency. On Linux and other platforms that use the +> ELF executable format, symbol information for the main executable may not be +> available at runtime unless the `--export-dynamic` flag is passed to the +> linker. + +## Source compatibility + +The changes proposed in this document are additive. + +## Integration with supporting tools + +Tools are able to use the proposed additions as described above. + +## Future directions + +- Extending the JSON schema to cover _input_ as well as _output_. As discussed, + we will do so in a subsequent proposal. + +- Extending the JSON schema to include richer information about events such as + specific mismatched values in `#expect()` calls. This information is complex + and we need to take care to model it efficiently and clearly. + +- Adding Markdown or other formats to event messages. Rich text can be used by + tools to emphasize values, switch to code voice, provide improved + accessibility, etc. + +- Adding additional entry points for different access patterns. We anticipate + that a Swift function and a command-line interface are sufficient to cover + most real-world use cases, but it may be the case that tools could use other + mechanisms for starting test runs such as: + - Pure C or Objective-C interfaces; + - A WebAssembly and/or JavaScript [`async`-compatible](https://github.com/WebAssembly/component-model/blob/2f447274b5028f54c549cb4e28ceb493a471dd4b/design/mvp/Async.md) + interface; + - Platform-specific interfaces; or + - Direct bindings to other languages like Rust, Go, C#, etc. + +## Alternatives considered + +- Doing nothing. If we made no changes, we would be effectively requiring + developers to use Xcode for all Swift Testing development and would be + requiring third-party tools to parse human-readable command-line output. This + approach would run counter to several of the Swift project's high-level goals + and would not represent a true cross-platform solution. + +- Using direct JSON encodings of Swift Testing's internal types to represent + output. We initially attempted this and you can see the results in the Swift + Testing repository if you look for "snapshot" types. A major downside became + apparent quickly: these data types don't make for particularly usable JSON + unless you're using `JSONDecoder` to convert back to them, and the default + JSON encodings produced with `JSONEncoder` are not stable if we e.g. add + enumeration cases with associated values or add non-optional fields to types. + +- Using a format other than JSON. We considered using XML, YAML, Apple property + lists, and a few other formats. JSON won out pretty quickly though: it is + widely supported across platforms and languages and it is trivial to create + Swift structures that encode to a well-designed JSON schema using + `JSONEncoder`. Property lists would be just as easy to create, but it is a + proprietary format and would not be trivially decodable on non-Apple platforms + or using non-Apple tools. + +- Exposing the C interface as a function that returns heap-allocated memory + containing a Swift function reference. This allows us to emit a "thick" Swift + function but requires callers to manually manage the resulting memory, and it + may be difficult to reason about code that requires an extra level of pointer + indirection. By having the C entry point function return a thin Swift function + instead, the caller need only bitcast it and can call it directly, and the + equivalent Swift interface can simply be a property getter rather than a + function call. + +- Exposing the C interface as a function that takes a callback and a completion + handler as might traditionally used by Objective-C callers, of the form: + + ```c++ + extern "C" void swt_abiv0_entryPoint( + __attribute__((__noescape__)) const void *_Nullable configurationJSON, + size_t configurationJSONLength, + void *_Null_unspecified context, + void (*_Nonnull recordHandler)( + __attribute__((__noescape__)) const void *recordJSON, + size_t recordJSONLength, + void *_Null_unspecified context + ), + void (*_Nonnull completionHandler)( + _Bool success, + void *_Null_unspecified context + ) + ); + ``` + + The known clients of the native entry point function are all able to call + Swift code and do not need this sort of interface. If there are other clients + that would need the entry point to use a signature like this one, it would be + straightforward to implement it in a future amendment to this proposal. + +## Acknowledgments + +Thanks much to [Dennis Weissmann](https://github.com/dennisweissmann) for his +tireless work in this area and to [Paul LeMarquand](https://github.com/plemarquand) +for putting up with my incessant revisions and nitpicking while he worked on +VS Code's Swift Testing support. + +Thanks to the rest of the Swift Testing team for reviewing this proposal and the +JSON schema and to the community for embracing Swift Testing! diff --git a/proposals/testing/0003-make-serialized-trait-api.md b/proposals/testing/0003-make-serialized-trait-api.md new file mode 100644 index 0000000000..73a6fbe1a2 --- /dev/null +++ b/proposals/testing/0003-make-serialized-trait-api.md @@ -0,0 +1,156 @@ +# Make .serialized trait API + +* Proposal: [ST-0003](0003-make-serialized-trait-api.md) +* Authors: [Dennis Weissmann](https://github.com/dennisweissmann) +* Status: **Implemented (Swift 6.0)** +* Implementation: +[swiftlang/swift-testing#535](https://github.com/swiftlang/swift-testing/pull/535) +* Review: +([pitch](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147)), +([acceptance](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147/5)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0003](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0003-make-serialized-trait-api.md). + +## Introduction + +We propose promoting the existing `.serialized` trait to public API. This trait +enables developers to designate tests or test suites to run serially, ensuring +sequential execution where necessary. + +## Motivation + +The Swift Testing library defaults to parallel execution of tests, promoting +efficiency and isolation. However, certain test scenarios demand strict +sequential execution due to shared state or complex dependencies between tests. +The `.serialized` trait provides a solution by allowing developers to enforce +serial execution for specific tests or suites. + +While global actors ensure that only one task associated with that actor runs +at any given time, thus preventing concurrent access to actor state, tasks can +yield and allow other tasks to proceed, potentially interleaving execution. +That means global actors do not ensure that a specific test runs entirely to +completion before another begins. A testing library requires a construct that +guarantees that each annotated test runs independently and completely (in its +suite), one after another, without interleaving. + +## Proposed Solution + +We propose exposing the `.serialized` trait as a public API. This attribute can +be applied to individual test functions or entire test suites, modifying the +test execution behavior to enforce sequential execution where specified. + +Annotating just a single test in a suite does not enforce any serialization +behavior - the testing library encourages parallelization and the bar to +degrade overall performance of test execution should be high. +Additionally, traits apply inwards - it would be unexpected to impact the exact +conditions of a another test in a suite without applying a trait to the suite +itself. +Thus, this trait should only be applied to suites (to enforce serial execution +of all tests inside it) or parameterized tests. If applied to just a test this +trait does not have any effect. + +## Detailed Design + +The `.serialized` trait functions as an attribute that alters the execution +scheduling of tests. When applied, it ensures that tests or suites annotated +with `.serialized` run serially. + +```swift +/// A type that affects whether or not a test or suite is parallelized. +/// +/// When added to a parameterized test function, this trait causes that test to +/// run its cases serially instead of in parallel. When applied to a +/// non-parameterized test function, this trait has no effect. When applied to a +/// test suite, this trait causes that suite to run its contained test functions +/// and sub-suites serially instead of in parallel. +/// +/// This trait is recursively applied: if it is applied to a suite, any +/// parameterized tests or test suites contained in that suite are also +/// serialized (as are any tests contained in those suites, and so on.) +/// +/// This trait does not affect the execution of a test relative to its peers or +/// to unrelated tests. This trait has no effect if test parallelization is +/// globally disabled (by, for example, passing `--no-parallel` to the +/// `swift test` command.) +/// +/// To add this trait to a test, use ``Trait/serialized``. +public struct ParallelizationTrait: TestTrait, SuiteTrait {} + +extension Trait where Self == ParallelizationTrait { + /// A trait that serializes the test to which it is applied. + /// + /// ## See Also + /// + /// - ``ParallelizationTrait`` + public static var serialized: Self { get } +} +``` + +The call site looks like this: + +```swift +@Test(.serialized, arguments: Food.allCases) func prepare(food: Food) { + // This function will be invoked serially, once per food, because it has the + // .serialized trait. +} + +@Suite(.serialized) struct FoodTruckTests { + @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) { + // This function will be invoked serially, once per condiment, because the + // containing suite has the .serialized trait. + } + + @Test func startEngine() async throws { + // This function will not run while refill(condiment:) is running. One test + // must end before the other will start. + } +} + +@Suite struct FoodTruckTests { + @Test(.serialized) func startEngine() async throws { + // This function will not run serially - it's not a parameterized test and + // the suite is not annotated with the `.serialized` trait. + } + + @Test func prepareFood() async throws { + // It doesn't matter if this test is `.serialized` or not, traits applied + // to other tests won't affect this test don't impact other tests. + } +} +``` + +## Source Compatibility + +Introducing `.serialized` as a public API does not have any impact on existing +code. Tests will continue to run in parallel by default unless explicitly +marked with `.serialized`. + +## Integration with Supporting Tools + +N/A. + +## Future Directions + +There might be asks for more advanced and complex ways to affect parallelization +which include ways to specify dependencies between tests ie. "Require `foo()` to +run before `bar()`". + +## Alternatives Considered + +Alternative approaches, such as relying solely on global actors for test +isolation, were considered. However, global actors do not provide the +deterministic, sequential execution required for certain testing scenarios. The +`.serialized` trait offers a more explicit and flexible mechanism, ensuring +that each designated test or suite runs to completion without interruption. + +Various more complex parallelization and serialization options were discussed +and considered but ultimately disregarded in favor of this simple yet powerful +implementation. + +## Acknowledgments + +Thanks to the swift-testing team and managers for their contributions! Thanks +to our community for the initial feedback around this feature. diff --git a/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md b/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md new file mode 100644 index 0000000000..4817bc955c --- /dev/null +++ b/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md @@ -0,0 +1,207 @@ +# Constrain the granularity of test time limit durations + +* Proposal: [ST-0004](0004-constrain-the-granularity-of-test-time-limit-durations.md) +* Authors: [Dennis Weissmann](https://github.com/dennisweissmann) +* Status: **Implemented (Swift 6.0)** +* Implementation: +[swiftlang/swift-testing#534](https://github.com/swiftlang/swift-testing/pull/534) +* Review: +([pitch](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146)), +([acceptance](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146/3)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0004](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0004-constrain-the-granularity-of-test-time-limit-durations.md). + +## Introduction + +Sometimes tests might get into a state (either due the test code itself or due +to the code they're testing) where they don't make forward progress and hang. +Swift Testing provides a way to handle these issues using the TimeLimit trait: + +```swift +@Test(.timeLimit(.minutes(60)) +func testFunction() { ... } +``` + +Currently there exist multiple overloads for the `.timeLimit` trait: one that +takes a `Swift.Duration` which allows for arbitrary `Duration` values to be +passed, and one that takes a `TimeLimitTrait.Duration` which constrains the +minimum time limit as well as the increment to 1 minute. + +## Motivation + +Small time limit values in particular cause more harm than good due to tests +running in environments with drastically differing performance characteristics. +Particularly when running in CI systems or on virtualized hardware tests can +run much slower than at desk. +Swift Testing should help developers use a reasonable time limit value in its +API without developers having to refer to the documentation. + +It is crucial to emphasize that unit tests failing due to exceeding their +timeout should be exceptionally rare. At the same time, a spurious unit test +failure caused by a short timeout can be surprisingly costly, potentially +leading to an entire CI pipeline being rerun. Determining an appropriate +timeout for a specific test can be a challenging task. + +Additionally, when the system intentionally runs multiple tests simultaneously +to optimize resource utilization, the scheduler becomes the arbiter of test +execution. Consequently, the test may take significantly longer than +anticipated, potentially due to external factors beyond the control of the code +under test. + +A unit test should be capable of failing due to hanging, but it should not fail +due to being slow, unless the developer has explicitly indicated that it +should, effectively transforming it into a performance test. + +The time limit feature is *not* intended to be used to apply small timeouts to +tests to ensure test runtime doesn't regress by small amounts. This feature is +intended to be used to guard against hangs and pathologically long running +tests. + +## Proposed Solution + +We propose changing the `.timeLimit` API to accept values of a new `Duration` +type defined in `TimeLimitTrait` which only allows for `.minute` values to be +passed. +This type already exists as SPI and this proposal is seeking to making it API. + +## Detailed Design + +The `TimeLimitTrait.Duration` struct only has one factory method: +```swift +public static func minutes(_ minutes: some BinaryInteger) -> Self +``` + +That ensures 2 things: +1. It's impossible to create short time limits (under a minute). +2. It's impossible to create high-precision increments of time. + +Both of these features are important to ensure the API is self documenting and +conveying the intended purpose. + +For parameterized tests these time limits apply to each individual test case. + +The `TimeLimitTrait.Duration` struct is declared as follows: + +```swift +/// A type that defines a time limit to apply to a test. +/// +/// To add this trait to a test, use one of the following functions: +/// +/// - ``Trait/timeLimit(_:)`` +@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) +public struct TimeLimitTrait: TestTrait, SuiteTrait { + /// A type representing the duration of a time limit applied to a test. + /// + /// This type is intended for use specifically for specifying test timeouts + /// with ``TimeLimitTrait``. It is used instead of Swift's built-in `Duration` + /// type because test timeouts do not support high-precision, arbitrarily + /// short durations. The smallest allowed unit of time is minutes. + public struct Duration: Sendable { + + /// Construct a time limit duration given a number of minutes. + /// + /// - Parameters: + /// - minutes: The number of minutes the resulting duration should + /// represent. + /// + /// - Returns: A duration representing the specified number of minutes. + public static func minutes(_ minutes: some BinaryInteger) -> Self + } + + /// The maximum amount of time a test may run for before timing out. + public var timeLimit: Swift.Duration { get set } +} +``` + +The extension on `Trait` that allows for `.timeLimit(...)` to work is defined +like this: + +```swift +/// Construct a time limit trait that causes a test to time out if it runs for +/// too long. +/// +/// - Parameters: +/// - timeLimit: The maximum amount of time the test may run for. +/// +/// - Returns: An instance of ``TimeLimitTrait``. +/// +/// Test timeouts do not support high-precision, arbitrarily short durations +/// due to variability in testing environments. The time limit must be at +/// least one minute, and can only be expressed in increments of one minute. +/// +/// When this trait is associated with a test, that test must complete within +/// a time limit of, at most, `timeLimit`. If the test runs longer, an issue +/// of kind ``Issue/Kind/timeLimitExceeded(timeLimitComponents:)`` is +/// recorded. This timeout is treated as a test failure. +/// +/// The time limit amount specified by `timeLimit` may be reduced if the +/// testing library is configured to enforce a maximum per-test limit. When +/// such a maximum is set, the effective time limit of the test this trait is +/// applied to will be the lesser of `timeLimit` and that maximum. This is a +/// policy which may be configured on a global basis by the tool responsible +/// for launching the test process. Refer to that tool's documentation for +/// more details. +/// +/// If a test is parameterized, this time limit is applied to each of its +/// test cases individually. If a test has more than one time limit associated +/// with it, the shortest one is used. A test run may also be configured with +/// a maximum time limit per test case. +public static func timeLimit(_ timeLimit: Self.Duration) -> Self +``` + +And finally, the call site of the API looks like this: + +```swift +@Test(.timeLimit(.minutes(60)) +func serve100CustomersInOneHour() async { + for _ in 0 ..< 100 { + let customer = await Customer.next() + await customer.order() + ... + } +} +``` + +The `TimeLimitTrait.Duration` struct has various `unavailable` overloads that +are included for diagnostic purposes only. They are all documented and +annotated like this: + +```swift +/// Construct a time limit duration given a number of . +/// +/// This function is unavailable and is provided for diagnostic purposes only. +@available(*, unavailable, message: "Time limit must be specified in minutes") +``` + +## Source Compatibility + +This impacts clients that have adopted the `.timeLimit` trait and use overloads +of the trait that accept an arbitrary `Swift.Duration` except if they used the +`minutes` overload. + +## Integration with Supporting Tools + +N/A + +## Future Directions + +We could allow more finegrained time limits in the future that scale with the +performance of the test host device. +Or take a more manual approach where we detect the type of environment +(like CI vs local) and provide a way to use different timeouts depending on the +environment. + +## Alternatives Considered + +We have considered using `Swift.Duration` as the currency type for this API but +decided against it to avoid common pitfalls and misuses of this feature such as +providing very small time limits that lead to flaky tests in different +environments. + +## Acknowledgments + +The authors acknowledge valuable contributions and feedback from the Swift +Testing community during the development of this proposal. diff --git a/proposals/testing/0005-ranged-confirmations.md b/proposals/testing/0005-ranged-confirmations.md new file mode 100644 index 0000000000..93997c86e9 --- /dev/null +++ b/proposals/testing/0005-ranged-confirmations.md @@ -0,0 +1,191 @@ +# Range-based confirmations + +* Proposal: [ST-0005](0005-ranged-confirmations.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Implemented (Swift 6.1)** +* Bug: rdar://138499457 +* Implementation: [swiftlang/swift-testing#598](https://github.com/swiftlang/swift-testing/pull/598), [swiftlang/swift-testing#689](https://github.com/swiftlang/swift-testing/pull689) +* Review: ([pitch](https://forums.swift.org/t/pitch-range-based-confirmations/74589)), + ([acceptance](https://forums.swift.org/t/pitch-range-based-confirmations/74589/7)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0005](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0005-ranged-confirmations.md). + +## Introduction + +Swift Testing includes [an interface](https://swiftpackageindex.com/swiftlang/swift-testing/main/documentation/testing/confirmation(_:expectedcount:isolation:sourcelocation:_:)) +for checking that some asynchronous event occurs a given number of times +(typically exactly once or never at all.) This proposal enhances that interface +to allow arbitrary ranges of event counts so that a test can be written against +code that may not always fire said event the exact same number of times. + +## Motivation + +Some tests rely on fixtures or external state that is not perfectly +deterministic. For example, consider a test that checks that clicking the mouse +button will generate a `.mouseClicked` event. Such a test might use the +`confirmation()` interface: + +```swift +await confirmation(expectedCount: 1) { mouseClicked in + var eventLoop = EventLoop() + eventLoop.eventHandler = { event in + if event == .mouseClicked { + mouseClicked() + } + } + await eventLoop.simulate(.mouseClicked) +} +``` + +But what happens if the user _actually_ clicks a mouse button while this test is +running? That might trigger a _second_ `.mouseClicked` event, and then the test +will fail spuriously. + +## Proposed solution + +If the test author could instead indicate to Swift Testing that their test will +generate _one or more_ events, they could avoid spurious failures: + +```swift +await confirmation(expectedCount: 1...) { mouseClicked in + ... +} +``` + +With this proposal, we add an overload of `confirmation()` that takes any range +expression instead of a single integer value (which is still accepted via the +existing overload.) + +## Detailed design + +A new overload of `confirmation()` is added: + +```swift +/// Confirm that some event occurs during the invocation of a function. +/// +/// - Parameters: +/// - comment: An optional comment to apply to any issues generated by this +/// function. +/// - expectedCount: A range of integers indicating the number of times the +/// expected event should occur when `body` is invoked. +/// - isolation: The actor to which `body` is isolated, if any. +/// - sourceLocation: The source location to which any recorded issues should +/// be attributed. +/// - body: The function to invoke. +/// +/// - Returns: Whatever is returned by `body`. +/// +/// - Throws: Whatever is thrown by `body`. +/// +/// Use confirmations to check that an event occurs while a test is running in +/// complex scenarios where `#expect()` and `#require()` are insufficient. For +/// example, a confirmation may be useful when an expected event occurs: +/// +/// - In a context that cannot be awaited by the calling function such as an +/// event handler or delegate callback; +/// - More than once, or never; or +/// - As a callback that is invoked as part of a larger operation. +/// +/// To use a confirmation, pass a closure containing the work to be performed. +/// The testing library will then pass an instance of ``Confirmation`` to the +/// closure. Every time the event in question occurs, the closure should call +/// the confirmation: +/// +/// ```swift +/// let minBuns = 5 +/// let maxBuns = 10 +/// await confirmation( +/// "Baked between \(minBuns) and \(maxBuns) buns", +/// expectedCount: minBuns ... maxBuns +/// ) { bunBaked in +/// foodTruck.eventHandler = { event in +/// if event == .baked(.cinnamonBun) { +/// bunBaked() +/// } +/// } +/// await foodTruck.bakeTray(of: .cinnamonBun) +/// } +/// ``` +/// +/// When the closure returns, the testing library checks if the confirmation's +/// preconditions have been met, and records an issue if they have not. +/// +/// If an exact count is expected, use +/// ``confirmation(_:expectedCount:isolation:sourceLocation:_:)`` instead. +public func confirmation( + _ comment: Comment? = nil, + expectedCount: some RangeExpression & Sequence Sendable, + isolation: isolated (any Actor)? = #isolation, + sourceLocation: SourceLocation = #_sourceLocation, + _ body: (Confirmation) async throws -> sending R +) async rethrows -> R +``` + +### Ranges without lower bounds + +Certain types of range, specifically [`PartialRangeUpTo`](https://developer.apple.com/documentation/swift/partialrangeupto) +and [`PartialRangeThrough`](https://developer.apple.com/documentation/swift/partialrangethrough), +may have surprising behavior when used with this new interface because they +implicitly include `0`. If a test author writes `...10`, do they mean "zero to +ten" or "one to ten"? The programmatic meaning is the former, but some test +authors might mean the latter. If an event does not occur, a test using +`confirmation()` and this `expectedCount` value would pass when the test author +meant for it to fail. + +The unbounded range (`...`) type `UnboundedRange` is effectively useless when +used with this interface and any use of it here is almost certainly a programmer +error. + +`PartialRangeUpTo` and `PartialRangeThrough` conform to `RangeExpression`, but +not to `Sequence`, so they will be rejected at compile time. `UnboundedRange` is +a non-nominal type and will not match either. We will provide unavailable +overloads of `confirmation()` for these types with messages that explain why +they are unavailable, e.g.: + +```swift +@available(*, unavailable, message: "Unbounded range '...' has no effect when used with a confirmation.") +public func confirmation( + _ comment: Comment? = nil, + expectedCount: UnboundedRange, + isolation: isolated (any Actor)? = #isolation, + sourceLocation: SourceLocation = #_sourceLocation, + _ body: (Confirmation) async throws -> R +) async rethrows -> R +``` + +## Source compatibility + +This change is additive. Existing tests are unaffected. + +Code that refers to `confirmation(_:expectedCount:isolation:sourceLocation:_:)` +by symbol name may need to add a contextual type to disambiguate the two +overloads at compile time. + +## Integration with supporting tools + +The type of the associated value `expected` for the `Issue.Kind` case +`confirmationMiscounted(actual:expected:)` will change from `Int` to +`any RangeExpression & Sendable`[^1]. Tools that implement event handlers and +distinguish between `Issue.Kind` cases are advised not to assume the type of +this value is `Int`. + +## Alternatives considered + +- Doing nothing. We have identified real-world use cases for this interface + including in Swift Testing’s own test target. +- Allowing the use of any value as the `expectedCount` argument so long as it + conforms to a protocol `ExpectedCount` (we'd have range types and `Int` + conform by default.) It was unclear what this sort of flexibility would let + us do, and posed challenges for encoding and decoding events and issues when + using the JSON event stream interface. + +## Acknowledgments + +Thanks to the testing team for their help preparing this pitch! + +[^1]: In the future, this type will change to + `any RangeExpression & Sendable`. Compiler support is required + ([96960993](rdar://96960993)). diff --git a/proposals/testing/0006-return-errors-from-expect-throws.md b/proposals/testing/0006-return-errors-from-expect-throws.md new file mode 100644 index 0000000000..c1ba77d5df --- /dev/null +++ b/proposals/testing/0006-return-errors-from-expect-throws.md @@ -0,0 +1,272 @@ +# Return errors from `#expect(throws:)` + +* Proposal: [ST-0006](0006-return-errors-from-expect-throws.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Status: **Implemented (Swift 6.1)** +* Bug: rdar://138235250 +* Implementation: [swiftlang/swift-testing#780](https://github.com/swiftlang/swift-testing/pull/780) +* Review: ([pitch](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567)), ([acceptance](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567/5)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0006](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0006-return-errors-from-expect-throws.md). + +## Introduction + +Swift Testing includes overloads of `#expect()` and `#require()` that can be +used to assert that some code throws an error. They are useful when validating +that your code's failure cases are correctly detected and handled. However, for +more complex validation cases, they aren't particularly ergonomic. This proposal +seeks to resolve that issue by having these overloads return thrown errors for +further inspection. + +## Motivation + +We offer three variants of `#expect(throws:)`: + +- One that takes an error type, and matches any error of the same type; +- One that takes an error _instance_ (conforming to `Equatable`) and matches any + error that compares equal to it; and +- One that takes a trailing closure and allows test authors to write arbitrary + validation logic. + +The third overload has proven to be somewhat problematic. First, it yields the +error to its closure as an instance of `any Error`, which typically forces the +developer to cast it before doing any useful comparisons. Second, the test +author must return `true` to indicate the error matched and `false` to indicate +it didn't, which can be both logically confusing and difficult to express +concisely: + +```swift +try #require { + let potato = try Sack.randomPotato() + try potato.turnIntoFrenchFries() +} throws: { error in + guard let error = error as PotatoError else { + return false + } + guard case .potatoNotPeeled = error else { + return false + } + return error.variety != .russet +} +``` + +The first impulse many test authors have here is to use `#expect()` in the +second closure, but it doesn't return the necessary boolean value _and_ it can +result in multiple issues being recorded in a test when there's really only one. + +## Proposed solution + +I propose deprecating [`#expect(_:sourceLocation:performing:throws:)`](https://developer.apple.com/documentation/testing/expect(_:sourcelocation:performing:throws:)) +and [`#require(_:sourceLocation:performing:throws:)`](https://developer.apple.com/documentation/testing/require(_:sourcelocation:performing:throws:)) +and modifying the other overloads so that, on success, they return the errors +that were thrown. + +## Detailed design + +All overloads of `#expect(throws:)` and `#require(throws:)` will be updated to +return an instance of the error type specified by their arguments, with the +problematic overloads returning `any Error` since more precise type information +is not statically available. The problematic overloads will also be deprecated: + +```diff +--- a/Sources/Testing/Expectations/Expectation+Macro.swift ++++ b/Sources/Testing/Expectations/Expectation+Macro.swift ++@discardableResult + @freestanding(expression) public macro expect( + throws errorType: E.Type, + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R +-) ++) -> E? where E: Error + ++@discardableResult + @freestanding(expression) public macro require( + throws errorType: E.Type, + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R +-) where E: Error ++) -> E where E: Error + ++@discardableResult + @freestanding(expression) public macro expect( + throws error: E, + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R +-) where E: Error & Equatable ++) -> E? where E: Error & Equatable + ++@discardableResult + @freestanding(expression) public macro require( + throws error: E, + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R +-) where E: Error & Equatable ++) -> E where E: Error & Equatable + ++@available(swift, deprecated: 100000.0, message: "Examine the result of '#expect(throws:)' instead.") ++@discardableResult + @freestanding(expression) public macro expect( + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R, + throws errorMatcher: (any Error) async throws -> Bool +-) ++) -> (any Error)? + ++@available(swift, deprecated: 100000.0, message: "Examine the result of '#require(throws:)' instead.") ++@discardableResult + @freestanding(expression) public macro require( + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: () async throws -> R, + throws errorMatcher: (any Error) async throws -> Bool +-) ++) -> any Error +``` + +(More detailed information about the deprecations will be provided via DocC.) + +The `#expect(throws:)` overloads return an optional value that is `nil` if the +expectation failed, while the `#require(throws:)` overloads return non-optional +values and throw instances of `ExpectationFailedError` on failure (as before.) + +> [!NOTE] +> Instances of `ExpectationFailedError` thrown by `#require(throws:)` on failure +> are not returned as that would defeat the purpose of using `#require(throws:)` +> instead of `#expect(throws:)`. + +Test authors will be able to use the result of the above functions to verify +that the thrown error is correct: + +```swift +let error = try #require(throws: PotatoError.self) { + let potato = try Sack.randomPotato() + try potato.turnIntoFrenchFries() +} +#expect(error == .potatoNotPeeled) +#expect(error.variety != .russet) +``` + +The new code is more concise than the old code and avoids boilerplate casting +from `any Error`. + +## Source compatibility + +In most cases, this change does not affect source compatibility. Swift does not +allow forming references to macros at runtime, so we don't need to worry about +type mismatches assigning one to some local variable. + +We have identified two scenarios where a new warning will be emitted. + +### Inferred return type from macro invocation + +The return type of the macro may be used by the compiler to infer the return +type of an enclosing closure. If the return value is then discarded, the +compiler may emit a warning: + +```swift +func pokePotato(_ pPotato: UnsafePointer) throws { ... } + +let potato = Potato() +try await Task.sleep(for: .months(3)) +withUnsafePointer(to: potato) { pPotato in + // ^ ^ ^ ⚠️ Result of call to 'withUnsafePointer(to:_:)' is unused + #expect(throws: PotatoError.rotten) { + try pokePotato(pPotato) + } +} +``` + +This warning can be suppressed by assigning the result of the macro invocation +or the result of the function call to `_`: + +```swift +withUnsafePointer(to: potato) { pPotato in + _ = #expect(throws: PotatoError.rotten) { + try pokePotato(pPotato) + } +} +``` + +### Use of `#require(throws:)` in a generic context with `Never.self` + +If `#require(throws:)` (but not `#expect(throws:)`) is used in a generic context +where the type of thrown error is a generic parameter, and the type is resolved +to `Never`, there is no valid value for the invocation to return: + +```swift +func wrapper(throws type: E.Type, _ body: () throws -> Void) throws -> E { + return try #require(throws: type) { + try body() + } +} +let error = try #require(throws: Never.self) { ... } +``` + +We don't think this particular pattern is common (and outside of our own test +target, I'd be surprised if anybody's attempted it yet.) However, we do need to +handle it gracefully. If this pattern is encountered, Swift Testing will record +an "API Misused" issue for the current test and advise the test author to switch +to `#expect(throws:)` or to not pass `Never.self` here. + +## Integration with supporting tools + +N/A + +## Future directions + +- Adopting [typed throws](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md) + to statically require that the error thrown from test code is of the correct + type. + + If we adopted typed throws in the signatures of these macros, it would force + adoption of typed throws in the code under test even when it may not be + appropriate. For example, if we adopted typed throws, the following code would + not compile: + + ```swift + func cook(_ food: consuming some Food) throws { ... } + + let error: PotatoError? = #expect(throws: PotatoError.self) { + var potato = Potato() + potato.fossilize() + try cook(potato) // 🛑 ERROR: Invalid conversion of thrown error type + // 'any Error' to 'PotatoError' + } + ``` + + We believe it may be possible to overload these macros or their expansions so + that the code sample above _does_ compile and behave as intended. We intend to + experiment further with this idea and potentially revisit typed throws support + in a future proposal. + +## Alternatives considered + +- Leaving the existing implementation and signatures in place. We've had + sufficient feedback about the ergonomics of this API that we want to address + the problem. + +- Having the return type of the macros be `any Error` and returning _any_ error + that was thrown even on mismatch. This would make the ergonomics of the + subsequent test code less optimal because the test author would need to cast + the error to the appropriate type before inspecting it. + + There's a philosophical argument to be made here that if a mismatched error is + thrown, then the test has already failed and is in an inconsistent state, so + we should allow the test to fail rather than return what amounts to "bad + output". + + If the test author wants to inspect any arbitrary thrown error, they can + specify `(any Error).self` instead of a concrete error type. + +## Acknowledgments + +Thanks to the team and to [@jakepetroules](https://github.com/jakepetroules) for +starting the discussion that ultimately led to this proposal. diff --git a/proposals/testing/0007-test-scoping-traits.md b/proposals/testing/0007-test-scoping-traits.md new file mode 100644 index 0000000000..d397a792e9 --- /dev/null +++ b/proposals/testing/0007-test-scoping-traits.md @@ -0,0 +1,515 @@ +# Test Scoping Traits + +* Proposal: [ST-0007](0007-test-scoping-traits.md) +* Authors: [Stuart Montgomery](https://github.com/stmontgomery) +* Status: **Implemented (Swift 6.1)** +* Implementation: [swiftlang/swift-testing#733](https://github.com/swiftlang/swift-testing/pull/733), [swiftlang/swift-testing#86](https://github.com/swiftlang/swift-testing/pull/86) +* Review: ([pitch](https://forums.swift.org/t/pitch-custom-test-execution-traits/75055)), ([review](https://forums.swift.org/t/proposal-test-scoping-traits/76676)), ([acceptance](https://forums.swift.org/t/proposal-test-scoping-traits/76676/3)) + +> [!NOTE] +> This proposal was accepted before Swift Testing began using the Swift +> evolution review process. Its original identifier was +> [SWT-0007](https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0007-test-scoping-traits.md). + +### Revision history + +* **v1**: Initial pitch. +* **v2**: Dropped 'Custom' prefix from the proposed API names (although kept the + word in certain documentation passages where it clarified behavior). +* **v3**: Changed the `Trait` requirement from a property to a method which + accepts the test and/or test case, and modify its default implementations such + that custom behavior is either performed per-suite or per-test case by default. +* **v4**: Renamed the APIs to use "scope" as the base verb instead of "execute". + +## Introduction + +This introduces API which enables a `Trait`-conforming type to provide a custom +execution scope for test functions and suites, including running code before or +after them. + +## Motivation + +One of the primary motivations for the trait system in Swift Testing, as +[described in the vision document](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md#trait-extensibility), +is to provide a way to customize the behavior of tests which have things in +common. If all the tests in a given suite type need the same custom behavior, +`init` and/or `deinit` (if applicable) can be used today. But if only _some_ of +the tests in a suite need custom behavior, or tests across different levels of +the suite hierarchy need it, traits would be a good place to encapsulate common +logic since they can be applied granularly per-test or per-suite. This aspect of +the vision for traits hasn't been realized yet, though: the `Trait` protocol +does not offer a way for a trait to customize the execution of the tests or +suites it's applied to. + +Customizing a test's behavior typically means running code either before or +after it runs, or both. Consolidating common set-up and tear-down logic allows +each test function to be more succinct with less repetitive boilerplate so it +can focus on what makes it unique. + +## Proposed solution + +At a high level, this proposal entails adding API to the `Trait` protocol +allowing a conforming type to opt-in to providing a custom execution scope for a +test. We discuss how that capability should be exposed to trait types below. + +### Supporting scoped access + +There are different approaches one could take to expose hooks for a trait to +customize test behavior. To illustrate one of them, consider the following +example of a `@Test` function with a custom trait whose purpose is to set mock +API credentials for the duration of each test it's applied to: + +```swift +@Test(.mockAPICredentials) +func example() { + // ... +} + +struct MockAPICredentialsTrait: TestTrait { ... } + +extension Trait where Self == MockAPICredentialsTrait { + static var mockAPICredentials: Self { ... } +} +``` + +In this hypothetical example, the current API credentials are stored via a +static property on an `APICredentials` type which is part of the module being +tested: + +```swift +struct APICredentials { + var apiKey: String + + static var shared: Self? +} +``` + +One way that this custom trait could customize the API credentials during each +test is if the `Trait` protocol were to expose a pair of method requirements +which were then called before and after the test, respectively: + +```swift +public protocol Trait: Sendable { + // ... + func setUp() async throws + func tearDown() async throws +} + +extension Trait { + // ... + public func setUp() async throws { /* No-op */ } + public func tearDown() async throws { /* No-op */ } +} +``` + +The custom trait type could adopt these using code such as the following: + +```swift +extension MockAPICredentialsTrait { + func setUp() { + APICredentials.shared = .init(apiKey: "...") + } + + func tearDown() { + APICredentials.shared = nil + } +} +``` + +Many testing systems use this pattern, including XCTest. However, this approach +encourages the use of global mutable state such as the `APICredentials.shared` +variable, and this limits the testing library's ability to parallelize test +execution, which is +[another part of the Swift Testing vision](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md#parallelization-and-concurrency). + +The use of nonisolated static variables is generally discouraged now, and in +Swift 6 the above `APICredentials.shared` property produces an error. One way +to resolve that is to change it to a `@TaskLocal` variable, as this would be +concurrency-safe and still allow tests accessing this state to run in parallel: + +```swift +extension APICredentials { + @TaskLocal static var current: Self? +} +``` + +Binding task local values requires using the scoped access +[`TaskLocal.withValue()`](https://developer.apple.com/documentation/swift/tasklocal/withvalue(_:operation:isolation:file:line:)) +API though, and that would not be possible if `Trait` exposed separate methods +like `setUp()` and `tearDown()`. + +For these reasons, I believe it's important to expose this trait capability +using a single, scoped access-style API which accepts a closure. A simplified +version of that idea might look like this: + +```swift +public protocol Trait: Sendable { + // ... + + // Simplified example, not the actual proposal + func executeTest(_ body: @Sendable () async throws -> Void) async throws +} + +extension MockAPICredentialsTrait { + func executeTest(_ body: @Sendable () async throws -> Void) async throws { + let mockCredentials = APICredentials(apiKey: "...") + try await APICredentials.$current.withValue(mockCredentials) { + try await body() + } + } +} +``` + +### Avoiding unnecessarily lengthy backtraces + +A scoped access-style API has some potential downsides. To apply this approach +to a test function, the scoped call of a trait must wrap the invocation of that +test function, and every _other_ trait applied to that same test which offers +custom behavior _also_ must wrap the other traits' calls in a nesting fashion. +To visualize this, imagine a test function with multiple traits: + +```swift +@Test(.traitA, .traitB, .traitC) +func exampleTest() { + // ... +} +``` + +If all three of those traits provide a custom scope for tests, then each of them +needs to wrap the call to the next one, and the last trait needs to wrap the +invocation of the test, illustrated by the following: + +``` +TraitA.executeTest { + TraitB.executeTest { + TraitC.executeTest { + exampleTest() + } + } +} +``` + +Tests may have an arbitrary number of traits applied to them, including those +inherited from containing suite types. A naïve implementation in which _every_ +trait is given the opportunity to customize test behavior by calling its scoped +access API might cause unnecessarily lengthy backtraces that make debugging the +body of tests more difficult. Or worse: if the number of traits is great enough, +it could cause a stack overflow. + +In practice, most traits probably do _not_ need to provide a custom scope for +the tests they're applied to, so to mitigate these downsides it's important that +there be some way to distinguish traits which customize test behavior. That way, +the testing library can limit these scoped access calls to only traits which +need it. + +### Avoiding unnecessary (re-)execution + +Traits can be applied to either test functions or suites, and traits applied to +suites can optionally support inheritance by implementing the `isRecursive` +property of the `SuiteTrait` protocol. When a trait is directly applied to a +test function, if the trait customizes the behavior of tests it's applied to, it +should be given the opportunity to perform its custom behavior once for every +invocation of that test function. In particular, if the test function is +parameterized and runs multiple times, then the trait applied to it should +perform its custom behavior once for every invocation. This should not be +surprising to users, since it's consistent with the behavior of `init` and +`deinit` for an instance `@Test` method. + +It may be useful for certain kinds of traits to perform custom logic once for +_all_ the invocations of a parameterized test. Although this should be possible, +we believe it shouldn't be the default since it could lead to work being +repeated multiple times needlessly, or unintentional state sharing across tests, +unless the trait is implemented carefully to avoid those problems. + +When a trait conforms to `SuiteTrait` and is applied to a suite, the question of +when its custom scope (if any) should be applied is less obvious. Some suite +traits support inheritance and are recursively applied to all the test functions +they contain (including transitively, via sub-suites). Other suite traits don't +support inheritance, and only affect the specific suite they're applied to. +(It's also worth noting that a sub-suite _can_ have the same non-recursive suite +trait one of its ancestors has, as long as it's applied explicitly.) + +As a general rule of thumb, we believe most traits will either want to perform +custom logic once for _all_ children or once for _each_ child, not both. +Therefore, when it comes to suite traits, the default behavior should depend on +whether it supports inheritance: a recursive suite trait should by default +perform custom logic before each test, and a non-recursive one per-suite. But +the APIs should be flexible enough to support both, for advanced traits which +need it. + +## Detailed design + +I propose the following new APIs: + +- A new protocol `TestScoping` with a single required `provideScope(...)` method. + This will be called to provide scope for a test, and allows the conforming + type to perform custom logic before or after. +- A new method `scopeProvider(for:testCase:)` on the `Trait` protocol whose + result type is an `Optional` value of a type conforming to `TestScoping`. A + `nil` value returned by this method will skip calling the `provideScope(...)` + method. +- A default implementation of `Trait.scopeProvider(...)` which returns `nil`. +- A conditional implementation of `Trait.scopeProvider(...)` which returns `self` + in the common case where the trait type conforms to `TestScoping` itself. + +Since the `scopeProvider(...)` method's return type is optional and returns `nil` +by default, the testing library cannot invoke the `provideScope(...)` method +unless a trait customizes test behavior. This avoids the "unnecessarily lengthy +backtraces" problem above. + +Below are the proposed interfaces: + +```swift +/// A protocol that allows providing a custom execution scope for a test +/// function (and each of its cases) or a test suite by performing custom code +/// before or after it runs. +/// +/// Types conforming to this protocol may be used in conjunction with a +/// ``Trait``-conforming type by implementing the +/// ``Trait/scopeProvider(for:testCase:)-cjmg`` method, allowing custom traits +/// to provide custom scope for tests. Consolidating common set-up and tear-down +/// logic for tests which have similar needs allows each test function to be +/// more succinct with less repetitive boilerplate so it can focus on what makes +/// it unique. +public protocol TestScoping: Sendable { + /// Provide custom execution scope for a function call which is related to the + /// specified test and/or test case. + /// + /// - Parameters: + /// - test: The test under which `function` is being performed. + /// - testCase: The test case, if any, under which `function` is being + /// performed. When invoked on a suite, the value of this argument is + /// `nil`. + /// - function: The function to perform. If `test` represents a test suite, + /// this function encapsulates running all the tests in that suite. If + /// `test` represents a test function, this function is the body of that + /// test function (including all cases if it is parameterized.) + /// + /// - Throws: Whatever is thrown by `function`, or an error preventing this + /// type from providing a custom scope correctly. An error thrown from this + /// method is recorded as an issue associated with `test`. If an error is + /// thrown before `function` is called, the corresponding test will not run. + /// + /// When the testing library is preparing to run a test, it starts by finding + /// all traits applied to that test, including those inherited from containing + /// suites. It begins with inherited suite traits, sorting them + /// outermost-to-innermost, and if the test is a function, it then adds all + /// traits applied directly to that functions in the order they were applied + /// (left-to-right). It then asks each trait for its scope provider (if any) + /// by calling ``Trait/scopeProvider(for:testCase:)-cjmg``. Finally, it calls + /// this method on all non-`nil` scope providers, giving each an opportunity + /// to perform arbitrary work before or after invoking `function`. + /// + /// This method should either invoke `function` once before returning or throw + /// an error if it is unable to provide a custom scope. + /// + /// Issues recorded by this method are associated with `test`. + func provideScope(for test: Test, testCase: Test.Case?, performing function: @Sendable () async throws -> Void) async throws +} + +public protocol Trait: Sendable { + // ... + + /// The type of the test scope provider for this trait. + /// + /// The default type is `Never`, which cannot be instantiated. The + /// ``scopeProvider(for:testCase:)-cjmg`` method for any trait with this + /// default type must return `nil`, meaning that trait will not provide a + /// custom scope for the tests it's applied to. + associatedtype TestScopeProvider: TestScoping = Never + + /// Get this trait's scope provider for the specified test and/or test case, + /// if any. + /// + /// - Parameters: + /// - test: The test for which a scope provider is being requested. + /// - testCase: The test case for which a scope provider is being requested, + /// if any. When `test` represents a suite, the value of this argument is + /// `nil`. + /// + /// - Returns: A value conforming to ``Trait/TestScopeProvider`` which may be + /// used to provide custom scoping for `test` and/or `testCase`, or `nil` if + /// they should not have any custom scope. + /// + /// If this trait's type conforms to ``TestScoping``, the default value + /// returned by this method depends on `test` and/or `testCase`: + /// + /// - If `test` represents a suite, this trait must conform to ``SuiteTrait``. + /// If the value of this suite trait's ``SuiteTrait/isRecursive`` property + /// is `true`, then this method returns `nil`; otherwise, it returns `self`. + /// This means that by default, a suite trait will _either_ provide its + /// custom scope once for the entire suite, or once per-test function it + /// contains. + /// - Otherwise `test` represents a test function. If `testCase` is `nil`, + /// this method returns `nil`; otherwise, it returns `self`. This means that + /// by default, a trait which is applied to or inherited by a test function + /// will provide its custom scope once for each of that function's cases. + /// + /// A trait may explicitly implement this method to further customize the + /// default behaviors above. For example, if a trait should provide custom + /// test scope both once per-suite and once per-test function in that suite, + /// it may implement the method and return a non-`nil` scope provider under + /// those conditions. + /// + /// A trait may also implement this method and return `nil` if it determines + /// that it does not need to provide a custom scope for a particular test at + /// runtime, even if the test has the trait applied. This can improve + /// performance and make diagnostics clearer by avoiding an unnecessary call + /// to ``TestScoping/provideScope(for:testCase:performing:)``. + /// + /// If this trait's type does not conform to ``TestScoping`` and its + /// associated ``Trait/TestScopeProvider`` type is the default `Never`, then + /// this method returns `nil` by default. This means that instances of this + /// trait will not provide a custom scope for tests to which they're applied. + func scopeProvider(for test: Test, testCase: Test.Case?) -> TestScopeProvider? +} + +extension Trait where Self: TestScoping { + // Returns `nil` if `testCase` is `nil`, else `self`. + public func scopeProvider(for test: Test, testCase: Test.Case?) -> Self? +} + +extension SuiteTrait where Self: TestScoping { + // If `test` is a suite, returns `nil` if `isRecursive` is `true`, else `self`. + // Otherwise, `test` is a function and this returns `nil` if `testCase` is + // `nil`, else `self`. + public func scopeProvider(for test: Test, testCase: Test.Case?) -> Self? +} + +extension Trait where TestScopeProvider == Never { + // Returns `nil`. + public func scopeProvider(for test: Test, testCase: Test.Case?) -> Never? +} + +extension Never: TestScoping {} +``` + +Here is a complete example of the usage scenario described earlier, showcasing +the proposed APIs: + +```swift +@Test(.mockAPICredentials) +func example() { + // ...validate API usage, referencing `APICredentials.current`... +} + +struct MockAPICredentialsTrait: TestTrait, TestScoping { + func provideScope(for test: Test, testCase: Test.Case?, performing function: @Sendable () async throws -> Void) async throws { + let mockCredentials = APICredentials(apiKey: "...") + try await APICredentials.$current.withValue(mockCredentials) { + try await function() + } + } +} + +extension Trait where Self == MockAPICredentialsTrait { + static var mockAPICredentials: Self { + Self() + } +} +``` + +## Source compatibility + +The proposed APIs are purely additive. + +This proposal will replace the existing `CustomExecutionTrait` SPI, and after +further refactoring we anticipate it will obsolete the need for the +`SPIAwareTrait` SPI as well. + +## Integration with supporting tools + +Although some built-in traits are relevant to supporting tools (such as +SourceKit-LSP statically discovering `.tags` traits), custom test behaviors are +only relevant within the test executable process while tests are running. We +don't anticipate any particular need for this feature to integrate with +supporting tools. + +## Future directions + +### Access to suite type instances + +Some test authors have expressed interest in allowing custom traits to access +the instance of a suite type for `@Test` instance methods, so the trait could +inspect or mutate the instance. Currently, only instance-level members of a +suite type (including `init`, `deinit`, and the test function itself) can access +`self`, so this would grant traits applied to an instance test method access to +the instance as well. This is certainly interesting, but poses several technical +challenges that puts it out of scope of this proposal. + +### Convenience trait for setting task locals + +Some reviewers of this proposal pointed out that the hypothetical usage example +shown earlier involving setting a task local value while a test is executing +will likely become a common use of these APIs. To streamline that pattern, it +would be very natural to add a built-in trait type which facilitates this. I +have prototyped this idea and plan to add it once this new trait functionality +lands. + +## Alternatives considered + +### Separate set up & tear down methods on `Trait` + +This idea was discussed in [Supporting scoped access](#supporting-scoped-access) +above, and as mentioned there, the primary problem with this approach is that it +cannot be used with scoped access-style APIs, including (importantly) +`TaskLocal.withValue()`. For that reason, it prevents using that common Swift +concurrency technique and reduces the potential for test parallelization. + +### Add `provideScope(...)` directly to the `Trait` protocol + +The proposed `provideScope(...)` method could be added as a requirement of the +`Trait` protocol instead of being part of a separate `TestScoping` protocol, and +it could have a default implementation which directly invokes the passed-in +closure. But this approach would suffer from the lengthy backtrace problem +described above. + +### Extend the `Trait` protocol + +The original, experimental implementation of this feature included a protocol +named`CustomExecutionTrait` which extended `Trait` and had roughly the same +method requirement as the `TestScoping` protocol proposed above. This design +worked, provided scoped access, and avoided the lengthy backtrace problem. + +After evaluating the design and usage of this SPI though, it seemed unfortunate +to structure it as a sub-protocol of `Trait` because it means that the full +capabilities of the trait system are spread across multiple protocols. In the +proposed design, the ability to return a test scoping provider is exposed via +the main `Trait` protocol, and it relies on an associated type to conditionally +opt-in to custom test behavior. In other words, the proposed design expresses +custom test behavior as just a _capability_ that a trait may have, rather than a +distinct sub-type of trait. + +Also, the implementation of this approach within the testing library was not +ideal as it required a conditional `trait as? CustomExecutionTrait` downcast at +runtime, in contrast to the simpler and more performant Optional property of the +proposed API. + +### API names + +We first considered "execute" as the base verb for the proposed new concept, but +felt this wasn't appropriate since these trait types are not "the executor" of +tests, they merely customize behavior and provide scope(s) for tests to run +within. Also, the term "executor" has prior art in Swift Concurrency, and +although that word is used in other contexts too, it may be helpful to avoid +potential confusion with concurrency executors. + +We also considered "run" as the base verb for the proposed new concept instead +of "execute", which would imply the names `TestRunning`, `TestRunner`, +`runner(for:testCase)`, and `run(_:for:testCase:)`. The word "run" is used in +many other contexts related to testing though, such as the `Runner` SPI type and +more casually to refer to a run which occurred of a test, in the past tense, so +overloading this term again may cause confusion. + +## Acknowledgments + +Thanks to [Dennis Weissmann](https://github.com/dennisweissmann) for originally +implementing this as SPI, and for helping promote its usefulness. + +Thanks to [Jonathan Grynspan](https://github.com/grynspan) for exploring ideas +to refine the API, and considering alternatives to avoid unnecessarily long +backtraces. + +Thanks to [Brandon Williams](https://github.com/mbrandonw) for feedback on the +Forum pitch thread which ultimately led to the refinements described in the +"Avoiding unnecessary (re-)execution" section. From 22bfdc28b73523c89145705d3de46f3cd4ddaa9c Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 4 Mar 2025 10:50:05 -0500 Subject: [PATCH 123/505] Add alternative considered: parameter packs --- proposals/testing/NNNN-exit-tests.md | 48 ++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/NNNN-exit-tests.md index c822fd90fb..29d2ac0775 100644 --- a/proposals/testing/NNNN-exit-tests.md +++ b/proposals/testing/NNNN-exit-tests.md @@ -246,7 +246,7 @@ describes how the child process is expected to have exited: standard, but not to the degree that signals are supported by POSIX-like or UNIX-derived operating systems. Swift Testing makes a "best effort" to emulate signal-handling support on Windows. See [this](https://forums.swift.org/t/swift-on-windows-question-about-signals-and-exceptions/76640/2) - Swift forum message for more information. + Swift forum message for more information. The type is declared as: @@ -287,7 +287,7 @@ extension ExitTest { public static var failure: Self { get } public init(_ statusAtExit: StatusAtExit) - + /// Creates a condition that matches when a process terminates with a given /// exit code. /// @@ -311,7 +311,7 @@ extension ExitTest { /// systems may only reliably report the low unsigned 8 bits (0–255) of /// the exit code. public static func exitCode(_ exitCode: CInt) -> Self - + /// Creates a condition that matches when a process terminates with a given /// signal. /// @@ -624,7 +624,7 @@ and control returns to the test function that is awaiting the exit test: ```swift await #expect(exitsWith: .failure) { - throw TacoError.noTacosFound + throw TacoError.noTacosFound } ``` @@ -737,7 +737,7 @@ let result = try await #require(process, exitsWith: .success) case signal(CInt) } ``` - + This simplified the set of types used for exit tests, but made comparing two exit conditions complicated and necessitated a `==` operator that did not satisfy the requirements of the `Equatable` protocol. @@ -756,7 +756,7 @@ let result = try await #require(process, exitsWith: .success) I settled on `StatusAtExit` because it was distinct and makes it clear that it represents the status of a process _at exit time_. `ExitStatus` could be interpreted as the status of the exit itself, i.e.: - + ```swift enum ExitStatus { case running @@ -766,6 +766,42 @@ let result = try await #require(process, exitsWith: .success) } ``` +- Using parameter packs to specify observed values and return types: + + ```swift + @freestanding(expression) public macro require( + exitsWith expectedExitCondition: ExitTest.Condition, + observing observedValues: (repeat (KeyPath)) = (), + _ comment: @autoclosure () -> Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation, + performing expression: @escaping @Sendable @convention(thin) () async throws -> Void + ) -> (repeat each T) + ``` + + Using a parameter pack in this way would make it impossible to access + properties of the returned `ExitTest.Result` value that weren't observed, and + in general would mean developers wouldn't even need to use `ExitTest.Result`: + + ```swift + let (status, stderr) = try await #expect( + exitsWith: .failure, + observing: (\.statusAtExit, \.standardErrorContent) + ) { ... } + #expect(status == ...) + #expect(stderr.contains(...)) + ``` + + Unfortunately, the `#expect(exitsWith:)` and `#require(exitsWith:)` macros do + not have enough information at compile time to correctly infer the types of + the key paths passed as `observedValues` above, so we end up with rather + obscure errors: + + > 🛑 Cannot convert value of type 'KeyPath<_, _>' to expected argument type + > 'KeyPath' + + If, in the future, this error is resolved, we may wish to revisit this option, + so it can also be considered a "future direction" for the feature. + - Changing the implementation of `precondition()`, `fatalError()`, etc. in the standard library so that they do not terminate the current process while testing, thus removing the need to spawn a child process for an exit test. From 45b3f89a19db3f91db192288473e1ff1cdda64bc Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Wed, 5 Mar 2025 00:43:17 +0000 Subject: [PATCH 124/505] add documentation link --- proposals/NNNN-environment-dependent-shared-libraries.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-environment-dependent-shared-libraries.md b/proposals/NNNN-environment-dependent-shared-libraries.md index e7a0569ab5..6a6cdbe8e9 100644 --- a/proposals/NNNN-environment-dependent-shared-libraries.md +++ b/proposals/NNNN-environment-dependent-shared-libraries.md @@ -4,6 +4,7 @@ * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) +* Documentation: [How to use Environment-Dependent Shared Libraries](https://github.com/tayloraswift/swift-edsl-example-client/blob/master/Sources/KrustyKrab/docs.docc/Getting%20Started.md) * Bugs: [SR-5714](https://github.com/swiftlang/swift-package-manager/issues/5714) ## Introduction @@ -12,9 +13,9 @@ SwiftPM currently has no support for non-system binary library dependencies on L Swift-evolution thread: [Discussion thread](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605) -Example Producer: [swift-rlp-example](https://github.com/tayloraswift/swift-rlp-example) +Example Producer: [swift-edsl-example](https://github.com/tayloraswift/swift-edsl-example) -Example Consumer: [swift-rlp-example-client](https://github.com/tayloraswift/swift-rlp-example-client) +Example Consumer: [swift-edsl-example-client](https://github.com/tayloraswift/swift-edsl-example-client) ## Motivation From 5d58ff928d6ef07fe1ad6906abd3cc3d7af8ea01 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Tue, 4 Mar 2025 17:08:24 -0800 Subject: [PATCH 125/505] Proposal to add epoch properties to SuspendingClock and ContinuousClock --- proposals/NNNN-ClockEpochs.md | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 proposals/NNNN-ClockEpochs.md diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md new file mode 100644 index 0000000000..88d77fe96c --- /dev/null +++ b/proposals/NNNN-ClockEpochs.md @@ -0,0 +1,58 @@ +# Clock Epochs + +* Proposal: [SE-NNNN](NNNN-ClockEpochs.md) +* Authors: [Philippe Hausler](https://github.com/phausler) +* Review Manager: TBD +* Status: **Awaiting implementation** +* Implementation: + +* Previous Proposal: *if applicable* [SE-0329](0329-clock-instant-duration.md) +* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) + +## Introduction + +[The proposal for Clock, Instant and Duration](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) brought in two primary clock types: `SuspendingClock` and `ContinuousClock`. These both have a concept of a reference point for their `Instant` types. + +## Motivation + +Not all clocks have a starting point, however in these cases they do. Generally, it cannot required for a clock's instant definition to have a start or the start may not be a fixed point. However it can be useful that a given instant can be constructed to determine the elapsed duration from the starting point of that clock if it does have it. + +## Proposed solution + +Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. Both of these properties will be the epoch for which all `Instant` types are derived from; practically speaking this is the "zero" point for these clocks. + +## Detailed design + +```swift +extension ContinousClock { + public var epoch: Instant { get } +} + +extension SuspendingClock { + public var epoch: Instant { get } +} +``` + +These can be used to gather information like for example the uptime of a system, or the active time of a system; + +```swift +let clock = ContinousClock() +let uptime = clock.now - clock.epoch +``` + +Or likewise; + +```swift +let clock = SuspendingClock() +let activeTime = clock.now - clock.epoch +``` + +## ABI compatibility + +This is a purely additive change and provides no direct impact to existing ABI. It only carries the ABI impact of new properties being added to an existing type. + +## Alternatives considered + +It was considered to add a constructor or static member to the `SuspendingClock.Instant` and `ContinousClock.Instant` however the home on the clock itself provides a more discoverable and nameable location. + +It is suggested that this be used as an informal protocol for other clocks. It was considered as an additional protocol but that was ultimately rejected because no generic function made much sense that would not be better served with generic specialization or explicit clock parameter types. \ No newline at end of file From b85a6b32fce631e13a62bc8c8ccb132b7f9e9845 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 5 Mar 2025 19:20:37 +0900 Subject: [PATCH 126/505] Update proposals/NNNN-SerialExecutor-isIsolated.md Co-authored-by: TTOzzi --- proposals/NNNN-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index e60b53a5ae..d73787dffd 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -8,7 +8,7 @@ ## Introduction -In [SE-0424: Custom isolation checking for SerialExecutor](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0424-custom-isolation-checking-for-serialexecutor.md) we introduced a way for custom executors implementing the `SerialExecutor` protocol to assert and and assume the static isolation if the dynamic check succeeded. This proposal extends these capabilities, allowing custom executors to not only "check and crash if assumption was wrong", but also check and act on the result of the check. +In [SE-0424: Custom isolation checking for SerialExecutor](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0424-custom-isolation-checking-for-serialexecutor.md) we introduced a way for custom executors implementing the `SerialExecutor` protocol to assert and assume the static isolation if the dynamic check succeeded. This proposal extends these capabilities, allowing custom executors to not only "check and crash if assumption was wrong", but also check and act on the result of the check. ## Motivation From 87d86ad19273f88f3a14251d3f299371e9213e04 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 5 Mar 2025 19:21:00 +0900 Subject: [PATCH 127/505] Apply suggestions from code review Co-authored-by: TTOzzi --- proposals/NNNN-SerialExecutor-isIsolated.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index d73787dffd..98ad33ea3b 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -57,7 +57,7 @@ This approach is better than not being able to participate in the checks at all - the crash **messages** offered by these `checkIsolated()` crashes **are often sub-optimal** and confusing - messages often don't include crucial information about which actor/executor the calling context was _actually_ executing on. Offering only "expected [...]" messages, leading to hard to debug crashes. - it is **impossible** for the Swift runtime to offer **isolation violation warnings** - - because the Swift runtime _must_ call into a custom executor to verify its isolation, the "pass or crash" method will crash, rather than inform the runtime that a violation ocured and we should warn about it. + - because the Swift runtime _must_ call into a custom executor to verify its isolation, the "pass or crash" method will crash, rather than inform the runtime that a violation occurred and we should warn about it. Today, it is not possible for the Swift runtime to issue _warnings_ if something is detected to be on not the expected executor, but somehow we'd still like to continue without crashing the application. @@ -90,9 +90,9 @@ extension SerialExecutor { } ``` -The Swift runtime is free to call the `isIsolated` function whenever it wants to verify if the current context is apropriately isolated by some serial executor. +The Swift runtime is free to call the `isIsolated` function whenever it wants to verify if the current context is appropriately isolated by some serial executor. -In most cases implementing this new API is preferable to implementing `checkIsolated()`, as the Swift runtime is able to offer more detailed error messages when when an isolation failure detected by a call to `isIsolatingCurrentContext()` is detected. +In most cases implementing this new API is preferable to implementing `checkIsolated()`, as the Swift runtime is able to offer more detailed error messages when an isolation failure detected by a call to `isIsolatingCurrentContext()` is detected. ## Detailed design From 911ad36dfaf2c23b98288caaa11cd9deb1c1478f Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 5 Mar 2025 19:21:41 +0900 Subject: [PATCH 128/505] Link to partial implementation --- proposals/NNNN-SerialExecutor-isIsolated.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 98ad33ea3b..d5db0285fe 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -3,7 +3,8 @@ * Proposal: [SE-NNNN](...) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: -* Status: **WIP** +* Status: **Partial implementation** +* Implementation: https://github.com/swiftlang/swift/pull/79788 * Review: TODO ## Introduction From 5accdb5b143b0bf089fe647f0beee6ce95c849e4 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 5 Mar 2025 13:40:52 -0500 Subject: [PATCH 129/505] Assign SE-0464. --- ...processing.md => 0464-utf8span-safe-utf8-processing.md} | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename proposals/{nnnn-utf8span-safe-utf8-processing.md => 0464-utf8span-safe-utf8-processing.md} (99%) diff --git a/proposals/nnnn-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md similarity index 99% rename from proposals/nnnn-utf8span-safe-utf8-processing.md rename to proposals/0464-utf8span-safe-utf8-processing.md index 26308fcadf..4576916bbe 100644 --- a/proposals/nnnn-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -1,12 +1,11 @@ # UTF8Span: Safe UTF-8 Processing Over Contiguous Bytes -* Proposal: [SE-NNNN](nnnn-utf8-span.md) +* Proposal: [SE-0464](0464-utf8-span.md) * Authors: [Michael Ilseman](https://github.com/milseman), [Guillaume Lessard](https://github.com/glessard) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [Tony Allevato](https://github.com/allevato) +* Status: **Active review (March 5–19, 2025)** * Bug: rdar://48132971, rdar://96837923 * Implementation: https://github.com/swiftlang/swift/pull/78531 -* Upcoming Feature Flag: * Review: ([pitch 1](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([pitch 2](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) From 80decd57475c3c4f136507931feb173d7e57c428 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 5 Mar 2025 13:43:16 -0500 Subject: [PATCH 130/505] SE-0464: Link to active review thread. --- proposals/0464-utf8span-safe-utf8-processing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0464-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md index 4576916bbe..cb9cb817fd 100644 --- a/proposals/0464-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -6,7 +6,7 @@ * Status: **Active review (March 5–19, 2025)** * Bug: rdar://48132971, rdar://96837923 * Implementation: https://github.com/swiftlang/swift/pull/78531 -* Review: ([pitch 1](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([pitch 2](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) +* Review: ([pitch 1](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([pitch 2](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) ## Introduction From 6af0259937cd87067c795b165f2951d7a525a9a7 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 5 Mar 2025 11:21:43 -0800 Subject: [PATCH 131/505] Nonescapable stdlib primitives (#2657) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial version of the pitch text * Proofreading edits * Resolve FIXMEs that I left in by accident * Add link to forum pitch; update TOC * Dedupe sections on lifetime management * Remove unsafeBitCast generalization for now The proposed variant is much too limited, and it also introduces a new axis of unsafety that may better be expressed with dedicated API. We do not see any _immediate_ need for bit casting between escapable/nonescapable types, so it seems we can safely defer this work. * Reword section on ObjectIdentifier; add note on ==/!= operators over metatypes * Add metatype comparisons; take back Optional.unsafelyUnwrapped; minor edits - Add generalizations for `==`/`!=` over existential metatypes - Update ObjectIdentifier.init to use the right definition now that it works - Take out the generalization of `Optional.unsafelyUnwrapped` due to issues with C++ interop. (I expect we’ll fix this in the next proposal in this series.) - Add explicit (illustrative) attributes to describe the lifetime semantics of generalized API. - General copy editing * One more round of updates - Correct number of SE-0437 (!) - Provisionally reintroduce `Optional.unsafelyUnwrapped`. (We trust the interop issue can be fixed soon.) - Add explicit sections in Detailed Design describing inferred lifetime semantics for enum operations - Reword the introduction of infinite lifetimes - More copy editing --- .../NNNN-nonescapable-stdlib-primitives.md | 892 ++++++++++++++++++ 1 file changed, 892 insertions(+) create mode 100644 proposals/NNNN-nonescapable-stdlib-primitives.md diff --git a/proposals/NNNN-nonescapable-stdlib-primitives.md b/proposals/NNNN-nonescapable-stdlib-primitives.md new file mode 100644 index 0000000000..788faef5cf --- /dev/null +++ b/proposals/NNNN-nonescapable-stdlib-primitives.md @@ -0,0 +1,892 @@ +# Standard Library Primitives for Nonescapable Types + +* Proposal: [SE-NNNN](NNNN-nonescapable-stdlib-primitives.md) +* Authors: [Karoy Lorentey](https://github.com/lorentey) +* Review Manager: TBD +* Status: **Awaiting review** +* Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] +* Implementation: https://github.com/swiftlang/swift/pull/73258 +* Review: ([Pitch]) + +[Roadmap]: https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206 +[Pitch]: https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253 + + + +Related proposals: + +- [SE-0377] `borrowing` and `consuming` parameter ownership modifiers +- [SE-0390] Noncopyable structs and enums +- [SE-0426] `BitwiseCopyable` +- [SE-0427] Noncopyable generics +- [SE-0429] Partial consumption of noncopyable values +- [SE-0432] Borrowing and consuming pattern matching for noncopyable types +- [SE-0437] Noncopyable Standard Library Primitives +- [SE-0446] Nonescapable Types +- [SE-0447] `Span`: Safe Access to Contiguous Storage +- [SE-0452] Integer Generic Parameters +- [SE-0453] `InlineArray`, a fixed-size array +- [SE-0456] Add `Span`-providing Properties to Standard Library Types + + + +[SE-0370]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0370-pointer-family-initialization-improvements.md +[SE-0377]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0377-parameter-ownership-modifiers.md +[SE-0390]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0390-noncopyable-structs-and-enums.md +[SE-0426]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0426-bitwise-copyable.md +[SE-0427]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0427-noncopyable-generics.md +[SE-0429]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0429-partial-consumption.md +[SE-0432]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0432-noncopyable-switch.md +[SE-0437]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md +[SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md +[SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md +[SE-0452]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0452-integer-generic-parameters.md +[SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md +[SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md + +### Table of Contents + + * [Introduction](#introduction) + * [Motivation](#motivation) + * [Proposed Solution](#proposed-solution) + * [Nonescapable optionals](#nonescapable-optionals) + * [Nonescapable Result](#nonescapable-result) + * [Retrieving the memory layout of nonescapable types](#retrieving-the-memory-layout-of-nonescapable-types) + * [Lifetime management](#lifetime-management) + * [Metatype comparisons](#metatype-comparisons) + * [Object identifiers](#object-identifiers) + * [Odds and ends](#odds-and-ends) + * [Detailed Design](#detailed-design) + * [Inferred lifetime behavior of nonescapable enum types](#inferred-lifetime-behavior-of-nonescapable-enum-types) + * [Inferred lifetime behavior of Optional's notational conveniences](#inferred-lifetime-behavior-of-optionals-notational-conveniences) + * [protocol ExpressibleByNilLiteral](#protocol-expressiblebynilliteral) + * [enum Optional](#enum-optional) + * [enum Result](#enum-result) + * [enum MemoryLayout](#enum-memorylayout) + * [Lifetime Management](#lifetime-management-1) + * [Metatype equality](#metatype-equality) + * [struct ObjectIdentifier](#struct-objectidentifier) + * [ManagedBufferPointer equatability](#managedbufferpointer-equatability) + * [Making indices universally available on unsafe buffer pointers](#making-indices-universally-available-on-unsafe-buffer-pointers) + * [Buffer pointer operations on Slice](#buffer-pointer-operations-on-slice) + * [Source compatibility](#source-compatibility) + * [ABI compatibility](#abi-compatibility) + * [Note on protocol generalizations](#note-on-protocol-generalizations) + * [Alternatives Considered](#alternatives-considered) + * [Future Work](#future-work) + * [Acknowledgements](#acknowledgements) + +## Introduction + +This document proposes to allow `Optional` and `Result` to hold instances of nonescapable types, and continues the work of adding support for noncopyable and nonescapable types throughout the Swift Standard Library. + + +## Motivation + +[SE-0437] started integrating noncopyable types into our Standard Library abstractions, by generalizing existing APIs and introducing new ones. In the time since that proposal, [SE-0446] has introduced nonescapable types to Swift, adding a new direction of generalization. + +This proposal continues the work of [SE-0437] by extending some basic constructs to support nonescapable types, where it is already possible to do so. For now, we are focusing on further generalizing a subset of the constructs covered by [SE-0437]: `MemoryLayout`, `Optional`, and `Result` types. Our immediate aim is to unblock the use of nonescapable types, especially in API surfaces. We also smooth out some minor inconsistencies that [SE-0437] has left unresolved. + +Like before, our aim is to implement these generalizations with as little disruption as possible. Existing code implicitly assumes copyability and escapability, and it needs to continue working as before. + +## Proposed Solution + +This proposal is focusing on achieving the following results: + +- Allow `Optional` to wrap nonescapable types, itself becoming conditionally escapable. +- Do the same for `Result`, allowing its success case to hold a nonescapable item. +- Generalize `MemoryLayout` to allow querying basic information on the memory layout of nonescapable types. +- Continue generalizing basic lifetime management functions; introduce a new `extendLifetime()` function that avoids a closure argument. +- Allow generating `ObjectIdentifier` instances for noncopyable and/or nonescapable metatypes. +- Allow comparing noncopyable and nonescapable metatypes for equality. + +We also propose to fix a handful of minor copyability-related omissions that have been discovered since [SE-0437] was accepted: + +- Allow `ManagedBufferPointer` instances to be equatable even when `Element` is noncopyable. +- Make the `Unsafe[Mutable]BufferPointer.indices` property universally available for all `Element` types. +- Generalize select operations on unsafe buffer pointer slices, to restore consistency with the same operations on the buffer pointers themselves. + +### Nonescapable optionals + +We want `Optional` to support wrapping all Swift types, whether or not they're copyable or escapable. This means that `Optional` needs to become conditionally escapable, depending on the escapability of its `Wrapped` type. + +`Optional` must itself become nonescapable when it is wrapping a nonescapable type, and such optional values need to be subject to precisely the same lifetime constraints as their wrapped item: we cannot allow the act of wrapping a nonescapable value in an optional to allow that value to escape its intended context. + +There are many ways to construct optional values in Swift: for example, we can explicitly invoke the factory for the `.some` case, we can rely on Swift's implicit optional promotion rules, or we can invoke the default initializer. We propose to generalize all of these basic/primitive mechanisms to support nonescapable use. For instance, given a non-optional `Span` value, this code exercises these three basic ways of constructing non-nil nonescapable optionals: + +```swift +func sample(_ span: Span) { + let a = Optional.some(span) // OK, explicit case factory + let b: Optional = span // OK, implicit optional promotion + let c = Optional(span) // OK, explicit initializer invocation +} +``` + +`a`, `b`, and `c` hold the same span instance, and their lifetimes are subject to the same constraints as the original span -- they can be used within the context of the `sample` function, but they cannot escape outside of it. (At least not without explicit lifetime dependency annotations, to be introduced in the future.) + +Of course, it also needs to be possible to make empty `Optional` values that do not hold anything. We have three basic ways to do that: we can explicitly invoke the factory for the `none` case, we can reach for the special `nil` literal, or (for `var`s) we can rely on implicit optional initialization. This proposal generalizes all three mechanisms to support noncopyable wrapped types: + +```swift +func sample(_ span: Span) { + var d: Span? = .none // OK, explicit factory invocation + var e: Span? = nil // OK, nil literal expression + var f: Span? // OK, implicit nil default value +} +``` + +Empty optionals of nonescapable types are still technically nonescapable, but they aren't inherently constrained to any particular context -- empty optionals are born with "immortal" (or "static") lifetimes, i.e., they have no lifetime dependencies, and so they are allowed to stay around for the entire execution of a Swift program. Nil optionals can be passed to any operation that takes a nonescapable optional, no matter what expectations it may dictate about its lifetime dependencies; they can also be returned from any function that returns a nonescapable optional. (Note though that Swift does not yet provide a stable way to define such functions.) + +Of course, we also expect to be able to reassign variables, rebinding them to a new value. Reassignments of local variables are allowed to arbitrarily change lifetime dependencies. There is no expectation that the lifetime dependencies of the new value have any particular relation to the old: local variable reassignments can freely "narrow" or "widen" dependencies, as they see fit. + +For instance, the code below initializes an optional variable to an immortal nil value; it then assigns it a new value that has definite lifetime constraints; and finally it turns it back to an immortal nil value: + +```swift +func sample(_ span: Span) { + var maybe: Span? = nil // immortal + maybe = span // definite lifetime + maybe = nil // immortal again +} +``` + +(Assigning `span` to `maybe` is not an escape, as the local variable will be destroyed before the function returns, even without the subsequent reassignment.) + +This flexibility will not necessarily apply to other kinds of variables, like stored properties in custom nonescapable structs, global variables, or computed properties -- I expect those variables to carry specific lifetime dependencies that cannot vary through reassignment. (For example, a global variable of a nonescapable type may be required to hold immortal values only.) However, for now, we're limiting our reasoning to local variables. + +Of course, an optional is of limited use unless we are able to decide whether it contains a value, and (if so) to unwrap it and look at its contents. We need to be able to operate on nonescapable optionals using the familiar basic mechanisms: + + - `switch` and `if case`/`guard case` statements that pattern match over them: + + ```swift + // Variant 1: Full pattern matching + func count(of maybeSpan: Span?) -> Int { + switch maybeSpan { + case .none: return 0 + case .some(let span): return span.count + } + } + + // Variant 2: Pattern matching with optional sugar + func count(of maybeSpan: Span?) -> Int { + switch maybeSpan { + case nil: return 0 + case let span?: return span.count + } + } + ``` + + - The force-unwrapping `!` special form, and its unsafe cousin, the Standard Library's `unsafelyUnwrapped` property. + + ```swift + func count(of maybeSpan: Span?) -> Int { + if case .none = maybeSpan { return 0 } + return maybeSpan!.count + } + ``` + +- The optional chaining special form `?`: + + ```swift + func count(of maybeSpan: Span?) -> Int { + guard let c = maybeSpan?.count else { return 0 } + return c + } + ``` + +- Optional bindings such as `if let` or `guard let` statements: + + ```swift + func count(of maybeSpan: Span?) -> Int { + guard let span = maybeSpan else { return 0 } + return span.count + } + ``` + +These variants all work as expected. To avoid escapability violations, unwrapping the nonescapable optional results in a value with precisely the same lifetime dependencies as the original optional value. This applies to all forms of unwrapping, including pattern matching forms that bind copies of associated values to new variables, like `let span` above -- the resulting `span` value always has the same lifetime as the optional it comes from. + +The standard `Optional` type has custom support for comparing optional instances against `nil` using the traditional `==` operator, whether or not the wrapped type conforms to `Equatable`. [SE-0437] generalized this mechanism for noncopyable wrapped types, and it is reasonable to extend this to also cover the nonescapable case: + +```swift +func count(of maybeSpan: Span?) -> Int { + if maybeSpan == nil { return 0 } // OK! + return maybeSpan!.count +} +``` + +This core set of functionality makes nonescapable optionals usable, but it does not yet enable the use of more advanced APIs. Eventually, we'd also like to use the standard `Optional.map` function (and similar higher-order functions) to operate on (or to return) nonescapable optional types, as in the example below: + +```swift +func sample(_ maybeArray: Array?) { + // Assuming `Array.storage` returns a nonescapable `Span`: + let maybeSpan = maybeArray.map { $0.storage } + ... +} +``` + +These operations require precise reasoning about lifetime dependencies though, so they have to wait until we have a stable way to express lifetime annotations on their definitions. We expect lifetime semantics to become an integral part of the signatures of functions dealing with nonescapable entities -- for the simplest cases they can often remain implicit, but for something like `map` above, we'll need to explicitly describe how the lifetime of the function's result relates to the lifetime of the result of the function argument. We need to defer this work until we have the means to express such annotations in the language. + +One related omission from the list of generalizations above is the standard nil-coalescing operator `??`. This is currently defined as follows (along with another variant that returns an `Optional`): + +```swift +func ?? ( + optional: consuming T?, + defaultValue: @autoclosure () throws -> T +) rethrows -> T +``` + +To generalize this to also allow nonescapable `T` types, we'll need to specify that the returned value's lifetime is tied to the _intersection_ of the lifetime of the left argument and the lifetime of the result of the right argument (a function). We aren't currently able to express that, so this generalization has to be deferred as well until the advent of such a language feature. + +### Nonescapable `Result` + +We generalize `Result` along the same lines as `Optional`, allowing its `success` case to wrap a nonescapable value. For now, we need to mostly rely on Swift's general enum facilities to operate on nonescapable `Result` values: switch statements, case factories, pattern matching, associated value bindings etc. + +Important convenience APIs such as `Result.init(catching:)` or `Result.map` will need to require escapability until we introduce a way to formally specify lifetime dependencies. This is unfortunate, but it still enables intrepid Swift developers to experiment with defining interfaces that take (or perhaps even return!) `Result` values. + +However, we are already able to generalize a small handful of methods: `get` and the two error-mapping utilities, `mapError` and `flatMapError`. + +```swift +func sample(_ res: Result, E>) -> Int { + guard let span = try? res.get() else { return 42 } + return 3 * span.count + 9 +} +``` + +Like unwrapping an `Optional`, calling `get()` on a nonescapable `Result` returns a value whose lifetime requirements exactly match that of the original `Result` instance -- the act of unwrapping a result cannot allow its content to escape its intended context. + +### Retrieving the memory layout of nonescapable types + +This proposal generalizes `enum MemoryLayout` to support retrieving information about the layout of nonescapable types: + +```swift +print(MemoryLayout>.size) // ⟹ 16 +print(MemoryLayout>.stride) // ⟹ 16 +print(MemoryLayout>.alignment) // ⟹ 8 +``` + +(Of course, the values returned will vary depending on the target architecture.) + +The information returned is going to be of somewhat limited use until we generalize unsafe pointer types to support nonescapable pointees, which this proposal does not include -- but there is no reason to delay this work until then. + +To usefully allow pointers to nonescapable types, we'll need to assign precise lifetime semantics to their `pointee` (and pointer dereferencing in general), and we'll most likely also need a way to allow developers to unsafely override the resulting default lifetime semantics. This requires explicit lifetime annotations, and as such, that work is postponed to a future proposal. + +### Lifetime management + +We once again generalize the `withExtendedLifetime` family of functions, this time to support calling them on nonescapable values. + +```swift +let span = someArray.storage +withExtendedLifetime(span) { span in + // `someArray` is being actively borrowed while this closure is running +} +// At this point, `someArray` may be ready to be mutated +``` + +We've now run proposals to generalize `withExtendedLifetime` for (1) typed throws, (2) noncopyable inputs and results, and (3) nonescapable inputs. It is getting unwieldy to keep having to tweak these APIs, especially since in actual practice, `withExtendedLifetime` is most often called with an empty closure, to serve as a sort of fence protecting against early destruction. The closure-based design of these interfaces are no longer fitting the real-life practices of Swift developers. These functions were originally designed to be used with a non-empty closure, like in the example below: + +```swift +withExtendedLifetime(obj) { + weak var ref = obj + foo(ref!) +} +``` + +In most cases, the formulation we actually recommend these days is to use a defer statement, with the function getting passed an empty closure: + +```swift +weak var ref = obj +defer { withExtendedLifetime(obj) {} } // Ugh 😖 +foo(ref!) +``` + +These functions clearly weren't designed to accommodate this widespread practice. To acknowledge and embrace this new style, we propose to introduce a new public Standard Library function that simply extends the lifetime of whatever variable it is given: + +```swift +func extendLifetime(_ x: borrowing T) +``` + +This allows `defer` incantations like the one above to be reformulated into a more readable form: + +```swift +// Slightly improved reality +weak var ref = obj +defer { extendLifetime(obj) } +foo(ref!) +``` + +To avoid disrupting working code, this proposal does not deprecate the existing closure-based functions in favor of the new `extendLifetime` operation. (Introducing the new function will still considerably reduce the need for future Swift releases to continue repeatedly generalizing the existing functions -- for example, to allow async use, or to allow nonescapable results.) + +### Metatype comparisons + +Swift's metatypes do not currently conform to `Equatable`, but the Standard Library still provides top-level `==` and `!=` operators that implement the expected equality relation. Previously, these operators only worked on metatypes of `Copyable` and `Escapable` types; we propose to relax this requirement. + +```swift +print(Atomic.self == Span.self) // ⟹ false +``` + +The classic operators support existential metatypes `Any.Type`; the new variants also accept generalized existentials: + +```swift +let t1: any (~Copyable & ~Escapable).Type = Atomic.self +let t2: any (~Copyable & ~Escapable).Type = Span.self +print(t1 != t2) // ⟹ true +print(t1 == t1) // ⟹ true +``` + +### Object identifiers + +The `ObjectIdentifier` construct is primarily used to generate a Comparable/Hashable value that identifies a class instance. However, it is also able to identify metatypes: + +```swift +let id1 = ObjectIdentifier(Int.self) +let id2 = ObjectIdentifier(String.self) +print(id1 == id2) // ⟹ false +``` + +[SE-0437] did not generalize this initializer; we can now allow it to work with both noncopyable and nonescapable types: + +```swift +import Synchronization + +let id3 = ObjectIdentifier(Atomic.self) // OK, noncopyable input type +let id4 = ObjectIdentifier(Span.self) // OK, nonescapable input type +print(id3 == id4) // ⟹ false +``` + +The object identifier of a noncopyable/nonescapable type is still a regular copyable and escapable identifier -- for instance, it can be compared against other ids and hashed. + +### Odds and ends + +[SE-0437] omitted generalizing the `Equatable` conformance of `ManagedBufferPointer`; this proposal allows comparing `ManagedBufferPointer` instances for equality even if their `Element` happens to be noncopyable. + +[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. This proposal generalizes `indices` to be also available on buffer pointers of noncopyable elements. (In the time since the original proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `Vector` with the same property. It makes sense to also provide this interface on buffer pointers, for consistency.) `indices` is useful for iterating through these collection types, especially until we ship a new iteration model that supports noncopyable/nonescapable containers. + +Finally, [SE-0437] neglected to generalize any of the buffer pointer operations that [SE-0370] introduced on the standard `Slice` type. In this proposal, we correct this omission by generalizing the handful of operations that can support noncopyable result elements: `moveInitializeMemory(as:fromContentsOf:)`, `bindMemory(to:)`, `withMemoryRebound(to:_:)`, and `assumingMemoryBound(to:)`. `Slice` itself continues to require its `Element` to be copyable (at least for now), preventing the generalization of other operations. + +## Detailed Design + +Note that Swift provides no way to define the lifetime dependencies of a function's nonescapable result, nor to set lifetime constraints on input parameters. Until the language gains an official way to express such constraints, the Swift Standard Library will define the APIs generalized in this proposal with unstable syntax that isn't generally available. In this text, we'll be using an illustrative substitute -- the hypothetical `@_lifetime` attribute. We will loosely describe its meaning as we go. + +Note: The `@_lifetime` attribute is not real; it is merely a didactic placeholder. The eventual lifetime annotations proposal may or may not propose syntax along these lines. We expect the Standard Library to immediately switch to whatever syntax Swift eventually embraces, as soon as it becomes available. + +### Inferred lifetime behavior of nonescapable enum types + +[SE-0446] has introduced the concept of a nonescapable enum type to Swift. While that proposal did not explicitly spell this out, this inherently included a set of implicit lifetime rules for the principal language features that interact with enum types: enum construction using case factories and pattern matching. To generalize `Optional` and `Result`, we need to understand how these implicit inference rules work for enum types with a single nonescapable associated value. + +1. When constructing an enum case with a single nonescapable associated value, the resulting enum value is inferred to carry precisely the same lifetime dependencies as the origional input. +2. Pattern matching over such an enum case exposes the nonescapable associated value, inferring precisely the same lifetime dependencies for it as the original enum. + +```swift +enum Foo { + case a(T) + case b +} + +func test(_ array: Array) { + let span = array.span + let foo = Foo.a(span) // (1) + switch foo { + case .a(let span2): ... // (2) + case .b: ... + } +} +``` + +In statement (1), `foo` is defined to implicitly copy the lifetime dependencies of `span`; neither variable can escape the body of the `test` function. The let binding in the pattern match on `.a` in statement (2) creates `span2` with exactly the same lifetime dependencies as `foo`. + +(We do not describe the implicit semantics of enum cases with _multiple_ nonescapable associated values here, as they are relevant to neither `Optional` nor `Result`.) + +### Inferred lifetime behavior of `Optional`'s notational conveniences + +The `Optional` enum comes with a rich set of notational conveniences that are built directly into the language. This proposal extends these conveniences to work on nonescapable optionals; therefore it inherently needs to introduce new implicit lifetime inference rules, along the same lines as the two existing once we described above: + +1. The result of implicit optional promotion of a nonescapable value is a nonescapable optional carrying precisely the same lifetime dependencies as the original input. +2. The force-unwrapping special form `!` and the optional chaining special form `?` both implicitly infer the lifetime dependencies of the wrapped value (if any) by directly copying those of the optional. + +### `protocol ExpressibleByNilLiteral` + +In order to generalize `Optional`, we need the `ExpressibleByNilLiteral` protocol to support nonescapable conforming types. By definition, the `nil` form needs to behave like a regular, escapable value; accordingly, the required initializer needs to establish "immortal" or "static" lifetime semantics on the resulting instance. + +```swift +protocol ExpressibleByNilLiteral: ~Copyable, ~Escapable { + @_lifetime(immortal) // Illustrative syntax + init(nilLiteral: ()) +} +``` + +In this illustration, `@_lifetime(immortal)` specifies that the initializer places no constraints on the lifetime of its result. We expect a future proposal to define a stable syntax for expressing such lifetime dependency constraints. + +Preexisting types that conform to `ExpressibleByNilLiteral` are all escapable, and escapable values always have immortal lifetimes, by definition. Therefore, initializer implementations in existing conformances already satisfy this new refinement of the initializer requirement -- it only makes a difference in the newly introduced `~Escapable` case. + +### `enum Optional` + +We generalize `Optional` to allow nonescapable wrapped types in addition to noncopyable ones. + +```swift +enum Optional: ~Copyable, ~Escapable { + case none + case some(Wrapped) +} + +extension Optional: Copyable where Wrapped: Copyable & ~Escapable {} +extension Optional: Escapable where Wrapped: Escapable & ~Copyable {} +extension Optional: BitwiseCopyable where Wrapped: BitwiseCopyable & ~Escapable {} +extension Optional: Sendable where Wrapped: ~Copyable & ~Escapable & Sendable {} +``` + +To allow the use of the `nil` syntax with nonescapable optional types, we generalize `Optional`'s conformance to `ExpressibleByNilLiteral`: + +```swift +extension Optional: ExpressibleByNilLiteral +where Wrapped: ~Copyable & ~Escapable { + @_lifetime(immortal) // Illustrative syntax + init(nilLiteral: ()) +} +``` + +As discussed above, `nil` optionals have no lifetime dependencies, and they continue to work like escapable values. + +We need to generalize the existing unlabeled initializer to support the nonescapable case. When passed a nonescapable entity, the initializer creates an optional that has precisely the same lifetime dependencies as the original entity. Once again, Swift has not yet provided a stable way to express this dependency; so to define such an initializer, the Standard Library needs to use some unstable mechanism. We use the hypothetical `@_lifetime(copying some)` syntax to do this -- this placeholder notation is intended to reflect that the lifetime dependencies of the result are copied verbatim from the `some` argument. + +```swift +extension Optional where Wrapped: ~Copyable & ~Escapable { + @_lifetime(copying some) // Illustrative syntax + init(_ some: consuming Wrapped) +} +``` + +As we've seen, the language also has built-in mechanisms for constructing `Optional` values that avoid invoking this initializer: it implements implicit optional promotions and explicit case factories. When given values of nonescapable types, these methods also _implicitly_ result in the result's lifetime dependencies being copied directly from the original input. + +Swift offers many built-in ways for developers to unwrap optional values: we have force unwrapping, optional chaining, pattern matching, optional bindings, etc. Many of these rely on direct compiler support that is already able to properly handle lifetime matters; but the stdlib also includes its own forms of unwrapping, and these require some API changes. + +In this proposal, we generalize `take()` to work on nonescapable optionals. It resets `self` to nil and returns its original value with precisely the same lifetime dependency as we started with. The `nil` value it leaves behind is still constrained to the same lifetime -- we do not have a way for a mutating function to affect the lifetime dependencies of its `self` argument. + +```swift +extension Optional where Wrapped: ~Copyable & ~Escapable { + @_lifetime(copying self) // Illustrative syntax + mutating func take() -> Self +} +``` + +We are also ready to generalize the `unsafelyUnwrapped` property: + +```swift +extension Optional where Wrapped: ~Escapable { + @_lifetime(copying self) // Illustrative syntax + var unsafelyUnwrapped: Wrapped { get } +} +``` + +This property continues to require copyability for now, as supporting noncopyable wrapped types requires the invention of new accessors that hasn't happened yet. + +As noted above, we defer generalizing the nil-coalescing operator `??`. We expect to tackle it when it becomes possible to express the lifetime dependency of its result as an intersection of the lifetimes of its left argument and the _result_ of the right argument (an autoclosure). We also do not attempt to generalize similar higher-order API, like `Optional.map` or `.flatMap`. + +The Standard Library provides special support for comparing arbitrary optional values against `nil`. We generalize this mechanism to support nonescapable cases: + +``` +extension Optional where Wrapped: ~Copyable & ~Escapable { + static func ~=( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool + + static func ==( + lhs: borrowing Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool + + static func !=( + lhs: borrowing Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool + + static func ==( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool + + static func !=( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool +} +``` + +### `enum Result` + +For `Result`, this proposal concentrates on merely allowing the success case to contain a nonescapable value. + +```swift +enum Result { + case success(Success) + case failure(Failure) +} + +extension Result: Copyable where Success: Copyable & ~Escapable {} +extension Result: Escapable where Success: Escapable & ~Copyable {} +extension Result: Sendable where Success: Sendable & ~Copyable & ~Escapable {} +``` + +We postpone generalizing most of the higher-order functions that make `Result` convenient to use, as we currently lack the means to reason about lifetime dependencies for such functions. But we are already able to generalize the two functions that do not have complicated lifetime semantics: `mapError` and `flatMapError`. + +```swift +extension Result where Success: ~Copyable & ~Escapable { + @_lifetime(copying self) // Illustrative syntax + consuming func mapError( + _ transform: (Failure) -> NewFailure + ) -> Result +} + +extension Result where Success: ~Copyable & ~Escapable { + @_lifetime(copying self) // Illustrative syntax + consuming func flatMapError( + _ transform: (Failure) -> Result + ) -> Result +} +``` + +Both of these functions return a value with the same lifetime as the original `Result` instance. + +We can also generalize the convenient `get()` function, which is roughly equivalent to optional unwrapping: + +``` +extension Result where Success: ~Copyable & ~Escapable { + @_lifetime(copying self) // Illustrative syntax + consuming func get() throws(Failure) -> Success +} +``` + +In the non-escapable case, this function returns a value with a lifetime that precisely matches the original `Result`. + +### `enum MemoryLayout` + +Swift is not yet ready to introduce pointers to nonescapable values -- we currently lack the ability to assign proper lifetime semantics to the addressed items. + +However, a nonescapable type does still have a well-defined memory layout, and it makes sense to allow developers to query the size, stride, and alignment of such instances. This information is associated with the type itself, and it is independent of the lifetime constraints of its instances. Therefore, we can generalize the `MemoryLayout` enumeration to allow its subject to be a nonescapable type: + +```swift +enum MemoryLayout +: ~BitwiseCopyable, Copyable, Escapable {} + +extension MemoryLayout where T: ~Copyable & ~Escapable { + static var size: Int { get } + static var stride: Int { get } + static var alignment: Int { get } +} + +extension MemoryLayout where T: ~Copyable & ~Escapable { + static func size(ofValue value: borrowing T) -> Int + static func stride(ofValue value: borrowing T) -> Int + static func alignment(ofValue value: borrowing T) -> Int +} +``` + +### Lifetime Management + +[SE-0437] generalized the `withExtendedLifetime` family of functions to support extending the lifetime of noncopyable entities. This proposal further generalizes these to also allow operating on nonescapable entities: + +```swift +func withExtendedLifetime< + T: ~Copyable & ~Escapable, + E: Error, + Result: ~Copyable +>( + _ x: borrowing T, + _ body: () throws(E) -> Result +) throws(E) -> Result + +func withExtendedLifetime< + T: ~Copyable & ~Escapable, + E: Error, + Result: ~Copyable +>( + _ x: borrowing T, + _ body: (borrowing T) throws(E) -> Result +) throws(E) -> Result +``` + +Note that the `Result` is still required to be escapable. + +We also propose the addition of a new function variant that eliminates the closure argument, to better accommodate the current best practice of invoking these functions in `defer` blocks: + +```swift +func extendLifetime(_ x: borrowing T) +``` + +### Metatype equality + +Swift's metatypes do not conform to `Equatable`, but the Standard Library does implement the `==`/`!=` operators over them: + +```swift +func == (t0: Any.Type?, t1: Any.Type?) -> Bool { ... } +func != (t0: Any.Type?, t1: Any.Type?) -> Bool { ... } +``` + +Note how these are defined on optional metatype existentials, typically relying on implicit optional promotion. We propose to generalize these to support metatypes of noncopyable and/or nonescapable types: + +```swift +func == ( + t0: (any (~Copyable & ~Escapable).Type)?, + t1: (any (~Copyable & ~Escapable).Type)? +) -> Bool { ... } +func != ( + t0: (any (~Copyable & ~Escapable).Type)?, + t1: (any (~Copyable & ~Escapable).Type)? +) -> Bool { ... } +``` + +### `struct ObjectIdentifier` + +The `ObjectIdentifier` construct is primarily used to generate a `Comparable`/`Hashable` value that identifies a class instance. However, it is also able to generate hashable type identifiers: + +```swift +extension ObjectIdentifier { + init(_ x: Any.Type) +} +``` + +We propose to generalize this initializer to allow generating identifiers for noncopyable and nonescapable types as well, using generalized metatype existentials: + +```swift +extension ObjectIdentifier { + init(_ x: any (~Copyable & ~Escapable).Type) +} +``` + +### `ManagedBufferPointer` equatability + +The `ManagedBufferPointer` type conforms to `Equatable`; its `==` implementation works by comparing the identity of the class instances it is referencing. [SE-0437] has generalized the type to allow a noncopyable `Element` type, but it did not generalize this specific conformance. This proposal aims to correct this oversight: + +```swift +extension ManagedBufferPointer: Equatable where Element: ~Copyable { + static func ==( + lhs: ManagedBufferPointer, + rhs: ManagedBufferPointer + ) -> Bool +} +``` + +Managed buffer pointers are pointer types -- as such, they can be compared whether or not they are addressing a buffer of copyable items. + +(Note: conformance generalizations like this can cause compatibility issues when newly written code is deployed on older platforms that pre-date the generalization. We do not expect this to be an issue in this case, as the generalization is compatible with the implementations we previously shipped.) + +### Making `indices` universally available on unsafe buffer pointers + +[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. In the time since that proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `Vector` with the same property. For consistency, it makes sense to also allow developers to unconditionally access `Unsafe[Mutable]BufferPointer.indices`, whether or not `Element` is copyable. + +```swift +extension UnsafeBufferPointer where Element: ~Copyable { + var indices: Range { get } +} + +extension UnsafeMutableBufferPointer where Element: ~Copyable { + var indices: Range { get } +} +``` + +This allows Swift programmers to iterate over the indices of a buffer pointer with simpler syntax, independent of what `Element` they are addressing: + +```swift +for i in buf.indices { + ... +} +``` + +We consider `indices` to be slightly more convenient than the equivalent expression `0 ..< buf.count`. + +(Of course, we are still planning to introduce direct support for for-in loops over noncopyable/nonescapable containers, which will provide a far more flexible solution. `indices` is merely a stopgap solution to bide us over until we are ready to propose that.) + +### Buffer pointer operations on `Slice` + +Finally, to address an inconsistency that was left unresolved by [SE-0437], we generalize a handful of buffer pointer operations that are defined on buffer slices. This consists of the following list, originally introduced in [SE-0370]: + +- Initializing a slice of a mutable raw buffer pointer by moving items out of a typed mutable buffer pointer: + + ```swift + extension Slice where Base == UnsafeMutableRawBufferPointer { + func moveInitializeMemory( + as type: T.Type, + fromContentsOf source: UnsafeMutableBufferPointer + ) -> UnsafeMutableBufferPointer + } + ``` + +- Binding memory of raw buffer pointer slices: + + ```swift + extension Slice where Base == UnsafeMutableRawBufferPointer { + func bindMemory( + to type: T.Type + ) -> UnsafeMutableBufferPointer + } + + extension Slice where Base == UnsafeRawBufferPointer { + func bindMemory( + to type: T.Type + ) -> UnsafeBufferPointer + } + ``` + +- Temporarily rebinding memory of a (typed or untyped, mutable or immutable) buffer pointer slice for the duration of a function call: + + ```swift + extension Slice where Base == UnsafeMutableRawBufferPointer { + func withMemoryRebound( + to type: T.Type, + _ body: (UnsafeMutableBufferPointer) throws(E) -> Result + ) throws(E) -> Result + } + + extension Slice where Base == UnsafeRawBufferPointer { + func withMemoryRebound( + to type: T.Type, + _ body: (UnsafeBufferPointer) throws(E) -> Result + ) throws(E) -> Result + } + + extension Slice { + func withMemoryRebound< + T: ~Copyable, E: Error, Result: ~Copyable, Element + >( + to type: T.Type, + _ body: (UnsafeBufferPointer) throws(E) -> Result + ) throws(E) -> Result + where Base == UnsafeBufferPointer + + public func withMemoryRebound< + T: ~Copyable, E: Error, Result: ~Copyable, Element + >( + to type: T.Type, + _ body: (UnsafeMutableBufferPointer) throws(E) -> Result + ) throws(E) -> Result + where Base == UnsafeMutableBufferPointer + } + ``` + +- Finally, converting a slice of a raw buffer pointer into a typed buffer pointer, assuming its memory is already bound to the correct type: + + ```swift + extension Slice where Base == UnsafeMutableRawBufferPointer { + func assumingMemoryBound( + to type: T.Type + ) -> UnsafeMutableBufferPointer + } + + extension Slice where Base == UnsafeRawBufferPointer { + func assumingMemoryBound( + to type: T.Type + ) -> UnsafeBufferPointer + } + ``` + +All of these forward to operations on the underlying base buffer pointer that have already been generalized in [SE-0437]. These changes are simply restoring feature parity between buffer pointer and their slices, where possible. (`Slice` still requires its `Element` to be copyable, which limits generalization of other buffer pointer APIs defined on it.) + +These generalizations are limited to copyability for now. We do expect that pointer types (including buffer pointers) will need to be generalized to allow non-escapable pointees; however, we have to postpone that work until we are able to precisely reason about lifetime requirements. + + + +## Source compatibility + +Like [SE-0437], this proposal also heavily relies on the assurance that removing the assumption of escapability on these constructs will not break existing code that used to rely on the original, escaping definitions. [SE-0437] has explored a few cases where this may not be the case; these can potentially affect code that relies on substituting standard library API with its own implementations. With the original ungeneralized definitions, such custom reimplementations could have shadowed the originals. However, this may no longer be the case with the generalizations included, and this can lead to ambiguous function invocations. + +This proposal mostly touches APIs that were already changed by [SE-0437], and that reduces the likelihood of it causing new issues. That said, it does generalize some previously unchanged interfaces that may provide new opportunities for such shadowing declarations to cause trouble. + +Like previously, we do have engineering options to mitigate such issues in case we do encounter them in practice: for example, we can choose to amend Swift's shadowing rules to ignore differences in throwing, noncopyability, and nonescapability, or we can manually patch affected definitions to make the expression checker consider them to be less specific than any custom overloads. + +## ABI compatibility + +The introduction of support for nonescapable types is (in general) a compile-time matter, with minimal (or even zero) runtime impact. This greatly simplifies the task of generalizing previously shipping types for use in nonescapable contexts. Another simplifying aspect is that while it can be relatively easy for classic Swift code to accidentally copy a value, it tends to be rare for functions to accidentally _escape_ their arguments -- previous versions of a function are less likely to accidentally violate nonescapability than noncopyability. + +The implementation of this proposal adopts the same approaches as [SE-0437] to ensure forward and backward compatibility of newly compiled (and existing) binaries, including the Standard Library itself. We expect that code that exercises the new features introduced in this proposal will be able to run on earlier versions of the Swift stdlib -- to the extent that noncopyable and/or nonescapable types are allowed to backdeploy. + +[SE-0437] has already arranged ABI compatibility symbols to get exported as needed to support ABI continuity. It has also already reimplemented most of the entry points that this proposal touches, in a way that forces them to get embedded in client binaries. This allows the changes in this proposal to get backdeployed without any additional friction. + +Like its precursor, this proposal does assume that the `~Copyable`/`~Escapable` generalization of the `ExpressibleByNilLiteral` protocol will not have an ABI impact on existing conformers of it. However, it goes a step further, by also adding a lifetime annotation on the protocol's initializer requirement; this requires that such annotations must not interfere with backward/forward binary compatibility, either. (E.g., it requires that such lifetime annotations do not get mangled into exported symbol names.) + +### Note on protocol generalizations + +Like [SE-0437], this proposal mostly avoids generalizing standard protocols, with the sole exception of `ExpressibleByNilLiteral`, which has now been generalized to allow both noncopyable and nonescapable conforming types. + +As a general rule, protocol generalizations like that may not be arbitrarily backdeployable -- it seems likely that we'll at least need to support limiting the availability of _conformance_ generalizations, if not generalizations of the protocol itself. In this proposal, we follow [SE-0437] in assuming that this potential issue will not apply to the specific case of `ExpressibleByNilLiteral`, because of its particularly narrow use case. Our experience with [SE-0437] is reinforcing this assumption, but it is still possible there is an ABI back-compatibility issue that we haven't uncovered yet. In the (unlikely, but possible) case we do discover such an issue, we may need to do extra work to patch protocol conformances in earlier stdlibs, or we may decide to limit the use of `nil` with noncopyable/nonescapable optionals to recent enough runtimes. + +To illustrate the potential problem, let's consider `Optional`'s conformance to `Equatable`: + +```swift +extension Optional: Equatable where Wrapped: Equatable { + public static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): return l == r + case (nil, nil): return true + default: return false + } + } +} +``` + +This conformance is currently limited to copyable and escapable cases, and it is using the classic, copying form of the switch statement, with `case let (l?, r?)` semantically making full copies of the two wrapped values. We do intend to soon generalize the `Equatable` protocol to support noncopyable and/or nonescapable conforming types. When that becomes possible, `Optional` will want to immediately embrace this generalization, to allow comparing two noncopyable/nonescapable instances for equality: + +```swift +extension Optional: Equatable where Wrapped: Equatable & ~Copyable & ~Escapable { + public static func ==(lhs: borrowing Wrapped?, rhs: borrowing Wrapped?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): return l == r + case (nil, nil): return true + default: return false + } + } +} +``` + +On the surface, this seems like a straightforward change. Unfortunately, switching to `borrowing` arguments changes the semantics of the implementation, converting the original copying switch statement to the borrowing form introduced by [SE-0432]. This new variant avoids copying wrapped values to compare them, enabling the use of this function on noncopyable data. However, the old implementation of `==` did assume (and exercise!) copyability, so the `Equatable` conformance cannot be allowed to dispatch to `==` implementations that shipped in Standard Library releases that predate this generalization. + +To mitigate such problems, we'll either need to retroactively patch/substitute the generic implementations in previously shipping stdlibs, or we need to somehow limit availability of the generalized conformance, without affecting the original copyable/escapable one. + +This issue is more pressing for noncopyable cases, as preexisting implementations are far more likely to perform accidental copying than to accidentally escape their arguments. + +Our hypothesis is that `ExpressibleByNilLiteral` conformances are generally free of such issues. + +## Alternatives Considered + +Most of the changes proposed here follow directly from the introduction of nonescapable types. The API generalizations follow the patterns established by [SE-0437], and are largely mechanical in nature. For the most part, the decision points aren't about the precise form of any particular change, but more about what changes we are ready to propose _right now_. + +The single exception is the `extendLifetime` function, which is a brand new API; it comes from our experience using (and maintaining) the `withExtendedLifetime` function family. + +## Future Work + +For the most part, this proposal is concentrating on resolving the first item from [SE-0437]'s wish list (nonescapable `Optional` and `Result`), and it adds minor coherency improvements to the feature set we shipped there. + +Most other items listed as future work in that proposal continue to remain on our agenda. The advent of nonescapable types extends this list with additional items, including the following topics: + +1. We need to define stable syntax for expressing lifetime dependencies as explicit annotations, and we need to define what semantics we apply by default on functions that do not explicitly specify these. + +2. We will need an unsafe mechanism to override lifetime dependencies of nonescapable entities. We also expect to eventually need to allow unsafe bit casting to and from nonescapable types. + +3. We will need to allow pointer types to address nonescapable items: `UnsafePointer`, `UnsafeBufferPointer` type families, perhaps `ManagedBuffer`. The primary design task here is to decide what lifetime semantics we want to assign to pointer dereferencing operations, including mutations. + +4. Once we have pointers, we will also need to allow the construction of generic containers of nonescapable items, with some Sequence/Collection-like capabilities (iteration, indexing, generic algorithms, etc.). We expect the noncopyable/nonescapable container model to heavily rely on the `Span` type, which we intend to use as the basic unit of iteration, providing direct access to contiguous storage chunks. For containers of nonescapables in particular, this means we'll also need to generalize `Span` to allow it to capture nonescapable elements. + +5. We'll want to generalize most of the preexisting standard library protocols to allow nonescapable conforming types and (if possible) associated types. This is in addition to supporting noncopyability. This work will require adding carefully considered lifetime annotations on protocol requirements, while also carefully maintaining seamless forward/backward compatibility with the currently shipping protocol versions. This is expected to take several proposals; in some cases, it may include carefully reworking existing semantic requirements to better match noncopyable/nonescapable use cases. Some protocols may not be generalizable without breaking existing code; in those cases, we may need to resort to replacing or augmenting them with brand-new protocols. However, protocol generalizations for nonescapables are generally expected to be a smoother process than it is for noncopyables. + +## Acknowledgements + +Many people contributed to the discussions that led to this proposal. We'd like to especially thank the following individuals for their continued, patient and helpful input: + +- Alejandro Alonso +- Steve Canon +- Ben Cohen +- Kavon Farvardin +- Doug Gregor +- Joe Groff +- Megan Gupta +- Tim Kientzle +- Guillaume Lessard +- John McCall +- Tony Parker +- Andrew Trick +- Rauhul Varma From 68da31ee2d3c21ab839a66d7459485412eb932ed Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Mar 2025 11:28:51 -0800 Subject: [PATCH 132/505] Initiate review of SE-0465: Standard Library Primitives for Nonescapable Types (#2724) --- ...ves.md => 0465-nonescapable-stdlib-primitives.md} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename proposals/{NNNN-nonescapable-stdlib-primitives.md => 0465-nonescapable-stdlib-primitives.md} (99%) diff --git a/proposals/NNNN-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md similarity index 99% rename from proposals/NNNN-nonescapable-stdlib-primitives.md rename to proposals/0465-nonescapable-stdlib-primitives.md index 788faef5cf..a4021f0a16 100644 --- a/proposals/NNNN-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -1,12 +1,12 @@ # Standard Library Primitives for Nonescapable Types -* Proposal: [SE-NNNN](NNNN-nonescapable-stdlib-primitives.md) +* Proposal: [SE-0465](0465-nonescapable-stdlib-primitives.md) * Authors: [Karoy Lorentey](https://github.com/lorentey) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [Doug Gregor](https://github.com/douggregor) +* Status: **Active review (March 5...18, 2025)** * Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] * Implementation: https://github.com/swiftlang/swift/pull/73258 -* Review: ([Pitch]) +* Review: ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) [Roadmap]: https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206 [Pitch]: https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253 @@ -184,7 +184,7 @@ Of course, an optional is of limited use unless we are able to decide whether it ``` - The optional chaining special form `?`: - + ```swift func count(of maybeSpan: Span?) -> Int { guard let c = maybeSpan?.count else { return 0 } @@ -200,7 +200,7 @@ Of course, an optional is of limited use unless we are able to decide whether it return span.count } ``` - + These variants all work as expected. To avoid escapability violations, unwrapping the nonescapable optional results in a value with precisely the same lifetime dependencies as the original optional value. This applies to all forms of unwrapping, including pattern matching forms that bind copies of associated values to new variables, like `let span` above -- the resulting `span` value always has the same lifetime as the optional it comes from. The standard `Optional` type has custom support for comparing optional instances against `nil` using the traditional `==` operator, whether or not the wrapped type conforms to `Equatable`. [SE-0437] generalized this mechanism for noncopyable wrapped types, and it is reasonable to extend this to also cover the nonescapable case: From f6efcfdfcf9e1423ba8d9f1b3a0a39caefb17be7 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Mar 2025 11:35:55 -0800 Subject: [PATCH 133/505] SE-0465: Add link to review thread (#2725) --- proposals/0465-nonescapable-stdlib-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index a4021f0a16..20e74ec1ec 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -6,7 +6,7 @@ * Status: **Active review (March 5...18, 2025)** * Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] * Implementation: https://github.com/swiftlang/swift/pull/73258 -* Review: ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) +* Review: ([Review](https://forums.swift.org/t/se-0465-standard-library-primitives-for-nonescapable-types/78310)) ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) [Roadmap]: https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206 [Pitch]: https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253 From 2df8b28f2559ce48b7a1f7b17b836139d3b3967c Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Wed, 5 Mar 2025 23:22:12 +0000 Subject: [PATCH 134/505] [SE-0464] Fix metadata of `UTF8Span` proposal --- proposals/0464-utf8span-safe-utf8-processing.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/0464-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md index cb9cb817fd..a2b09f6528 100644 --- a/proposals/0464-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -1,17 +1,17 @@ # UTF8Span: Safe UTF-8 Processing Over Contiguous Bytes -* Proposal: [SE-0464](0464-utf8-span.md) +* Proposal: [SE-0464](0464-utf8span-safe-utf8-processing.md) * Authors: [Michael Ilseman](https://github.com/milseman), [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Active review (March 5–19, 2025)** * Bug: rdar://48132971, rdar://96837923 -* Implementation: https://github.com/swiftlang/swift/pull/78531 -* Review: ([pitch 1](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([pitch 2](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) +* Implementation: [swiftlang/swift#78531](https://github.com/swiftlang/swift/pull/78531) +* Review: ([first pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([second pitch](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([third pitch](https://forums.swift.org/t/pitch-utf8span-safe-utf-8-processing-over-contiguous-bytes/77483)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) ## Introduction -We introduce `UTF8Span` for efficient and safe Unicode processing over contiguous storage. `UTF8Span` is a memory safe non-escapable type [similar to `Span`](https://github.com/swiftlang/swift-evolution/pull/2307). +We introduce `UTF8Span` for efficient and safe Unicode processing over contiguous storage. `UTF8Span` is a memory safe non-escapable type [similar to `Span`](0447-span-access-shared-contiguous-storage.md). Native `String`s are stored as validly-encoded UTF-8 bytes in an internal contiguous memory buffer. The standard library implements `String`'s API as internal methods which operate on top of this buffer, taking advantage of the validly-encoded invariant and specialized Unicode knowledge. We propose making this UTF-8 buffer and its methods public as API for more advanced libraries and developers. @@ -522,7 +522,7 @@ extension UTF8Span { ### `UTF8Span` from `String` -We propose adding `utf8Span` properties to `String` and `Substring`, in line with [SE-0456](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233/17): +We propose adding `utf8Span` properties to `String` and `Substring`, in line with [SE-0456](0456-stdlib-span-properties.md): ```swift extension String { From 4b3973c780329ad08aeba254b4b23661bbc896b8 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 5 Mar 2025 18:16:47 -0800 Subject: [PATCH 135/505] Add a proposal for configuring default actor isolation per module. (#2667) * Add a proposal for configuring default actor isolation per module. * Add an alternatives considered section for using an enum in the package manifest API. * Update alternatives considered based on pitch feedback. * Update and rename NNNN-control-default-actor-isolation.md to 0466-control-default-actor-isolation.md Assign SE-0466 and update metadata for review --------- Co-authored-by: Stephen Canon --- .../0466-control-default-actor-isolation.md | 219 ++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 proposals/0466-control-default-actor-isolation.md diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md new file mode 100644 index 0000000000..062ceeded2 --- /dev/null +++ b/proposals/0466-control-default-actor-isolation.md @@ -0,0 +1,219 @@ +# Control default actor isolation inference + +* Proposal: [SE-0466](0466-control-default-actor-isolation.md) +* Authors: [Holly Borla](https://github.com/hborla) +* Review Manager: [Steve Canon](https://github.com/stephentyrone) +* Status: **Active Review (March 5...19, 2025)** +* Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) +* Implementation: On `main` behind the `UnspecifiedMeansMainActorIsolated` experimental feature. +* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482)) + +## Introduction + +This proposal introduces a new compiler setting for inferring `@MainActor` isolation by default within the module to mitigate false-positive data-race safety errors in sequential code. + +## Motivation + +> Note: This motivation section was adapted from the [prospective vision for approachable data-race safety](https://github.com/hborla/swift-evolution/blob/approachable-concurrency-vision/visions/approachable-concurrency.md#mitigating-false-positive-data-race-safety-errors-in-sequential-code). Please see the vision document for extended motivation. + +A lot of code is effectively “single-threaded”. For example, most executables, such as apps, command-line tools, and scripts, start running on the main actor and stay there unless some part of the code does something concurrent (like creating a `Task`). If there isn’t any use of concurrency, the entire program will run sequentially, and there’s no risk of data races — every concurrency diagnostic is necessarily a false positive! It would be good to be able to take advantage of that in the language, both to avoid annoying programmers with unnecessary diagnostics and to reinforce progressive disclosure. Many people get into Swift by writing these kinds of programs, and if we can avoid needing to teach them about concurrency straight away, we’ll make the language much more approachable. + +The easiest and best way to model single-threaded code is with a global actor. Everything on a global actor runs sequentially, and code that isn’t isolated to that actor can’t access the data that is. All programs start running on the global actor `MainActor`, and if everything in the program is isolated to the main actor, there shouldn’t be any concurrency errors. + +Unfortunately, it’s not quite that simple right now. Writing a single-threaded program is surprisingly difficult under the Swift 6 language mode. This is because Swift 6 defaults to a presumption of concurrency: if a function or type is not annotated or inferred to be isolated, it is treated as non-isolated, meaning it can be used concurrently. This default often leads to conflicts with single-threaded code, producing false-positive diagnostics in cases such as: + +- global and static variables, +- conformances of main-actor-isolated types to non-isolated protocols, +- class deinitializers, +- overrides of non-isolated superclass methods in a main-actor-isolated subclass, and +- calls to main-actor-isolated functions from the platform SDK. + +## Proposed solution + +This proposal allows code to opt in to being “single-threaded” by default, on a module-by-module basis. A new `-default-isolation` compiler flag specifies the default isolation within the module, and a corresponding `SwiftSetting` method specifies the default isolation per target within a Swift package. + +This would change the default isolation rule for unannotated code in the module: rather than being non-isolated, and therefore having to deal with the presumption of concurrency, the code would instead be implicitly isolated to `@MainActor`. Code imported from other modules would be unaffected by the current module’s choice of default. When the programmer really wants concurrency, they can request it explicitly by marking a function or type as `nonisolated` (which can be used on any declaration as of [SE-0449](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0449-nonisolated-for-global-actor-cutoff.md)), or they can define it in a module that doesn’t default to main-actor isolation. + +## Detailed design + +### Specifying default isolation per module + +#### `-default-isolation` compiler flag + +The `-default-isolation` flag can be used to control the default actor isolation for all code in the module. The only valid arguments to `-default-isolation` are `MainActor` and `nonisolated`. It is an error to specify both `-default-isolation MainActor` and `-default-isolation nonisolated`. If no `-default-isolation` flag is specified, the default isolation for the module is `nonisolated`. + +#### `SwiftSetting.defaultIsolation` method + +The following method on `SwiftSetting` can be used to specify the default actor isolation per target in a Swift package manifest: + +```swift +extension SwiftSetting { + @available(_PackageDescription, introduced: 6.2) + public static func defaultIsolation( + _ globalActor: MainActor.Type?, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting +} +``` + +The only valid values for the `globalActor` argument are `MainActor.self` and `nil`. The `nil` argument corresponds to `nonisolated`; `.defaultIsolation(nil)` will default to `nonisolated` within the module. When no `.defaultIsolation` setting is specified, the default isolation within the module is `nonisolated`. + +### Default actor isolation inference + +When the default actor isolation is specified as `MainActor`, declarations are inferred to be `@MainActor`-isolated by default. Default isolation does not apply in the following cases: + +* Declarations with explicit actor isolation +* Declarations with inferred actor isolation from a superclass, overridden method, protocol conformance, or member propagation +* All declarations inside an `actor` type, including static variables, methods, initializers, and deinitializers +* Declarations that cannot have global actor isolation, including typealiases, import statements, enum cases, and individual accessors + +The following code example shows the inferred actor isolation in comments given the code is built with `-default-isolation MainActor`: + +```swift +// @MainActor +func f() {} + +// @MainActor +class C { + // @MainActor + init() { ... } + + // @MainActor + deinit { ... } + + // @MainActor + struct Nested { ... } + + // @MainActor + static var value = 10 +} + +@globalActor +actor MyActor { + // nonisolated + init() { ... } + + // nonisolated + deinit { ... } + + // nonisolated + static let shared = MyActor() +} + +@MyActor +protocol P {} + +// @MyActor +struct S: P { + // @MyActor + func f() { ... } +} +``` + +This proposal does not change the default isolation inference rules for closures. Non-Sendable closures and closures passed to `Task.init` already have the same isolation as the enclosing context by default. When specifying `MainActor` isolation by default in a module, non-`@Sendable` closures and `Task.init` closures will have inferred `@MainActor` isolation when the default `@MainActor` inference rules apply to the enclosing context: + +```swift +// Built with -default-isolation MainActor + +// @MainActor +func f() { + Task { // @MainActor in + ... + } + + Task.detached { // nonisolated in + ... + } +} + +nonisolated func g() { + Task { // nonisolated in + ... + } +} +``` + +## Source compatibility + +Changing the default actor isolation for a given module or source file is a source incompatible change. The default isolation will remain the same for existing projects unless they explicitly opt into `@MainActor` inference by default via `-default-isolation MainActor` or `defaultIsolation(MainActor.self)` in a package manifest. + +## ABI compatibility + +This proposal has no ABI impact on existing code. + +## Implications on adoption + +This proposal does not change the adoption implications of adding `@MainActor` to a declaration that was previously `nonisolated` and vice versa. The source and ABI compatibility implications of changing actor isolation are documented in the Swift migration guide's [Library Evolution](https://github.com/apple/swift-migration-guide/blob/29d6e889e3bd43c42fe38a5c3f612141c7cefdf7/Guide.docc/LibraryEvolution.md#main-actor-annotations) article. + +## Future directions + +### Specify build settings per file + +There are some build settings that are applicable on a per-file basis, including specifying default actor isolation and controlling diagnostic behavior. We could consider allowing settings in individual files which the setting should apply to by introducing a `#pragma`-like compiler directive. This idea has been [pitched separately](https://forums.swift.org/t/pitch-compilersettings-a-top-level-statement-for-enabling-compiler-flags-locally-in-a-specific-file/77994). + +## Alternatives considered + +### Allow defaulting isolation to a custom global actor + +The `-default-isolation` flag could allow a custom global actor as the argument, and the `SwiftSetting` API could be updated to accept a string that represents a custom global actor in the target. + +This proposal only supports `MainActor` because any other global actor does not help with progressive disclosure. It has the opposite effect - it forces asynchrony on any main-actor-isolated caller. However, there's nothing in this proposal prohibits generalizing these settings to supporting arbitrary global actors in the future if a compelling use case arises. + +### Infer `MainActor` by default as an upcoming feature + +Instead of introducing a separate mode for configuring default actor isolation inference, the default isolation could be changed to be `MainActor` under an upcoming feature that is enabled by default in a future Swift language mode. The upcoming feature approach was not taken because `MainActor` isolation is the wrong default for many kinds of modules, including libraries that offer APIs that can be used from any isolation domain, and highly-concurrent server applications. + +Similarly, a future language mode could enable main actor isolation by default, and require an opt out for using `nonisolated` as the default actor isolation. However, as the Swift package ecosystem grows, it's more likely for `nonisolated` to be the more common default amongst projects. If we discover that not to be true in practice, nothing in this proposal prevents changing the default actor isolation in a future language mode. + +See the approachable data-race safety vision document for an [analysis on the risks of introducing a language dialect](https://github.com/hborla/swift-evolution/blob/approachable-concurrency-vision/visions/approachable-concurrency.md#risks-of-a-language-dialect) for default actor isolation. + +### Don't apply default actor isolation to explicitly `Sendable` types + +This proposal includes few excepts where the specified default actor isolation does not apply. An additional case that should be considered is types with a conformance to `Sendable`: + +```swift +struct SimpleValue: Sendable { + var value: Int +} +``` + +This is an attractive carve out upon first glance, but there are a number of downsides: + +* The carve out may be confusing if a conformance to `Sendable` is implied, e.g. through a conformance to another protocol. +* Global actor isolation implies a conformance to `Sendable`, so it's not clear that a `Sendable` type should not be global actor isolated. +* Methods on a `Sendable` type may still use other types and methods that have default actor isolation applied, which would lead to failures if the `Sendable` type was exempt from default isolation inference. + +A middle ground might be to not apply default actor isolation to types with an explicit conformance to `Sendable` within the same source file as the type. This approach would still have some of the downsides listed above, but it would be more straightforward to spot types that have this exemption. + +### Use an enum for the package manifest API + +An alternative to using a `MainActor` metatype for the Swift package manifest API is to use an enum, e.g. + +```swift +public enum DefaultActorIsolation { + case mainActor + case nonisolated +} + +extension SwiftSetting { + @available(_PackageDescription, introduced: 6.2) + public static func defaultIsolation( + _ isolation: DefaultActorIsolation, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting +} + +// in a package manifest + +swiftSettings: [ + .defaultIsolation(.mainActor) +] +``` + +The enum approach introduces a different way of writing main actor isolation that does not involve the `MainActor` global actor type. The proposed design matches exactly the values used for `#isolation`, i.e. `MainActor.self` for main actor isolation and `nil` for `nonisolated`, which programmers are already familiar with. + +The primary argument for using an enum is that it can be extended in the future to support custom global actor types. This proposal deliberately puts supporting custom global actors in the alternatives considered and not future directions, because defaulting a module to a different global actor does not help improve progressive disclosure for concurrency. + +## Acknowledgments + +Thank you to John McCall for providing much of the motivation for this pitch in the approachable data-race safety vision document, and to Michael Gottesman for helping with the implementation. From 82aa810bdd3bf49d1e8a246f97ca59ecaaa40c00 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Wed, 5 Mar 2025 21:21:22 -0500 Subject: [PATCH 136/505] Update 0466-control-default-actor-isolation.md (#2728) Link back to review thread for SE-0466 --- proposals/0466-control-default-actor-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 062ceeded2..81f289408c 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -6,7 +6,7 @@ * Status: **Active Review (March 5...19, 2025)** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Implementation: On `main` behind the `UnspecifiedMeansMainActorIsolated` experimental feature. -* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482)) +* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321)) ## Introduction From b74e6ac1b68530495b2ccf2d0b3e2cb1f6481415 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 5 Mar 2025 22:15:09 -0600 Subject: [PATCH 137/505] Update the Swift evolution process documentation to incorporate Swift Testing --- process.md | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/process.md b/process.md index d38eeec80e..d9c71b07b3 100644 --- a/process.md +++ b/process.md @@ -5,10 +5,15 @@ Swift is a powerful and intuitive programming language that is designed to make ## Scope The Swift evolution process covers all design changes, no matter how small, to the Swift language, its standard library, and the core tools necessary to build Swift programs. This includes additions, removals, and changes to: + - the features of the Swift language, - the public interface of the Swift standard library, -- the configuration of the Swift compiler, and -- the core tools of the Swift package ecosystem, including the configuration of the [Swift package manager](https://www.swift.org/package-manager/) and the design of its manifest files. +- the configuration of the Swift compiler, +- the core tools of the Swift package ecosystem, including the configuration of + the [Swift package manager](https://www.swift.org/package-manager/) and the + design of its manifest files, and +- the features and public interfaces of + [Swift Testing](https://github.com/swiftlang/swift-testing). The design of other tools, such as IDEs, debuggers, and documentation generators, is not covered by the evolution process. The Core Team may create workgroups to guide and make recommendations about the development of these tools, but the output of those workgroups is not reviewed. @@ -31,9 +36,11 @@ There is a natural tension between these two goals. Open evolution processes are The [Core Team](https://www.swift.org/community/#core-team) is responsible for the strategic direction of Swift. The Core Team creates workgroups focused on specific parts of the project. When the Core Team gives a workgroup authority over part of the evolution of the project, that workgroup is called an evolution workgroup. Evolution workgroups manage the evolution process for proposals under their authority, working together with other workgroups as needed. -Currently, there is only one evolution workgroup: +Currently, there are two evolution workgroups: * The [Language Steering Group][language-steering-group] has authority over the evolution of the Swift language and its standard library. +* The [Testing Workgroup][testing-workgroup] has authority over the evolution of + the Swift Testing and Corelibs XCTest projects. The Core Team manages (or delegates) the evolution process for proposals outside these areas. The Core Team also retains the power to override the evolution decisions of workgroups when necessary. @@ -93,8 +100,11 @@ Please state explicitly whether you believe that the proposal should be accepted 1. **Develop the proposal and implementation** - 1. Expand the rough sketch into a formal proposal using the [proposal template](proposal-templates/0000-swift-template.md). - 1. In the [swift-evolution repository][swift-evolution-repo], open a [draft pull request][draft-pr] that adds your proposal to the [proposals directory](/proposals). + 1. Expand the rough sketch into a formal proposal using the + [relevant proposal template](#proposal-templates). + 1. In the [swift-evolution repository][swift-evolution-repo], open a + [draft pull request][draft-pr] that adds your proposal to the appropriate + [proposal directory](#proposal-locations). 1. Announce the pull request on the forums and edit the root post to link out to the pull request. 1. Refine the formal proposal in the open as you receive further feedback on the forums or the pull request. A ripe proposal is expected to address commentary from present and past @@ -128,6 +138,28 @@ Please state explicitly whether you believe that the proposal should be accepted [draft-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests +### Proposal templates + +When writing a formal proposal document, start with the most relevant template +given the primary subject of the proposal: + +- Use the [Swift template][swift-template] for proposals concerning the Swift + language, compiler, or standard library. +- Use the [Swift Package Manager template][swiftpm-template] for proposals + related to SwiftPM, including the design of its package manifest files and + command-line tools. +- Use the [Swift Testing template][swift-testing-template] for proposals focused + on Swift Testing features or public interfaces. + +### Proposal locations + +When opening a pull request to add a new proposal to the +[swift-evolution repository][swift-evolution-repo], place proposals which use +the [Swift][swift-template] or [Swift Package Manager][swiftpm-template] +templates in the top-level [proposals](/proposals) directory. Place proposals +which use the newer [Swift Testing template][swift-testing-template] in the +[proposals/testing](/proposals/testing) subdirectory. + ## Review process The review process for a particular proposal begins when a member of @@ -211,6 +243,10 @@ A given proposal can be in one of several states: [status-page]: https://apple.github.io/swift-evolution/ [preview-package]: https://github.com/apple/swift-standard-library-preview/ [language-steering-group]: https://www.swift.org/language-steering-group +[testing-workgroup]: https://www.swift.org/testing-workgroup "Testing Workgroup page on Swift.org" +[swift-template]: proposal-templates/0000-swift-template.md "Swift proposal template" +[swiftpm-template]: proposal-templates/0000-swiftpm-template.md "Swift Package Manager proposal template" +[swift-testing-template]: proposal-templates/0000-swift-testing-template.md "Swift Testing proposal template" ## Review announcement From 47d96fc2add76b8ae808790a75706a1c22f4fe6d Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Fri, 7 Mar 2025 00:42:27 +0000 Subject: [PATCH 138/505] update link --- proposals/NNNN-environment-dependent-shared-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-environment-dependent-shared-libraries.md b/proposals/NNNN-environment-dependent-shared-libraries.md index 6a6cdbe8e9..d1068526ea 100644 --- a/proposals/NNNN-environment-dependent-shared-libraries.md +++ b/proposals/NNNN-environment-dependent-shared-libraries.md @@ -4,7 +4,7 @@ * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) -* Documentation: [How to use Environment-Dependent Shared Libraries](https://github.com/tayloraswift/swift-edsl-example-client/blob/master/Sources/KrustyKrab/docs.docc/Getting%20Started.md) +* Documentation: [How to use Environment-Dependent Shared Libraries](https://github.com/swiftlang/swift-package-manager/blob/b586467575580f2365e8f5a29c949379724db795/Documentation/EDSLs.md) * Bugs: [SR-5714](https://github.com/swiftlang/swift-package-manager/issues/5714) ## Introduction From 2e676204dc7b4d0668d859cf23e0846c6e76f3d0 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Sat, 8 Mar 2025 19:04:31 -0800 Subject: [PATCH 139/505] Mark SE-0436 as implemented in Swift 6.1 --- proposals/0436-objc-implementation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0436-objc-implementation.md b/proposals/0436-objc-implementation.md index aa2e049179..517599b667 100644 --- a/proposals/0436-objc-implementation.md +++ b/proposals/0436-objc-implementation.md @@ -3,8 +3,8 @@ * Proposal: [SE-0436](0436-objc-implementation.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Accepted** -* Implementation: Proposed syntax implemented in [apple/swift#73309](https://github.com/apple/swift/pull/73309); enable using the `ObjCImplementation` experimental feature flag +* Status: **Implemented (Swift 6.1)** +* Implementation: [swiftlang/swift#73309](https://github.com/swiftlang/swift/pull/73309), [swiftlang/swift#74801](https://github.com/swiftlang/swift/pull/74801) * Review: ([first pitch](https://forums.swift.org/t/pitch-objective-c-implementations-in-swift/61907)) ([second pitch](https://forums.swift.org/t/pitch-2-objective-c-implementations-in-swift/68090)) ([third pitch](https://forums.swift.org/t/pitch-3-objective-c-implementations-in-swift/71315)) ([review](https://forums.swift.org/t/se-0436-objective-c-implementations-in-swift/71712)) ([acceptance](https://forums.swift.org/t/accepted-se-0436-objective-c-implementations-in-swift/72053)) ## Introduction From a39c5fa4d9dfdc0aa83f209b332ba54b15a8f09c Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Mon, 10 Mar 2025 05:24:13 +0000 Subject: [PATCH 140/505] [SE-0465] Rename `Vector`, add syntax highlighting --- proposals/0465-nonescapable-stdlib-primitives.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index 20e74ec1ec..687c0f999e 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -357,7 +357,7 @@ The object identifier of a noncopyable/nonescapable type is still a regular copy [SE-0437] omitted generalizing the `Equatable` conformance of `ManagedBufferPointer`; this proposal allows comparing `ManagedBufferPointer` instances for equality even if their `Element` happens to be noncopyable. -[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. This proposal generalizes `indices` to be also available on buffer pointers of noncopyable elements. (In the time since the original proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `Vector` with the same property. It makes sense to also provide this interface on buffer pointers, for consistency.) `indices` is useful for iterating through these collection types, especially until we ship a new iteration model that supports noncopyable/nonescapable containers. +[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. This proposal generalizes `indices` to be also available on buffer pointers of noncopyable elements. (In the time since the original proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `InlineArray` with the same property. It makes sense to also provide this interface on buffer pointers, for consistency.) `indices` is useful for iterating through these collection types, especially until we ship a new iteration model that supports noncopyable/nonescapable containers. Finally, [SE-0437] neglected to generalize any of the buffer pointer operations that [SE-0370] introduced on the standard `Slice` type. In this proposal, we correct this omission by generalizing the handful of operations that can support noncopyable result elements: `moveInitializeMemory(as:fromContentsOf:)`, `bindMemory(to:)`, `withMemoryRebound(to:_:)`, and `assumingMemoryBound(to:)`. `Slice` itself continues to require its `Element` to be copyable (at least for now), preventing the generalization of other operations. @@ -481,7 +481,7 @@ As noted above, we defer generalizing the nil-coalescing operator `??`. We expec The Standard Library provides special support for comparing arbitrary optional values against `nil`. We generalize this mechanism to support nonescapable cases: -``` +```swift extension Optional where Wrapped: ~Copyable & ~Escapable { static func ~=( lhs: _OptionalNilComparisonType, @@ -547,7 +547,7 @@ Both of these functions return a value with the same lifetime as the original `R We can also generalize the convenient `get()` function, which is roughly equivalent to optional unwrapping: -``` +```swift extension Result where Success: ~Copyable & ~Escapable { @_lifetime(copying self) // Illustrative syntax consuming func get() throws(Failure) -> Success @@ -670,7 +670,7 @@ Managed buffer pointers are pointer types -- as such, they can be compared wheth ### Making `indices` universally available on unsafe buffer pointers -[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. In the time since that proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `Vector` with the same property. For consistency, it makes sense to also allow developers to unconditionally access `Unsafe[Mutable]BufferPointer.indices`, whether or not `Element` is copyable. +[SE-0437] kept the `indices` property of unsafe buffer pointer types limited to cases where `Element` is copyable. In the time since that proposal, [SE-0447] has introduced a `Span` type that ships with an unconditional `indices` property, and [SE-0453] followed suit by introducing `InlineArray` with the same property. For consistency, it makes sense to also allow developers to unconditionally access `Unsafe[Mutable]BufferPointer.indices`, whether or not `Element` is copyable. ```swift extension UnsafeBufferPointer where Element: ~Copyable { From 0527db5becdcd78c35cf3d7ff8cc777190f19290 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Mon, 10 Mar 2025 16:48:28 -0500 Subject: [PATCH 141/505] Mention the Platform Steering Group in applicable places too Co-authored-by: John McCall --- process.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/process.md b/process.md index d9c71b07b3..b7765840e9 100644 --- a/process.md +++ b/process.md @@ -36,9 +36,10 @@ There is a natural tension between these two goals. Open evolution processes are The [Core Team](https://www.swift.org/community/#core-team) is responsible for the strategic direction of Swift. The Core Team creates workgroups focused on specific parts of the project. When the Core Team gives a workgroup authority over part of the evolution of the project, that workgroup is called an evolution workgroup. Evolution workgroups manage the evolution process for proposals under their authority, working together with other workgroups as needed. -Currently, there are two evolution workgroups: +Currently, there are three evolution workgroups: -* The [Language Steering Group][language-steering-group] has authority over the evolution of the Swift language and its standard library. +* The [Language Steering Group][language-steering-group] has authority over the evolution of the Swift language, its standard library, and any language configuration features of the Swift package manager. +* The [Platform Steering Group][platform-steering-group] has authority over the evolution of all other features of the Swift package manager and its manifest files. * The [Testing Workgroup][testing-workgroup] has authority over the evolution of the Swift Testing and Corelibs XCTest projects. @@ -243,6 +244,7 @@ A given proposal can be in one of several states: [status-page]: https://apple.github.io/swift-evolution/ [preview-package]: https://github.com/apple/swift-standard-library-preview/ [language-steering-group]: https://www.swift.org/language-steering-group +[platform-steering-group]: https://www.swift.org/platform-steering-group [testing-workgroup]: https://www.swift.org/testing-workgroup "Testing Workgroup page on Swift.org" [swift-template]: proposal-templates/0000-swift-template.md "Swift proposal template" [swiftpm-template]: proposal-templates/0000-swiftpm-template.md "Swift Package Manager proposal template" From bbcf82e613451c2abf6ed22120fb0b6e289fff4c Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Mon, 10 Mar 2025 16:48:55 -0500 Subject: [PATCH 142/505] Use a list to mention Swift Testing and XCTest Co-authored-by: John McCall --- process.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/process.md b/process.md index b7765840e9..ac6131ea56 100644 --- a/process.md +++ b/process.md @@ -12,8 +12,9 @@ The Swift evolution process covers all design changes, no matter how small, to t - the core tools of the Swift package ecosystem, including the configuration of the [Swift package manager](https://www.swift.org/package-manager/) and the design of its manifest files, and -- the features and public interfaces of - [Swift Testing](https://github.com/swiftlang/swift-testing). +- the public interfaces of the following libraries: + - [Swift Testing](https://github.com/swiftlang/swift-testing) + - [XCTest](https://github.com/swiftlang/swift-corelibs-xctest) The design of other tools, such as IDEs, debuggers, and documentation generators, is not covered by the evolution process. The Core Team may create workgroups to guide and make recommendations about the development of these tools, but the output of those workgroups is not reviewed. From 4a6a87dd227366ebc379fe742e62dd6bbb93689f Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Mon, 10 Mar 2025 17:04:24 -0500 Subject: [PATCH 143/505] Replace two outdated links in 'process.md' This is a small PR to replace two links in `process.md` which still reference the Apple GitHub organization instead of swiftlang. (I noticed these while working on #2729 but they were out of scope for that PR.) The existing links aren't broken, they do redirect successfully, but it's nicer to use the correct URLs. --- process.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/process.md b/process.md index d38eeec80e..93919f4c2e 100644 --- a/process.md +++ b/process.md @@ -111,7 +111,7 @@ Please state explicitly whether you believe that the proposal should be accepted Proposals that can ship as part of the [Standard Library Preview package][preview-package] should be paired with a pull request against the [swift-evolution-staging repository][swift-evolution-staging]. All other proposals should be paired with an implementation pull request - against the [main Swift repository](https://github.com/apple/swift). + against the [main Swift repository](https://github.com/swiftlang/swift). The preview package can accept new types, new protocols, and extensions to existing types and protocols that can be implemented without access to @@ -208,7 +208,7 @@ A given proposal can be in one of several states: [swift-evolution-repo]: https://github.com/swiftlang/swift-evolution "Swift evolution repository" [swift-evolution-staging]: https://github.com/swiftlang/swift-evolution-staging "Swift evolution staging repository" [proposal-reviews]: https://forums.swift.org/c/evolution/proposal-reviews "'Proposal reviews' category of the Swift forums" -[status-page]: https://apple.github.io/swift-evolution/ +[status-page]: https://www.swift.org/swift-evolution [preview-package]: https://github.com/apple/swift-standard-library-preview/ [language-steering-group]: https://www.swift.org/language-steering-group From 0344e4f3c3393981437d2bc9197817aeaac687e4 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 6 Mar 2025 17:55:35 -0800 Subject: [PATCH 144/505] Lot of edits --- proposals/nnnn-MutableSpan.md | 375 ++++++++++++++++++++++++++-------- 1 file changed, 289 insertions(+), 86 deletions(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index f128749662..fce33b83e7 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -30,13 +30,19 @@ These functions have a few different drawbacks, most prominently their reliance In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`. ## Proposed solution -We introduced `Span` to provide shared read-only access to containers. The natural next step is to provide a similar capability for mutable access. Mutability requires exclusive access, per Swift's [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Exclusive access cannot be modeled with a copyable type, since a copy would represent an additional access, in violation of the law of exclusivity. We therefore need a non-copyable type separate from `Span` in order to model mutations. + +We introduced `Span` to provide shared read-only access to containers. The natural next step is to provide a similar capability for mutable access. A library whose API provides access to its internal storage makes a decision regarding the type of access it provides; it may provide read-only access or provide the ability to mutate its storage. That decision is made by the API author. If mutations were enabled by simply binding a `Span` value to a mutable binding (`var` binding or `inout` parameter), that decision would rest with the user of the API instead of its author. This explains why mutations must be modeled by a type separate from `Span`. + +Mutability requires exclusive access, per Swift's [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Exclusive access cannot be modeled with a copyable type, since a copy would represent an additional access, in violation of the law of exclusivity. This explains why the type which models mutations must be non-copyable. #### MutableSpan -`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan` relies on guarantees that it has exclusive access to the range of memory it represents, and that the memory it represents will remain valid for the duration of the access. These provide data race safety and temporal safety. Like `Span`, `MutableSpan` performs bounds-checking on every access to preserve spatial safety. +`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan`'s memory safety' relies on guarantees that: +- it has exclusive access to the range of memory it represents, providing data race safety and enforced by `~Copyable`. +- the memory it represents will remain valid for the duration of the access, providing lifetime safety and enforced by `~Escapable`. +- each access is guarded by bounds checking, providing bounds safety. -A `MutableSpan` provided by a container represents a mutation of that container, via an exclusive borrow. Mutations are implemented by mutating functions and subscripts, which let the compiler statically enforce exclusivity. +A `MutableSpan` provided by a container represents a mutation of that container, as an extended mutation access. Mutations are implemented by mutating functions and subscripts, which let the compiler statically enforce exclusivity. #### MutableRawSpan @@ -44,7 +50,7 @@ A `MutableSpan` provided by a container represents a mutation of that container, #### Extensions to standard library types -The standard library will provide `mutableSpan` computed properties. These return lifetime-dependent `MutableSpan` instances, and represent a mutation of the instance that provided them. These computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. For example, +The standard library will provide `mutableSpan` computed properties. These return a new lifetime-dependent `MutableSpan` instance, and that `MutableSpan` represents a mutation of the instance that provided it. The `mutableSpan` computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. For example, ```swift func(_ array: inout Array) { @@ -56,7 +62,47 @@ func(_ array: inout Array) { } ``` -These computed properties represent a case of lifetime relationships not covered in [SE-0456][SE-0456]. In SE-0456 we defined lifetime relationships for computed property getters of non-escapable and copyable types (`~Escapable & Copyable`). We propose defining them for properties of non-escapable and non-copyable types (`~Escapable & ~Copyable`). A `~Escapable & ~Copyable` value borrows another binding; if this borrow is also a mutation then it is an exclusive borrow. The scope of the borrow, whether or not it is exclusive, extends until the last use of the dependent binding. +The `mutableSpan` computed property represents a case of lifetime relationships not covered until now. The `mutableSpan` computed properties proposed here will represent mutations of their callee. This relationship will be illustrated with a hypothetical `@_lifetime` attribute, which ties the lifetime of a return value to an input parameter in a specific way. + +Note: The `@_lifetime` attribute is not real; it is a placeholder. The eventual lifetime annotations proposal may or may not propose syntax along these lines. We expect that, as soon as Swift adopts a syntax do describe lifetime dependencies, the Standard Library will be modified to adopt that new syntax. + +```swift +extension Array { + public var mutableSpan: MutableSpan { + @_lifetime(inout self) + mutating get { ... } + } +} +``` + +Here, the lifetime of the returned `MutableSpan` is tied to an `inout` access of `self` (the `Array`.) As long as the returned instance exists, the source `Array` is being mutated, and no other access to the `Array` can occur. + +This lifetime relationship will apply to all the safe `var mutableSpan: MutableSpan` and `var mutableBytes: MutableRawSpan` properties described in this proposal. + +#### Slicing `MutableSpan` or `MutableRawSpan` instances + +An important category of use cases for `MutableSpan` and `MutableRawSpan` consists of bulk copying operations. Often times, such bulk operations do not necessarily start at the beginning of the span, thus having a method to select a sub-span is necessary. This means producing an instance derived from the callee instance. We adopt the nomenclature already introduced in [SE-0437][SE-0437], with a family of `extracting()` methods. + +```swift +extension MutableSpan where Element: ~Copyable & ~Escapable { + @_lifetime(inout self) + public mutating func extracting(_ range: Range) -> Self +} +``` + +This function returns an instance of `MutableSpan` that represents a mutation of the same memory as represented by the callee. The callee can therefore no longer be mutated while the returned value exists: + +```swift +var array = [1, 2, 3, 4, 5] +var span1 = array.mutableSpan +var span2 = span1.extracting(3..<5) +// span1 cannot be accessed here +span2.swapAt(0, 1) +_ = consume span2 // explicitly end scope for `span2` +print(array) // [1, 2, 3, 5, 4] +``` + +As established in [SE-0437][SE-0437], the instance returned by the `extracting()` function does not share indices with the function's callee. ## Detailed Design @@ -79,7 +125,7 @@ We store a `UnsafeMutableRawPointer` value internally in order to explicitly sup Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. ```swift -extension MutableSpan where Element: ~Copyable { +extension MutableSpan where Element: ~Copyable & ~Escapable { /// The number of initialized elements in this `MutableSpan`. var count: Int { get } @@ -100,7 +146,7 @@ extension MutableSpan where Element: ~Copyable { mutating func swapAt(_ i: Index, _ j: Index) /// Borrow the underlying memory for read-only access - var span: Span { borrowing get } + var span: Span { @_lifetime(borrow self) borrowing get } } ``` @@ -118,99 +164,164 @@ for i in myMutableSpan.indices { } ``` -##### Unchecked access to elements: +##### Bulk updates of a `MutableSpan`'s elements: -The `subscript` mentioned above always checks the bounds of the `MutableSpan` before allowing access to the memory, preventing out-of-bounds accesses. We also provide an unchecked variant of the `subscript` and of the `swapAt` function as an alternative for situations where bounds-checking is costly and has already been performed: +We include functions to perform bulk copies of elements into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. The bulk operations return the index following the last element updated. ```swift -extension MutableSpan where Element: ~Copyable { - /// Accesses the element at the specified `position`. - /// - /// This subscript does not validate `position`; this is an unsafe operation. - /// - /// - Parameter position: The offset of the element to access. `position` - /// must be greater or equal to zero, and less than `count`. - @unsafe - subscript(unchecked position: Index) -> Element { borrow; mutate } - - /// Exchange the elements at the two given offsets - /// - /// This function does not validate `i` or `j`; this is an unsafe operation. - @unsafe - mutating func swapAt(unchecked i: Index, unchecked j: Index) -} -``` -##### Bulk updating of a `MutableSpan`'s elements: - -We include functions to perform bulk copies of elements into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. - -**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableSpan`. We could revive the option of using a `some RangeExpression` parameter, or we could use the return value of a `func extracting(_: some RangeExpression)` such as was [recently added][SE-0437] to `UnsafeBufferPointer`. The latter option in combination with `mutating` functions requires the use of intermediate bindings. This section may change in response to feedback and our investigations. - -```swift -extension MutableSpan { +extension MutableSpan where Element: Copyable{ + /// Updates every element of this span's to the given value. mutating func update( - startingAt offset: Index = 0, repeating repeatedValue: Element ) - + + /// Updates the span's elements with the elements from the source mutating func update( - startingAt offset: Index = 0, from source: S ) -> (unwritten: S.Iterator, index: Index) where S.Element == Element + /// Updates the span's elements with the elements from the source mutating func update( - startingAt offset: Index = 0, - from elements: inout some IteratorProtocol + from source: inout some IteratorProtocol ) -> Index + /// Updates the span's elements with every element of the source. mutating func update( - startingAt offset: Index = 0, fromContentsOf source: some Collection ) -> Index - +} + +extension MutableSpan where Element: ~Copyable + /// Updates the span's elements with every element of the source. mutating func update( - startingAt offset: Index = 0, fromContentsOf source: Span ) -> Index + /// Updates the span's elements with every element of the source. mutating func update( - startingAt offset: Index = 0, - fromContentsOf source: borrowing Self + fromContentsOf source: borrowing MutableSpan ) -> Index -} - -extension MutableSpan where Element: ~Copyable { + + /// Updates the span's elements with every element of the source, + /// leaving the source uninitialized. mutating func moveUpdate( - startingAt offset: Index = 0, fromContentsOf source: UnsafeMutableBufferPointer ) -> Index } -extension MutableSpan { +extension MutableSpan where Element: Copyable { + /// Updates the span's elements with every element of the source, + /// leaving the source uninitialized. mutating func moveUpdate( - startingAt offset: Index = 0, fromContentsOf source: Slice> ) -> Index } ``` + +##### Extracting sub-spans +These functions extract sub-spans of the callee. The first two perform strict bounds-checking. The last four return prefixes or suffixes, where the number of elements in the returned sub-span is bounded by the number of elements in the parent `MutableSpan`. + +```swift +extension MutableSpan where Element: ~Copable & ~Escapable { + /// Returns a span over the items within the supplied range of + /// positions within this span. + @_lifetime(inout self) + mutating public func extracting(_ bounds: Range) -> Self + + /// Returns a span over the items within the supplied range of + /// positions within this span. + @_lifetime(inout self) + mutating public func extracting(_ bounds: some RangeExpression) -> Self + + /// Returns a span containing the initial elements of this span, + /// up to the specified maximum length. + @_lifetime(inout self) + mutating public func extracting(first maxLength: Int) -> Self + + /// Returns a span over all but the given number of trailing elements. + @_lifetime(inout self) + mutating public func extracting(droppingLast k: Int) -> Self + + /// Returns a span containing the final elements of the span, + /// up to the given maximum length. + @_lifetime(inout self) + mutating public func extracting(last maxLegnth: Int) -> Self + + /// Returns a span over all but the given number of initial elements. + @_lifetime(inout self) + mutating public func extracting(droppingFirst k: Int) -> Self +} +``` + +##### Unchecked access to elements or sub-spans: + +The `subscript` and index-taking functions mentioned above always check the bounds of the `MutableSpan` before allowing access to the memory, preventing out-of-bounds accesses. We also provide unchecked variants of the `subscript`, the `swapAt()` and `extracting()` functions as alternatives in situations where repeated bounds-checking is costly and has already been performed: + +```swift +extension MutableSpan where Element: ~Copyable { + /// Accesses the element at the specified `position`. + /// + /// This subscript does not validate `position`; this is an unsafe operation. + /// + /// - Parameter position: The offset of the element to access. `position` + /// must be greater or equal to zero, and less than `count`. + @unsafe + subscript(unchecked position: Index) -> Element { borrow; mutate } + + /// Exchange the elements at the two given offsets + /// + /// This function does not validate `i` or `j`; this is an unsafe operation. + @unsafe + mutating func swapAt(unchecked i: Index, unchecked j: Index) + + /// Constructs a new span over the items within the supplied range of + /// positions within this span. + /// + /// This function does not validate `bounds`; this is an unsafe operation. + @unsafe + @_lifetime(inout self) + mutating func extracting(unchecked bounds: Range) -> Self + + /// Constructs a new span over the items within the supplied range of + /// positions within this span. + /// + /// This function does not validate `bounds`; this is an unsafe operation. + @unsafe + @_lifetime(inout self) + mutating func extracting(unchecked bounds: ClosedRange) -> Self +} +``` + + ##### Interoperability with unsafe code: ```swift extension MutableSpan where Element: ~Copyable { + /// Calls a closure with a pointer to the viewed contiguous storage. func withUnsafeBufferPointer( _ body: (_ buffer: UnsafeBufferPointer) throws(E) -> Result ) throws(E) -> Result + /// Calls a closure with a pointer to the viewed mutable contiguous + /// storage. mutating func withUnsafeMutableBufferPointer( _ body: (_ buffer: UnsafeMutableBufferPointer) throws(E) -> Result ) throws(E) -> Result } extension MutableSpan where Element: BitwiseCopyable { + /// Calls a closure with a pointer to the underlying bytes of + /// the viewed contiguous storage. func withUnsafeBytes( _ body: (_ buffer: UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result + /// Calls a closure with a pointer to the underlying bytes of + /// the viewed mutable contiguous storage. + /// + /// Note: mutating the bytes may result in the violation of + /// invariants in the internal representation of `Element` + @unsafe mutating func withUnsafeMutableBytes( _ body: (_ buffer: UnsafeMutableRawBufferPointer) throws(E) -> Result ) throws(E) -> Result @@ -255,10 +366,14 @@ extension MutableRawSpan { ```swift extension MutableRawSpan { + /// Stores the given value's bytes into raw memory at the specified offset. mutating func storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type ) + /// Stores the given value's bytes into raw memory at the specified offset. + /// + /// This function does not validate `offset`; this is an unsafe operation. @unsafe mutating func storeBytes( of value: T, toUncheckedByteOffset offset: Int, as type: T.Type @@ -270,21 +385,29 @@ Additionally, the basic loading operations available on `RawSpan` are available ```swift extension MutableRawSpan { + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. @unsafe func unsafeLoad( fromByteOffset offset: Int = 0, as: T.Type ) -> T + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. @unsafe func unsafeLoadUnaligned( fromByteOffset offset: Int = 0, as: T.Type ) -> T + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. @unsafe func unsafeLoad( fromUncheckedByteOffset offset: Int, as: T.Type ) -> T + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. @unsafe func unsafeLoadUnaligned( fromUncheckedByteOffset offset: Int, as: T.Type @@ -294,55 +417,116 @@ extension MutableRawSpan { We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element. -**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableRawSpan`. (See the note above for more details on the same considerations.) - ```swift extension MutableRawSpan { + /// Updates the span's bytes with the bytes of the elements from the source mutating func update( - startingAt byteOffset: Int = 0, from source: S ) -> (unwritten: S.Iterator, byteOffset: Int) where S.Element: BitwiseCopyable + /// Updates the span's bytes with the bytes of the elements from the source mutating func update( - startingAt byteOffset: Int = 0, from elements: inout some IteratorProtocol ) -> Int + /// Updates the span's bytes with every byte of the source. mutating func update( - startingAt byteOffset: Int = 0, fromContentsOf source: C ) -> Int where C.Element: BitwiseCopyable + /// Updates the span's bytes with every byte of the source. mutating func update( - startingAt byteOffset: Int = 0, fromContentsOf source: Span ) -> Int + /// Updates the span's bytes with every byte of the source. mutating func update( - startingAt byteOffset: Int = 0, fromContentsOf source: borrowing MutableSpan ) -> Int + /// Updates the span's bytes with every byte of the source. mutating func update( - startingAt byteOffset: Int = 0, fromContentsOf source: RawSpan ) -> Int + /// Updates the span's bytes with every byte of the source. mutating func update( - startingAt byteOffset: Int = 0, fromContentsOf source: borrowing MutableRawSpan ) -> Int } ``` +##### Extracting sub-spans +These functions extract sub-spans of the callee. The first two perform strict bounds-checking. The last four return prefixes or suffixes, where the number of elements in the returned sub-span is bounded by the number of elements in the parent `MutableRawSpan`. + +```swift +extension MutableRawSpan { + /// Returns a span over the items within the supplied range of + /// positions within this span. + @_lifetime(inout self) + mutating public func extracting(_ byteOffsets: Range) -> Self + + /// Returns a span over the items within the supplied range of + /// positions within this span. + @_lifetime(inout self) + mutating public func extracting(_ byteOffsets: some RangeExpression) -> Self + + /// Returns a span containing the initial elements of this span, + /// up to the specified maximum length. + @_lifetime(inout self) + mutating public func extracting(first maxLength: Int) -> Self + + /// Returns a span over all but the given number of trailing elements. + @_lifetime(inout self) + mutating public func extracting(droppingLast k: Int) -> Self + + /// Returns a span containing the final elements of the span, + /// up to the given maximum length. + @_lifetime(inout self) + mutating public func extracting(last maxLegnth: Int) -> Self + + /// Returns a span over all but the given number of initial elements. + @_lifetime(inout self) + mutating public func extracting(droppingFirst k: Int) -> Self +} +``` + +We also provide unchecked variants of the `extracting()` functions as alternatives in situations where repeated bounds-checking is costly and has already been performed: + +```swift +extension MutableRawSpan { + /// Constructs a new span over the items within the supplied range of + /// positions within this span. + /// + /// This function does not validate `byteOffsets`; this is an unsafe operation. + @unsafe + @_lifetime(inout self) + mutating func extracting(unchecked byteOffsets: Range) -> Self + + /// Constructs a new span over the items within the supplied range of + /// positions within this span. + /// + /// This function does not validate `byteOffsets`; this is an unsafe operation. + @unsafe + @_lifetime(inout self) + mutating func extracting(unchecked byteOffsets: ClosedRange) -> Self +} +``` + + + ##### Interoperability with unsafe code: ```swift extension MutableRawSpan { + /// Calls a closure with a pointer to the underlying bytes of + /// the viewed contiguous storage. func withUnsafeBytes( _ body: (_ buffer: UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result + /// Calls a closure with a pointer to the underlying bytes of + /// the viewed mutable contiguous storage. mutating func withUnsafeMutableBytes( _ body: (_ buffer: UnsafeMutableRawBufferPointer) throws(E) -> Result ) throws(E) -> Result @@ -350,57 +534,69 @@ extension MutableRawSpan { ``` These functions use a closure to define the scope of validity of `buffer`, ensuring that the underlying `MutableSpan` and the binding it depends on both remain valid through the end of the closure. They have the same shape as the equivalents on `Array` because they fulfill the same purpose, namely to keep the underlying binding alive. +#### Properties providing `MutableSpan` or `MutableRawSpan` instances + ##### Accessing and mutating the raw bytes of a `MutableSpan` +When a `MutableSpan`'s element is `BitwiseCopyable`, we allow mutations of the underlying storage as raw bytes, as a `MutableRawSpan`. + ```swift extension MutableSpan where Element: BitwiseCopyable { - var mutableBytes: MutableRawSpan { mutating get } + /// Access the underlying raw bytes of this `MutableSpan`'s elements + /// + /// Note: mutating the bytes may result in the violation of + /// invariants in the internal representation of `Element` + @unsafe + var mutableBytes: MutableRawSpan { @_lifetime(inout self) mutating get } } ``` +The standard library will provide `mutating` computed properties providing lifetime-dependent `MutableSpan` instances. These `mutableSpan` computed properties are intended as the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. - -#### Extensions to Standard Library types - -A `mutating` computed property getter defined on any type and returning a `~Escapable & ~Copyable` value establishes an exclusive borrowing lifetime relationship of the returned value on the callee's binding. As long as the returned value exists, then the callee's binding remains borrowed and cannot be accessed in any other way. - -A `nonmutating` computed property getter returning a `~Escapable & ~Copyable` value establishes a borrowing lifetime relationship, as if returning a `~Escapable & Copyable` value (see [SE-0456][SE-0456].) - -The standard library will provide `mutating` computed properties providing lifetime-dependent `MutableSpan` instances. These `mutableSpan` computed properties are intended as the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. +##### Extensions to Standard Library types ```swift extension Array { - var mutableSpan: MutableSpan { mutating get } + /// Access this Array's elements as mutable contiguous storage. + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } } extension ContiguousArray { - var mutableSpan: MutableSpan { mutating get } + /// Access this Array's elements as mutable contiguous storage. + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } } extension ArraySlice { - var mutableSpan: MutableSpan { mutating get } + /// Access this Array's elements as mutable contiguous storage. + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } } extension InlineArray { - var mutableSpan: MutableSpan { mutating get } + /// Access this Array's elements as mutable contiguous storage. + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } } extension CollectionOfOne { - var mutableSpan: MutableSpan { mutating get } + /// Access this Collection's element as mutable contiguous storage. + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } } ``` -#### Extensions to unsafe buffer types +##### Extensions to unsafe buffer types -We hope that `MutableSpan` and `MutableRawSpan` will become the standard ways to delegate mutations of shared contiguous memory in Swift. Many current API delegate mutations with closure-based functions that receive an `UnsafeMutableBufferPointer` parameter to do this. We will provide ways to unsafely obtain `MutableSpan` instances from `UnsafeMutableBufferPointer` and `MutableRawSpan` instances from `UnsafeMutableRawBufferPointer`, in order to bridge these unsafe types to newer, safer contexts. +We hope that `MutableSpan` and `MutableRawSpan` will become the standard ways to delegate mutations of shared contiguous memory in Swift. Many current API delegate mutations via closure-based functions that receive an `UnsafeMutableBufferPointer` parameter. We will provide ways to unsafely obtain `MutableSpan` instances from `UnsafeMutableBufferPointer` and `MutableRawSpan` instances from `UnsafeMutableRawBufferPointer`, in order to bridge these unsafe types to newer, safer contexts. ```swift extension UnsafeMutableBufferPointer { - var mutableSpan: MutableSpan { get } + /// Unsafely access this buffer as a MutableSpan + @unsafe + var mutableSpan: MutableSpan { @_lifetime(borrow self) get } } extension UnsafeMutableRawBufferPointer { - var mutableBytes: MutableRawSpan { get } + /// Unsafely access this buffer as a MutableRawSpan + @unsafe + var mutableBytes: MutableRawSpan { @_lifetime(borrow self) get } } ``` @@ -411,23 +607,23 @@ These unsafe conversions returns a value whose lifetime is dependent on the _bin Failure to maintain these invariants results in undefined behaviour. -#### Extensions to `Foundation.Data` +##### Extensions to `Foundation.Data` While the `swift-foundation` package and the `Foundation` framework are not governed by the Swift evolution process, `Data` is similar in use to standard library types, and the project acknowledges that it is desirable for it to have similar API when appropriate. Accordingly, we plan to propose the following additions to `Foundation.Data`: ```swift extension Foundation.Data { - // Mutate this `Data`'s bytes through a `MutableSpan` - var mutableSpan: MutableSpan { mutating get } + // Access this instance's bytes as mutable contiguous storage + var mutableSpan: MutableSpan { @_lifetime(inout self) mutating get } - // Mutate this `Data`'s bytes through a `MutableRawSpan` - var mutableBytes: MutableRawSpan { mutating get } + // Access this instance's bytes as mutable contiguous bytes + var mutableBytes: MutableRawSpan { @_lifetime(inout self) mutating get } } ``` #### Performance -The `mutableSpan` and `mutableBytes` properties should be performant and return their `MutableSpan` or `MutableRawSpan` with very little work, in O(1) time. In copy-on-write types, however, obtaining a `MutableSpan` is the start of the mutation, and if the backing buffer is not uniquely reference a copy must be made ahead of returning the `MutableSpan`. +The `mutableSpan` and `mutableBytes` properties should be performant and return their `MutableSpan` or `MutableRawSpan` with very little work, in O(1) time. In copy-on-write types, however, obtaining a `MutableSpan` is the start of the mutation. When the backing buffer is not uniquely referenced then a full copy must be made ahead of returning the `MutableSpan`. Note that `MutableSpan` incurs no special behaviour for bridged types, since mutable bindings always require a defensive copy of data bridged from Objective-C data structures. @@ -509,11 +705,18 @@ Unfortunately, tuples do not support non-copyable values yet. We may be able to #### Mutating algorithms -Algorithms defined on `MutableCollection` such as `sort(by:)` and `partition(by:)` could be defined on `MutableSpan`. We believe we will be able to define these more generally once we have a generalized container protocol hierarchy. +Algorithms defined on `MutableCollection` such as `sort(by:)` and `partition(by:)` could be defined on `MutableSpan`. We believe we will be able to define these more generally once we have a generalized container protocol hierarchy. + +#### Exclusive Access + +The `mutating` functions in this proposal generally do not represent mutations of the binding itself, but of memory being referenced. `mutating` is necessary in order to model the necessary exclusive access to the memory. We could conceive of an access level between "shared" (`let`) and "exclusive" (`var`) that would model an exclusive access while allowing the pointer and count information to be stored in registers. + +#### Harmonizing `extracting()` functions across types + +The range of `extracting()` functions proposed here expands upon the range accepted in [SE-0437][SE-0437]. If the prefix and suffix variants are accepted, we should add them to `UnsafeBufferPointer` types as well. `Span` and `RawSpan` should also have `extracting()` functions with appropriate lifetime dependencies. #### Delegated initialization with `OutputSpan` Some data structures can delegate initialization of parts of their owned memory. The standard library added the `Array` initializer `init(unsafeUninitializedCapacity:initializingWith:)` in [SE-0223][SE-0223]. This initializer relies on `UnsafeMutableBufferPointer` and correct usage of initialization primitives. We should present a simpler and safer model of initialization by leveraging non-copyability and non-escapability. -We expect to propose an `OutputSpan` type to represent partially-initialized memory, and to support to the initialization of memory by appending to the initialized portion of the underlying storage. - +We expect to propose an `OutputSpan` type to represent partially-initialized memory, and to support to the initialization of memory by appending to the initialized portion of the underlying storage. From 5340db1e42756b6738efaaee3ef9a90adedeb262 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 11 Mar 2025 13:34:11 -0700 Subject: [PATCH 145/505] editorial fixes --- proposals/nnnn-MutableSpan.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index fce33b83e7..803fdd0424 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -37,7 +37,7 @@ Mutability requires exclusive access, per Swift's [law of exclusivity][SE-0176]. #### MutableSpan -`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan`'s memory safety' relies on guarantees that: +`MutableSpan` allows delegating mutations of a type's contiguous internal representation, by providing access to an exclusively-borrowed view of a range of contiguous, initialized memory. `MutableSpan`'s memory safety relies on guarantees that: - it has exclusive access to the range of memory it represents, providing data race safety and enforced by `~Copyable`. - the memory it represents will remain valid for the duration of the access, providing lifetime safety and enforced by `~Escapable`. - each access is guarded by bounds checking, providing bounds safety. @@ -90,7 +90,7 @@ extension MutableSpan where Element: ~Copyable & ~Escapable { } ``` -This function returns an instance of `MutableSpan` that represents a mutation of the same memory as represented by the callee. The callee can therefore no longer be mutated while the returned value exists: +This function returns an instance of `MutableSpan` that represents a mutation of the same memory as represented by the callee. The callee can therefore no longer be accessed (read or mutated) while the returned value exists: ```swift var array = [1, 2, 3, 4, 5] @@ -713,7 +713,7 @@ The `mutating` functions in this proposal generally do not represent mutations o #### Harmonizing `extracting()` functions across types -The range of `extracting()` functions proposed here expands upon the range accepted in [SE-0437][SE-0437]. If the prefix and suffix variants are accepted, we should add them to `UnsafeBufferPointer` types as well. `Span` and `RawSpan` should also have `extracting()` functions with appropriate lifetime dependencies. +The range of `extracting()` functions proposed here expands upon the range accepted in [SE-0437][SE-0437]. If the prefix and suffix variants are accepted, we should add them to `UnsafeBufferPointer` types as well. `Span` and `RawSpan` should also have `extracting()` functions with appropriate lifetime dependencies. #### Delegated initialization with `OutputSpan` From b15d39a8d9def33623bf904f2bd1892b5500550c Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 11 Mar 2025 17:13:37 -0700 Subject: [PATCH 146/505] more typos --- proposals/nnnn-MutableSpan.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/nnnn-MutableSpan.md index 803fdd0424..7ba38b7a00 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/nnnn-MutableSpan.md @@ -96,10 +96,12 @@ This function returns an instance of `MutableSpan` that represents a mutation of var array = [1, 2, 3, 4, 5] var span1 = array.mutableSpan var span2 = span1.extracting(3..<5) -// span1 cannot be accessed here +// neither array nor span1 can be accessed here span2.swapAt(0, 1) _ = consume span2 // explicitly end scope for `span2` -print(array) // [1, 2, 3, 5, 4] +span1.swapAt(0, 1) +_ = consume span1 // explicitly end scope for `span1` +print(array) // [2, 1, 3, 5, 4] ``` As established in [SE-0437][SE-0437], the instance returned by the `extracting()` function does not share indices with the function's callee. @@ -169,7 +171,7 @@ for i in myMutableSpan.indices { We include functions to perform bulk copies of elements into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index. The bulk operations return the index following the last element updated. ```swift -extension MutableSpan where Element: Copyable{ +extension MutableSpan where Element: Copyable { /// Updates every element of this span's to the given value. mutating func update( repeating repeatedValue: Element @@ -179,12 +181,12 @@ extension MutableSpan where Element: Copyable{ mutating func update( from source: S ) -> (unwritten: S.Iterator, index: Index) where S.Element == Element - + /// Updates the span's elements with the elements from the source mutating func update( from source: inout some IteratorProtocol ) -> Index - + /// Updates the span's elements with every element of the source. mutating func update( fromContentsOf source: some Collection @@ -196,7 +198,7 @@ extension MutableSpan where Element: ~Copyable mutating func update( fromContentsOf source: Span ) -> Index - + /// Updates the span's elements with every element of the source. mutating func update( fromContentsOf source: borrowing MutableSpan @@ -245,7 +247,7 @@ extension MutableSpan where Element: ~Copable & ~Escapable { /// Returns a span containing the final elements of the span, /// up to the given maximum length. @_lifetime(inout self) - mutating public func extracting(last maxLegnth: Int) -> Self + mutating public func extracting(last maxLength: Int) -> Self /// Returns a span over all but the given number of initial elements. @_lifetime(inout self) @@ -292,8 +294,7 @@ extension MutableSpan where Element: ~Copyable { } ``` - -##### Interoperability with unsafe code: +##### Interoperability with unsafe code ```swift extension MutableSpan where Element: ~Copyable { @@ -457,6 +458,7 @@ extension MutableRawSpan { ``` ##### Extracting sub-spans + These functions extract sub-spans of the callee. The first two perform strict bounds-checking. The last four return prefixes or suffixes, where the number of elements in the returned sub-span is bounded by the number of elements in the parent `MutableRawSpan`. ```swift @@ -513,8 +515,6 @@ extension MutableRawSpan { } ``` - - ##### Interoperability with unsafe code: ```swift @@ -697,11 +697,11 @@ It is desirable to have a way to split a `MutableSpan` in multiple parts, for di ```swift extension MutableSpan where Element: ~Copyable { - func split(at index: Index) -> (part1: Self, part2: Self) + public mutating func split(at index: Index) -> (part1: Self, part2: Self) } ``` -Unfortunately, tuples do not support non-copyable values yet. We may be able to use `InlineArray` ([SE-0453][SE-0453]), or a bespoke type, but destructuring the non-copyable constituent part remains a challenge. Solving this issue for `Span` and `MutableSpan` is a top priority. +Unfortunately, tuples do not support non-copyable or non-escapable values yet. We may be able to use `InlineArray` ([SE-0453][SE-0453]), or a bespoke type, but destructuring the non-copyable constituent part remains a challenge. Solving this issue for `Span` and `MutableSpan` is a top priority. #### Mutating algorithms From 7a3ed493f68ed49770fa932173d35960cb2784dd Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 11 Mar 2025 17:16:05 -0700 Subject: [PATCH 147/505] christen MutableSpan as SE-0467 and begin review --- proposals/{nnnn-MutableSpan.md => 0467-MutableSpan.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{nnnn-MutableSpan.md => 0467-MutableSpan.md} (99%) diff --git a/proposals/nnnn-MutableSpan.md b/proposals/0467-MutableSpan.md similarity index 99% rename from proposals/nnnn-MutableSpan.md rename to proposals/0467-MutableSpan.md index 7ba38b7a00..0ed4faecc7 100644 --- a/proposals/nnnn-MutableSpan.md +++ b/proposals/0467-MutableSpan.md @@ -1,12 +1,12 @@ # MutableSpan and MutableRawSpan: delegate mutations of contiguous memory -* Proposal: TBD +* Proposal: [SE-0467](0467-MutableSpan.md) * Author: [Guillaume Lessard](https://github.com/glessard) -* Review Manager: TBD -* Status: **Pitch** +* Review Manager: [Joe Groff](https://github.com/jckarter) +* Status: **Active review (March 11...25, 2025)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) -* Review: [Pitch](https://forums.swift.org/) +* Review: [Pitch](https://forums.swift.org/t/pitch-mutablespan/77790) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md From 5022e3e1266f2e1783a595932015e51f7871cdf6 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 12 Mar 2025 15:17:44 -0400 Subject: [PATCH 148/505] SE-0451 implementation has been merged, will be in 6.2. --- proposals/0451-escaped-identifiers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0451-escaped-identifiers.md b/proposals/0451-escaped-identifiers.md index 6971096741..639a1e1a9b 100644 --- a/proposals/0451-escaped-identifiers.md +++ b/proposals/0451-escaped-identifiers.md @@ -3,7 +3,7 @@ * Proposal: [SE-0451](0451-escaped-identifiers.md) * Author: [Tony Allevato](https://github.com/allevato) * Review Manager: [Joe Groff](https://github.com/jckarter) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#76636](https://github.com/swiftlang/swift/pull/76636), [swiftlang/swift-syntax#2857](https://github.com/swiftlang/swift-syntax/pull/2857) * Previous Proposal: [SE-0275](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0275-allow-more-characters-like-whitespaces-and-punctuations-for-escaped-identifiers.md) * Review: ([pitch](https://forums.swift.org/t/pitch-revisiting-backtick-delimited-identifiers-that-allow-more-non-identifier-characters/74432), [review](https://forums.swift.org/t/se-0451-raw-identifiers/75602), [acceptance](https://forums.swift.org/t/accepted-with-revision-se-0451-raw-identifiers/76387)) From dd024db6d983d5b15cd7995920a9d321a89c19d0 Mon Sep 17 00:00:00 2001 From: "Mykola (Nickolas) Pokhylets" Date: Thu, 13 Mar 2025 02:39:26 +0100 Subject: [PATCH 149/505] Proposal to add `Hashable` conformance to `Async(Throwing)Stream.Continuation` (#2700) * Proposal to add `Hashable` conformance to `Async(Throwing)Stream.Continuation` * Apply suggestions from code review Co-authored-by: Frederick Kellison-Linn * Apply review comments * Removed backdeployment considerations * Continuation hashable conformance is 0468 --------- Co-authored-by: Frederick Kellison-Linn Co-authored-by: Freddy Kellison-Linn --- ...tream-continuation-hashable-conformance.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 proposals/0468-async-stream-continuation-hashable-conformance.md diff --git a/proposals/0468-async-stream-continuation-hashable-conformance.md b/proposals/0468-async-stream-continuation-hashable-conformance.md new file mode 100644 index 0000000000..00791b140f --- /dev/null +++ b/proposals/0468-async-stream-continuation-hashable-conformance.md @@ -0,0 +1,130 @@ +# `Hashable` conformance for `Async(Throwing)Stream.Continuation` + +* Proposal: [SE-0468](0468-async-stream-continuation-hashable-conformance.md) +* Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) +* Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) +* Status: **Active review (March 12...25, 2025)** +* Implementation: [swiftlang/swift#79457](https://github.com/swiftlang/swift/pull/79457) +* Review: ([pitch](https://forums.swift.org/t/pitch-add-hashable-conformance-to-asyncstream-continuation/77897)) + +## Introduction + +This proposal adds a `Hashable` conformance to `Async(Throwing)Stream.Continuation` +to simplify working with multiple streams. + +## Motivation + +Use cases operating with multiple `AsyncStream`s may need to store multiple continuations. +When handling `onTermination` callback, client code needs to remove the relevant continuation. + +To identify the relevant continuation, client code needs to be able to compare continuations. + +It is possible to associate a lookup key with each continuation, but this is inefficient. +`AsyncStream.Continuation` already stores a reference to `AsyncStream._Storage`, +whose identity can be used to provide simple and efficient `Hashable` conformance. + +Consider this simple Observer pattern with an `AsyncSequence`-based API. +To avoid implementing `AsyncSequence` from scratch it uses `AsyncStream` as a building block. +To support multiple subscribers, a new stream is returned every time. + +```swift +@MainActor private class Sender { + var value: Int = 0 { + didSet { + for c in continuations { + c.yield(value) + } + } + } + + var values: some AsyncSequence { + AsyncStream(bufferingPolicy: .bufferingNewest(1)) { continuation in + continuation.yield(value) + self.continuations.insert(continuation) + continuation.onTermination = { _ in + DispatchQueue.main.async { + self.continuations.remove(continuation) + } + } + } + } + + private var continuations: Set.Continuation> = [] +} +``` + +Without a `Hashable` conformance, each continuation needs to be associated with an artificial identifier. +E.g. wrapping continuation in a class, identity of the wrapper object can be used: + +```swift +@MainActor private class Sender { + var value: Int = 0 { + didSet { + for c in continuations { + c.value.yield(value) + } + } + } + + var values: some AsyncSequence { + AsyncStream { (continuation: AsyncStream.Continuation) -> Void in + continuation.yield(value) + let box = ContinuationBox(value: continuation) + self.continuations.insert(box) + continuation.onTermination = { _ in + DispatchQueue.main.async { + self.continuations.remove(box) + } + } + } + } + + private var continuations: Set = [] + + private final class ContinuationBox: Hashable, Sendable { + let value: AsyncStream.Continuation + + init(value: AsyncStream.Continuation) { + self.value = value + } + + static func == (lhs: Sender.ContinuationBox, rhs: Sender.ContinuationBox) -> Bool { + lhs === rhs + } + + func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + } +} +``` + +Note that capturing `continuation` or `box` in `onTermination` is safe, because `onTermination` is dropped after being called +(and it is _always_ called, even if `AsyncStream` is discarded without being iterated). + +## Proposed solution + +Add a `Hashable` conformance to `Async(Throwing)Stream.Continuation`. + +## Detailed design + +Every time when the `build` closure of the `Async(Throwing)Stream.init()` is called, +it receives a continuation distinct from all other continuations. +All copies of the same continuation should compare equal. +Yielding values or errors, finishing the stream, or cancelling iteration should not affect equality. +Assigning `onTermination` closures should not affect equality. + +## Source compatibility + +This is an additive change. + +Retroactive conformances are unlikely to exist, because current public API of the `Async(Throwing)Stream.Continuation` +does not provide anything that could be reasonably used to implement `Hashable` or `Equatable` conformances. + +## ABI compatibility + +This is an additive change. + +## Implications on adoption + +Adopters will need a new version of the standard library. From f492f715dec6fd035debab894f41e81d1464a662 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Wed, 12 Mar 2025 22:00:51 -0400 Subject: [PATCH 150/505] Update 0462-task-priority-escalation-apis.md (#2735) --- proposals/0462-task-priority-escalation-apis.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0462-task-priority-escalation-apis.md b/proposals/0462-task-priority-escalation-apis.md index 1f270b4150..5174719ca9 100644 --- a/proposals/0462-task-priority-escalation-apis.md +++ b/proposals/0462-task-priority-escalation-apis.md @@ -3,9 +3,9 @@ * Proposal: [SE-0462](0462-task-priority-escalation-apis.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Freddy Kellison-Linn](https://github.com/jumhyn) -* Status: **Active review (February 20...March 2, 2025)** +* Status: **Accepted with modifications** * Implementation: https://github.com/swiftlang/swift/pull/78625 -* Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) ([review](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997)) +* Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) ([review](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997))([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0462-task-priority-escalation-apis/78488)) ## Introduction From 834651da2bdc2d578a9fd2c4db47ab50b719594c Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 13 Mar 2025 01:05:40 -0400 Subject: [PATCH 151/505] Accept SE-0463 --- proposals/0463-sendable-completion-handlers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0463-sendable-completion-handlers.md b/proposals/0463-sendable-completion-handlers.md index 3200e21039..498ab8ba80 100644 --- a/proposals/0463-sendable-completion-handlers.md +++ b/proposals/0463-sendable-completion-handlers.md @@ -3,10 +3,10 @@ * Proposal: [SE-0463](0463-sendable-completion-handlers.md) * Authors: [Holly Borla](https://github.com/hborla) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active Review (February 27th...March 10th, 2025)** +* Status: **Accepted** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` -* Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) ([review](https://forums.swift.org/t/se-0463-import-objective-c-completion-handler-parameters-as-sendable/78169)) +* Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) ([review](https://forums.swift.org/t/se-0463-import-objective-c-completion-handler-parameters-as-sendable/78169)) ([acceptance](https://forums.swift.org/t/accepted-se-0463-import-objective-c-completion-handler-parameters-as-sendable/78489)) ## Introduction From ceabe4683d8914afb67edd8e3af876cc8210c2c2 Mon Sep 17 00:00:00 2001 From: Harjas Monga Date: Thu, 13 Mar 2025 15:09:01 -0700 Subject: [PATCH 152/505] Swift Task Naming API (#2619) * Initial Draft * API Renaming * Update to some APIs * Update APIs a little bit * make snippets swift syntax * Link to implementation, and startSynchronously proposal * Add unsafeCurrentTask accessor to proposal * Update 0454-task-names.md * remove the nil default * Update proposal header and assign SE number to task naming. --------- Co-authored-by: Konrad `ktoso` Malawski Co-authored-by: Holly Borla --- proposals/0469-task-names.md | 272 +++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 proposals/0469-task-names.md diff --git a/proposals/0469-task-names.md b/proposals/0469-task-names.md new file mode 100644 index 0000000000..20d872fe89 --- /dev/null +++ b/proposals/0469-task-names.md @@ -0,0 +1,272 @@ +# Task Naming + +* Proposal: [SE-0469](0469-task-names.md) +* Authors: [Konrad Malawski](https://github.com/ktoso), [Harjas Monga](https://github.com/Harjas12) +* Review Manager: [Holly Borla](https://github.com/hborla) +* Status: **Active Review (March 13 - March 27, 2025)** +* Implementation: [swiftlang/swift#79600](https://github.com/swiftlang/swift/pull/79600) +* Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) + +## Introduction + +In this proposal, we introduce several new APIs to allow developers to name their Swift Tasks for the purposes of identifying tasks in a human-readable way. These names can then be used to identify tasks by printing their names, programatically inspecting the name property, or by tools which dump and inspect tasks–such as debuggers, swift-inspect or others. + +## Motivation + +In previous generations of concurrency technologies, developer tools, such as debuggers, have had access to some kind of label to help describe a process’s concurrent work. Ex: Pthread names or Grand Central Dispatch queue names. These names are very helpful to provide extra context to developers when using debugging and profiling tools. + +Currently, Swift Concurrency has no affordances to allow developers to label a Task, which can be troublesome for developers trying to identify "which task" is taking a long time to process or similar questions when observing the system externally. In order to ease the debugging and profiling of Swift concurrency code, developers should be able to annotate their Swift Tasks to describe an asynchronous workload. + +## Proposed solution + +In order to allow developers to provide helpful names for Swift Tasks, the Swift Task creation APIs should be modified to *optionally* allow developers to provide a name for that task. + +Consider the example: + +```swift +let getUsers = Task { + await users.get(accountID)) +} +``` + +In order to ease debugging, a developer could create this unstructured task by passing in a name instead: + +```swift +let getUsers = Task(name: "Get Users") { + await users.get(accountID) +} +``` + +Or, if a developer has a lot of similar tasks, they can provide more contextual information using string interpolation. + +```swift +let getUsers = Task("Get Users for \(accountID)") { + await users.get(accountID) +} +``` + +By introducing this API in Swift itself, rather than developers each inventing their own task-local with a name, runtime inspection tools and debuggers can become aware of task names and show you exactly which accountID was causing the crash or a profiling tool could tell you which accountID request was slow to load. + +## Detailed design + +Naming tasks is only allowed during their creation, and modifying names is not allowed. + +Names are arbitrary user-defined strings, which may be computed at runtime because they often contain identifying information such as the request ID or similar runtime information. + +The following APIs will be provided on `Task`: + +```swift +extension Task where Failure == /* both Never and Error cases */ { + init( + name: String?, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + priority: TaskPriority? = nil, + operation: sending @escaping @isolated(any) () async /*throws */-> Success) + + static func detached( + name: String?, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + priority: TaskPriority? = nil, + operation: sending @escaping @isolated(any) () async /*throws */ -> Success) +} +``` + +In addition to these APIs to name unstructured Tasks, the following API will be added to all kinds of task groups: + +```swift +mutating func addTask( + name: String?, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + priority: TaskPriority? = nil, + operation: sending @escaping @isolated(any) () async -> ChildTaskResult + ) + + mutating func addTaskUnlessCancelled( + name: String?, + executorPreference taskExecutor: (any TaskExecutor)? = nil, + priority: TaskPriority? = nil, + operation: sending @escaping @isolated(any) () async -> ChildTaskResult + ) +``` + +These APIs would be added to all kinds of task groups, including throwing, discarding ones. With the signature being appropriately matching the existing addTask signatures of those groups. + +> Concurrently under review with this proposal is the `Task.startSynchronously` (working name, pending changes) proposal; +> If both this and the synchronous starting tasks proposals are accepted, these APIs would also gain the additional `name: String? = nil` parameter. + +In addition to that, it will be possible to read a name off a task, similar to how the current task's priority is possible to be read: + +```swift +extension Task { + static var name: String? { get } +} + +extension UnsafeCurrentTask { + var name: String? { get } +} +``` + +### `UnsafeCurrentTask` access from `UnownedJob` + +In order to have an `Executor` be able to inspect a task name, either to print "Now running [Task A]" or for other reasons, we propose to offer the access to an `UnsafeCurrentTask` representation of a `ExecutorJob` (or `UnownedJob`): + +```swift +extension ExecutorJob / UnownedJob { + public var unsafeCurrentTask: UnsafeCurrentTask? { ... } +} +``` + +This allows executors to inspect the task name if the `job` is a task, and has a name: + +```swift +public nonisolated func enqueue(_ job: consuming ExecutorJob) { + log.trace("Running task named: \(job?.unsafeCurrentTask?.name ?? "")") +} +``` + +We use the `UnsafeCurrentTask` type because it is possible to obtain it from an `UnownedTask` and therefore it is not safe to refer to it without knowladge about the job's lifetime. +One should not refer to the unsafe current task after invoking `runSynchronously` on the job, as the job may have completed and been destroyed; therefore the use of the existing `UnsafeCurrentTask` type here is quite appropriate. + +This also allows us to expose other information off a task, such as task local values in the future, if the `UnsafeCurrentTask` were to gain such APIs, without having to replicate "the same" accessors into yet another API that would be accessible directly from an `ExecutorJob`. + +## Source compatibility + +This proposal only contains additive changes to the API surface. + +Since Swift Tasks names will be optional, there will be no source compatibility issues. + +## ABI compatibility + +This proposal is ABI additive and does not change any existing ABI. + +## Implications on adoption + +Because runtime changes are required, these new APIs will only be available on newer OSes. + +## Future directions + +This proposal does not contain a method to name Swift Tasks created using the `async let` syntax. Unlike the other methods of creating Tasks, the `async let` syntax didn’t have an obvious way to allow a developer to provide a string. A suggestion of how we may provide automatic names to Tasks created via this method will be shown below in the [Alternatives Considered section](##Alternatives-considered). + +### Task names for "startSynchronously" + +If the ["start synchronously" tasks proposal](https://github.com/swiftlang/swift-evolution/pull/2698) would be accepted, the name parameter would also be included in those APIs. + +## Alternatives considered + +### Actor & DistributedActor Identity + +#### Actor Identity + +> Note: While not really an alternative, we would like to explain why this proposal does not propose to change anything about how actors are identified. + +This proposal focuses on task names, however, another important part of Swift Concurrency is actors, so in this section we’d like to discuss how there isn’t an actual need for new API to address *actor naming* because of how actors can already conform to protocols. + +An actor can conform e.g. to the `Identifiable` protocol. This works well with constant identifiers, as an actor can have a constant let property implement the `id` requirement from this protocol: + +```swift +actor Worker: Identifiable { + let id: String + + init(id: String) { + self.id = id + } +} +``` + +It is also likely that such identity is how a developer might want to look up and identify such actor in traces or logs, so making use of `Identifiable` seems like a good pattern to follow. + +It is also worth reminding that thread-safety of an actor is ensured even if the `id` were to be implemented using a computed property, because it will be forced to be `nonisolated` because of Swift’s conformance and actor isolation rules: + +```swift +actor Worker: Identifiable { + let workCategory: String = "fetching" // "building" etc... + let workID: Int + + nonisolated var id: String { + "\(workCategory)-\(workID)" + } +} +``` + +#### Distributed Actor Identity + +Distributed actors already implicitly conform to `Identifiable` protocol and have a very useful `id` representation that is always assigned by the actor system by which an actor is managed. + +This id is the natural human readable representation of such actor identity, and tools which want to print an “actor identity” should rely on this. In other words, this simply follows the same general pattern that makes sense for other objects and actors of using Identifiable when available to identify things. + +```swift +distributed actor Worker { // implicitly Identifiable + // nonisolated var id: Self.ActorSystem.ActorID { get } +} +``` + +### AsyncLet Task Naming + +While there is no clear way on how to name Swift Task using `async let`, the following were considered. + +#### Approach 1: + +Since we effectively want to express that “the task” is some specific task, we had considered introducing some special casing where if the right hand side of an async let we want to say at creation time that this task is something specific, thus we arrive at the following: + +```swift +async let example: String = Task(name: "get-example") { "example" } +``` + +In order to make this syntax work, we need to avoid double creating tasks. When the compiler sees the `async let` syntax and the `Task {}` initializer, it would need to not create a Task to immediately create another Task inside it, but instead use that Task initializer that we explicitly wrote. + +While, this approach could in theory allow us to name Tasks created using `async let`. It has at least one major issue: + +It can cause surprising behavior and it can be unclear that this would only work when the Task initializer is visible from the async let declaration... I.e. moving the initialization into a method like this: + +```swift +async let example: String = getTask() // error String != Task + +func getTask() -> Task { Task(name: "get-example") { "example" } } +``` + +This would not only break refactoring, as the types are not the same; but also execution semantics, as this refactoring has now caused the task to become an unstructured task “by accident”. Therefore this approach is not viable because it introduces too many easy to make mistakes. + +#### Approach 2: + +Instead of attempting to adding a naming API to the `async let` syntax, we could instead take a different where if developers really want to name a structured Task they can use a `TaskGroup` and the compiler would generate a good default name for the Tasks created using the `async let` syntax. Drawing inspiration from how closures and dispatch blocks are named, we count the declaration in the scope and use that to name it. For example: + +```swift +func getUserImages() async -> [Image] { + + async let profileImg = getProfilePicture() // <- Named "getUserImages.asyncLet-1" + async let headerImg = getHeaderPicture() // <- Named "getUserImages.asyncLet-2" + + . + . + . +} +``` + +These names at the very least give some indication of what the task was created to do, and the developer can opt to use the `TaskGroup` API if more control is desired. + +A slight alternative to this suggestion, is instead of using the name of the surrounding scope, use the name of the parent task instead. For example: + +```swift +Task(name: "get user images for \(userID)") { + async let profileImg = getProfilePicture() // <- Named "getUserImages.asyncLet-1" + async let headerImg = getHeaderPicture() // <- Named "getUserImages.asyncLet-2" + + . + . + . +} +``` + +This approach doesn’t allow developers full control over naming tasks, but it is in same spirit of allowing developer tools to provide more context for a task. + +## Structured Names + +There was some thought given to the idea of allowing developers to group similar tasks (in name only). Consider programs that create hundreds of tasks for network requests; by allowing grouping a runtime analysis tool could surface that in a textual or graphical UI. The API needed would be similar to the one proposed, but with an additional optional `category` argument for the Task initializer. For example: + +```swift +Task(category: "Networking", name: "download profile image for \(userID)) { ... } +``` + +Then a debugger than wanted to print all the tasks running when a break point is hit, it could group them by this optional “Networking” category. + +This is not in the actual proposal in order to keep the API simple and doesn’t add much additional value over a simple name. From 60a85e72fd7487fb012d88b3a28e4882f1b5327e Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 13 Mar 2025 15:14:33 -0700 Subject: [PATCH 153/505] Link to review thread in SE-0469 (#2739) --- proposals/0469-task-names.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0469-task-names.md b/proposals/0469-task-names.md index 20d872fe89..ebded646f8 100644 --- a/proposals/0469-task-names.md +++ b/proposals/0469-task-names.md @@ -5,7 +5,7 @@ * Review Manager: [Holly Borla](https://github.com/hborla) * Status: **Active Review (March 13 - March 27, 2025)** * Implementation: [swiftlang/swift#79600](https://github.com/swiftlang/swift/pull/79600) -* Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) +* Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) ([review](https://forums.swift.org/t/se-0469-task-naming/78509)) ## Introduction From 1b82a5557c30d8442481df436e6d35862595ab68 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 17 Mar 2025 16:50:32 -0400 Subject: [PATCH 154/505] Update attach() function after discussion on the forums and with Stuart --- proposals/testing/NNNN-attachments.md | 51 ++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index 02c02f5610..91e6887990 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -84,9 +84,10 @@ public struct Attachment: ~Copyable where AttachableValue: Atta sourceLocation: SourceLocation = #_sourceLocation ) - /// Attach this instance to the current test. + /// Attach an attachment to the current test. /// /// - Parameters: + /// - attachment: The attachment to attach. /// - sourceLocation: The source location of the call to this function. /// /// When attaching a value of a type that does not conform to both @@ -98,7 +99,27 @@ public struct Attachment: ~Copyable where AttachableValue: Atta /// disk. /// /// An attachment can only be attached once. - public consuming func attach(sourceLocation: SourceLocation = #_sourceLocation) + public static func attach(_ attachment: consuming Self, sourceLocation: SourceLocation = #_sourceLocation) + + /// Attach a value to the current test. + /// + /// - Parameters: + /// - attachableValue: The value to attach. + /// - sourceLocation: The source location of the call to this function. + /// + /// When attaching a value of a type that does not conform to both + /// [`Sendable`](https://developer.apple.com/documentation/swift/sendable) and + /// [`Copyable`](https://developer.apple.com/documentation/swift/copyable), + /// the testing library encodes it as data immediately. If the value cannot be + /// encoded and an error is thrown, that error is recorded as an issue in the + /// current test and the attachment is not written to the test report or to + /// disk. + /// + /// This function creates a new instance of ``Attachment`` and immediately + /// attaches it to the current test. + /// + /// An attachment can only be attached once. + public static func attach(_ attachment: consuming AttachableValue, sourceLocation: SourceLocation = #_sourceLocation) /// Call a function and pass a buffer representing the value of this /// instance's ``attachableValue-2tnj5`` property to it. @@ -134,7 +155,7 @@ conform: /// /// To attach an attachable value to a test report or test run output, use it to /// initialize a new instance of ``Attachment``, then call -/// ``Attachment/attach(sourceLocation:)``. An attachment can only be attached +/// ``Attachment/attach(_:sourceLocation:)``. An attachment can only be attached /// once. /// /// The testing library provides default conformances to this protocol for a @@ -226,7 +247,7 @@ that refines `Attachable`: /// /// To attach an attachable value to a test report or test run output, use it to /// initialize a new instance of ``Attachment``, then call -/// ``Attachment/attach(sourceLocation:)``. An attachment can only be attached +/// ``Attachment/attach(_:sourceLocation:)``. An attachment can only be attached /// once. /// /// A type can conform to this protocol if it represents another type that @@ -297,11 +318,12 @@ Package Manager: --attachments-path Path where attachments should be saved. ``` -If specified, an attachment will be written to that path when its `attach()` -method is called. If not specified, attachments are not saved to disk. Tools -that indirectly use Swift Testing through `swift test` can specify a path (e.g. -to a directory created inside the system's temporary directory), then move or -delete the created files as needed. +If specified, an attachment will be written to that path when the attachment is +passed to one of the `Attachment.attach(_:sourceLocation:)` methods. If not +specified, attachments are not saved to disk. Tools that indirectly use Swift +Testing through `swift test` can specify a path (e.g. to a directory created +inside the system's temporary directory), then move or delete the created files +as needed. The JSON event stream ABI will be amended correspondingly: @@ -384,6 +406,12 @@ version too. [swiftlang/swift-testing#824](https://github.com/swiftlang/swift-testing/pull/824) includes an experimental implementation of this feature. +- Attaching attachments to issues or to activities: XCTest supports attachments + on `XCTIssue`; Swift Testing does not currently allow developers to create an + issue without immediately recording it, so there is no opportunity to attach + anything to one. XCTest also supports the concept of activities as subsections + of tests; they remain a future direction for Swift Testing. + ## Alternatives considered - Doing nothing: there's sufficient demand for this feature that we know we want @@ -423,6 +451,11 @@ version too. Instead, `Attachable` includes the function `preferredName(for:basedOn:)` that allows an implementation (such as that of `Encodable & Attachable`) to add a path extension to the filename specified by the test author if needed. + +- Making the `Attachment.attach(_:sourceLocation:)` methods a single instance + method of `Attachment` named `attach()`: this was in the initial pitch but the + community discussed several more ergonomic options and we chose + `Attachment.attach(_:sourceLocation:)` instead. ## Acknowledgments From b35dcb6dc27088506f858dcd630f8ec6e091a1ed Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 17 Mar 2025 16:52:54 -0400 Subject: [PATCH 155/505] Add a link to the cross-import overlay pitch --- proposals/testing/NNNN-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index 91e6887990..8610d5397e 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -33,7 +33,7 @@ we will introduce a new protocol, `Attachable`, to which types can conform to indicate they can be attached to a test. Default conformances to `Attachable` will be provided for standard library types -that can reasonably be attached. We will also introduce a **cross-import overlay** +that can reasonably be attached. We will also introduce a [cross-import overlay](https://forums.swift.org/t/cross-import-overlays/36710) with Foundation—that is, a tertiary module that is automatically imported when a test target imports both Foundation _and_ Swift Testing—that includes additional conformances for Foundation types such as `Data` and `URL` and From 60a149180491dfce5e6d22275f11d66727434944 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 17 Mar 2025 21:25:23 +0000 Subject: [PATCH 156/505] "adopt" -> "migrate" & alternatives considered * Move SwiftPM changes to alternatives considered * Consider the alternative of an independent command line option * Add more alternative naming considerations --- ...NNN-adoption-tooling-for-swift-features.md | 190 +++++++++--------- 1 file changed, 96 insertions(+), 94 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index a7b69dd356..e8f9ca34b7 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -1,4 +1,4 @@ -# Adoption tooling for Swift features +# Migration tooling for Swift features * Proposal: [SE-NNNN](NNNN-filename.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) @@ -92,32 +92,30 @@ and testing code where a change in behavior is preferable. ## Proposed solution -Introduce the notion of an "adoption" mode for individual experimental and +Introduce the notion of a ***migrate*** mode for individual experimental and upcoming features. -The core idea behind adoption mode is a declaration of intent that can be +The core idea behind migration mode is a declaration of intent that can be leveraged to build better supportive adoption experiences for developers. -If enabling a feature communicates an intent to *enact* rules, adoption mode -communicates an intent to *adopt* them. -An immediate benefit of adoption mode is the capability to deliver source -modifications that can be applied to preserve compatibility whenever a feature -provides for them. +If enabling a feature communicates an intent to *enact* rules, migration mode +communicates an intent to migrate code so as to preserve compatibility once the +feature is enabled. This proposal will support the set of existing upcoming features that have mechanical migrations, as described in the [Automation](#automation) section. All future proposals that intend to introduce an upcoming feature and -provide for a mechanical migration should include an adoption mode and detail +provide for a mechanical migration should include a migration mode and detail its behavior alongside the migration paths in the *Source compatibility* section. ## Detailed design -Upcoming features that have mechanical migrations will support an adoption +Upcoming features that have mechanical migrations will support a migration mode, which is a new mode of building a project that will produce compiler warnings with attached fix-its that can be applied to preserve the behavior -of the code once the upcoming feature is enacted. +of the code under the feature. -The action of enabling a previously disabled upcoming feature in adoption +The action of enabling a previously disabled upcoming feature in migration mode must not cause any new compiler errors or behavioral changes, and the fix-its produced must preserve compatibility. Compatibility here refers to both source and binary compatibility, as well as @@ -131,92 +129,33 @@ This warning will belong to the diagnostic group `StrictLanguageFeatures`. ### Interface -#### Compiler - The `-enable-*-feature` frontend and driver command line options will start -supporting an optional mode specifier with `adoption` as the only valid mode: +supporting an optional mode specifier with `migrate` as the only valid mode: ``` -enable-upcoming-feature [:] -enable-experimental-feature [:] - := adoption + := migrate ``` For example: ``` --enable-upcoming-feature InternalImportsByDefault:adoption +-enable-upcoming-feature InternalImportsByDefault:migrate ``` -If the specified mode is invalid, the flag will be ignored, and a warning will +If the specified mode is invalid, the option will be ignored, and a warning will be emitted. This warning will belong to the diagnostic group `StrictLanguageFeatures`. In a series of either of these options applied to a given feature, only the last option will be honored. If an upcoming feature is both implied by the effective language mode and -enabled in adoption mode using either of the aforementioned options, the latter -will be disregarded. - -#### Swift package manager - -The [`SwiftSetting.enableUpcomingFeature`] and -[`SwiftSetting.enableExperimentalFeature`] methods from the -[`PackageDescription`](https://developer.apple.com/documentation/packagedescription) -library will be augmented with a `mode` parameter defaulted to match the -current behavior: - -```swift -extension SwiftSetting { - @available(_PackageDescription, introduced: 6.2) - public enum SwiftFeatureMode { - case adoption - case on - } -} -``` -```diff - public static func enableUpcomingFeature( - _ name: String, -+ mode: SwiftFeatureMode = .on, - _ condition: BuildSettingCondition? = nil - ) -> SwiftSetting { -+ let argument = switch mode { -+ case .adoption: "\(name):adoption" -+ case .mode: name -+ } -+ - return SwiftSetting( -- name: "enableUpcomingFeature", value: [name], condition: condition) -+ name: "enableUpcomingFeature", value: [argument], condition: condition) - } -``` -```diff - public static func enableExperimentalFeature( - _ name: String, -+ mode: SwiftFeatureMode = .on, - _ condition: BuildSettingCondition? = nil - ) -> SwiftSetting { -+ let argument = switch mode { -+ case .adoption: "\(name):adoption" -+ case .mode: name -+ } -+ - return SwiftSetting( -- name: "enableExperimentalFeature", value: [name], condition: condition) -+ name: "enableExperimentalFeature", value: [argument], condition: condition) - } -``` - -For example: - -``` -SwiftSetting.enableUpcomingFeature("InternalImportsByDefault", mode: .adoption) -``` +enabled in migration, the latter will be disregarded. ### Diagnostics -Diagnostics emitted in relation to a specific feature in adoption mode must +Diagnostics emitted in relation to a specific feature in migration mode must belong to a diagnostic group named after the feature. The names of diagnostic groups can be displayed alongside diagnostic messages using `-print-diagnostic-groups` and used to associate messages with features. @@ -232,7 +171,7 @@ This proposal does not affect binary compatibility or binary interfaces. ## Implications on adoption -Entering or exiting adoption mode will affect behavior and is therefore a +Entering or exiting migration mode can affect behavior and is therefore a potentially source-breaking action. ## Future directions @@ -243,14 +182,14 @@ For some features, a source change that alters the semantics of the program is a more desirable approach to addressing an error that comes from enabling the feature. For example, programmers might want to replace cases of `any P` with `some P`. -Adoption tooling could support the option to produce source incompatible +Migration tooling could support the option to produce source incompatible fix-its in cases where the compiler can detect that a different behavior might be more beneficial. ### Applications beyond mechanical migration -Adoption mode can be extrapolated to additive features, such as -[typed `throws`][SE-0413] or [opaque parameter types][SE-0341], by providing +The concept of migration mode could be extrapolated to additive features, such +as [typed `throws`][SE-0413] or [opaque parameter types][SE-0341], by providing actionable adoption tips. Additive features are hard-enabled and become an integral part of the language as soon as they ship. @@ -259,49 +198,112 @@ model, and their metadata is kept around either to support [feature availability checks][SE-0362-feature-detection] in conditional compilation blocks or because they started off as experimental features. -Another potential direction for adoption mode is promotion of best practices. +Another feasible extension of migration mode is promotion of best practices. ### Augmented diagnostic metadata The current serialization format for diagnostics does not include information about diagnostic groups or whether a particular fix-it preserves semantics. There are several reasons why this data can be valuable for users, and why it -is essential for future tools built around adoption mode: +is essential for future tools built around migration mode: * The diagnostic group name can be used to, well, group diagnostics, as well as to communicate relationships between diagnostics and features and filter out relevant diagnostics. This can prove especially handy when multiple features are simultaneously - enabled in adoption mode, or when similar diagnostic messages are caused by + enabled in migration mode, or when similar diagnostic messages are caused by distinct features. * Exposing the purpose of a fix-it can help developers make quicker decisions when offered multiple fix-its. Furthermore, tools can take advantage of this information by favoring and auto-applying source-compatible fix-its. -### `swift adopt` +### `swift migrate` -The Swift package manager could implement an `adopt` subcommand for interactive -review and application of adoption mode output for a given set of features, +The Swift package manager could implement a `migrate` subcommand for interactive +review and application of migration mode output for a given set of features, with a command-line interface similar to `git add --patch`. ## Alternatives considered +### A distinct `-migrate` option + +This direction has a questionably balanced set of advantanges and downsides. +On one hand, it would provide an adequate foundation for invoking migration +for a language mode in addition to individual features. +On the other hand, an independent option is less discoverable, has a steeper +learning curve, and makes the necessary relationships between it and the +existing `-enable-*-feature` options harder to infer. +Perhaps more notably, a bespoke option by itself would not scale to any future +modes, setting what might be an unfortunate example for further decentralizion +of language feature control. + +### API for package manifests + +The decision around surfacing migration mode in the `PackageDescription` +library depends on whether there is a concensus on the value of enabling it as +a persistent setting as opposed to a automated procedure in the long run. + +Here is how an API change could look like for the proposed solution: + +```swift ++extension SwiftSetting { ++ @available(_PackageDescription, introduced: 6.2) ++ public enum SwiftFeatureMode { ++ case migrate ++ case on ++ } ++} +``` +```diff + public static func enableUpcomingFeature( + _ name: String, ++ mode: SwiftFeatureMode = .on, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting + + public static func enableExperimentalFeature( + _ name: String, ++ mode: SwiftFeatureMode = .on, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting +``` + +It can be argued that both Swift modules and the volume of changes required for +migration can be large enough to justify spreading the review over several +sessions, especially if migration mode gains support for parallel +[source-incompatible fix-its][#producing-source-incompatible-fix-its]. +However, we also expect higher-level migration tooling to allow for +incremental progress. + ### Naming -Perhaps the most intuitive alternative to "adoption" is "migration". -We settled on the former because there is no reason for this concept to remain -limited to upcoming features or mechanical migration. +The next candidates in line per discussions are ***adopt***, ***audit***, +***stage***, and ***preview***, respectively. +* ***preview*** and ***stage*** can both be understood as to report on the + impact of a change, but are less commonly used in the sense of code + migration. +* ***audit*** best denotes a recurrent action in this context, which we believe + is more characteristic of the static analysis domain, such as enforcing a set + of custom compile-time rules on code. +* An important reservation about ***adoption*** of source-breaking features is + that it comprises both code migration and integration. + It may be more prudent to save this term for a future add-on mode that, + unlike migration mode, implies that the feature is enabled and can be invoked + in any language mode to aid developers in making better use of new behaviors + or rules. + To illustrate, this mode could appropriately suggest switching from `any P` + to `some P` for `ExistentialAny`. ## Acknowledgements -This proposal was inspired by documents prepared by [Allan Shortlidge][Allan] -and [Holly Borla][Holly]. +This proposal was inspired by documents prepared by [Allan Shortlidge] and +[Holly Borla]. Special thanks to Holly for her guidance throughout the draft stage. -[Holly]: https://github.com/hborla -[Allan]: https://github.com/tshortli +[Holly Borla]: https://github.com/hborla +[Allan Shortlidge]: https://github.com/tshortli [SE-0192]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md [SE-0274]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0274-magic-file.md From 23ba17fccc9a0bee8f7f7b2d0a00e24ea5d436e1 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Tue, 18 Mar 2025 09:51:51 +0900 Subject: [PATCH 157/505] adjust how we check for the presence of the is... API --- proposals/NNNN-SerialExecutor-isIsolated.md | 45 +++++++------------- proposals/nnnn-is-isolated-flow.graffle | Bin 158389 -> 112899 bytes proposals/nnnn-is-isolated-flow.png | Bin 75953 -> 80747 bytes 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index d5db0285fe..03eb470d26 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -2,9 +2,12 @@ * Proposal: [SE-NNNN](...) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) -* Review Manager: -* Status: **Partial implementation** -* Implementation: https://github.com/swiftlang/swift/pull/79788 +* Review Manager: TBD +* Status: Implemented + * https://github.com/swiftlang/swift/pull/79788 + * https://github.com/swiftlang/swift/pull/79946 + +* Pitch: [[Pitch][SerialExecutor] Improved Custom SerialExecutor isolation checking](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/) * Review: TODO ## Introduction @@ -125,37 +128,15 @@ This proposal specifically adds the "if `isIsolatingCurrentContext` is available If `isIsolatingCurrentContext` is available, effectively it replaces `checkIsolated` because it does offer a sub-par error message experience and is not able to offer a warning if Swift would be asked to check the isolation but not crash upon discovering a violation. -### Enabling `isIsolatingCurrentContext` checking mode - -Similar as complex equality in `SerialExecutors` this feature must be opted into by flagging it when the `UnownedSerialExecutor` value is returned from a serial executor's `asUnownedSerialExecutor()`. - -Previously this was done by signalling the feature in the `UnownedSerialExecutor` initializer like this: - -```swift -// Existing API -public func asUnownedSerialExecutor() -> UnownedSerialExecutor { - UnownedSerialExecutor(complexEquality: self) -} -``` - -Which enables the following `isSameExclusiveExecutionContext` check, which can only be used when a "current" executor is present, and cannot be used when running code outside of a Swift concurrency task (!): +### Detecting the `isIsolatingCurrentContext` checking mode -```swift -// Existing API -public func isSameExclusiveExecutionContext(other: NaiveQueueExecutor) -> Bool { - other.secretIdentifier == self.secretIdentifier -} -``` +The `isIsolatingCurrentContext` method effectively replaces the `checkIsolated` method, because it can answer the same question _if it is implemented_. -In order to enable the runtime to call into the `isIsolatingCurrentContext` the `UnownedSerialExecutor` **must** be constructed as follows: +Some runtimes may not be able to implement a the returning `isIsolatingCurrentContext`, and they are not expected to implement the new protocol requirement. -```swift -public func asUnownedSerialExecutor() -> UnownedSerialExecutor { - UnownedSerialExecutor(hasIsIsolatingCurrentContext: self) -} -``` +The general guidance about which method to implement is to implement `isIsolatingCurrentContext` whenever possible. This method can be used by the Swift runtime in "warning mode". When running a check in this mode, the `checkIsolated` method cannot and will not be used because it would cause an unexpected crash. -This sets a flag inside the internal executor reference which makes the swift runtime call into the new `isIsolatingCurrentContext` function, rather than the other versions of isolation checking. In many ways this API is the most general of them all, and generally preferable _if_ your executor is using some kind of mechanism to track the "current" context that the Swift concurrency runtime cannot know about, e.g. like thread local values inside threads managed by your executor. +The presence of a non-default implementation of the `isIsolatingCurrentContext` protocol requirement. In other words, if there is an implementation of the requirement available _other than_ the default one provided in the concurrency library, the runtime will attempt to use this method _over_ the `checkIsolated` API. This allows for a smooth migration to the new API, and enables the use of this method in if the runtime would like issue a check that cannot cause a crash. ### Compatibility strategy for custom SerialExecutor authors @@ -194,3 +175,7 @@ It would be ideal if this method could have been bool returning initially, but d ### Deprecate `checkIsolated`? In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. + +## Changelog + +- removed the manual need to signal to the runtime that the specific executor supports the new checking mode. It is now detected by the compiler and runtime, checking for the presence of a non-default implementation of the protocol requirement. diff --git a/proposals/nnnn-is-isolated-flow.graffle b/proposals/nnnn-is-isolated-flow.graffle index cfe1fc4d456e8156a6bdda297874bcbaae83c397..b476f5ab47a94be7a4a840e9951c310ea7ba826e 100644 GIT binary patch literal 112899 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 literal 158389 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

    5e5{bPUWtNXgvR_590sfiUWZDE3L5 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 z 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

    g}9B@X5SAb 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 z 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 G-~R$m4s+!I literal 75953 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 SOs8AmpS+C9qvD6gum1-)9r!T- From 9128d2a1220398889b296a6e9912c97ad7b692f0 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Tue, 18 Mar 2025 10:00:36 +0900 Subject: [PATCH 158/505] Update isIsolated diagram to be more precise --- proposals/NNNN-SerialExecutor-isIsolated.md | 10 +++------- proposals/nnnn-is-isolated-flow.graffle | Bin 112899 -> 170172 bytes proposals/nnnn-is-isolated-flow.png | Bin 80747 -> 84498 bytes 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 03eb470d26..0125b5baf3 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -132,18 +132,16 @@ If `isIsolatingCurrentContext` is available, effectively it replaces `checkIsola The `isIsolatingCurrentContext` method effectively replaces the `checkIsolated` method, because it can answer the same question _if it is implemented_. -Some runtimes may not be able to implement a the returning `isIsolatingCurrentContext`, and they are not expected to implement the new protocol requirement. +Some runtimes may not be able to implement a the returning `isIsolatingCurrentContext`, and they are not required to implement the new protocol requirement. -The general guidance about which method to implement is to implement `isIsolatingCurrentContext` whenever possible. This method can be used by the Swift runtime in "warning mode". When running a check in this mode, the `checkIsolated` method cannot and will not be used because it would cause an unexpected crash. +The general guidance about which method to implement is to implement `isIsolatingCurrentContext` whenever possible. This method can be used by the Swift runtime in "warning mode". When running a check in this mode, the `checkIsolated` method cannot and will not be used because it would cause an unexpected crash. A runtime may still want to implement the `checkIsolated` function if it truly is unable to return a true/false response to the isolation question, but can only assert on an illegal state. This function will not be used when the runtime does not expect a potential for a crash. -The presence of a non-default implementation of the `isIsolatingCurrentContext` protocol requirement. In other words, if there is an implementation of the requirement available _other than_ the default one provided in the concurrency library, the runtime will attempt to use this method _over_ the `checkIsolated` API. This allows for a smooth migration to the new API, and enables the use of this method in if the runtime would like issue a check that cannot cause a crash. +The presence of a non-default implementation of the `isIsolatingCurrentContext` protocol witness is detected by the compiler and the runtime can detect this information in order to determine if the new function should be used for these checks. In other words, if there is an implementation of the requirement available _other than_ the default one provided in the concurrency library, the runtime will attempt to use this method _over_ the `checkIsolated` API. This allows for a smooth migration to the new API, and enables the use of this method in if the runtime would like issue a check that cannot cause a crash. ### Compatibility strategy for custom SerialExecutor authors New executor implementations should prioritize implementing `isIsolatingCurrentContext` when available, using an appropriate `#if swift(>=...)` check to ensure compatibility. Otherwise, they should fall back to implementing the crashing version of this API: `checkIsolated()`. -While the relationship between `isIsolatingCurrentContext` and `checkIsolated` is not ideal, the boolean-returning version was previously not possible to implement due to runtime restrictions which we have manage to resolve, and thus would like to introduce the better API and better user-experience. - For authors of custom serial executors, adopting this feature is an incremental process and they can adopt it at their own pace, properly guarding the new feature with necessary availability guards. This feature requires a new version of the Swift concurrency runtime which is aware of this new mode and therefore able to call into the new checking function, therefore libraries should implement and adopt it, however it will only manifest itself when the code is used with a new enough concurrency runtime As a result, this change should cause little to no disruption to Swift concurrency users, while providing an improved error reporting experience if using executors which adopt this feature. @@ -170,8 +168,6 @@ If we determine that there are significant good use-cases for this method to be This would be ideal, however also problematic since changing a protocol requirements signature would be ABI breaking. -It would be ideal if this method could have been bool returning initially, but due to some restrictions back then it would not have been implementable the to what concurrency integrations were available to Swift. - ### Deprecate `checkIsolated`? In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. diff --git a/proposals/nnnn-is-isolated-flow.graffle b/proposals/nnnn-is-isolated-flow.graffle index b476f5ab47a94be7a4a840e9951c310ea7ba826e..9215bacf9e3508f078ca6b7837a01ee2c143568a 100644 GIT binary patch literal 170172 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 literal 112899 zcmV)dK&QV@O9KQH000080IW@NTD9_h+CMD-0RDUc015yA0AyiwVJ>iNX>)Y#eF=0E zRon2rlcpOK(w(J1pk?b4CYeblp_J|`-J9+yB~7MDXquEPEu~fw5fxMv6+zr6pt1;x z%A$yfxV<9EjtUC;DuSq>;s(n9%uHHZD2m^A)N{VS(=*B4<}T0vJoipo*JQOgT_pL5 zM2;{bkO+ApG4e(}$QSt`f7B24M*(O68i*t)5Cx%N6oNug7z#&&&|owK4Mh=X7#fa7 zASoJ&MxjU)g+`+>Xe=6s#-nHygJMw}lA#HRL~^7+*(itq%Y(ZB6~bpZq^nRh(jg0S zz@G)V`BXD%K{NTbZRiI0yb;|Dr8&@&`@036nu~6Ql4}0u{tA$#ve03%xw38b_F73u zrbFLkPO}@_jjYX8#yXr9yRB9-(CuWC9j-dN-eGi3VOwh@fd+eHlY@0S3v6i?X9JYg zlsegTo6F*03-u`>pH{k$jr{@ zr8K87lP{H+U5!?LsIJE)!UBZ3rRiO44YvSzrcv+W8-(=eDNCD|D=f+2V4-!1#b&ay zg=xa5gG>&6eZ7_KL`7FOQyY0;lv|80Gi0j)Jo$DP55a2a$5>#qwsP2D`L!iO5#)5K z+z_5=)k=n1YzC{_$foEG4JHSG%E+VLV&M809xSoU60nj1Yv7i6B_LAr3i*k4_LXn9 z@pJ^M$kn$3X879BJbN?C%|ACZ^`;O*YomiI|!KhXt18$pIjRDHOT&R*S2Z z?`H^4OvzS@$;S28otkucfJxR-VrID>g|91Nt+SzO$L4*&Bsy2Z~3NN)2`+Ypj)2q$Im$8MAV%mF04htw^y} zWoOxw>7taP?2>eIvbms?RLbkhbF2naD&&m?rSd9sT~?Vj8R}Ehm0GPLXGT?dKAD_d zo}OGX1KMQFw6>&XcA&{9v9#W5*Sm`4YHrNrzk9R}l!nr^PFOtvwoN6M%QW0YQ3_hY zXc$ebl+h^KJxwR0tYVs!NPK;LODfY#d}}4)Q|vZ}-Y6a0;IcdIW2Jd|tG>nAU|Eie z_Mu`_g0!f#)Y+sruv(+urLUEY)3AD0Pio|HqgrEBQ7ollHOhJgtB}i8P-S3PvaU`e zXA1)RXCc%-3uKR-kRa4(b2*ALQ=}D@RZ^clpfCJDSI8048=OsfB^g=-S9W@;)CrAH zkL$-npkLtHAD2}qm7>3P1sa+hE`)F)q$wb21El9d+S=l3;>yoLI;5_FOA}sP+5r=U z^dK&664J4J8zG&YWIA_220kD32WxBAP%-t0J2K1QK{k-GI=*Z{bA*GUL0

    zy&HK2_d_Dxqfmpp@RsXWhB(eEA8}Hkd;Y>#_ew0}KAaX4|6FRZR%&oNnuR)!Ey1$% z2TL*pEXUzsDUJinPyyN{9`s5&Zx3owC7Oy1$c!4ns%rte?`AX)EkO662hc<4F|-n` zM(fc=v>9zfuc9~5JLr9M5PgJ>qtDS-=q&mXUBDRo-~b$q2jdZVG>*Xvtj3dZI?lz# zxDrppCTzoQd;`7(FTjiNLwGq}ji1F^@vHc4ycd6fPvBGdJNzplBKi{{#4utEF@aDM z$;1>wOVki1Vg@mbm`mJEEFn6Gb;Ks(RpK4uAaR`dia0MqqJE+<(MVC8NG(bg6^N=t z^&*GpM$vrHVo`@^z34^Jo1*=q=NlkB`q_pBSG6p8_AfkIQGC&r+XtKCk%f^ZDH8 zXWxFlBYYLU8NOA%Hs3kEi+$JlZui~id(!uUpTuvp-$cIxKcio(-$K8YelPmH=l8ka z1^+<*vHl7ETL0<(H~TN~U+@3A|55+%`}ONLs-LD`Q9nz++5MLEd#2x8{Z91zrGHTW z=>Dnwb^YD_@9zI({~i55=>L5{K){%Qq=2dbSHRr?s{>vO_&DI_0l@=g1F{Dg2i!DZ z*?>(0_6_)Epx?mJ1Cs|%9XM;?;(^Z%d~e_xiJxSQBvqo9+$dQl*(y0KIUg7tC=VAVL4O$WOTF_^~qTtBj)L=vKEx{{;Ul0B~#5-hcNOs8d zkOd)6hwKSC8yXZ!hn9uT3|$uba_I3eQP`NU>@aKC!my2Dhr)gh9~Pb*&W7I+zCL_k z_)mj|4oVut4w^q`!=QtMejO|woIbc=@V$dK4?Z@;Ye@8vq9H9q9v$-fkTXL=hQ<#y z44pr8d5-Y z`y+Qoo{bt2l^1nG)Y_;INBfOdk2a5faP*s_e;PA(O!=7G#%vz*<=8=Ev&YUFyLRl+ zaRK8J$ITemG48;4@A2yK4dWjf|9&(Pt&BEDFN=OJhKNzcSYjTD*&8d4)x_FjJ7N#V z^^Z%AYmQqRcS05>%azTMZI*pAA!rRFPmM|(opRhdP_+;tiX_FtH zd^~YvqCT-B@zbQpBxBMONhg!XCr?jam;6l%nc_%!A?2skiK*?WJJLjHnQ8OW_M``; zm!?0I{&B{r3{%G1jI)`_%(l!OS>miIS@&ig&K{O+$X=a&HiyY+&)GGl|CEv`4^8s2-qHNg`L_Jc1*jmq;J$)mg<}h66uwmCT~t`KtmunkdGQU!ZKbK4VF>JY+dHJ!|@7(|>9x zXn3;WlC|8rq0zT-TH{t*kgdVC%Rbyb)4sPUrfFW&@fj0mJTT*|V~XPmCwA62x41&U znA+_g=f2f_qIq)jvgV&#%37YA89386b9ZZW>m98pXJyP<)#lY^Xxn+i$Qy3H;Y53K z`|=y{jdeHfyeaagxi@`2J9G9^H~Zh*aPzx!$T^GV{BTS8EicX;Hh1>i&u-1Ub?v+X z^BnUI-xhz{W4C+VZn=HW9n>95@A!SbasGc6kP8+sxOk`G&i~vcziY`|m+r2=d(T4E z!bk7%zQ=aYp?eeWeQHtQqFIYRyD#s)P4`RhpMU=k57a*J_F{VRV-Na2=zj3{lH4U* zmPReTXX(X<%nu!0ma=Ta!x0bP@$gTN7$4d9XwswW9~<`Ag2#S+-17L5<(bPjb&Tm) zyuy1$^NKH4maTkqm3r0cCx$$+;ECU!v^{zJsp6-0t!7rQUK6oq;aXy?d+n)px^?eA zo%ZyW^>OQ$ZwTA4;2HFc`6Zol-(tXIzOXxee+Rnx1V?X2DT z(Q6g29oSX0YtQRbUVrP2j5l6;Gx^O|-b#3D+uIZ0-ufT)e>T6PdS}yadu6_P=o;`@lN~^AGMlRC?&hVcp^5M~p|l{J{Fb zxeuE^yztTNqvE6Uk4cU#{y5^}j!(vavf;Su_{%5KPVD})U8iUn;)bb}Hl4`=_f(F@~;3F8zk-1hf;hKw+Svu#E$yeFyrbAAG{QPPqrEP6-a#Ai+sTCRp|3Nb}9V=C+ zR5FI9G^B$2peRPs9xH9rkQy1IRFN9bhnfQakOP*QQInnzjl8{`^CjCTnpVe3)!cIm zk|txNa)nCM-o6~!SD+>|134;E^|ofcQ!0;4{57Fz#bN)1$i%aP&E_Zh5&BS&3S}Hg z#mUuDlAK5@Co1I97!ocCmWW1i?R(|=t;B%RiUkLx1iV2KCmedfPH9z)FJd4lv<$W zP3XT+zDif%c3CYpw#3zHWvi0iE_qIa?!{;PO;(OO(w z$R+TqkW;N>VE0~2i*qZA?Jazyr%VVWRj1m)jkF0xS^P*9nGTDQqrMuUt^}M2uG*I^fsGHDR(FdB0aQ|~dRv3cDQpOXdPhZX|V2} zN1KbY)5=mfxH?ODKx(z%GMA=W^-iaUSHN4ADY_Vgq?lM~oJvW_G+it}Y1DF#=qXYm zmuZx8h1~O@0=81nif+8d@xwl}0X>7BMbDKv&3cd?WlopF-oWk!XQR3_&7p5`^2xpE z1+=MFGKiZ{vej-g73y8)OlxbCIoW0~+Z|;FmW$QaN=AFQzQn9=Vx2MpkXI2*L7!|G6L-F`>3eya{a&xE0?jvxY@i?-+9P|O6b9I7D z>deQ!ChC!=uE<+<_00e9#PJ^a^H=0AUXlOpihPSk>D@g)^NPG`V$Xb7e9wH8C*KJR zEv(H5w+rsMaNiI2O1Phgdl%dX;QlY%KfvupAQVCfeQ^j*-sQ9E7$mtE8isPh^}qEb`hXiA+Dm#kJQ<7iTuEKdf0r&6iTx!x?G6@44rGfsg$eNE`h z1GDUg@82(7y42Z@qaQE$800AsLpsW{cnPGNJn1AzPxGV+DMFJ(p7xMl*V!J@+dSz& zNT2njgCPCBCmjsw)4sLqa;slg2v$Je~dQ5a^rl2hxvsj`hAL$O6}L^x{GE z6557dM%&RVpzfx_{TiBH*|qVd<$_0AZfiiB57td7FT8#Ie9L+HFO~c4M{l4v(Oaku zy^S2)hLCpa_!2QVS>5_|jjS41@nJ7JYko~90Ml*`^!5hd75&LD*6Jq{`*zXTKz zYfSbu+Ux75b=d8$+4zZm{lkY1A6*({b6c$k0|pF~1O^3%gof$zOSo{V-3AicS(;x` zoSDKG!Q{Dlg8~hLELZ^c#><6eQ3g)yWRp_EIVzsXttMRKwtR0FMQq?KL1}n*!w*C!smVA^Sz^B@t823X3e;srcJ=C5^$L!lRS2vZ&h2ILam9FD&_6fZE^)k#Y)wbqWuUu zjE=x4AHq0CVWf}ICt#eMfX`21W}l#HaQtlCk+l-GN$(KOky-i3X1dK}v9X=i;BT?H ztj**yLy5uSFm!)_&*xdVvz{)U5Es?z9VXTVZCx$)Cd=iv<;gZnqu#|vcCMquXm>>> zzP)tmbZ6 zfU9L{QcZSV0DhI6lqtC=sZuSMY1DLA9i@(y(khu+qts|rq=sUY?d@g7EO$a}KRUz5 zO20NXxmt^G1FxVe8h)c0sjq&aNZ92}eaX^>xItOc1D3v;sgJo@8 zqR#4O;hV1@g<_H~B>4xUb?i)VU5%`?&MbPoGyb9w$QYHL%H8ktI^&?r?Z zicu>WwJKK1C>a?E1Wap46_`tEImK^ysb$^hUCz*4>|ZUTX-1<_lLD1_BLBamOP49w zLtPjHb?N?T>iYkNZfy4U{pcwy!d_U6EZAFDY!^0+xFgyXg?18Jbq9Gzvzcq4^CW zTBd|Gc3w&)buA*n{c!)QiDUo}NlhP-{7ppC$~wEKL;_S2D6vE)?maP;Q@fJshj9qd zz#1Hi!=Oz#9)u(CFgzNM#S%=H71}K}ms6|NTddW&b`!wP%5B$GWY~pQL{{LzcnBU^ zD;d`Yi;}^u0!=5EGYS>ArLLqkGKEIYFr-Qi^rBEv?Nx0`l>%zOY~hk}(4cCjy_yqE z9!=-bj(9j8fu-Gu1&_p|a3sp9%wqM%WQW7vQkKh_^oG{z4A7vgP~^K8Rxw7By%&$e z<11Jz|F(g11&+oOuwoyM!Lc|F%SxNLb(MRn|HACc@(Rk*wFN>)B$jtuO<8VsepeMG zRC!jnA1kp6Ggyr$;e=A&eAIFf)N;Gd`>+O2#PR4o;dpsbi`HaPC@Q;%H8RO#2=>Og ziNLu@z`3cwx#_^USv==zWSr5_d2y!|Vx<&C$>efUMZ+>E4MS@be@(pOWSnv}=ce_E z_kTvbX8_}7N=%W7pESykbBt>~fy;d>^SfSUdO1?r#GwpwYUpO`_ zT8WFX7MI})fj3I9?D{4nG%v;SKbV!!rX0&JPfsYS~E4|sl~}9 zS-trvcn;{VTR?x!1O0V7=&uDH_k`-H!GJ1hwMHgaacBCtnW-5@^%wQmTzu=*`s=nn z{q@i2uRB10&6m_hCT>Zjr*ZmgT5sfV7m&l2u$U(Yl?t2=iUPNTgj>## zAQ>1HDFY`}LxQ*fcNKh&zvzf8#P?iH4vYF6k$=b$xgY4^0ZBz<;*s&gczdS&N)5UM zFT;=E4*V3ppVOdA@k5;Q0R;}iU(-bk3hu>DS|y_>nxQl_#p!cE^0k_RRsnNB4Z=jt zsN`TR(7XnHSW?-kK_A7B;m5C~L05F(mG}uk8?F*G=ygs=c;-n#gI?#%IyLC(YiiJk z@mjnNZ{##+8t@6NmMP_ONv+ykLo|Ao-75c&PH`0)RAwAXb* zd}owb2o94{safxo3az9TXSUN0Fb0TwUdOl`Bjy_?_G)&$1bTKG=-F35&%O$Jb{DT_ z<%+A#E)}T+t6Tx*w?;{;RBE;IFPdF17QS)J-<|9DO9|1KV18P2AD=BPiQz(=& zTEh(qpP=oymw{+TE(3CvtCcE^643EieTWb6hgTEx(LQ4SXNdV@Am&dbIbbtJ*tpGO z$&{;OV4vd8@mKf^K8L@t~Ylz$8Bcll%fqasim+cfqyl#cE&}N(O99YiN}MW=T=J z$d@xp85o#dY{KmZU4u)0!arZlCBFif%;@8izllrSHhr_+V%67K*;uLFAvHMkPBUxl zVx5b?I=@LWA`?H`c!77fGP_xl1R^j&5WeV~B%Ke%aqm$oXmB7Hnl}WvVj61|4v z2od1}4g}%VEfhzH3GY91APB#{DBQmhg(Lc*(?ow%O$M0?DKzDQ^E) zBUh@q*Zyd=T*iQ;peVImu7Mf<#jpzzKn%D_HV~4&u**Lab|He0g$R};MkbyZv3oWr z2a>J`yAWZ-U}7jCCB_gzpgxIkVo@4lmcKi|(wlgsKs?eQ9vKji8W4|@1pk6j$>d5(*>&De$(c?-TPl!v8j>P89mzWw za#}7^s+can`r6V_NvN)tj%vVqV;|Q4Caia}n;a}WX1i=P5fedL#!FNnEe~AcPs=df zWx`}4kw_vkz-m&~N>puaz~wRx33fEa9k%SyQVTee&Sn zkO$cy4{|^r9G6otG9^V)8b(dQWWam|#iSr*l$vC~QUb-GW<0;AaQ)`e z6e9O(fso&4F8xF1QXvR{BFT`*#G~&7@8AT$`0fHgOOz62LYXl4`p9F)Gi#y9^Zad zJc_6$rV>ViC8iS%L?LHT>xh~^jYkb`Q)$3(l?#3~O5Su3um@D_^J(q+}B@<7z4C1Rk2xCnf(rDH*Ht_q?|t zO#p7;-chhSr1tvGw;7}^y|bZ9l)6EbHcR|Ll&;yv2X8}qqnTEqnOQ(H?Lad(0nNuey0nhUN>I8oSO*|V&YcfclJdW{ zwL{D!Zo8Tu?&#av`A4>PP&Samg2=>=i#PIz!ve2Xq<0hd5)Tqfh)0OWP&TJX7ZUgM zqWUPgQYP0ZIS;G-Pc$Q^OBZzz_Yn^WI`aNrb!qnwg?5WMUHZp8^NP}=PL~o75zDTj zPKie)*VyOm{<7anqJvmLtm1-CWLuk>l&Kgc;~AAyb${890!6A)$VtHf?X)dd_Mqt} zfTp+i*_QvZZ7FC=r_`)(W~CkrllvbkR(58mJ=s~z&Jh0dMQ3?pFJ|Ub#9HE6;yGdq zv6Yz3amQ+6&7X3|&^DkPnaV>yJ!?7USl2;3O>7W|e*JYa$1@yr{9(sH^&2JPPVRV~ zc!Ah-P44KOH?Cg(HsTfHb>a=;9bz}(=9d35vHf~qc=*FbabVcdLA*-5CM<8~UwU_e z*ww43xDp(Xb^_x~;w|Fszxd+8)xda<*hd^8J|I3OJ|RwUz<8h7%i-jTS%4f-lDrsc zzrH1Lu-M;093Tz}i#y1{;*Yu&njPj~a9#cLi}ZlvL*gUi=(Rwxs&`OG{JMMRj}o5| z|0TZYO=>FCsxAavQ)+(RLu#G`scGx81pX#@*yTqgBy{=R-OoA_8;MiIY2qx0Oj%o- zQm&9GJHx0~AhY)f>sQ3LT!i(^w4xT`d*TP;M-I)*6+A1a z=_>`sHCgw34;=mkI9%3e@cg^GEc_26cUm-DVBoSf)13fT5x)?>5*IlFm~aIFDCJ#> z<(i1U&;#+m0pe%(G4J1mQj1e+Y_;hdxp%^?t&rt{qpVTtvUmGoiXPY{E{Tu`i$v(0 zB<^YkzgD=s7d(rI?syh?0iHMYG5Ehq4dX2Jm$y>KUllwzm{~(ZwueNz1ACWJAhM0R7l%YWB1Cfvls&hk?JK`Z%k}|pAY0zC~)p~u)hd>_V zQq)h>UleeSGbbWRhbT}K%-gP_AkM_S_V_}h5aF!Jbx!2EULO_>5)Bnah(?OW5)(N% z3>FQkl?-pAz^f7%fuR*LilNn%LPcwo8aYL^_iS(t5Of~95e*X!7mc_U2u5{?B1NNx z)kSe2_>-Z9mSZ?L{K*`8UwzLr>34{tMH56C(PSL4QWPVK6~&2Q3PE7?se2yvsS=7* zH213#l!6hG9KyiMxYoIK5xG(%7f~Xmh!Li(z`ge_)YAM9Idl#ql&QF~uJMF2wXnf* zt${niK2a1ensoiA-F=ZS|C3>7F#)6zg_Cd@uEmXb7G8)S!E5klyb~Y7X9$A-{VNrb zN7NDR#GS+vVkMZ&uMo$GGsJly_wk}+QK4w6Xol!+(K1noXshTA(NWPU(GQ~Eyu@BZ zycn+%FTGc**F3L9UXOY`?X}Tsi#S+3NIYCTQana{vv{6(f%qQrI`OmOP2#QMm&Dt| zFN?Q}cZy#V9}^!JpAvs7{=s`hP(zS4XhzUOK`Vk*1w9qCH|VRNpMt%D1A;??BZJ2W z)4`L2rv&E*&kmjwd`s}$;G@Am2VV#wLi&Y-gbWKA9wH5y6f!v^DI`54BP250 zge9UOqA|iA(Gt-b(H3oqZj5e@Zi$`~eRuSR=vSlnL?4g-F8WeT|Cr%1V`3)6P%)EY z(qqbFHpc9aITCX$=JVK?SVe4NY+7t~Y<_G>Y(;E+tU0zl_NLgUV>iZbj@==fD_bpF zKY^IgZ-Qh(=!D_qjpPDy3AvnHL9Qd$ll$dku%+Z7)vK2@Al ze6P4ji6|MRq0*>As)nkgOjHv!i@KS*i@KY-k9vT5h+09dp`N3*Qm;~HsPCzZv=2Ri z4yQ-a6KEwpkxrzu=zO}6E~RT}Gkq6*f<8@uOaDOsrm9g*S6NkVRf}qg>Jilws@ zHxlBw)tj~BeV|T{kjPEmk&iF0UJ2NnI zNTwt$T8R;)arU zOTN>lYxA`w+6t|{bYJNwr6)>Hm!2uZWumf4W$9%(Wz}WIvc@t;SzGzB3ZkN{qPD_V zVX1Ib?yo#v`Dx`>m0wp8RbExeRT))Ns%iDSEvKaLD#IiN%yGkN!@F@w{!<} zAL>5QeW^R8`$l)6#;az0%?&lT*37S2ShJ*dcx_B=T&=2BU0YN8Ozqa%?X|Df?$*cY zC+a8Z)AgBptA2<6ZT%koe*ICyBty2L*q}AI4YLeO4O5Wl zjWQ!+R2vhFiN;)Gsd2jT5o3q(N#is1j{5uRm(*{rKUn`^{U`NbntV(Wlgvb!l%^C@ zrYYA{YAQ2To6M#erbVU)O)r~{nogL$FnwzdH4ir@m{ZIJX05r>TxT|z&1SdxM)PCl zmFAu1FU?<@zcXL347QB2WLfeoRhC+d(b8zKS)7*HmOCs9ERS3ETaH+cS-xnfXlQJB zwBgBybqy~!ywUJp!-0lljfsug#=9HuYh2Q}+@54FwclpH(|)i0p&7$xP&1S>>@!?5 zT4&60PI6W{r#fdjS2@=>H#@gEUv>V+`Hu5_=RxPk&R<<3m&_IKN^^l7>$=VLl_B(yIk+O_PF-Dj<`;^33oqttXtzwaaX&I?pF6)_d@qt_cQLT?w#(#?&I#S+&{Q4 zHTyP4HOre-&GF4?&FRg>&DEYCrS$xV1W|I&AEj*8{XbAk0|XQR000O8tW9!S@7S>w z>WTpX@sk1o3;+NCaB^jKX=QgVYH(#|?0g4UQ_r^VhJYx=NJol6K~WKqu7U(bnusV$ z7ekd!K%_}XKm?=g^-fP{{SfE4L1L6H_o6vCFY7tcNS+;`78-*?Nq-#Om* zcak4j?98mJnOU=Dt=Ti1ImVm=cAYgaHUQYz0Kka#0+@I}S3kt#8UUD@0*3(r*bcD8 zdH@_Oij@Tr2Yx2@eD;66vK`2W{432_`SVLAfnCyAPY-dy+|0oEoc^C!v-3Lo`Fa1$ z=Hq+gy1C(LX=@u>X|5#z0tf(HtgE?hYGlf%D${`*83`I7{|kit)1eniNh|~Xd-R=LPeY^vm|185#>3Lm! zEiSP>MOcso&H(zrIo3-WumDs6H9#3q2dr3a^!LlC{i%!|fCT)2P~bY?0k{F~zztUE zQ>-g~fH&aEqKyGxz!^{kj<9GI;3x~~Kim4R+wkA6Az8hyHO=ZH(SN(yO!?O5X9 z{f9y@+Q?~J~Ip^@>~OP4JytytA_c5%Jt=I-Gca3e4%I3)CD z)a~e)*gJ9YY4`3wNY8kfnN?WyxcEuQ(`U~stEy{i>t4OCZ*6Pu=l>6!@WmEh4Li-%tKowLjJDKUc9^|E-$+ zrDFe9uSu2?vi~VTSZ_`U1j4zEla;n@-}WQ`=_+?XM+AE{ba(%;=sYd z!Nq#-;@QEo>%W|s(=5{y!JGhiA#5yVg75=yfKDrnKM4HB9~Kbihu=Ez2M2^X@LLD| z;D9g(f9t>>91!NvZyor91Hv5stpk5>K$stY>%boz5a!5l9r%L-!W{jr1AlP*((41* zzLe;hU0@rz-yBRKc=abW9V88l!;>2I3vI?cQazj|Bu;7&3nQ)iE7MP(b`ZGoW%mlA zaD&VQRs)!TG$H{`xrB0N0wvq>IhjC=8(7Q)429=YsGEgM;9GqPcnuSeSognrj0xaw zDlq~17b{x_A)lasbN%VxDcyuCjL^~j&Gt9j-)w)g{iWD`U$Z7{cI4f{i8J`dO~_I0 zSCt1*u4OYz85HqGTjbpjUB%PWdoTI8@x%z6DbZ@MTHKF{r0O$)Zg2V{_^S6XX1xQ0 zKzv}+7rO9A0oSj*NQzBi0?v6q*l9LQpfY4D_cJxlmsS_HcmZ;85?J*^in*d3HJ||?4Jqf zue{*;U(=_mz#QA2Qv+)?)5h_(9v@5sR1Y3G&Af#t5VKk{j?dDP)u8OC~x|<)v89@9mCv@3@B8 zUDuTPl7!poH7HN|eu-X#R$GEqZmtqB&SmZlzK=RbW<1j;O5(q+$}su{ohuvN@0OK% z?zK#{JMKDp+sQv|Wn*@gOn^^x_7iHFqUOzZFXl-wL{`L6_Y4WdJ@PzqFW;o>-m2X6MEg`Czn*r(VLW3(y@#Bl&v=MS`f}&XCzgNS9|1Rd zifu>6V?;5&DYp^a2f!7w;5_nnqZU?QQnLiVTJQSsZfPHG@zyoxprONc2TO0lX8h~l zyqL!k4XLN4f+;R9K|YZjWH`CbxS>9`|6-!CkK{cYTT|W?>1`L%^V~zN_x9YL2zYdX zYdKsPBoh#ExVkT`$dnlg`Xi*a2YzjjCqiiTK(_J6uQ!T^<_8{ED=17QapJZ<$8Vo1 zY>-;LoOaaWjT>IGeRd)kpF#|Cq^i-v$kDOw_DUVOuspk=KocJo1;sEAg-?O*S;vkR z`%5GT3*O%w`@WiuQqr=Pgoc1$3OyNn!Ek@|-t@TV)9#}R+6p^F)5CZR^sZkP!fyzi4?ZPozBh3UO4DvW z+6;RkoL%NQV!JIRynOkH<?S|YLPQbDsRG6gHi4aGynTTGC5A4wj>%R8pHFvL@kQLWE%V;}ZF=(dUmqqA(bU&ins(lvLO+Ag`0W;_M zV1zTd>;n^FFhTbZ9UP(+_O?9>GG(~0!3L9;S7GvTLRAjp0Cfk>8+I#!^rCrocM@@y zCIjbJ54myjfLSFxYqP3b+o;m;qiA4brgIl$q^SV=r4sqWP-!)ZWp-3en84t)E$%GN z4afRl0LuhCFp0RTlun5;tP)LKO}r~+!APb~b&waK{(@>?3 zwWM4K2zvrzEXeEMPaz3DoM9eQdInSo3<)BGf0}z4Nd8)*qw1xR+_891WCr!!Q8+;O!M3$kEp#*^0WEiDz zur%-mmi=8q!HW2myImdxqw*Ywn!AQP$_c6}J0zSOCHC&Hl!dGZHD+|d#A#fl?*y($ z^lmUKv~W~M#w2Xp-PG1WgEfaZ*;Yfz10wpJH%Gq&juf!Wneq^tUz51kf8K1T=@CoV zWEvlz6%LM4xlxFLvWdRg_NtIVw>sxn zE!shpiYxjJNv+3Ihc&j%sYbHKUP*H#!#h4KHfasu+}2_kVwnmzrp>G>s+(SoOnRuC$9W?a_VFG) zdLi1eO)_;ZcQ=Tqo<oy_F{SsZ3+nySdw~#~|rX8y%^J z=#P02Z5bbOTL*kMjg!1@aKywT5X-qV>vYRqVIk01p!KV$$CI>^^ZQ#MoDqK8rC~LJ zpPDpSbAwqd6X4h8BQ>-K^zL~>7BLyCzMU+Rrs<=jmWEXB+7TVd>aKPsAcXNyN@N0J ztU^di2t7?*o{w#BW1iEuy~X6E_s8LN;r?C; zB++&R1a4i;_SR&^fRy-uQISXA` zWxuE+lwp!g^z{*XaL4}YyC+5y_OC6kZr^)HHwZh1tC%GU!-<+C+tIFx+K2T@caA72 z-pIMutr_a)DdLK1*+a1Nk|~NXmT&M-NNR_SqLonAB)4WJ5NkWy0fkMgmnRf-EEs=& z8d@CWklMyA&`|u~?U^eP#=E6ml6%^=s=Ovda>~^obY=xgxcl;z5uRUZS;)s6cC`$& z5!AY}O?sEETp8LQJ(2M(JM2c0&mS#POv!SV}#FGgfZi;G_W^H(i*I>|RK zKH$)LD*u@apcfY6j^I3yiL*7a5lts)QuJIj&&ti9XQkkf{%gCHUh__6o@re%6Lin6 zZR&CS#r#h$-xZ2ow0lmorkCMd*5WbHRh)Z@$Pz{nEk!%?ao>k*^O_-W+|Au-$#kWzzQ zzsm+F9-9|pqbBL2ub|xNMNO(6tnrUhpdJL}yRJ&HESVb1VYBnhRUqfqNGeat7F(*M zYur<5cg@mU_~9lk0~{4j(ws{nddy?Dp?roJY$z1DE|#%x!nojy*A_g!QD?82h89Pt zVp%z{EVC&2qU3cWjd`}4wd9wOjRQ@_uv%=3!6>c*vdk`qLTE;oV<(39Kgg}yrR9`s z=y&FN<^5!ROY_+<_k|`S@Z!ALtpyd(CNRQ`Z1{q&d z1#Dt7)LaeU8%qjYzs^SWC*PYlY)gqib2fkpWD`q!8T}g9JIa=6HYI*%^?2QRw3DKu zA^AuA@>A#FTucC|6bTojVYpf+g-5iN2nmZ5UJ^>XJo-!Cta}#s*roNA-RF#ODs9U@ zcI-0)76NITtqpF$j<3ucw%bwb-jE6>ypnui_kFN6M*L2x&T*^| zSoXAp=t@PR)Jb)%2{JkvR2|R3WgR*49%T-z{qv5+txTYE^@I1_ou3;F+9S}F7xjez z7TCUV5k;B6{wj(e6R4=V$OMLj>ERfJGSF<#YT(N8e&x=afq9%&S=dG(gM0 zwkB~KFHEi5EyjLy4{Qg`juh3L6cx+tn9-lF=*!j`>nEsdz z?z($E^cdJi+JYspia3+rg?2m#Ul=tFaeVUKRWqz0(49=(9p&64|6OJdLzE+rQf`9q zVn+X-V<6kSLO>S-TIVBg@@mi?ZzJhnV>bnZvIDUs(YQ4B}}%^qta} z)tp&EqbXH_W(ew&*V;yBq=r$hs1LtSRdb0i;xt-I*<-tRmG`N9LIgmTzA-?S58$BQUF2PUkI(!KB3?tddMurm1 zZb4(3cB6D(fnG0aT8$>kYVHRQim}&sZ%;N%RHQe@^6ox+>o9h8gQV1otIBB2k;5Zy z7pH&Yfyj=EW{7=XQ~WB{I4Y1zJJ$sS)SNCquc`}EW4uN4kW*qX?y!kqTk@W0OtHrn z6Nn=!s!e7$csRsRgp(Zx?cOenT;9FgMV2?&>&sG;I4wM-174@T)>bBQc`y(sa)9N~ zZU4L!V|NPkX>uwd@8y+a`l+qTx&svxtBq0d^e9%}KeEx@fw#v{oSQ&LQW3?3tVOd4 z7rj=21*7yQq#I(C_Y*s6J`br?UU_H1=;t*`?r64{_t?s4nNUhW`OGVgUFr~FaFTas zy3W0ku^v({3V&h-rJ!o-ecs#+yH|b3=~bGD25~P!*+?347w*dH{r>*Mt32eGXDm;O zgPuq8c(Q1B(f-=Ym1w&`~7nI-g3s#5a7 zdvhz$m|4yyu8@XSxQMz&ZOq!mk?K^D*y5vss_*LrzZ%Q9^6q+@(DIhI8M4)-51@Cm zMnG~2er2R=E}xduyWz3t|W&IbqK{X2(b2-W4?_Z%nho9%|!M4nA-> zZ9jaF_wghCt2L~aSE(hZw5;s{1u4(L3jkR+o(Z&QDnDz_Q1;RoqQ~9eXgEn(L_nPl+%)}$|$5%(r98v7rNvwm!36RhQEB_n$cr@P1+ z=6MrV?HQJNyVcirqKERTR+)e>L(~lEJtI0o(<+oQxmbD4Y&|>dHAkUQ)gi63YAC>u zn%w^oEzEce=WjZM5~LT>1m|Y?Rxmr!dqP@GPkd?K;)UzCkQ{79e}QpZ6GOR@6|v=4Oz>VkClxl5WEZJp zlc&VePH~)lZgqU;MYJXNJH24m} zSnNqY<>(cZ?GTjs_IV-vo@cJXAQ#bxHD&?}Q1W0V)ezI71EcsLW3Nh+Fv(3KPqO{p zn`B;Uh@9vczH~)7zR$)6)$GVyZhiQL@t*TTul&Vl^5&3YA)Y;~u!S4$BteuRy!md| zrnR!gqmQ55rr30&H+Z2SO`)N&vQ?)`j?HfKTRcF!Pwu~^BZq#At1geFo(WNH*38u= z8C2orm3UURFww+wbvJL+Uq4e}>g8_z`nD|pbM`Tdsq*Gkh0c{d$H4)rA!8B_Fl20L z(qzPKh6H#v-1eAKV2*~7oa&W{6rHe#Lm{=%72Kx>HDveJR_uL%adXdS$4TOx`yt>0 zbSY8OB!uASkLov}V57{)$%O4@C=8ru(b61$Hx{ytoY3AnFuqkAhu zB-%zMP&YBr)$%9B=R&G1(+rXxUFqOC>m2#yj1#K#Fs*iW)k)ccd08)4#quV5qcfn|{1%2$teSx@)coj?#YsPO+nXn>krZ~~D zOu$Vk5wo+A^Tl#~1*xwj)E}Rn9bEOX>HW&#nU+uIgc$?8uH!#^c=gIK) zyvcb2SL+(UnljwtQP4Rk7Z^XmCH4+fQlWLxV}9&>@^O=kczK2>lCOcnus$uVuEX zs|y(~nkT^$GRJHldW(j9(T{bvU5GADvL$q5#k$p#+I5^l-ODF0X2ux3<&|7rRD+LO zbua-bRuM!JB@5OnB|rBrqkleVTKmplkk=&k z3bFkV4W+uGhcae&l%fSe*ql;gH7@De2;Xt6?|QK~Url?MQ`pD)`wu5H*fO;{_+z9+ zU3dGYP-;k{oq2qom?~(89m{?6#0hRF#ngT4Az(nmBl;b~qk@yVm8P7fXCE4*9p|P! z&-dXqIEDQveh@-NQlddq3C4#LP@+GfKeE200~R}TlGJ-&yfc!XD>u3>K^8ZbOmV~= zI1^`iNHmDQvHAUW(@7W`S}+7dU;-V}&Xy$D>ISrh2}F|?MYpamXU(LI=twub8O~4t z*!w)R!yInv+Iy zk=4DHGak7i2~)Q?j;T1@Ew@m9qj#&MUq`@{Y=*a5b)(vYqw^`TiZls=lE8BPMoTh< z>(+6_ny|n+sP|WmUjA3v-q#J@Cv}eO!`+Z?MxR7+4&mH+Fx+5R$BF8@Ay#KT;y>0X z96lDMSnhMmD=hT!5$@(n)Yk$#H1NZZ4{$_x>TDaw0vwbfm>Fm{&y$c6E6#FuOma**vZ7ZhXqg8KjSXo8iD0kC zp+{D;yPeKTkBuFiJ$@XrX8V@_0rCktp~Nt8Tg9{Dglk1i;EDX!7Nbd*UdRMK)uQ`g z6b(=KmJ<$(UHqrVGXFsQ(woeG-%I~r2k5W7Vg2vx6Dy*vK(?ApW9-O$$z_Bx0pzY_ z(G$g=P9WlHv?MGW8}IgLzu*vjekfS>5p+n1ZR3sbH!hm8RU2YU0>yGDqtjWc*sX?X z6Go{sfr7d&3~1v8r`^+qAqEiAe{XEr3?6BM5)ZAzxs7KKPF)u)~Gas>yi20J&Zz^hY z&9$9NfvZLj9!4no9Y1*x@>N{^6BKm9#^Ba9z%?eoqu|CeN$xD~_%P_j1oV)}On_85 zg86YELI+par2BWiNcr31kd>|9Y=5(56$k#-V_Nx)-NASZ=cetSx992Vc?xFOeMD&< zsal%1ChshIc8X)@G=;dYEkO0jnxer4|Cy%ZfBHQ2kDU|$|2)70`2w93WSHvBL+SCh zqm0y^t2okk#u+Ft6BtwJVFG80L%E1?OyEEPIhN6(z|t(E&sYQ)$^`at#b8!J|LGZ^|5%Msy;KjB8R${W=$jQq2|oktjH=1JGa?_IOf|fyA#1kA zt5fZT+x+*sO=(2D_D&4MI)IvFIKCu-rjYNxN098BTDBZCVOp9tF*Z9n)h})+>l|HH(dUI)L1+!+#ONvbU&yzVP5xN7Ej zGkr_v#f?;ZyW`2$i7#!nz27!R)!gX?!tL}?7$(5?g{r^=J`992f!mBaCh+z$rY)4w zgIQNYVDRuVCh$!d2#@@o^>^0)bXK$lro{`rBmABX2|?s6K6PhppqkJ0zC-AMZ*Fhj ziK>!Ek8=m|u?|e&mLf`k#R!AXi$`lM*HV3HHaFCIk3YPA#Czwp8}RA$x%-YQ0M?0K z&IH_*#@#4!^jvLcQsr!WozHW`MCg{YPGs3ZQ-hDUN5%tOzr_afHv}1YuAAM$)ySfO^kgn)~BzxhsTyyirl4EDf$3R&g;o%46j{~+gr87E^5S5?;z6J5FrA=Sk# zWZRF-7_F9lRVzFD{yh22(23Fv%L>C(aaD(xa*_cE)8FTpeii&)bNye3|Bucu{nn>n z0MK7%pI?&#J^wQpML?wFaiax5ldhZC$Q!s_OX&T$rfeeV;4u!MW?1m)#VC&jSU{PS_)zm@E7hXUf?|D+{! z^-$4_`yMXvLDB4T-HGXrymo|e>tr^EKOPbD7Cu|)tn)Bnl# zWh-A2S4%s3`GT?R9B?Adt7qLT8Nop_A+X`$J5i@dlo#b9hmRi`y`w4Z<-EFe*X;(C& zxzeB0ju(KzbHTAFD^dx?sR=Z7#7|#3mpj=}UpkU*`^sS~&ZX9P&$8izm+f!g?@FB4 zj({%Cw>Qa?>Y~(2Mp2HXHjB32F7oz>DMK&zdueQGmKI!5GZkuxco?6yF}?>Y782Z1 zZ}2RCoZVNQ$Br7hisx22cdv6nz4_DUXtX={rRC}#`V-9D;|wOi!#LVT$Ii{hT;-3w zG*oSz8C~2VtK@~^$qPKxR!h`WSXWMjZ$eqy&F(q@m zNC_uxf%iH z-+p3DPof3=u3a;YxOeIuH&DVi@+NG~tzF^T8a^*-AJ|LC+c^!cAWU*^B#hY({wU1V z)oF)ZyO6pHeJQCCfXHG3FLA9(F*k!-^CslGG;|~?qYxh&E#?(OIyaozy?ivZ4r)vq zOczNci_SF0z_%@vnLvv&gA@H>W@qesvSG_fbHpyY`L&Z7l*W}{QEDvzTY9a*%@15_ zzI6l)ALwoi<6j=hx-cwf=Y_24m)wI|+jL5K?>a+F7QSxgXpL3`b4ZiTg0_?3_l_*H zn9ohpc29~i$ZJCaejHA2r>DrBq1Zm0pjW*i(UIyylO9CDl_nbnNo{Qd;MdPxQ)yI7 z>%NCc!=ZPYE-x{54hQMM$- zSTYRH1d_E6Jq6*dwn3G3Xwjh>tygPqmDO*)pR0Acd`-*oU@Ql3b>dX|fhH6yb{nJ} zCCQ`qk-l_V4&Dd5)w89xd+u>*z*V6VsChCyv!9*&wCcQPCxedVLq8&;;bN%$WL3Ox z3i5nNU8!#ihheB<$jY+shOMB>XJD-@^w}F1o~rO z*)nFlB2yeud)C?LLgm}G>-m1smtS5)B#KVU*M+olHp}SO1ufEZJ+kckk zO~)}HG&eGmsE@}biEBprFqA_sof}ec&S;YlLV>iJpme#Kc>PzCd;L`!&(1yKGB5H9 z?OKf`ARj=YT9YAdSpfv)FUZbf_bEowe#f8GD?q+jA>m}L-NA(hWtpov8wK;i09&`^J5&2Ztug> zo`QM=M7tgARu8F?Uc;w}-&Rbx<6E=xMrYf!zrXB7XjNu5zm_3igNYDF1mX)S+8j3~ z*K7vR#7W4OSzdQIXDQLH#oV?n)bWUek>c%llJ-WcD&M;Az9)WnO9lV{9f~pn+o(4f z-Mc~z3H@CdelVbu!85X9a#GW7aGeUP>@UuK*zBSmB z7I0KA#t1{2WSHa{2E7djHh6a6s)WzhHk2DBuE?$$@E&~-c=!YsLU$IXU;OPw{Xcq9 zzsAlQ$R}tV=G#pegbA!(CFgw~{8R4`5VYLbW+p%tZFHlp*KaZY_Lc+41SrQ@A-z&Z z9`#U@G7}hzvKkZqdrxeFzC2hM5Bz8FqlZ#L&rw56B;ciHTj_Qd*{8FKM-eujyQCiw zeTi}3raI5AT~R$`|IRPO!Ov?xFCO+1+Lf2m#F5>Klft+s^z)lIe(ovi@G6)Xvu+6% zWTPa!#rtiZ8$jy!D5dvVi+r}*I3Evya)jVjuX&inN-j5u!z1H^bp*g6y#3*mir?Eu z>Rq5dFFJ*OrgG0~(k7w2gjLUZt9A*N00QbfN~>c^ z#Z@V0H7_d_-W1l=#$}$8gCCs$jZuw2*^N75r=EI}e_ZnqTli7B4*()B9K9g+WkIKlq(|`^UaImq2~mlU+!E))<@5oR1yz*MIe}b_#;*x@5DB5$uB9Pq z3**JZ*J`LT#W{)lBup;EcywEzLP^az-il^32*L0(I%WkM<;h$fSGDNrXq788g<5iN z55i0QOucC>)@iizOYiGioAEO{$Gh2#<&s)XKWD@Y{5)#$9#M5Zj;ax2Wi?bdQr>7m zKnN`hc-DWdyICMNtmL{(W%IeCa<+Uyx=Nru>lxLa@m?H8^diMEM7>V5*K^!OoO(Jw ztH0~jH(v)E8BY9>TqmIi!%qXXqjHa;3koCPF!fn*f6(iBSi}~x6)A;s9abkgw{9ia zhhQ$fs!Amct!B*}6mRkQ+;H~}=6Y$p4*i-LbZ#uwoZ4`8l(1HeU)PX}(gJm6= zksD6VRcSs_F4c9lf$aL$`cp1FGKWPTzLZtmZHHW6jlf-m*VfK5y891?2)aZ)=CnLlbAk zbY!P!r@%PE8^yJArUoX;NWT2WI;yCfj;-d}E}WO#{ETOtr;i}}zT z^iI@n@@5u|0QekdmH87X_jAP+uJW??Efe6cl`+2r19Cr{GF^)|;}K)IxfBUzirPGku55{rA~*awoM$m-v1j&ZVhOVg`hM zE~VU_W0{?JIKF(6ai^rcpC-q}1Z1s7*Dr9rg^@;mn82A!1UH6Y6ianjhB&4HxwS7( z5KejoqopDctQk%k(`H{s=QoSX1J6SlMnw#9B5pDM=L%4(ALg5WIEFRhMzVsWpxJeO zodX#BG5C*tDWF#^6DT}HR%HS^T9`n$@CN<2RR1ig1Va)iQ-j)a`JOrl$v=-q#EFPs zy@yoz__2KkW;7o!cDbRU;YzfH1xK0@Z*`zoR)d*S2;6<6F^W3(P2_!8Zemj5o zl&F|=RH}Xdf4pHy$M3J?F#PM}%R>i$OZ5+z>U&!|Y*(WRxobY9MPmRh3ih|vUKJX})<~V+v>()I^ALhQp0UHO zX^%=IrX2(#A8m~;hX3>LLH=X!cm5h1*Z$kn)c*r?{OA?%Ps2J#nZQ_a8D>ecW`zkr z;h%I#{q(3Kxb?G_(ECCp^ug>o_%7NBvc%aetGH6d8ni(#v+Xpx?y zsDD@zcdbo$JnlZ?nkcf%5V<=beO%!7mDI#XJKZ4$zrc#e{{}#Rk^O7`a9xyNK=3dI zgT!ZvnuPxG6zdPJ12y3glPK$#Z_)zOq|E#5BWGkMig}UJ<|^Zd>FHIz7|%7H30fE# z+wvmmSW7YLIO*F8V=tMbD!Qg(rcl4m{g#NLqvL_#oe*A^>uejY!aw5VXhJ3(N%+?~ zO4c-X^2z>|#U40KwlG8_sK#o-Hzvz4^OLi}LTIG!r_{ca7{Vs80^h$aFZQNfD~#8k zWB04lkN3

    f;$RU)x{B72jIkuOD9C>~M%{p-rGvl*s*0ch>(m;1}7M z@{b-Ja8(Ra;u@$)=E1{=&z`h1tRe#S2O5nW&HJ{tm7Y8Io@?ft{iM@osA0ZLD~gAd z(ghd7ILs!`ipf;n2Uq5&G8p@krw!Z~y><6%lG31rZ9?~YAkW|B2Out@$D6j%iD@L#0z~SiviP_*%-Wmih-eTJS(HiQs(c=C5c178Q18w25$4SH=QC`Ocs$y5E&%sh~CSCbIxz%9ZgJ|${BkGptAo25~c2YqaP-e`9wS>#F83C7RC-4GEJ9D6lF z=*-ag6;JfhQN@~`p%UvSIj(|z&m{fqCJP)YIwU<+jNPt(ovO%(7Cik0hU%}5Uu09# z|ClL}|IP#$+zMo^t|m_K6dt>crt%SSip3<-lP!3-;=a{^PCK(6Z?4FDqrkPsdaA{6KM_fF zn&9bf%!UKjjmkfgYUNItR~&rZ`smT8aCgW?Ydq~BJss|*wI;-PCo)^3)XoG%S5EZb zxsk`S(u1Fd6ZO^T8h!F6J?aOJTr+;mCmVBmwp}Z6bT7%U`KmMty6Wmm4GEd-u&u?- zD{(E3;z)5zgXhm@JTb8KQQ=CP^-$GPD^soT-lcnTM?Q2>Jf7j=V>j1XMM{TDnu&I- z;8KFqAs5X=^xRMbOu*A9_j<>kaa5Jtf+K`;>e2#-AJ+hke`75^uNqxP6|oJ;u=DUeFtuUzJO&TVTo)7AeItE#;tDn z6i>B0582n+b|IHM&eynvzO(!^|0`#3#C2svjx7^t#_=*bXKSsRZ5Uk3C!XXyMxC$! zc%wJ${OhKyuROS_mfgmPzH3LQ#k1YVT+Cm6vXUXGQcOU-VkXd{uOkC`4yY@;k|_Oc z6AKR-%wKtM;&)v^(|dfgPO^A^DnGWQ3wxzzDH?x`EQN~+45h)4$Y89Yo8JUV(|2If zBt*uU{oFFo5uXDeR@wGm*X>2IBGVm6notzuHZ&FoYT}r{{AISyVqpTy3f90=ZaztQ zYE0fd^I_f8RPLhNp6EdJVY6)m>8VdF_SU%o$2w3jRz^jzr!2(oB4|Of9KA5Io&)LH ztV;uL&9|kh)wkFC=2rODRP*#*`+ol03C`V|Jn{g#^dh1k7NhMthm6V-Z;}kTN6{sX zwug(F;Xcj{HChy{1c_pwT=f|BeX)OJDa-s`C)#_xZ~Fv$p#us zcH*iG^2h<_!GWS~pX>D_MI~3ecVZ8p_|c6Kd`te}Tm1II!^KiD!Mo6Qo->$EHARDYBI;<$y;N^4bx;bIc@Q9ED=W(q&3a@Gf-MMBh z=JTq#I!)y%Xz&yPo+!SMr}M%Y{}!KS=M`j;eoBqp%%0JjxSQ?xs{CgdxIcV@QcM*F zPpn;hm9`w*@G&yYO7V;6ceZpVGj^PEF&I{WV$GVjF0UX28m;`p!pcMBtUtO8J*HkM zPz`%Fp)dC+yY`*N(+QZCnT!w{T@-Y?64lO-7;H50lF-{(=D|53Gk?959LHXJ>@8nZ z{3N!+EMbp$BPc-EW`70*^EdJxgEVS)%MA*S|efa zrO&Zx4uiXJM^A6>7Nb8TL2p%?#W1#iK*K)KiOm)m?)Ba zoxij8#Z~(jN4Jw3L*6kH8mWCdTJyV)N#=5*PoR#27agf+6cX%Zjh__Trjqcvejp@% zzIBT$)<@}DW%X?vWgEp}>&z=X2l&6Ieiz|*aM_}rglyYCgjS-t(j&Ez1U>}II`R>< z;amyp5dZLlO+)SG`t_s4?RuftjAP%0>}6|K`~gt4C~$faLzyv@KAI;Gn8INl;)PGn zuQMsIS6Iqpb?wNPxBEg~3SW*!-QBj^Pi4E@S8>`iR==L5?ImGi;n$KN1V)x34!@V| z9ZcEmG|AjE*;6%K?ws;2GWl)auta=>ara3tmOZ$28=UX*w?WB+d?eO1k=G`Q5JQ>l zObB~!r)-iCt}P_WBbX@c_T8$0BU*kS8G!3AV&7+C=5jP(JldD=@H?2wx`YiF7kJMQ z7h{T`p5G!+Mr|u#D}>kQQk%}P-7Qc~6FO=s0k5i|vqm?|$0M3LpM0NYXQziZJAB}} z`N;{io##E)Y$N3kS!azcbMQ^6=Kw8){z^K2D=@hS-+QmQ(2|EIM?tKTmsTQoTui+u z1V#yHilXfKi1S3=$yFK&oR#b*&0jE8JWzkAWU1cEBMIpxc{Bo=O$oG2Gi|P_@D@yW zfKGeLlLXI_F!5*(Mtd#1PVo(4+U_b?sIBhom@hlzW;%Ezkbh^kr&HbGQ|Ve(0#y}l zy_=D;>10!TG;|5W=S)s%v%@5OpoP`c#sAR0sGjt_nDY45gZUhB!<5xQozIB-ceg9L zNJIgcbHi46Y&+Y0%0vJqg`T;N9F3EiB z?);pT@?q1~s(FnM-Giu0X-kP_S#EW{^KC6~(RHaHDL3P+Ew4L?BbHU?$r)<;}lq zGS)wSbD4II{`2ALxM*8L;xqDuy!!Ah+Tr0woh?P;>7cf&lUEvX9zB@H*Nc#uj{=fw zwwB0-_>vf%qao1CV8HxdzZ>BWXXHfc1Z;b$ndUB&M_f+O7GJk~a@oTN_`#~&SkonA z5XaZwo(J^^KB4~<*D&;6^jy*bs^M7geObr)G*z%aB{bL0<|Pu^ZYGM!{jC6*bkfNLPLebyW6z|5&LKcEEQetawN%LCga+)QtrS7 z&a}Op9|MmK@8Cpzx`;ltFQa+T3;W-Wq9K-8J{36<{&AcM;)aJ&TP)PV0O{` z9jV&1bHhs7`vbgqi<+~hG!KOrPPH#rnh9kn2A?qz_KSRJ19`poI@`wVY5?_=C$4&} z`Hd1`q3W?-!8Bs}s$ET4W6}{%g=_ASymPRJyjfdmxOC(=m2#i#)8DKVn^zeV6&^~O zZ*4k2=A6kSz$Ddp+Wv)J3%1SjL>tOL0s3lBOSy_^2>Rz-VD&bxz0;zO`Q6RZY8 zM$G~=M-r8yUQN&0$nM$EXvh^?BelO=;nRcCMrzA3gPmmAY_2R#n9@l3hii;nzn^komwY4nJ$dRc=ED0F38tt*3_kObBdL(K=N*RH;s0+J40%ym~6)}WC z-@K}>=*F|PFS^sgW@Gl1)q_-<`C^T=!~`95{5VMq`{_n^0Kix!Tl>CdY9edGt2LJ-GVlCw;eSNU3f-4 z$@qX4rB|sdO~CLv75Hb`^7Gbe2~d6;FZNZ0zMGS?ac|1q7*$pM-O8Dgit{n%+q~A^ z9fWXo=tvBr-0(?=mMt1mF|&Mp%GzG`y0+p6dxHTZ5uE&#MmCI}JKI2ROSuKd+Udj3`+fW(1V5kS*W6XM z>0c8mO%Koq&;g5iTui_h7M~}Gf)St-u+FP6Qr&Ho;LZBTA#Hw*BB89__twf~^HcoP z#KimEyv6tPWmP6gC958#G(E6_EHMuy`c7EIE1^t16r&3~f&_Z~U5gg4AL4x`OKNUi z+LU~IN27Mr^8Ib4MIRxyA8~VQV;I8K0;)RL!wRxG2-ymkT7x!En{j$sR+=e3bL2J8 z^cnfOdtW?!de}R7qwk*IzBt0*!?YNqWkWoB<~CDw_JU@*q<1y-o_h{_*jXTY zr<_<2h|Jh`EX`_?+L~*9TxS1uiH!sC0F456Q{`#)gN&nK7$uROu5Dc6F{3iL?m}Xe zI1=>yPbOna+M;&nx(AznVSje7lkj|UIA+#uE_n3|d4W1#GfGsTUJgkx!jUD#ojt^L z67Xa=#WlLR)Ye#R3g|t=yF$C7yubgQ=sG*=*B*dYR7J)#jIB}Y1&tjvn>X8Wiq!Y* z+ky$7@0NVGI#FeW{9XE%5D#092rH@{nZ24-yRw%3IyjbzuS#XVsthHiw(8(l@z>hHgMM>$P(SCVtPn}?0q`rDtk{4a1Vbk4R~i<2~E)OevpQ zffJ3}F_ncY6L^d8Nv-;d#=*OX2KN7S?=w*?3VFL5{A9S_m^(}1t<+(t=Zrji->(eo z+x0!8+Rdj`97TpOcu^8AZ0mdgj?W{1e>BG`?r6o~`7ZyeWR{~=_WN0^cRQGK{r)@7 z6*gu@jwBgB)a)5eY?~D7Yv91knDSf>hVA2?szQi~)@`)?nA5v9ew-%^#7@vzRqmyp zqh(_}EZETflS;H)n9GEHtJpEBenmyq;3igxRw9>x5KrD)_-K^p3+n+GlHaytaR2dL zL*|5=BN1d-+DlOiIgF`%J#K0xB@$l1q4jh+7BQB^{?CGtYBBuuWx?yOd)(2>By zFP?DDVT+`u!EsV#IR+@wgW?iJRbYUK4-yNvFlE0@#q>3me1zOAR&h7-iGmLWTiE)Q*u?xKk<1q)$+K_}g;&2E|I8Ju6t7~rqj7aXXuf>JAE82g8U#?Ex8@IPy(^Di%Z0aEYX;vh* z)a?adC{_8FBFFH+5L41jizZr*FUpC^5n8)jSKZ}c;1KV~(O)uoK!y5hBT($#sU+gn z(5oV!C>u zS7XGTo%MB+UZ7k(_)T+$JecpSZ)JcgYgc=irrsDp%)mj&&ek^sEEnJn;a-}QY36>LjgA}i8*;D5J(l*8dQ#zBB)MBezD2}#;8>~By(kgV&&&M*I3YJv&!J2G zO4)d|6#__Kq1$giuM+nLjHll1PW#gbn;if0LMH#(A}W9K)PR4Y>4=dFh5~Z9>D_SQ z1`~YONY#Xm8S!h0KO(^U$Eg?D%C-^;@k1Q8*I4(?N^XJK9IiV8%B|bA$(sG+?&M?> z`K-$Nmi(tF1Ic&Hk^exn)?ekN{?RkgKYIxCKQneg257nvSEJpI2|t}sPXr7L)?>>O?P%{L$##HH^a6!#3jJ6HnhlFsksoh;} zDVsP<=9x3?tmyc@0w$V+!{EexoHGNoUzLVSDM5BZ4>WyjWxHQQc0M)hRdcPPFfVOO zlVy8V*iw(>O~EijTp)QHTC> z0ve{DSK9Ty1`jQmqc9X{2I!+0p@;TlN}K^&Y<|sx!C#;c!Z!UdJ8p|O>YYU33amPj zCJm?Co%UgXr2jpB@~?;fPkt!6!Gv;#-Zu#$k_+(`f>ez8x$}cw1(gl8DJ`eHKb5TU zcPe;Av$QJn`}*6Jp#*7fOI{|7j*+9TCz7xl?4j z@t?ZKo^xK20g8dSgC9*v(Up<@%{jtO#M|N1&o6ggtg3R@*K{3I z?mJ9PIlKpeZ0O*&(q$MR7>t8%+yf>?p$DfneVLk{OIMo#ip~2CrGQOcVT{);Tn-UF z3tm<`Lr0^zsfpPzJTI*Tw=m5~7rf8pwwN(hZmPPLCe3swTP(~OAj0y({loOpb_{G9 z_YpRDJ&;PJitT`Pe$%f+;2aL&vwM<-IY-&g7@+o{Z=061>KHnv8S@xZ{BC_`huLE& zlKJx)at#BN7YYVUn6vHhyMAL|F62=VB2*^+VSt!Uysh8V&!5abqe#Ew@3zH=GC?V( zNd^7YkpqaB34T~V6!7d&@|qjr+GP_#clmMo3rA-UD}eUgXR!7&Xg^$M8Vu=_D?^+5 zhQc;akuQI{3LL#COu74%O;u-r%22r7D<|%o2i2}{GJV%zVi&!6gZYLF-?y?L3=jkg zf3rQ#$NYd>of@F*i8+idh64ZUSiXNK-tSKySpVO)%(0IcAWzJw5CPm$*T6!|nNE$* zUvJBa8I8+Crz--tt180A`nOzji>beq>Sk5wcl6GS_h+oVEEplbk>8IJ9aM>+vP zGNVY1&i5VR1v|c-eCapcJ|8q1-b0o+b^DWUH>#%?JqVXvg$mLKvsJ>c);gHsVbMSO zb)XE8^TU$Hsz7CaTj5g0GbVEzZfsknG1R*Q(39x#!Kuo?7#zYva9L725_OU;8MdtV zEw?IxKs58y&27a5C?t8&R*Y-}l)YH3K8NKACXN=8u|N><@-i6*wB3EABUS7!N(2xs zmkgjI{uuN(?lWCuIjW|4FVb!&XtOyvx!pL%Lg6t)A4Rs36KF-yJxHUmnWz}F2Ea`) z%r8#sTXy8`Z)#`%X8&a=SutW0WBxWg=L4>xF{0h+KR@Ma`Zt|V*P12Ur4?&@9*cfp|HirW+z%}b#7_H2dz>bx z;AK3uEMyLtSdK*Upzonh0jU&wK!Y4h;#_$~3ha3A8WR8$08H1f z6FZ}C_2H`#_NjqkFlZlt`Fr^y4Y^NeZ06+>bQ0-YB)r8a>lir_7z!!|mRf!q^`V?X z_+nJAm>Z;64yOSE%G)f3dV@a+8H(Z0L&-LLXSf?4$C%L2lcY4V*C3g?##{ zT2*Az*qHJ)RStf1FWt5Eq-sJ8w=4@bi2=gnVf$eVdO!rzbeBwkLKY2C8E??TXpTO* zG!u~t-6kf+DV7bE&R53tsj}j?_GVA5>kPL3NYJ8->S%lXTnCUAt$e%uP&o`wtbFS)0*PPhB$ls7 z##8Q7wFb9hWkjbwWa~!S?+|KDl!)B}e)6WxZ0F}AE?u-u)b9p`v>Tqtur#aN_g39x z8gwR;>P}o=g)wD}oSqH`;)$Iz+Tl=Mp(X7EUzU`~YmysLk zzRfJ>S;pDOw_>P8#Lm?t6ch9}SVd&@%zD_yHFun7ljKtWFyj98W9=BHqGudD>Z57n z##wQ)@>0*glt`BEFFgtfk^6yo$_S;nRi_V~RF58eS9C4jI8t;~s5dd5}IWPW~Yki~JC8>l9 z>lDo)*s!C}cf%*!HuuPDy)Os64`H+>=3EqloWxr}!ePPBa)85$u{xF%2vVwjikAv= z*KY55B*_3#<;c6ib;&Jb)<)c_9n)yHdkq(3-#z&8`nHRa0#oYWy=yuM$YQ`f#0nXY z5vsk{jT0uCOwGBde9KvY>oWu7AI#D7Mr4O_gb4s+se&Ynhg4%iJmw-Wgb%qzmooP^ z>(_i#>|OQlHf3A1M=;MciRF2pb4tWvZEyJVyHgzK0YOZ&`BoP2cDj%1z?{(! z0lkRv(9>CL?S4!Mj6MPw&%j%|r3g_E6w^XD9ZeLfgL033v_9e}Iv)RV=kd@FzL-_m z^s754*6(yJ1YMiBMb+LFX{W7+*%+TslYs``3zCo7@;g6Ccw9-4ejTxW|Hd|XXlp^I8a?B72CP|UeB%ep} z^~s$UBrD428tas)i|5>i%Hto~DU^g6)A>R~xQ@q{U=LO>7w+zUSJ z0uwjkYw7ziJyEe3V$u+7hd1%>K9;Hp8u!1Vf88ZOn^rM6l3N>EjcoB5Mn z_vX(f_gac6c;A-0dgnZABYY-`suBP&4H}()LNzCDwQ8rZ?>XM&``QcHTLw;#MWEhO zkfe^4En$|WCpPnH85ECaiGWfTu3GiWH>Rg!j>u~)j;=n7Y0<-y75Aup9#V7}8P!aOmf65%Qcj z6i{>D*tT+GsM&x&#fo|zfRo;LPA9fwB>~Kgd1B0F(Q-GZJ#k~qej)^SF=9SgxhUA$ zEvdk2OoHvrb1fi#h6(rcxm$RPy^2kgrin3Q+dmhc(&pjMiZX@P-*E~o!R4N z@aRkN>m8N{r^HXp!-O$ziBY({0rft7K+Twa=F-}@gIvF+uJP4JMqfX&nYpsRE_niz zlPeF8075{$zZ1}tUH)5@OCB8Y3LT|m&ol=KOqciLT}-PFRhR+F;S*)PPrekhA@lDA zG5@8HVot+qhN!}31Y9Ts_jE9*wJ*T6HI$A)`oQ9f`cC%Yy~|K3foJk6K>^>p(HN zmy=GP+$=+Pp2P`dX7Nf~jT?*gvNvRa_J8a;W?3Ye?0d&!(5z>+r*AzBUaiy&85Oi& zhD4rbfW`u3POztIY4dj>0;Geuab2l4clI0*HUA*Uav;fql(TwFABu8}Ivcc*pY9T{->vq~RFA3~v*=iAiLDY7f(L(c*6D_l;W_Aa1}T z*xcT(zDCP;Nt@jyJgtN9cHz#{v1=8>Qu;enR>bzGRUu;ROya7&Rz62gZ0Xj!Ef`ny zA%pid{SDeJK_2IC^tCu>J@{!NnRS1w_xJnIKCN#ed2aZ5imZhG3uOSI% z%L?wm$71ukX&Ku!Yd^UJopc)-D6TQzNSk(@tJM^4oorBD%$O}HA;aBQ-gQK5%(GNJ z`N#KXW$G;?R$q;?-+@5cq0rs}ErR z6Nv29ks|Ad&1LJz9c)w#jS6N#>R8k?dV)T9>_QPrKm(F+V>vGE|7Zc|yf(+UZiFqWH zKN@s+wO=T1@JZR#iIuG9qtz>Yn``dpR9~&T)j@BU+|6`Yt;fuwvlm9crV>;Sbvb@3 zox$~2i(e*;5=8l=%RawM>W$*K#;;#;l!zNCG63B1xG<<#FPaZg0i-mOiJ$LM7Uyj9 zk+T`IM_0<*!=)+@^~HRuMeGlETy!+QmVYP-ZygplZeu*4+>N^d+tHYcgp>Kw86eZ! zSQD%kjj0M|d(aY?VJMt-B(tfI32Nu&ySAY7OuaISfWCMz(x8rnNoMy119sxo#fE(I2Y_F9VUf>ey^GmN6xpwN3BP%Yx#d2 z;_>s7{#s+mPkVcEutt=}=u< zF`4mFw4NZkP+-1THFtLQ#;l+1R8`>03}GrErz|R}NgR3aqak5}&-5F%ctvgCT+_Nm ztzob&dxU}KN9RPIP$`x&b>oF<=Eyip7U_FPQIW+Be8fDmTvH!ZdFn)iMicHum7`4A zt>yU(Lue0)gJbnwD)K9Ld_|hR6LBq5qJTYp9}nKa8qC|n7f}U&ShK4{j(`57cY!o9 zHpQ=c>q(@69O#I^9sKd35_C$h9yljkl?abh!%XKpa*`%$A~2B15*@ZcSFP7I71ePz z=7GLlY~vgoX=jV~o*jF1U`Av?$3fcT}u)=_R z?U=e|M$J8|5E7?;vR2x}n8=1P^@z{d5Iy0XDH9l~_cK6=Lz8zeaem57Z-tHa&EUT# zzHrA$R#7a(Mjd)o=@qCGJ_nVv7;La{?6;(rnupc(5Nd}?{0s#m~q=IGba6K^`}SH<2mS#4atUMeTSmB7_~ z=d^b7`dCc=wet6a7&iws2FM~3nf+q~C5I3)-&dw?q#%?WF(mIRA<-SuY6#Nz_u`qW zs!2a8E76-Yuz9qV9eog&lL$h|5cyUb5v9~aw3ir{ZUo`^TF&e1H4%gmHY3SmyOJkg z?bzS>9o$iWO$TR$PQMuCW`OhuE^*FGJ;Y+%AP?XbO)sYS&|K&6iP1RW>NhufH!(bm z{#B_n*yLve>`x%Nc+AKQp_3{!);Y-uBoaSQ*#Q~&L@|Bd zbP{i;MQx5{z4mMaZnTDIP$FmG8d7&zk3*u?Je8K88w%sMnK6#1b7Pu~n_xh#0g<gm)ZFSU_XZ_)2DRncv44(!}p+kfqb@_l#|N{Yly{!V-C1Pl>y ztjjRoCP~1oRk9#FzX0b&Hn*^>8}#~7lMSyF{cLpbou_mKH8xW5snP_Ljh3U*z(YBU zG6yKU)ru3HZLjaXb}n;cRV*YsRE&jHL@H80)F)W^^=IxL4TWXnqTswJ9tso*#XQ7R zajwJ{Q_qr`qIAEUM%TYwm>RW~oVAcQVNZ5YrZ0w-U1qI6dU*WhM)mUO_DVNt>OAdv zlQ7kmSlb#eWdy_$m)pGviw$xw4ZQNw`rt<#r8O(o-X9-pZ8)M3_cm;a4L!!x_33uC ztL79_6pCd05DG^3V7QqS2A-R8q0CDGtZ~BV%W-|~jps@K8(#uB&c4Mf^{oZceoyzNv^ojD`(GXZHy#8^`RA{N{Ilo**c81GWlEt_$&{>q#5q*R@4!+3qe zVcW0!B5uOj5-|JGA7&Qo`dT zK~$Az(}mH`$b<%3LUFGGa3zR=mq+9ymLp`M-Y;M>RH#SoE^mh0` zAe`x)w!?nKF(ZhDEp+jIpVB>b1e&Os%vrCSFOyXI`ZRNBcAqbOY`u2{sVLJsW%Y7dmV6kt(f+M0MxBa15Y%u$~ByAD*{jus>b5Rxx2btU* zBAXIx+j`jPUu9W|*bb=-wFY>hdov`{9kqBx{fwc|r?g4Z*~?m|P8|)>MJ&AiJJof1 z)<=!$T#LjZase=rPqhP{VLb#Ecdg@n^3_sr2=bk5_V@F3PM!;|8T?6JF|d}p1J2^h zhw{_AnN}LgHo^^iNayaSLMd9h1Aam271&qlm(!njR-TegU9GyrIY0Dwytz3dmVS|w z9L)fgr<*Y`icEZn6#Tg>cwGY~Lx60LX5(`A0eoaZqE9SUPN^fD(9KIRl*A?kDA&Vk z?ajQ%&s;k`z5Hnv*fH_^PGLC~cewPhwco>+lT#1oFSotxe|`pKP33zG^ESUiP=Qze zsKi@D+~>{1BBMGk8|EHdB=?O=1qV0K3f$vNC$FPTt6YXd^P3OVL6|za`4q;5N2%5B zVmcN$C}V%6swzymsH36LsO~wxN{Wcdcbj0=VJna;hy{Mn((atZ$>y`Xlh4iH{5Wx> z|LUT)jQ8k09Q8QRI=vnas|pNnkRsKRT>&_)4qr$lS7gf(9kCL1mDNqv_x9Lx;C61^ zc8kNv-6?RO5JevC9_%5{li2Mzsq%DPfNSRE3{0UF`W*2}DwaFCyt?7dNX1S6sV>hW zGngy8s)jySz!LQXOu)^zG;e;r?}W@!zeOoIumU%Q*v(0FWT9o^+}GLApEKjPTX$TD zQHiAuj+2n^R&roG`|ZxIYq(0q!wXUOU;9gG^@#|SjdWH|(#Ite%JI(}X|Hj;{RKfoE9UD)nNF%GOqRj_1jMyr8?)QG9`*+)T=k!|KguOQf6v*Nhcw9HOU&9vZQ|B97YYYA&wG2Vln#Tn z_F{E#y8L9pAd`ApuY=6*as>aLuYoQ5brad}JY5ebidiWDIvJpgJbK_8|B5*74bD|D z21v1z?8{U>m6lB9BSH(ozz?8%F&p+US3Zi=2{7$Ad}wI%A11l8_4m}-DHIc?raYkK zVpd%G7@*BgC%Dnjylp4tOHU^Qi5w?V13nBgig6047VER8q z9x2re;3k2|G+Gf=gHUp%xe3;*!&LyluMcQ`Ji%4<$VaVO0`I%b75%t<|8b*_1$uES zUncxQStyEzXuSn6@sdUKd+n8=AQD^qeV&36l1EQ_AHX^~D00L-sQ87gsExtR2!Z1& zubUkWSxh;l?$Qq-3+el$D94aoP#BT{>SzK3@h=xueISo?wD+XTB#w9$xWsqo&ze@4 zI=M=?N{6f#zlZ_R5V>_zdy#o2q|S$%7LsmieeRjG_?njze>MPuMIIkkKO+LRzm0J#`M_Q zwkfL2C{uIufQg?@C(^`xqH(~PY6fUl^4H~J00TsqP-2Q`?kY)}0peuZ)o^2~`o%m3 z$Z(9{L+4$^?Cc4Je)y}GfAn7d3@3*HEQG{J94q|*>fATzDeC!@E5yO@*GpPm&}#2n z?j>H62E6i>#$%}xqf36@!n^NtK4gGgx?SyvHSxt0)Bqr@a%#kW{JfA|^*-5a-^U~> zlq7VVb4oxVxWC=-`r8iX{cgCw3=SO30R66qzaQ{7&S7DjUj_Vs!%5h0hs#3d_+{{Z z%gDsv&dI;uL;F`R|ERrWrT-QHY;Cwk!JMCijY;c~=mS6$!8l&WDG)CeUAjqe@V`=9 zS7kC^oBaLN5t-r(=M$_ur2U8FV|Ks(;~6Z_zZ0DH73DyY1`usHev}zW$^;0XfpEc* z6-YIo)hct-$UAzXetC}N-A^N*BIeB7ZcqKC5 zuHyBpYN(VZ-maP?R3h;z=go4JO%kS6w4KS_N`eKQ*9-QGySIjM3pFScCL_8FnT!~M z>{i?CBsJ6XZRi0&cD-Sc81=X(eA6DPz+~T#{(obiYAik0wJnD#J&Iv!oTcyZANqgn zfBZh6kBP2+!;GfKfC;g+6}JZ}?FQqfDk`>(8b_7Td%U;3E3ThTb5)gpo13Q6mUUP* ztT8K3B^&%KW0Fj>$iuHBBcbRZrEaeVEZsG?*HB~?Z2GS**71)O^!Nj0HDY_F042UK zs?#()jDEDQ!RsX)K$B-W>?Q^-d5HFnb}2R#K-8>EtgdwcXRhs+_C;*&ivdw3`e80p z@pLs>CKaO{i8>WnfLv|?OH_j;-K-_^8`4~_)P|iDKw)8BJkp_Q@y(;FvfsvM?=wK1 z7Nb%#fvZ=DF+a&jz?~@7;V4ORjkA`Las1hKI;gx)^EG$T*Ot|ub$zR&`N`^6*Q{>0 zfQRoNW{Uz`rl0vl;&`Y>h)bV+s`T+*hdNCYF4td(bz#+$j?41q%5om^`)>rwKcoKB zbjgNravRfIxCFE^K)2GEs`b^KAuLsg0ZL+Pg^~AHFm>b+J(-9DV3je zOi0#XUaAw(rbVgWE(qmPxGc7eRNPlHbDpAgsk18mC$#TaAW!{$Y0`4Q24@>?N0;vb z14M=(dv+EBwrKyYio$YWvr*f=zw~a%?LH|A_wb~|>YBXm%}gaJTLohd+iTMN`s@Kk z$Mkusj*rR4A@+;_|pYHWh^ndd~A#CuP-P!Gg&pI9aty1b8dwD7PUwttq%RjdXaHip4fp z;LJ>{%s%=|YbHGM#IxW=(=+alpC{d|y^^|og*y@`k>78#&)&Gi$wS;GB(9nf5#(AT zZe^RI544&CQ7=%2eOuhC8dq!kU-tc|eAl0w9OUGNXE9}u3$OP(^CXI0J=+40ZRZ=a zAa}$0saFA+8C@_Q-ug`DETL0Ba@{oXa{c$Tf$8o${d+bnKY^a^T;3OPCJ={3-64Ww z8qQII={?zptG+?74JY#5(TBq?56IP|uB@65=4kr8`uX-LL0yAG?+drkgB18_bPt9f zszPr@iw|O4VUKWoQ4TZl$|eJ)^Te;Ucn58Y=_Gw{^-Hug#lb*bv`Zkl)sF*u=_|_? zbGlq92Efb=G-C$Ng1XVKT7`=Sb5~oe#Cv&GlFj1B8lF9UpyZa`m2$vuBl7y5eK?Py zdEAN;v4{{E`xrq76$^X$5P9h)obUuDnzen{8g;f3ZWp&t&bh(ue_ z_WsLvPyY;!@6Vn{^v^WqF1j|7zK*wPo{~acD62A~i1h};Li=TPq>XjF=d1b%wT!un#~rzX&7V;5c@n3@u{QwYnI1MEu>~sI zr=v?yJ#!ToZdw(jy6TP3cD@=d5_|CY4VD9f#_SK^Q8`4ro-kJnl2|y*jpqHQ zzMcgm53`YX{{SlK&(Qe(>`{0-@HSXY&q_TW&cBo`GNcp8E?E#8a3Xb984(0Y@n;iG zQ}1p0Xe-X|dyyx^5)P(!!ZtX7N(RV9y92iC>j8oTK0YH#^e6yFWMzPuzT5%>6iKEf zV-_&63=jyy0PV>B$F*3$`9ATt|6TsKtGNCm`F|D3jdXGw?Ip|^JE}~+OG<2^z+}cg z6-|uN3QZwSsFwj!XAjj%jZW=VaM>71G`xp31f(dJ=^Z$BIzQ4Fe=&)~x+lE#^j*>T zgNwVNLKlnP2bGi26`vi?t##lG-Tqc&pb_VsvkN9LKp(gnAi8lLU22SM!T`ObL#QAe z12lX8-!5hQ?bpBi=f77i_>18G@dPtb0+gHR?kNGPeIZh;x#>h01LW|1)S#+bYv@u{ zx3HJ;+p2H5vj;VtbY^09?f%R66tm4pVMga2h5|4Gwn)BdTx^3?A>e;)K+`0ETdS{c z(!NCfUTsd7(3J6^i6viKeR*l#R196xiI7f{!Y07he=x|bR6BKzM=_Ps>}161{p4h5dUT6_elIzv=WtZ`mbt>7~FmfL()0$%lL zp567HNWt?b5BT!cpr2tA*I={sO{RZy$R=m^e(is;M9d#Jrtz=RIsacOnoK{zhTuwj zk|T*(9QD|xGm%z2Y}V@6jmj=c9XY%AGMjM!@~wdXWov@HV}Md9{mjY9aKtPwO*Vb_ zXIJkZA~5lPdi7SEn82JRHl;)B2o9!WCjDNa>JtuM9_x!Mff|xUtUjHb{kEr3wM~3E+5x4+Ce^+*C(T9AbXKH=hNF{C5Kc3ywq5i6({n)Tp4>Ax5u~7 z=*x@O2ePs`50z7okSy?tiE3+i86Y+!&X^?fJ==ifJ{r+Dp5!DkSynI7VQi@?Q9|s)+re5=5LCc$+5Eve_fDDK7D^M3>a$0;&TA=D~@G8eB#up zRk;9xijAM~bo4sJ8~JtRcIasj<%2VAk~{^ECJ)sQl)UKe6S(8!=xl$J#i8ZOkuzE% z^Y{D`{NV@by|@~_2>RY-47X5+qp-%dNe$D0DluPkEX{oOT7$6~m>V#YS0y#a6 zj7hgbp}o0v(G6bHT^Jrd$?J$+lq1+#kjJnz*Iqr&SNx)VSF;XVy~NulULcyt01;%0 zYbQY@t#ksyZLgqNfn)RiM;Co1UIc=&q+P##<8(6g9W89=*gxST2(Yw43x+XXf8imEAi$x5iUQ8oHdfzU;HX;?}C0iDu6UI(;0`B zr1!&E=o0RMqG@yq(obaQvZ|lBntZ>iQ|2KPGZyj7ZRHEbb|4BgW?DyvbQc;Gc#x1NmbnvZ49;j()~F1RM(E@MP86o7T9#* z#B(1b;*ShyH9?9J0=ZbtQc(9k^+4pY^Oqcr<*o|q&2DM36dK-&IPW4SRK!|0P#k$0qHL@QhyA72+i6m!_U=%=|-QFwSXF6#~=jR)H*9zRUcI7?yvR zAZ&5`6*8msE&EQaKxo6fNXkpk?$P~+(zPn?W zBoWW*lK0B9Pm3j=eVeDiYYy`0b+mFPjZH_;dqAM$X`*5Jqg5(6m>_d{%CY{^x5W*Imh|KzR{itbT;lw%!oWIPzM|UjDd=F4YCr-4tzBAfoL3{7*v zT?WXaKJ5Iu=Oh9ddt^dL#CPxP9_&{JXfJ&bT%F!FH9XalBSsZ_3s|>y*d;!~diuBw zy43W0W`5>Kxz$e2NZMZ?mdqxorzGADLU;ATpH5Xzt!`l`YJ8FJRU;DO2_^n*y=8+0 zF}%Hnb3*TTax2cmRO$BFVUDXJAAdA$_0l1zLnPjOuRJ%|6TK%?&u&8v8*B2tH2YRR zosl=;*3!zFmW}EQ)fJ4H-NMQurCRToq=ge80`8;Mg|AaZYia|1n|0>KZtYlp{M?ha zWAyC~av7e{BmtCD5cEOqYz@-X$|3>A2XKFAlKk#n6)!1c+O?W~`b&*LP;!sFN|^YR zZ?k^Vw(q_41K^?on~%71$f`&QQ&X}ZBz4B#{aBSKxM&wK7+<9Clf*fuLe|jK&xk2f zcx0M((lhitXlUr_e*}U2Z{?^2wI{YuMMmQ^#Qc4q@MoA zlLw~RmQO2ppjFV{rZ~`hfIFS-IU+g^E-w}{bErWd=L&*fhPE{eb1Ni=iVIqv2ZdS4 zYofX7eGCvQ&dm*S8#qOvzy)eDg~wZ>RU6w(smhvST+%O1#Ca+uW=_4}yZbkk)U*c( zXMi{)XgPF#>ir=)E7c0Y0P#+`74&$&zM-up7~6HN)Fv?Hz1zp1_p;h-;?me2kYNv+ z4kEb;-Z9zoKp;VxPtZLvR85oebj^vK0pb=PUcEVC&wlq{DD=+nu`m;4|87(8{{?JK z=0G^*F8ULW8)dKk0Od!LZRxyTo$@Jr^6;8BHJbBkrkPuQf)=<<<^gATxMOuG^)6tD z@8JXN+cU8-oBu!t3Qs4CC7gf3cP;lF_z^}J#YW7# z(7%=V=zg1>YIYH3PXpE3oG%H7EEU$4s=-z~#P~EnH*=3`0OzN7l&evcqbAxrVSGwa zV7DKhc)y{Tt@UVlZTd6O zEFHA$_ZPlCZKH%|fPlk8D>eil{#Ja5G9lt=)4Rt8kv|5>edG1gEaYdg$Z1ga+=uNK zd^K)ZHq!d4Aq7TNBNfB=pmM-yryhx&e4FOA_T>@uv#9aU{q;I8jtkAGadm(`NlZ5! zp#-5nqEA#0LGJQJzek+I5A$>{*4eJqoGs>m&;6939>4Nd=f#K$Xf`f1#NQCLNOU4s z)1Kqp%r9@B1N3L?y)c*iXEe+abJy*@9<<))d~Gc+`Z*gv_kpA8>Om53NEmV}EfdX# z@BA(ulHSB$_y@g>Kgz3+RX=tm$R(~1hNg$7wO%*V5%^M`~vXI5pG~1eg4{N zn!FZ#T(mGi#YWbpX`<8fH0o2;n)uGomBVbi>bbbn^nD00Q^`B~M9~kBV5=n3gM)1#u|0 zRp!vo?PTtGvFI_QopKzK2 zONt|cxK7@oJ*FQ;mJT(`asi3%0VVMBaW$B}aisJ%CYn>5Rx2_Rc{+7Sg z%_oAoFo=RskkzHNq_3YlTO=Ky>8=hvh!cbO&*|rN>7;m@-HVGj>g}sIes-F5*p6}z zpVK)NJ|*5D{|5Mp$Hu5uH?kR}UGq_!5j1+Nb6n-CwCU>)dxy3B;sTla72E5`J&hX; zpB8Havmr2o)FU(Y%GiB?-xs@td`Jeu%NuV+t{hizI%A8JSmL~_(N5K-y~DXcVjb0D zKV-82u}-fMwSqyH>`g@4U%pF`7~{U)E@;|WW^^m~66f~;8@wx3*k>kjRSEAiO2H2` zTRfON^N#q+QN2&|sr)1LlG?E?p37^!w^JM5Tvubi8S_TYCPFE^jseNs_| zI$>_^&e5SToV&$?DS;+AkEwlBZbDaxPrD>IhrDd&_5&lo(ziDs0!g2{c|GDQRrI8U zCd=AYn~&&Yv__aSj0I@&VMXQ!VC19)Duj-{L=k?&uR!EaSwoNAH53OGk7H3 z0B3(B&9+nn6k!&jF4OiA>h@t~Q4d_rv@Y5o_{5R5*0f6W5y0OH7;&AEIocs(Fb13z z_ZAG1&R>0Bbf$qzVB_l3gb^vl4Rv+nYLpqR4(0-WD0?)$8O9GiI6REFw;w~=pBwSlC}eMrD3MCOi;|6`dHggcTh`F|H(PFr+2QB)LP@D zZ-nVVdvlvWv|60kb1>Nl5PHR&GW=`}`rshdy9L4rU59=m99BpsR(Y}~b;P}6iTn{j zml>w+lmWWTMd(I?w<77##F!0xk1Hb#koy=iz&p-HU9aoM+h^xj+aITKY*I!d>xMVv3i--U>Li*I?Tpj;e-JM65Y z6}hjG`5LOQHu+e;&c#XodZ4g?)~Ik?=Qg?`O#a3c7u z@(}H(=OgdtNKns{Tndt2E|-=MJEFGv$19Co;HocdSvdAgPwZVle1?;^X^(|E-H8)T zO76I^#A7vVF3r_KqGM%~J8&1yKu+~I*(#Q;RgoPw=2*FyOntDNQ`wV9RU-bJ{!v%Z zRXo;njAWSqJ?|^|@h6#AgHe8?d0%2|rDj$9;--fdG+|ZiAC5E$V>|f(^I|!oX0pza zw-00Se6#)Nv}NLWzNKUOp&e{A{-Q+4eq!d&%H; zYF$_KOd{<{7L;pjDh9OuR(Tp5jUirwjr4U+PbKIei1VFfo85v~S3j?tN+aH{YQ1hF z?4vzZyTrqer>+h^sOPwv^`JY*W(7k_i8Higbd4L zln`OZKHf`1QFl%MT*>cIP7fIh~U-O+@g9GLkM`a^! z_4s%`DxJJ)m?~-VO8lpK@p#N869Cn8u3$;79bD585XzuzU~4g}ljn`e>X$VZuQDA{ zM~XD7pVSFZh`C{q&qMSHsw!zHo@zoIYneO{x!o?ye+<b1n<(-*<ZLe=#{ zMV?n3ad}sle9V`LD_>Qt^hniAKi1Qc{58Xb^+!21>mSTvZHbHQyNr-e}{!vLa#mtZav|$fd0@Kxe;mj(R$0 z8Yz5IF&$Iz+&p~xM<{gum-qME6Ng{LE+~mRutpgDQ|dfDyJUfF<-c~R+aDk&?|=FX zLYZVk#t)&+&A`W;KESyGU{SRUkcf^FzK2Kqkxk2Bt%nC&;+ zpWpL-p5J{xzxVSj@AEwG{l51f*B{r3<2sk)IL`0)ye`MLH~RkgE{BicNyFIdB0q{< zj@D+66qimBc&M2Tg*v|X zyysSNq{%_IAAlu=J6Nu zx-fOZ=B|$=Xit#5M*M{$2F<0lq9(KEex(E==a53)^id zj88p=JH7NMWAB6<2P6oP{EA?~9!$;d`m49pVr}+>o8fg9J`*wVKKJQuZ+>q0LWge)>eBr( zO-|}$?YhcfEo_|hDSU88;LmHK8Tu##B&3AocVx zH2@mhqEC$2u}@Ki#daxt9Z$KhJYrQFa;ZaD;NbR+agadA1<+m;VY7XRjR`%Q5Tb}L z; z4MmdPJfR^`S5>g*RU0k;(6iE&uP0A$RkSF5*~*9nb40S}B)&4|O+~ZN2f#;=o=_}~ zoH-6r#r9SHlolb~;!>72UQF$)^rhm|mTcw&XICWe#UHsUR?RD%K)^&mQ~(oF4WTC$ zElVG&|5IN)3hw{TG{mdiW=MGUZHfI^XQh$hjxXXzzZ7mgJIr~m_o^_`0>VxolAW9A z1Sd)Bh%<8~hN{ft6_{2-%UNfDoUoE1_S8w;P0Vh6nOQUJ;w+*YDn@0U#~lqWBg246 z)sC+cJx`LG>WhjTJ?pWbTda2_zh11l(a}GRj6OMcP|5N(=tv%&W1<``-VA{Dwc4cY z?|lBYlVZ1ZN=f$$e<06^kaJ(i1}-e{I_1ws?tSk4zP-|16a-wIxY@0W?I7C%{)F!# z8V=6OoqAg*XNuG>vsq=e$bXCFI+q_%7&MxqFbQXX z8few$vpn*a%Cc(u2Ok^1+&Q|u^pgQ{hNeK+fQb2&05SqtgNEy#CGp-uS&u!M_*M~k z>TdHV=aIVF?emlQou@cUtbI+M9SVmi({d4qSCL|Wo`B7plbVf2OMU)Ga(|`r>{Ur? zOPcZ6hNWBLh+?==pzSdmaRaE@0yEyZaGxH)c5t)r??F_4o0FZlyWw@J1Aq6uE1eN*%&&a-h?rP8UXzTx}E zf_a0;iiEr7GcA>Gjcgg|uY?ihz!XK!o2~{_viC4R5h%W2Xc71o5!oA`n-jk%U+uqD zd&5Gd!tM0?{uq|N`v+k;r;G2<3ZSmETX^eERX(a8P&r?YNk@ z$i-%R6Sf9Ed$wCL5g~@NEJ`;lF`kgKR9Pad2NsLPwPWH%z6QKr`xw8t)obe`O>h{ zlXtDvjI8uFzQ>=#_*6!sS!vOb3vdD873HkHKfZj!>K8#V|D4XJUsi!NnLoe)kZH_0 zEw>@`#@?&7mHh<91nOx9DEPIblId(j!&tcdn`waE4)F64E{H0(Rn3@sFMZ9iEnF}L{+1Zw< zB;ugiuUHVaFJ1X~lMol-@evFEpxh!7DLO=pB#mm&5(y`{dcJYAyW0rz?)iHBD$aQ zV3t0KBEImYxHU#mxF|Xj{-vd;<_(nR@~@ERTRIyI(7kY|GMz10)(|+z36;s*gD+S@s)p>XF zOh2cYRoA9&g<5zl>B)tr%REy0Wn_taMw|RnfP2%_vu?=%9p2rzKw>4gF=0*r26*a; z<_`D=YH~`q0{hVJ7X^krviaM-Y9Y08NDP_@Bi_JGdK1jLhhk>cNI~spN!W(=8FwDz zN6lT;)}h{O`Ui|6#!nRnW}XYe?)e@8IU0i|X)gjR0@`5*k<1yIBum|JfVHEAMl@}e z4mCfz z^FF!S@Mx+-heAI##zbYn1q@?$?Iu;BB-oEhG&nKdDLNJ~HtO9}lfzi7%uT}LeEb~| zu5D)%G04rKwyTF12%3=3CCtB3qWTe1tULB$8wW|tc0j_MAJ;%8)-$t9!$jtWu%A zuhU=IU#EBKpsO(1nkp1Tuueh?BYGiPB!!4y@>Sn`4N40d9^_Zs8-)2wsvEt(V0E_U z_{T-tC~iKUhsZ+=(A{hriUIO+2%Yz6Hg@->r_;TcY zA@5?40dVjglUMnSA?hLD_iAX>SsKT_xJPdT|Hy*KtC#0<;G>Q zYMS_NH!jJTqCo!&tChp1#l^n=X77DyG0{}#YdIv3r?aG=C&IcvBvDV4z^;h@^J^Bh9fMPOMVOK3X4S6 zSmhBJAUi?$c=F?3B!jN&!D@lMqdCOgj?&a=AaRj(^ zHy*r|WEO)XLspUd#|aoG2q$yp)CK1-;dFKQ#Zj~zx~z<9H`4t))3i7`&x~U^e$lzX z^$uT6dh6i^{)~q6@BR3YZOWJiq+2By;wzL`15X34)=}~UDAp9wAQU-%!AxNt=Ob}$ z?*(qD-hcOMFbJ@wbA}O7cyc^~1)!LWi0~kL>XSqo9?3t=>-<nn7MO2L{Be|j_zqhc8B@UU}Uk;FbD`#PFCX@G^n$~mvrwNEV z{M+tmC0d=X6FzMcM>h1E6rFEKs2fT|TqG&K%#D5V!IYO;mr8*j@=|EZwcL8VK3Bi+ zh13|%l0fWcfJ|r&(787`NMVgnSIg#9qsby$KdyzO%uf2>XIaS#)u<_ZlU9LBr%^M89bCQ7UihMV)T2@b6wY)ay-%NB^koCqgJDT~a&Nyf{_O#`O(*FJ>+a1M;IE zp${q(HU(`i#>FF!IUqgzBzs+6C>=YbBNr&cpYHl10BZreL%j#6&u=EsH2^;XlAU^e ztc9ZtP`FJ&ye+eNUvcEK-_lec**;5ZfK%|k3QGIhSw;9~eb9ZxAd*E_mZC{LIf51j zAjT@Ms#Pz3XF~3^O1~32rHxsV2YO;0AHT8e>o)uJ&x+yvMYhY7>i0*ri#YaVsRTd% znPj;i)@+pTQ|UBS>oA|VjA;1bDozsCMW_cqNw^gL)H=fWor#?(PdAH}S z(%I?at2ZBMvz!Ykl1FNo&rl#y<}e#6cXji4)Xk*@N&0Ecw5)f&Hl>2eHCRrd%fJms32FKxJ{9s$P2_Tp$)dhmR9zP^Tms!N zww(8p0|omggb~c*u{j$-6nDTU|AU5)gcUI^$|E^_*#75u@~)QEawfd*yL@sQVHRB& zBD%gd2g5=wX=yvCBf(~Pvkp@i{BC^hr?OAzu}XLQ=1O&BzJHJmC9AV7c75r1_$h}d za3!uLt}R7t&brm_FkCwI{35+;G*fW|5^aZ1_lDki{IeI;=h;AKScnrHeoW#~#{eCIgTAA| z%xHwhLzLm?>c^4Q8evy=?mcm@DAFA0t>n7GCDPEDzG&|AqcKyRPjhFvH4V(gJ7uTJ z3r7H2>>a4&Sq0(_$#zX#rO;!fF7)WpA(>$QmXAPq`Y%VbnRoTmDu@?A0)>OhN5aIy z`CkQx)tP~2spn%Vc6h8ia$@_!Xc?#f70z64?l30?$RLW~M;8u)Qcc4m3_wU#aP8(g z4@IAPjrIZVQV3TZ{*4p*SwDXr1{k#%K6U^H#xz4HlzcSuX=mw=-Rd`74T%(QvLiFC z8?8b)HJhPQa6O>tE!O*i57dqLa%*KcS@LP-?<$R|hCmy_elD%zbvQ(umLy~E#|}5F zzv^y-mIc1DJXTpyDL>h-E?~2t`7m_iN8J|tx)%dF0$<${U{tf0d<}cwHez9gW5Nf z{Kra2!e7@dhLi^gzdR>Zq%YZXh<{+Y2tm9z-YcJ%|8q`*$4zd|9n4u@{4n$$4jqN4 zc^%iuD|?YCW`>o^7chyRKcVStFC*ON_k268Qdge|Bt`&}(6?)Gt@QIGR0jie1Soji z_+1xTc#kk;+!zFg$OIR+`p#vWLo7K9SvF=>Xvt`{;AV1IH7(b5M1F({E;+hbb?)YR zb6rz%4cD8c2YWAGOxI|C^x4RWx&+onwpnOOC?aDqoEj^omQBq-N@1-bS~ob499!LtLGlBY*Xu?;6lNNwWM1~Fak&zCOeWx?ud?is z#slHd3p;5MI3Bd@ABf!&#Gb4nVQO}j7!|F+U}~#OC7+;x@7bv2H_e z5TTu$Y%_?7Ac&gT;b0HCfNETB%4``vjr$%Xq;^cUmiDzDtM&D8?gh8UzAPT>;4_sa z2uZjI0CQtHN>#y(u9oxWyWm5+_KhzJ^)+&nv(+59V$)NWj261P2XCK#(+aX4L4#=V z5I!md@SbOY;_7p-gB2kp$RME~MmkjVxWVrGbP&Jph3#3j@WPBl#Cr0}kN3zI73Sh% zG?3wMDLPXQvkh^w-@qM__=RL#SjI-m+c3geaNfrSu%hp;$McCGYA{gaz=TlD|V$;S8i+JWG6`SKDod4c-Qs`t=cXNVE zj5(-Ju0VU@%d7$|86n7Y=74WdcL(Q9D~JTKXEL{aU-9|;7(Vw~RjSkJ_T#v?yU4&~ z>F~L6!}vevYoI^Wk-J5mFeDaSW0!?@e0!pzY*ni%SxY-+Ve1Z8O2cUX{n`7Tm#!R^ zJ$^=1*F7A1QPXVihDaKdsE`?;G2eT8^UO$NL8}6{2&!FBX~e)cK!Th>tgrLeB3I;3 zWQ2vXY2EBsE3UdmG!cArH(0};ZZ+Gt+HFs@2DZ9R~HJug3Jf4@f=YISwci)x>+r(N=6!b1~va$`sstKLkd&HrMJmMWtF|)Hf z>W41a0P#07Hfj-pLqhFmkxW3}|&eY3O<#q0A@OQLPrj@m# z*z{_2O4oBZjtKy)2_MoZx^PW2$+{iJ0aqqw4sqLEdGe?{pmIhjI~o6BnJq^zQT!$l zpm+?KSGHM}hIE2WuJyn`wYbS1inNblJ64YHtKEd-@yygrIR1m~i7`l4k?^FS*C9ejYw!-$@?1l7Z=O6jE4lD7ktW z1VHDZQMJ5@u!i0BMLbk;ipT!ixUK>|Ae6hadir#azoK0J_RE2*|L6#57g zy&ZHVdbIbea{RCjhFYZ#l9!DdB92vs$kycEMC-8}HT1mQ1QPz#yO)Zz#gT;oGp%lD z98OY2^YarwKC0Hp4(&vnIALOaf^TKG#iH+FQzWmE-3cL`vEvHaXLoa48gIIACYG=|VUU~1KcT?@)m@C+2s-yCHdctw zWovCKnB0&v@08NRVTpiq@J}2Br|rA*l3-zg8BA=Q%;`D@zw{Y+#Y3-|!|>mGKLRs; zeaApZ>tOdb!g(s;aSQ1s8reKmf%p*&CLacPiQ98pi42ej1H@JO%DV)Z?cDdPHa6!H{*66q;=S}0p79aK(9AK>%DMjapwtrIu4TzPU&^m>1T`f}i z&CiWQ`TUI@GPf4h_Vavy)A)sXmEj)AQIH$QCp(9CdwK)V#~NvXylQJc7rr4LBD4b0 zAm!Ib5b~xZW())(qU=jf5uYdK*Xk(XrD53m3m#8=WLLsOIHBC^-V)1;H$OlKlN zimR2A0iF9il~e&%g5I=amsrgx+`{FgJFDAQ?DEn8l3LS#=5lPCBcVQRV5u^HYOF+UdK>U7LrkJr zYNf0@v?2XIvYimoCi)k2W1@WWrk404!l?xV%M20EBIh8!{!h7>d$pB-Lc^c8j1=uY zirPJw+v8NFKru~EUq9dD^x^u?{7k~lj(1_28W;OCAQv;JYUHBJW%B01az*hNwJzMNm<|6 z`KAG$kkg_5;LA*6!R5*XKeXIET-8C`h8aciSFR>W!^ExV?6kk+D4Vqca2@L~dckk= zc=ECsJz9a5iWa+r_%4F0n_7L+NJ@Esf~{7N$)??X&Y3!8iB3}2_pY1mZ+;#!%Wh$S z$T5HM4>no}`VLE>xCvI|d zK5!@+E>^MTcmS{`x{qGVhOU40HXircY53e3I&amOyAsm@dTp7Woh4KM>jv`GW(w>8 zT^#WZ%WsOj~6RJN0L7S}Nu~EWALH z^!R;~0Rt4zg!Q4O`ZpUMDSB(pz73MxcFG5B({^YAUKnALfD>0~5_)Oomy9N_)h#jpDCE@p(06 z=am|i7)n12@ZvsnxHLD=-F8F4hf;Re=iuif>q% zSP4*y1|QLYiNG~UWl@?O>yWcLu?e-~is~y>0zSW_=8uivZfu`Y+iLAq-%>e2i}!8e z!kYmKs@*UtxWuOn^eO$)d)3~fFXb2CXIws2dnO~BuZP9U*^iJj@T(Cvyvc)TLmt*p z#U6rUO{~8&S!rHwq-%W4pO*< zg#rpT!Pi$3q_pl3`$%0tYM9{ds9Uu*5*&6Qz?%G&mW!Ora})ujh?HAE(xU>F zZ)TJ8BXvW(_EB%|MQkL84-&BseGgKLzIsU=8K2tzuu-u+(dA=(WfVF04tF5X;?0nM z$(^6M;!}<|R>@rs|APbO#%ElU6Xe_-T3@GkMiv$BPqaaaM##yscC_*+)$qeA{TL}Q zHRJf_(r52xE|D)O`f;4@V7tE3oEh=VzDV)F^MB)M_bZA0 z2LU~@kRWbizBn#+({sV;t9;W`|k7}QoFr(ylp%cE#=wtdRg z(o02E{;W}%>{6noyqTrbj|nXzJ08=ahyoN9x_H@ErA0^NzuosyE$BDR?w)y%&pzw< z#i_w{>-$p?nRk&FWIu=Dh}(1ye~J!V9Y~mCfD#?0zQeC#ccT_fVnUOqLR>J7#!{UV zP8AIz9nqbp0viVNkC%K@Q;@{#o8eFiw8{{v+;XgLhP_jCr0pVhCC6O8WvlgF#1}I^ zbw#y8p1Sah{+Y%gK$h%{9)E-ZPWEg#y$$x~&aEqrA-sJ*_Rx-S@#^qva8krACP`L+ zaKl-FE@BzMERnAAQyZ2Hw^aE^bc9q%20d(ZlCOPO{AJYbwU@hB|Fz1|!$Tpr2&FEKduV?h7Ue0gC- z)O|uf*@9NBD~eD0q}sw&dgo{6%KD()nW6IMMHxE2xrfs~{o)TRUy=IrvGUnJNIj_u zD2K+Z=XF=x-&sXXT@}_^QxdPa^rproIH~utSh7@{d{yHT#`Zmv288c3VNC^n03z9d z9;T`j^o4R$Hd=mS^9M*KLa#jvY>G`6+KZ&ET0e1?J4nT?rx9^xv>bc#wYZz#^V)g6 zG+#7%71BqxmYTflA$P;|8+G`g0Vyqa3p`o(dVme)hAemwM>MOPOzK(Bob?jt!6nxA z$KJI&U$A`Bqu%P`)rE#YsgH%+);n)Y=wleRI@O4;q^+UOdKfXOtu$}X-=8o0cvbef z_c0NoEOFV#DP44Pj^l3tUh;L|;#}I~Dvs>jQk~c3$R6Ws`Fh;$LRrp+mg*zhg2Q;u zKG`KL1FP$&*dNTmIA@VuBB0au!lorJQF<`K~s|g}kk|OqGu@vSvF_7NShy zm>Y@!bF{D$i|9gevG5Ciesc}=xg$OocdzB}Pe&?jzvv4QH|+^HE4Lqh2ntb!&ZXjN zEW4{TvJtW*%ec5-3KadHA91ZdK~Y<8yp*w~h44@AUT3KxOW{y3dA$^@eTSlJ1}sS{LuD!X25s)Fs$0J1Bvy<$3_rQJ-OKxPQ}5G zf6Z>qI-K)7{>e+ZVxitb)|9RHc5(4b8J+MpRwjhjK(?7bGUG|(q7R@o^RCw<*^rcz z`pR+fvL;EJr>Cyn*1F~L=#@}9+DYej`WZ!gI%mqO{vyOTC@X{?Q0>5)mPK9hpSJNF z6umL*G3KYqD!Fz(ygj4nU8mfGFM7>V{h4NKsy(1_0< znR04AbxXr0Q^Z*N7pAoR78DsIHcOU|{KL z_4Jjdy5fdRG5M`UBP->K_NT!wjJVQmEyLLtb~`I0khSb_7*F099A6!bgQ^Lfs$AI} zuW<2reQ!M1nvBZw2hY@HKa_`SWj|IO1bh1uJ~0!p1EvGVNgq9jMYStZlE9LyxmOq< z;xqlSs#HzmS6knjuj+Fs)T*fPQA?GRabXEGdq9kt2HF5tq8Z@`ilq5l*}GeNHr}GP zqvDQ%l8B!uzfne)P-p>kPU+fPmS_4P!y>o>EfT>=RR%H$xFoHdTudt5blym%V)KKp zv2w)^ew-lrmAJmofy$R*Bsmyz; zInqbh@TBXBV^S@*6c6XWo_2FKr%pXrDhG_aU*j!MG5jE3?APd}K6H5vVn~ zI8qjCu$4J$$RY$ex8BXmll(?@b#u}KU!OF;IoZ(#tFrE)Nv?`QdHhO-Rr$Z;MXdy` zO+0a+wIoHpDw6GY(}_r1lAPQ0gc40RW5`XjF#+=^X<&lD8%I^vuoicWAV}SH^s?I0 zr&pd)GHz5bxDzwA_0g?Y1}x3o*$j%u;mRZ^em5D-;xKDR|F&Nc^(41NTtKNbj6-R9 zNOuk?bpO5bl$SeKy1s$%6ZRhv9$RFaEZkJJ?UXL<^ycM|I*yVla-XJq=CNR3(#z{| z68@P7*f_8GDD24M%htcnnZ=?+;65a@1kJ1yqDJaJJ&n6J(xGl=_v#DQHr^@P0K{@= zv@t{6Emd)T2n!`!63tpSCmYBKB;NL^&vuG1=}FCvo;Yf6@kqt5f!^!&59AKmyokLl z?X5D+(|CoGWffM#9EsWFlsPSis$7WkY;vUwj<=lh3oUnOIV%#fSSK(uV|+>?df4br z?BLJD@Uyindt3|<2Ycs`FrpJ&y&3iEZo~K56tfj?Th@?X<55a^H>R4|L8uf}uz`lsOyiY>q_B&Th4BZ5c&Q%*X z1U-w&507Z845ek)f_Z`|$+C3sm z78wPY3qw`GT6B&L;<7%eK4RWX3fSz12}1D#FMKuZd4=xbe5qsaml0l2 zWj*~su^RYJ5u|DZ7}7z6$_hl5B-&9amFMIIsloePTG6I~yE#HCF4K$ouRg;}cwBNxi87OTK&H#}0$T z**!yu6L}Uy6qUa~%Dc^K&E?HKyCZpiVgC1DUnm%#w=hze{i23{oiSW9EcSVA$9k@3 zJ%osyLq+LY<9Vd~ey_AV&g`jNZR+a#G*&0~Oj@nx#=Ga{)#uIMwNxo68NY+FF+eV` zSR5ObpMZ*e+_W4Icf#`u+n2n|HH@zuCx03I!4cKvA>^-j%oe`AM92gJS&r?f+>kc*|*m{m(^~|2z#7-ZLDyL}v zEbBqlFGug-(ySj#D~`bxiIqlq9b0>ELtO$@WCR?iba*nG*`Gy)8!s|>gYbSbvh6HH z@M5jBPzw+>-#ipozs-@=uI?RE>lC-m=4c)deJa5Qnrd4{JoKJHXwkb-hv{0p+_1hA zC3BU0!Ka1mhc!_=cT%+J-IGG^?7Q){@DjT4)UyRym8D+x9%QX`Bt$aUh0bYA(Og4| zRM-6>2PqD9o*Nm*)w&KgD;ICQW65zIJ+Y;x$MW)Ij~m{(9z(R+Jla)U<@OoyXUk0_ z3zU3+*KPDm?{KR^jrb0d4cT^)i3>ytX>kzk)q=AmkAxNg9uKlwbb2Yyn<)7aA#YJg8 z@A0XA>6D|Umn;M1AOD3e{OWI)4jw@g}|k~;m1SqgM#L-Q}iU%F9Sr>WN&pz5r7Gn$Sm4EBxXkN5rWdi}4DiobJdq<=Xo z_G*a8`9noSEps3ruPOpRLt3Qn(sfBHCw16=82mrp;E)Ba z4z5|eva9`}h*(LmtSfnGrZLioml!jePcczfKg0PBB$s)KHS?Y_m^@AVfGM_FYtm}p zOc2c$f69MnYKS*_Q$Eqg-Tddzl~1;|M#r9}U+$GNXUA&%Md0;E6O<+ZOTYkzI0h&N z{8#t?B-_f9RKx%c%m4YPEjo+=0xbTv$^4%rWB+0C|9p%8g7EI%BmtVxgz5pOqS!<` zP)BsVUt<9n3^S(5^);Yl*UqQ-3?w7uK$b@NM?ty7LIJfK?3()u|8seye_{WeSYGa+ zDUfRb#h`g4FW`bNh#^$S+LPQdm3A-_LV%O(<#NZq0C8RL-8}EpAK906mp%*9MPM7R z7@#ZA4jf>MqFa7rpV+bP1rwQs%7=IV7@f&s+Xon+tq*B{EwVn2#>W8hBJu9XJ?l$g z*f2~6+1^j9h5n2KLKz?~bq4556BO@8$AWkCsTY|u_ksahbO41R4d4-f{#}mzjT!7< z{3cathygmimPp*)5To1zin<(66CG2C9+&d0hSn-RI%IHT{!yZC`PL_pkeGNL9j2>C@wpaTsC^lv-ZMTlupx{cn5x zFN{ANf_aU;#QcREiYIcIm$*w8@nC?SJ^I@T0PWNN(aHbBPEH6H(uYxX&;+;xA&qqf zeCQEJU>f_ymrq_Yz2;;>WuYja(;ufPlF2Wgf7MpV`}yQQrtcq}{6{DM?m7w3=jmpf zX3Ra#EriLh%b&phy3e*a?v_)e%}!Kp9@Pt|!Aq&OVZ%_-r9`R-S-bChajsV-zImI2 zqWsZ-Gnv=XfAs+iIp*IaL->EM;-&7?{OJ(XVch`mZmsfl#N%pfS&B0B1?4RDcot=r z_Z#nWS)1dcE}z3?`HC@b4fRuohAhvX#d3bsA(Ky;r~``&C0K7*tGey4SDN00E`?;E2KJ=QuV(p@tZ=YRUL{cYR?k`Ka>Lo1#yLweUP}l#o$pdGH zj2Cx6LsbaN=^N~r903SDdYDGyQVu@F zeRlI^D%QHXA=fg`_2Klvvqflpoo&R0qr&?K4M2#{|2jqSAJMpp*JjJOX(w%I&`efzJ_e`$$p#c|$h zg9*^(;RX)ZXSF&_zMfm3Its7yqUD!$IMo_|Zuv^LqHf&r@I9gy_T=CCb^*;#%R*~Y zuaFed&}vkEVCBu_00JiVNjD|*75C#L|5r1m6yro0OT2ZcmecX5OW+_2SSlIX5Z7fY zK@KHVZb-fD@qUX1`n%2Wm^g8t0SoL@MPrDiipr9NSQf{LtwD%q{jW=1v06z`FBBF^ z_Nf_0pQc^{hUQSo(qfrgSSjSC5rIK0xm_YtR?WtkH6({ikU#7A0_hpnHl39mn@D{` z%GtO;swAXs=*(lH9C?9${APr~iB5!Coeq*p%ADbOr~>!gB`PU4OoFhu7RWq?k=NcQwLZw9D@-<STw>IqdUMxJ3xwt0a{JZtPd2o2%S1lrsEzkZ7Bp`Tn@^1$N(G>N~J*9JXc-(+cJG zbW|XfR>=P#SzLZS>6IbTKVufG$5U&(n{y=2{}{qetp6lblWI$(CzT=FlvOqCO->e7 z*8?Fg$FK1D2q+h;#dSj%pcmV})|!{rzQT)$Xa?x&H;lL0q=^HNuk^r6JFV@r^hC#m zmWNN%+M(&a#19OROny<=r$OUPP043MEc>!VYcdwlAyxJWz*XyO$6F-kFLQiKGGHzZ z)@PmgM(Hc(uMF6|x6aKCJ_o~(*`!sjZ55GcJ`ZcAVW-HpL|oKD>OA3KT0+-MyFGQ{ zjHlD<&`Mo}fvOg-W9HL*)%@M7H0ytThQx?M=ZXu!q}>i^;vX#wqLAgGuXp3FxfRb_6W#{uA*SBIn{MoAih!(Ha%5Z6gtn# z`xzZqa>;CSda(Lc9_ugHtF|GQ%F&fL@sq5i-Fd4rmolm`Ni_oL4W4XTBS52kTHdsP z3A`Mh%ApT(AKXeZNf-&t71h%VuRdWTSmVXxn8yIIjRGDdUi@+_TK0~&wsh4T0|Z*j z#bM#Hh2Dcb<{ztQOWSh3CI(A~l6`!Q^*ZZ=8dfTV{+YtYf9u8a_byHLA4&L{$hp_Z zx||-^B-ogkmP8l#%so+wr#;0;P!)yZF9tD>w6QOfC zsJh*rp?LHeV#E5VTao8k0Nnn>XXg9wpY_e!k=X7YcR4M`8|21Z4Ffby(E^+QYiw|VsXcfXx3nDx5F51k2s9Y(f^(K*5FRACZ(x2YAb ze@r(3?o%NaCu=s!WtdTLl@j~(%;w_TeGuZyf3|m6i;=kSyU~!-fT|@BIzPp`VaB_b z5h9vBd;jBJ)i0hjHBn>HXY8k2Cp-*5A;0Q~m937)05{dPuP!DO!>HxaEaOnHw(HlY z{_)wW7bLHrNjx-1X2#6iTgNNCmW`Wi)NHAs829d%g0bWPO%c`>FSWYc%Rbt^%6AXDRB@U$#eg7xtO z#g%_EIy7m83jGF)QXPR3;_OnlVkit`TGZvItuCf=sKmL!*Ofh@Ds?z@#yf*nh2}9P zEt7po4IRyFs^vqj6HnY{!4$oLJ@RTNrp($2WL-_{K5nEU$2diczv95RI<47Ev(X_zCI)S!n1jo z#VKOf$1ENccpKIs8bOMb>oP;p6KbR;5l<0PNoIC9n*#14{n}+j)riQ+`7wf&uE)_}eDU-?Tr% zWK?wqXyYIQWT-%ZQU!j3sZoZ1+XRFC!|XrI{%4!zrK+Lkc_X0rVgZABzl0z<^xI~O z7^EqZ-f^QgScNd=RCiGP%dCK5_C|VVGRg_|;IBSFocQstz*bE9d;qzyg!D?Ia05(& zYO$tGIe>-&f((#?I^{a@hero&Kh5@E`7z_ovELVU3`RfHr8uuDN^l)62u(_uagIIe zd~;JSwe$4rH}cQZL1MbrF$_?LExjMSV?&i-fMO2iGeA8n3{V}Cnv3g(QUu}p3{dIH zS~oT=xw}_~*PM;ukbAn2yREL&=k(M*Pd}FI@FM=iCV8>fDF>wFo3xij*9rC3Rt0zK!4sIK@tz~(vPS8 ze{Wk*zYCy!Kmq&yChy)3odE*ancFIl2So`v>_YUT3yB9YK;WXkdC;94s-jsOc;~bi z6kug%fcOpn`hI^1yg=2b1;tVKkw_|Q1p^dYL(7K#tOB$cAWj|~1}JS}sb?Kii1-3# zV}QKPQlMgTK+Rm^PRhO8X&ui=hw`K2Zgwpd3d0$or-o;2Tx0?LBMa6z7_kB(iTw7q zn3*BD!BhkAU*E6kBC|-mzh}YQD>Md(c%d45Cks->2%} z(-IwpzyEg7yDVH+Qrh5hv2#o7O6tia_s16_BfW>9csuy{|A)Qzj%upg_J%j2BGN?Z zEeI$mO+`Qv2o}1CqI4lDQX?P&f)Wx00i{S$K;VI3K{}BxEs>6((pwNhK&1u}fv_R% zi{~BpeD8gpGsb=H9rxVhx$pU7F<=e$+H37K+i$M9=41gcE}OD|_hL{mW^-|-CjzlQ zXA!qky;6_A<3cS|ut6u=yQ=acw*SXhA44uK&KLq;t6+iE@l92fM$wM8z7m_`DW{yq zQ6SfRme3{GxzMnGC{+F@ji3J+A-u{0p4w4-8KEAqt>E&X#Y9-Zcn{OUr46^f{sJ{W z-4&+){#RJszb|sKxU~BZ!3VT$|1r8}FL}z6{#y^}C=0lb=0h#$x&I6l|D(|T8Nm7< zgFXQcM$u0@pUEC>G;bLJ1_=RFv&a9WKCeZO!VJ#NPGJ!%jAJSFd; zzFe?!M@=>dMKpr6e#%76`_`?MVLMIBip?&HvwV*H(qj0|dzx%YX-;J1k1R9$ZD$!P zJRZ@T=PEgY!oba6s!lv)V^@_fsz$=idX$Ao=!nUs) zr@A%hrNa$9Gqx=deD?+L6MSfrGF@ZuG+<@37s7ljtz@Ws7vpV-ap46&BEnx3Gl=G1b_ zqNuhWHujV{!T#_h;g|Gtps#wQN`o?`V+x7Kj(f{2 zRp^G?(I!z@0N$Ot#K^(95+b48y7n`;ogQfNv*1-y|3aMy%`ErfT^8UT{K9DUjvKeu z0mZ{o*S766;aUt82GeE)KqWNk0onK>c_jhm0ewJ4LO_@4f+25-$-ALuO0O@=+AGk` zzWlNa>nHTq00!r%;j5YR#amL>ha2|Kpt%tH7|$D&1zHmxIct?iSXG(cJmkukJLu*i z{y?l@gu z11b_bhN{d<{M>8?`E!NtzFK}#N~!aYnxmsE;)=!f_h8-PH)zC7Y07)p+9!I9Gt=SNB! zPQAMK!IxT8GX}{#Xm;@Sy;B$TQ~JS>Rtfdk<9ym}`jQO^7yAQ4JTR(iH%>l*-|ID% zdK6N0XnTkR(+B4xkiY_}6%(LtS*I>AUL*I}gXS$vrNLrMW&CB!#M0q-g(UCglF8|5 zlds7KRj}^Q2+D|PzM2gf)tIf;t-+Hl;07{+1-#zV%auQe6Kvp{Ru^4l0=?@+Aw7b@ zc8*zA?OGp)!%4cGys=MoTfc=CRbg7QpzQ=m00dMDB8d`VV}#}mH{3MeT?l`--g1qf zf`nV9w|m|>o{#%m%a3D@70Mm)5t|A#*`iTzGm5bC!Sz4=pDolVatS6H5lDWy%h%V| z&{MIhu_9X}-5GyUoN%}IH6Q7n&YEltK%0)Crwl^9(Bo{)NA$tajONfhbj2LHZa--` zQ1A^rNIMpTMSD1YOe6(Q8{^}e>^TMF3&$iI_f2<@#xV0}ek9idnj4|v>Nkyh(wS#r z;WO9t#`9wV_w%bC>vHcEjoOQV6iq0^vyxnlUCh!YMBy5zxxKmIL*`3={$#(o8r^H$H(Aua)@ z?4$zZ!t^AGv#l5ox*d5Cc@*?584r#&%rKQRueTxWGZk#fKOt4H=+uThfH=meM(B}w znB1gXx;q)y(x`2WzCsZmPRR4fK-BPDtGRG9d#>Z`lY2Ls%>DDPjx`f`j!#;&O&7J7?>t)fW?KC0wvsS`flux; zBTYR52;(yFYzbK1+|zzPErsfR*z~Bs`fuC`UNd0WiSLbfaA*u(nR!{9Ji=fIumFSP z#-275`62`loraLaXCPtda$JP2W{7t9Y<+bS-S}>wB}(-n!98=SQ_b5p{g~kCJ6C*f z)V>E8$uDubSYGBhR(24}5j;CRLXsx404p#spMJ_3K6jw7A2O5Y6_JbaRv*f&7r*W8v~3C?iI)l)1x+_F}LsGUo(a0M6`!9vQn_Q z*AMr=gCxv_V!Imd09`Gk5lOI~9=cH43|sJf!bYDGVQsiwh6hTj^QPUNgqWImdaJ#t ztTlac7ubn!IsBfl%lfUx1M1I$&iI-cOiK`Woor0?2X8QsQS|Fy%s(~FC$ydD_m1n^ zVUl5jKk!AEr}NXX!-rrErn@<|;_Zf+a%9G2kya$U0RO4LF}xrDx^o~$?1M+s7oc>UAGxa_|1j zVYbP}vzR8R7;;#IK)!^M4vsb;izEe6^nXY`8xFXqE_ka%^$UKpM~L9TF$SCgk}94y zEpae}K=&C`v!!@2%^q|l`U;JCAyvpfy0)S+c{58@Q@KSBv1Nu%-U~YY-J{uzW>2rYoFXRc_O6E? z)ntzI7I@48xHU14al5g6o}&1m2#0%`BrBr~^Ap$Ox7XjOp^>py%+l-Kll!1Eu`e|@a6K^E3HNf;l?{sPuc|Bu{#xjh$z6MZvOsu>ch+nGO%*CUL*s@XA? z*_|@x)TDUe=*As^2^~@TUKgr!HFy;ApsGa1F+uFp4H1+ePkln=!JNzKH)4Yy8a=sP z_MChX7|&ESfaEzi7rcSr53DYGIe8X!{hmbkj<$wam1FHKhv(+Z%9A=}r-ruZ$z;ew z{S&ArO`Hq#QQaF{sVDLzjQ@)R!6UVUB*zojP#ZJ(U4*YJg&TF$nqNCjv7o1F9$GaU zw=OWc(-Oa6A<~36lM(o7mKwZ@Y{N=!RPt=lKMFf_d|xCPKyt3wPTR79$W%UhpRPDf z2O$pPC-?R%)`9Usr7ii6sMq)IQanXtecli@a+U)WvX+dNp9{Y#U~A>mY?D-PA5kEl zsTZ6_P<_DlmD)by8f2gJx=o)conD3XezJ z1>*y+QvgRmxWCS}L3n1!EAL72=Nr(iGW&nHC*gm5?lN{Qznktdx)JkM&imPKVIPZ4 zoONKJ5{6Vz8Z1Gh#*y9Mla4ZZN4u4@wYAkoK5ajC&sWwpORVti;UB6+MkPt_NL~P= z?IlhY>Y)xE=FQ#->XBn-jGKK0@LqMWR^vgdtr07Cnqgc9+#tCbdp<@xD(Ssy3s4N~ zY#3=Lkgag|nkjSwT@}SPQl}=OA2MaYM*8^i)tjN`?RQ!%yPHm`>j))@6NBYl-tX5) zbj?=Pl3l9 z)h*-S)YjFdTn`uPbvv)xm(lhr6+%p<6bzIHHsn#N17C?b>NO?8AAY+GQ-sGY?uz9Y0? z!D@6|G%)$JTodn&i=2Y#lJ6u9pw0of@gAz)Fv2KX_$^rUN|XMitl*xE@?EzRz}3!J zjt^_e*y<-H-{M^#N4yH_>bkQ_H+K5qxm(=)UJW*nb za>s%M!z?*-Fzx;1^An8v^@q_e^%W*+HsS{|Ns^bc z_b#7Kx@{mPy^CvY)(~ljfHUfl8gtOSh*PxVh~3~l&*_!88VT2u@AbaA;6Olkx_9b5 z?-uSGynBwg$Y018%Hdt=@X1^1pxvRHf{!U7&Wz_!59m&OFy}ND4OgI=^Bk|%-m4(z zBA)Omsp4DBZ@C8pgIlgY%m2c$6?COa+WbP_($~R2cz$uo{`Sqhz$cnt&cuIgbjEiE`u+~t8C`eeDipQu&b@YuxbF?J6y97623jEP&gq5O}1Q}K}mpIhW!m1GqPzqMW;!Rdwji8!)2|Gbu7PxQ&o|@kX~S>FJGXBJEeeg=^ZkB_Rr0 zO-jBf<|cB`3~GZRLK|@@v2ppXrKOJr>?}sZ;#J?v64{01Q7)wedlV(WSw~ zEjI7t2RYUb2(t&IYbGqcMSU+1)?fjr!~sX-%!*>AY?+A zXimF?{7BkBss$S`G#OC#zg~Go&17UcF0(D%q%C+ggnmCvuQ`Td&0s5EcOx23h<+HE z@r{jaWD0Dlag6NoWx6G~b_;F;{rR7%F_d-23nYj31eivAx;A_Z2a?Qi5bXAv2{3_J zu{Ny20zeXQe?s`1Ic0n*B9!n5DGjx7=wSg*1}TVJpoT{AZE(XN=}XwQh17@1_kr!t zIOYd!Y#KxIJ?ms%<P9mB|}j#4D&G9>obU8*%X*f!7|G9&c^tZa$(o&V531 zrn+Q`bYT)D?zK9{6zNrU@>y5)vHQ}Ru=ntrHc#P{ci!*BR6Z95BDiQ?iz}3~Ed=hL zC#es&FwJ_G+g)dReSDUQgSUL&T)pw7XIsvbyW0^DrS=LX+TY>W$Q9l!3ZfxETAL0g zRt?L6*fp%L079E=Hza&sl(ZE%jz+($1U^<*mq?XchMfiS{C1dLN>pCLgyAIU^0c#b zrCzKWC~F~;R%*O|&ljMg>G-kZmknjDjJ^h3Pc*q6B_(Je(*%Ri*;9I&&Ugb|(ja0O z#>I;ZCFZc+N}G7icr$!k?)IGQn~&Z~`@M^s!DF>R@o5}S2hEh(Z@U*R0vB#CBUbFo zeAN67CNNfTIOtl~X)b9nN1$e|^d7>AXhf?UO4_>G!2;T@6ixf`)l3YP2=ue*4lD$| zyezkc^=2+FXm!jVL&clbwI>tqQaRUBQ0-yIJqqFZcG?rQj~LRZ_FTtIH(L3Nts^=p548h}=7QQnO#$)V$7BCR7-bPnr0m<$}2yMF^YF@|IlV-~TK9ta1 zSU{O}D|E{z`yDQl@Z&sPo&{Ws6<{cuZTcvJ*H`sL9v^l`zk6-q1Liqo6QN zACBIuyR-LT#dSXyA*1i=I!7wLDEL0>?CI)|8tJ<9dRBASa!*7{Z;C@wp7eOxy0`G= z;4qAA72Kc)dAx?+8!YO0x5hDli7$81^2p6edA=&4lXJ%wG={>yH$taINWQP=XBcUL z5WIXVmFKl7u~R*&$Ro~7btruKkf3koM$VfypVPM+W)xorA36|Rxn3RZbiUe4x6jLr z+P5BZSHJxw?gShETjHNiW7>N5!Epl2Q}*MYld_@emK2dVRpJkk8B?r*xr@KMZ@M5C z=HqEv6&~4(mPV@OwG()eA5p-*^W_wq#yr!a$%U=*%C~l7@+LXPduI`^TPM!)UvWw9 z`WBXvKab7WbbL3PVjb^ph@W?6s5UN#_8B5Qy$C{V+s=0^vqOfT1w@hx=OKIOoYRa8 z(sJHsEz4#aij72DzJlsoAHf-df2f5*Of86g|gvLaX?b> zqRwQAgO`AmDoxfd>@ON-e8;@936 zT;4imH`4OX(J^mGYVB04amm^UxOf8K53}vW{mwxh`Tz!DPNIImWmH)Jri6#B3PrB`|JMW|T|up=NC@vw zANIhsS{4oFfjuN6NKsw?{vv0gZada4%g09|z}-{pvB49I_=G?!H7(Kcp4{ngW95Y({$*5Oo-c>3GyNotP3NAx&~I?#{01&h`fV`MUggC(71ppC=c zvx5PP^#;lKtK-HBmfjLkYM;KF+*!&O7D@$@ML(h7u(3*H4?z+s89Xx+^|W}A1@QDl zRq8>mV0&Gab+t2`Q#1UHo}Snh=PZ$>N^CO$LO)fAeLQ2Ix@bPQ zl(R20pLFnDGFNa_VP)3MR#U4R+poDSPRRt~#?gta{c^Jrn z`wDlHb2G29XY6-z!kjCRQI&H>R|eM+^HlbWpG7#Q>kmgwFaMSWqqW!^UI5x zYoUHLGiKN1k!nVSz699AmW+c9T3CspKxvnYWX7lQg_=~G`!CyfwB~h&5e+MS<-}I^ zBrea*KF7{a$sf6ze^T-Z*K*Jj+YCHdMD}O4GPqcP$$m^| zbwyBy5l2R%*Ir%aC+KGTv3K(^n}P{N*ajhLXOrvc-Zj~>Ab#0F$7Q=%F{h#Pp9*i zNcRyz)0UF-8;qQ)(8C){g`j<2KVtbDZ$3}D_UJ(2xP#V#lkSpN=#7^`yUoE0vZOsD z4$I*|5XVB$Qgr19ihcCc7z4Hb*%pc1V))z0aLs4M*lXR!vNqQ8{C8h4mSR5lbLYMb z-~PnD^O#OP@7I7Y#)_2OC&R-^7L^xYp7DQX&2eGbQu<`iaSqUerUhq;_Tg>`YzMWe z`@zU*UrD-ZePzSbw)@CDYHekf+VRH?5&I?#1&!RtYk2DK4ox5li*aeCPQ#cr&{SB0=Bb7DxG1x(6r zLrDO100h;!=)x?3=rOokvsXeO!=>}AV#+~M?X37`y&^W3dvqs^oo$6yTDDpWFo)3s znh6n1*_dh1TZq%d54rCW?3LxW*M)dq_rM`D6$lcDk9Hxat~aJoi%pX8=)k3sqt?JgbGQoUOj;n?nzWTukK^;~G3qbyOc z!T{2(-LVpm)c_$ZU^^ake;LgD?4)5o(%|h^Z0dT#HDmZxEVq2jNx?9sZ*sOb7joZ@ z-g>YEsY17|2ze4JVJ*HKh(HSLaf3AZ5MBFqXI{$>Q!f1Jw|olG*W_$O?Vg;Ez8U9g zpy0lBwlFPKL?>LumfH8_Wnz=7!PJpCgKPJ41ip<^Z>AAd6WGd!_-&(U;*@oNgTOuN z(>I?=()EW>v!1q>G>2VJ9y(47cL@ikr1IApmuEy$Xa`YESFrm*+Vqpyf-J?>OCR7~ z-urFtiEN#+iSeM1JeJYxOSw_f)Y&8(!;A-jYqxh8D;)V$*)4%>NqWZ_v7li9`7GKp zWy$7O-x=mZj5KQgobVcyzE4YOoXI^zu{YbM&`3E*Okh*<-puPg7%5xQgb)Y4jrj@1 zNxx26VRApFXg6nbRKpo43(ET;?_0gZ<@l2L#AJmJK<(p+B-G=uOCN;GW(at~blM}_ zwRslc7K@A6noKDOb}=4UD{;4LctBcGJRp zrUc^I)N2wb5P9^fLcA{{`zAK|#P`({`>!(BImlh{ci2#6o3J5(7?_5PxwoS$Md|x^ zrqW`tQg$DTg45nxlzgm19OfOdv8{`no;ssb`RIE55SPk}@bK}|YvwRe<+ou7*Bf$n z?xPtGIeMd|a=Pm(v9S-{SA z%G{)6<&%EGr~SFNf2&O1BP6bH$Egz#aS7uR9@9^GV~)spU46T8$;?{uXhF&qszChv z5VtTWPlGVoor4&b$1#;ag7&tEpOA$)EH}8g75M9c0$|zXyNMNQ)RKBJ%5_32 z1081_o$q~#Lzw2rwuW5eR(EDh^?pHrjVRxz$dQCt&zIu(K&gET{U)f%KJHBFOx zs95}!G?8Ratr57ZYv8FarrEK&bZ=_Gm6Y>pceItfMLSMM;u4y}ps5M?Rbm5#ALoW1>%IWnH5n`&m}T24@zet!PZ?D6j_kI3xVN*{G3A(1 z%=csI7NfqIvY{pH6}>lv3SdQQId2bX0{ka|CK=Eb63?PR(|~MAUAkCqd(>692Pc?zG8MOZ$?q_9FfECiV^=UL2e@ee|VF zKvmo>>VtAb53(Otjv*Oim`%>y6iDl-Pwwr=Q@vFoCH^+$^|k1W*vf(RT~-S5XVdO@ z4=YWYj4m3Afmi+(#AAhRFj1+7iF;>Z%Ahf zmk)T~Tve6h9Z-t-jyHVR`9acD{PxGlrgn|E80N#mlh78 z;dabHsw!cX#_f$XY8_&9*EB_`=3=Gb^bsT z_CQzo)YDAAARO3V0=CZ+%LV$m-^+Ibds=lmO|Eb2n@+k}<#^YqtNuE2;GGd~+)gdq zHI3tYuAUiQZ7)AJ1D6M`M2to>38hkpsfi_xuT6PPn_ntfLkv!^#cu(^w;!v{UiUfu z{q#$WT&9?ZQubaD?k*&vM2>vdP*v$Km*bT8x%Oyfnp%9;&AxK{u?M%y8a1;htToH}2Yd}>@wu3~_6{fW|q%CgOOdxd@PY(sn7B9c}EF@2rHsDo}X znrCKJ41lLAi&lTlZp+oCFWY-ueGhW-zISP3o}<^rycYACE47gaFSgi+?c`_zrjpS9 zFpHXILX^cugZwLWNhFR12*UKP{w@LSMJ_b@Az}CUO0c#e)JbQYJ+VPmatKjAbY;7T z`{J8%6s2y>ONsN7KocsWWTSyQ2VI&5X94XC2f_Vhd+bJ-u0FEPnr+ufVlKW6)6J)I zgR+DW;%v0#h-n22n6c(TaDaQ+JsnX!BgTK}Sq!+ym4F^woZ1(<5|u3ub&}|2zxIkT z)t`|)zJfSHX3OPws%*1c9OKF!(i-R1GuDUQXztmKE{%3!zuU8bcAWY7Xy;R7a#3@v z+@7wMvv0QxcFJz*3ObJ&0>X3_!0Z*xKFY|_S47-mr0DK|D?X)}o4=U^9k0ppgfzN+ zwfCZAH7Erh6F6shq1Am0zoJ+ssLF|e6OC4pyM$PZY6>v$|=&jOMU3?ct;%-Xi%+}|si zbzu2Ljfwg$j@oC<-))-a{8Fz82+sKKrpt|BmFco%JH~5WM@q+4EagB7HT`<-#QavV z4x+kPf#y0;G%eQ0tr~&5=Ek`jz5%oE3-A@3w{;MGbW3&JLTjDZmaVT8$QI%YWT3)v=D{|VbhykS}>FzrUx1$f|zuJvtf7tMQ zbPq6^GD7vQqC~gmmk=&j4Xy-$D<#)NdKWG_3Xk6{JN&YA*8Oai(B6k6F1g0lc2q^e zdx1w8D|7{>F6d8WplomX)He>O=4Ca<0Y7v^ZgUy5K5(wcop*4K&U5tGI`ErLXk^B& zoSK^W8&OIlVfl}?6+U^-%O+LC8BmcNF+DhJ3)x2(e;r)vr0JxJzFZzN|H6Kkn*1?k zZ{92J(zlg~>JjL2+|qanvKLm#|DXtQjJ!UX`O}}`5L%fLz$g6Lf9`HY*V}@tviIz> z!rJYU?`dv@{L!;K$N3UkX1kO)f!qVSkOyQTG}SYNGR38s38Y}KFL~f4q|(GU1uR)m1elq5rRu~W`cvpG z7BDK;!U9bDv5t?KVu+r|8B};$5rcmL%fTj&Ocw9~4ZdRHj^h|AF<2%BVC3oVM70>v zAw&8?C~p?ftjEaJEXLiUY2&G(8LnwEwwe4v-t9qg?z(H3^rkBpOSsK%_EGG;JqB7Y z|2Fyf4RiI|qB;*-cA5tEaE;C1byfyLU)oRDpG%s+8|P~-9X)0QmG6_HH7CvYbzK_nRU0%S%1H2voP-0iK)`p zp(}!_G$Xoud7rNKOyk)mf;e3~SCv#nO+ILP`Fu)~k=x-Ub1_d)@O-guvsj`DCJ%cG zA>Xfm3UPp<*j(a;Dr>_KlpXxTW4WgklNI)FB%z}{xHTPO-B;s zy|XNt&|1_ZfUqL-r^zG;JSM3O9$5eFq}{9f@_WDOkAD7=eqkw@7&YV=rS{u1SERji zDKm{=(O0D#DxPninS7~kVQm6t99RecBm<@JbfBtXOODrFW-yN?RR)mih!anidCZ5C z`)+AE2Bg20HUqfzIPM+Te6kBzmU%(3onq6503JHyO3fqJPpjok`Nm~)msL4-H>w^y zqq5vOaC_OUakU7MPmYJsfcMtCptIP*hIwifu*o6bDL)^c3Anf%VWYj5FM>e_%!vQ@>9s%~k?V(2M>#Vc1{4)$kdeG^_@EBC^$H>P>_ zWYI5E&Qj|bPpZ(o3s6a2<6OEG=vTUs=y{A_>{YFkoB3HhCB~>Q@0-!}cir`#R-I-~ zw{l?|cFa!bKBjCiu4Ph@k&jgFo?$?nYdlfcUyjZ9&fh(_tX`|aG?noooXMF{u7@8( z;UNla$p}Rj~JEF&R*gl}&Csn`z6Fh&_zm4qMK@ zKNRrjVgZx;7i@kZ|NpO%NbcXYpV`BGp_`fsA}nBJIFbeA#UB27#qAF_rvC@B#{7w< z4}HfL=d=N~uugYI%`Z&;%uToq{mNWp0kng*=&k!Tn74ms)&G^eY|3AMhQ?`=GRcQf zwK?Dr?r3hz787d#Cafays2#SnY)MKi(lV( zj};4;p8FeJY##f0;|p|&=VHdxv=Znl>*`Fkgx~%B^9tBM>xhe=n8%RaR4g}mb_Ojz zhZ1HUP|MBnaL9h)b(8Ys^_*f=RkB^TdV1%VSMu+21bSnXrz|6J>F zWK3-4YUX+2bq2c^l}ROlSJ<7Xn9SAMfgL|9MEtSl5?2`WKSZ+i1pJfFE0-AQST)Zr zgn)mbKamfq^zyO!2Ze;ZkA;tll0UYF0pbU-Dr5mt5P6>wSv~rAytyMTYPrLrBHV** zr&Rfuo4l|N>>5kFeOi2b%qCXu#mRQ5B;U}4xEWqmhqAn-=?P3Z&V{sF`CAWoi!erD zMr^S4#r|RFCV#^3JFt!mnk-;;oR&_;joD!~*VXAe(3kpPYN!@B=4TeL2EnoMFn<{f z=nVK9U7&c(Pq(O-lD0kGB0D%QeMcc70E}cL2=)Zz7Lvgjy zR2yYxs5uMZa32h??M9Qwa1}TP*9sd_pDjlHkcRxB;}V7i=o7xMF|;uIms}PQRVdnEa0`DZISIWI-Bp3A>>tN+k_$uFqy{K z{QZ;S{@M1&93~^9e@kxtF5LhoQ5Uv~{DS6VV;yeFDP&OHH4J9)tH3@wp~f~$l$Om& zkwo5)dalH|xb+L5#s3^({u(J3|3#SpHNw>VsXNJJ2NvK@T*eZz3*P(%n-4L4$48pG z89h;3GsyecjDJeX{54Yb{pnU}+u^+TEoCDdadyhd%3ijdB9j&LrbpqxxdP#@syyW) zy!GK_^0IO3JL?LSIJ3ynQA>15qTaryt$<_;_>0kTyE8u$Zw8ZY*roiI&*`_D`#q-~ zP#W_Ktn9Dk_FwZK%`lA7BSHw$&&k_yrcQ`=`6DVV1hp#{$Mc*8aysTC3$19r?HP!+T7zL6OT%{Wmnn_~+)=YzD%ypF&eTi#(0 zJeJ>0yp+iqyeTHK9r(i4_HKVBb9X3N^_#&bfk@4fGsY9XYTxeYkxl4c>Ue%`HR#kU zSjCkiCf8EEA#M5PO5aQe+?(j!ojH6Zm#J$M#TW!^+KH3u4QdqA9r|^p1E>yf%Ha3- zBGGuco=oW%DGD@mbupgsu^p$aiV0@SPlU?o2Q0u7v(0=)ovX$FjnjOM<@Lh(p!sjk z^CM+|v-oBGO&ckh(;N|pnIUX*`XursLKYMzn>&Jnl+0EK-!NUjDOI?Yh0TCnZOn&R z!ol@yk(6f_wCEAnRUx(Km2K- zjx3;p+~rFTaY&&5Ph?sDZ`U)wMsA=#&A*xTWZ#Gtx~0nuoV2@nrq$u*F-N?YmE*aM zYH~OF*oo5J>4Ff&J4L{qJBQTi;!}*vtr_ldReHOdS6U_H%%!7VX%<^KJ18tzS%=@f ztZ>Hgz*TwR{nS@mb33FWMJ8d21@J9Qs!@2qkDK+WDq`!ODW7~YiPuWC!G~3N8!GPR z)&mZPoq$Rqc7pO04eMwp@bQ#1S1Uf{owa$Eu|;*=^TVNos|Sp3L_hhxGbz zr?YsksigNcF;_dOJ-e2bo&Vv)^54Koi?mQwJ-M3&oEgS#4gJ)g5NOR%2Mx;mf(3L` z6+oMRjbvy4DVqG%?)dyi?H5B4%G17&@f{sdQRF}$T?+K3aO>`P?GUUlecxC@ue3m6 zLp|Tz>wRXpR=(l+YwJByy?@{F2kANsFcu?#Ci7^z)4!Fk-R(ks%K~1-`O*~vdVZd8 zT!vIdGo)NlMEN)Wm)G%70=|X$ln1oBH0aTO~>Z__J6#Vv+G8Q293~Z&`eM@qWH6+gA6B|5?&HbH- zgKaTbvW@7GpGLI%Yc|{+e!&!GtN#bD5rmqW7)KhKZ_SXt9%|D2YZZe0a~Sv+3}E;t zqD}*f`ZCm~XPfx|NuPrv1arzr%~=1-AsFEcavZhm+dLJ`4OXj{epu`HS#kI85Q3uo zm5=i~qe0h$@C6LXQJ*dJGQ#38iMmHukrU2P-{oL|me|b&o%Fxc>;JCNHUA6FURHfc zXJ-<2c)~dK6+zS$%1*RY~?-K%#l2jX4;kDnh^vFv`(;{~kf|B-ORke??{ zkZmf+3GXFDlBW6eX;#rKbO1_CL8}73K_A5-86a`cMB6% zp0Mft62!}c2cOSuN^DW>U81xz+yy(tR6cfa7<^5(G*F&eiG%D#O6QRr$voCFhx)PI zp1#vy=|Nh6%vI;WtTM}^HN+q>vPN9?v!6Lg;$H;EwlI|j+DnL87e;K$+-~k0`zkf>-b@%@~0ovdH`U?Nteb*wM zZLS)lmLUpFiBO)$16;bR^9GQ2gEq#|>zOD)4;|k}s&c85d>8PN`7`e<)oz;hp0MA; z7y*cBWt}DW|KYs#pW?$``lx9W)(Wd0S*jvh?peqd9%(?qy$k1Rtj3(rs4nLo`C`y^ zAU@-SeUSV%e(ol*9Dzcmp8;}2Ec7O9ODUBAa)+>h&NWmE0@;aMyQGRE@7-VlNq>zS z^Gz5NWyTz+VQzC~0YCI0WCEmIogrlIOW)qe0>0k==_X(^4O4Q4YRCd!KK5n-VQDye zf-zmYV=0ye815Zs0UYY6O_{&On1PHW)Z9x))YO3$79iip0{AF2ITp}&u9^kBHzzQS za|GThlO>rvPGs`{BsU{xEfaY;D0AgQ;Ps~bi(R1b&U>}&9( zo%ZUz;ke<%Y3?Q_Csy4PyqI0M@-<(+!AE%`1E+yfS;x?C?w#)32!^ObxD^u2l_Yk~s8yj>l zl@OK$oj12kfU@M~jg9KU#?hB=A3s`HXvP(+{DA|-X{NzFR1J_wGop)ty_3+gBcR%P zdu55|y}A(dizBJ>I|b6MNOzB|rab@cngqbmWTayE7?LHap=4-tlSJ-he4a6Nq9F?R z?&HQSf!ppu9o0KR*8kt!ANC|a>2opO;@o;3%cu-A@J!*P9KCdwi~Ch`F;D&Xo$oX1 ze|K5Mq;^-_XpfKbyw@Mq7e*J%q`-)?O*p;;QM$!2u{R(p`;>LI>s>zG+A)b@uaEZC zPs4OLop=0AIs8wdEdDo5azR}<7;a3-i_%1Kfl(a(xr?d(qZ6(7O?Q0s7K#On1Yw8R=n66#0|6wRSuNX$Yh`NELl4CnKX?MK8Pm%yXI}uI=kxy; zed2#j@?Vqu^OJ-bBcNd9R8LH{;9JUU3&}uDSvbdb z31BJze*%sC!r?_fcfzB504U(oB8n_3JF zW(!uC1q?=9{2y|C{mSt~|02x)mkIM14wU)N5hm6a{6?8=mEi$jk$a|sS{x-UEZg;= z*n93YkGnMkYvu>kLxSYm=h~?8Zx3B7o(d0c+IopQf|dN_H;n-gevtWKc=sFDr`?!5j239&qJh`vcdjSd99YQI7#~6N#V4n%U%PHc7`WXRw~DL zJxpEYk_@k$y|cREmwfaR^8-#qUyBYW?*Zc}?#(*B57!#+^PFOEsQBO)?3YTDUQhVd zFKbOi28;7`Zoh#$)SyS+I16HE90UMAl>JiK}C!AF2lr~tx0j{ zBz#9n>H2KhVr5ge#3T$Q(Qz?oq7Eq$)l07-3i6DVg`2upDr|^-7bsdG=7QEqCL#7mU0&$57nMYq0TOo?W z3R5=#Mm^@)IxZe6LRZeA2T@=#bUvB%R|w64(m(eM(Mt&1C{5Utc`P zzj8!h|U$ZsVbY; z-Yh5FdCHvcy-aJEk#V*0FfNlqNpm3AEWv212;r(h%|=B73cYR#EBlW8)k3XIEi-Rn z?{ZZo&u6#Q3qN#ri0|N04q%E=(jH*>5niC*wB;CQ3ruj$NuLGSMqHrSB$SLgW7F^D zIn@=XIll2UvlQQ~7&syC!7IhNPNQB27fa|j`smig6^Naq2NMd07Jr$mTTjVm0TsUS zv5sHHAB&?q-^KDqK0e7e$_cZy{jMIi?1NBb0XuBLlpKe*BKq27&8QMTi2!Yzy^i=+ z(vycq3Q{Z}`2I*Qu134vQjorbkxKWY$TyL`!K>do;_bR@Z->JdACVr8o)mv%;uN%v zM``;WKLdzEAME4jQXJPBE~*UdAeP|T=8$^$@is)ZQbzk`Kh5f@8Rc`ld;B#$l*vc>EUVe+>oaz_GPG0(GPT2JPOab@*TiBC+6pBEVmJTsNw z)#UX5vG<-~O?Bl5U_v*2no`AL=+T+ND~n- z3ZWyB4$_oPs0o5n0trf(lER5=ogZhfZ=Ze6K5OrFzJ2ZWV_X+=Ud%Bvp7E6Xo@0*Z zS&>L@Hjm+-IjXv|K|NkGf%CiQ*@bM-=(4`95r#Zz^`PvBfuRVe8h?GjO4s0wl~vq0CPW4K=LWxjL(4nNeb_L$mXQ#EXUd zn^xWrNx%Kr_l8rM(YhLV-(|?=2F(Z_4S<7)fkO}6fk0x$h0e%hAMd&bPKT0wM>JPH z41O>RpdGu9lHu8Tdvs?})S8_C32~yHg4z69PIn(`)A8GJbAMO&W^Jm*wDNOi+kI%) zjv>OW;=bT11659rZ|wUX#Vq%38upGk53UnVBD?jvCYBRWNrjT+EBV9%C)1ijE0vHs zDf@F?$LG!-rOCNHv*$l;7t?uOe%|l|jlH}RA^}V5EIdjHq9ZvBy-WH%D_}Q>)RpfI ztv;Veyzf2nTso|D_cqTVH|`kza-8oXp52sDq=OMzZx+sdP^J_|w|WB$2y624)Y*^h z8ajPP=}3oNOvKXa$9){<0q8ak1b~-vJJ5IuYR=bcj5^$$jJrWW6udT5o7)bcP72>0 zIBI<)=w0`)xWi9RoX}5P{5F%Deg*I{l7Txx(+sA1svmNPICUF@JzI90aUaNebS6hd zSpH6ojEu%0+q9>INet5Z+0G&smXtM^1H-%&%i9H(tG=8f0|mBn~8)d@gfc6`nf) zsq-ZCDR*D9AyH_8@QaK>BLTlQT|l#99e=IB2=^MlA#Ocfa&e;I0Q7vNxJgA-e|tGA zGE=YRChvVV+Mf9}Yau$-lwfoG0Mu>)30h2r@Ee^1TCRUZNYZtmP$$Q(j-7H&i+=LM zrReWxH_nb}>5TSKT0+xr2AyW3`BP{_kMHfc*adB%ynM#I!X1EKEo5HscP{?x%R7@= zbqlU>rorGx$HorNuFuA3%Q(n zE}PguKS{g6f}~ZzqEqU2yJh8~U*6^Wuf}BKY}9ny{XXaXe0@*$SXE<3ti*e+-ScKh z{RT)qq{oJfHFFKP>VvYtDbH?$-sE7qR&%EXDT1@$4(9G(*DP--dpwr+z2Ez!R4WlI z7tny`?+jAvzzINnqJ4>>NTKT0hJ457@y!!D8|e933ySEAZ(cvo7N2jOc%l_9-NnAo zD8b0#3UQf>!iZA{JZoyc?IANMVU>$)Kw!5xXMW|z!^w1V-=32me}#wq7E4;E6?O9#UK)bw#Py|FMydH3cMl)+qvndTl{cJAYnmegHc6YYL@Dxj0 z!?0~ZX%2|WKZBtTQ$%{9cqnn?Q-)3F!{+O`o%sbOM>KBbSt>ROyFRM5|MBVcmR;i# z8HOo`_+e7RaU5+&V7ot(kZy&0bX%_CT#z-O`ebIz|8;S?lKOb!02F|V zwSzlO{_@k2sL!0t#RM$XGGb4=HoZ-Ra2cV^FgI&}op?;dcN! z7RqO^uuA^16JhyAb8K|qE#BTks#N>TJ&}bJ@NiK|(63hQVi=mqy-kY-xR#(Xt!@6U_DlUxLJ2E9srIUe)l+Bldq3$nmR8We8L$P1zC z2A2CX4<*^=NSUb2uQuvAy?2fIvwA0m&lw&+jEMafiut}r_5Rp2hFmIHtn(@Iemm=@ zFWjt@>YZlS3Yv9k4$w<)IC;o;hbSNQZP`zk0#4I`&Wt&colvcoRj|Dtv^Z0>%eSd! zN+)09d1wnn%`_#rkQ~wGe3K-fu8fiZ^{j)K1xPMd-W;H@%_@9%Yem%u$zO3Qm4;A3#;mrbS7O}M3CO>fZs>t*R?+8w5X zir21sr9afAGdJ*32cTXQplApYVafw(j^nz2%JJ?!G`OYjR@~I^ar}<#Y^0RO>W(cD zT=4K_7`xC{K#z!=;b(H!2GNY^XC}ie3zN0USL^MLw5JT(otqn+ zzAt(+MwxvdLM_Ij0-IVjUIF}_2cVN}$2S&F&MqT@LNqX2L7>s^zMXwCh5CW9Z?0W0 zRaX?7dn>`diOD5H5haG2Pli^(S<)=jI~RQ9q9h$To5Y z&3ywQ`3^uq$Qc_O##5#m`~-P1p6*h)!4#Ol4CXjScC8ua=%1a#tMw=MWL>Gy!YZ+` zeU{Abf!H(u-_bKDVh|}=jr4=Y;my0W{d9()q4fqm=;1qIR(d;IuVkJW^Xi|v_E0N( zIB;>}rwCQKsfoNza-q4vb+3SD-ou{sx<5L(rGT%oQEXq1aX!)mnbF-3``2O*GKjCp z9XE(CKTSdx%+Q2RP3`V*kwgwainY|c2cQqNb_bv_Ax1RP_`k@3@aIu5a|-uh3CDQ4 z$cOyl;PfxYKS@!0Mmz_g8Ef(sGl4~D|MkCx=-aSbVnfFP2(<`is@`CZ;e9jzz)J4G za0C9tUpBn69`!H0h2k?L=7xj5WwcGG%C&JXD_zLFX%oeGf(>Lnh~NW8XlG#UbZ3^O z2Mv9kiq}ORpSAX{a_K(*aECtCL#=yZ`)WQ>;t`v~O%UUCF|H7r(53@))2!*nYR8DPPJ?$9k`woNsEGhXqk9BU z?u~8ZorT5Ok$dBkI-h%wSBF-XV*}H8+-UFBY%6|WpS%3dcqFHk{R;~-rm9i~x{*A0 zkT-F7ho$PhPxEf}^<+r*ML(FYE15L^ts&=iV9w>(bq$?bF2|=$=lfJ+9=4?ZmcIs6 zkkhCr3J!&kMT|E)b!iB-M$S*5l0pwaeE9hSRrB|CGA4bKJ2JEz*PwTMjBj(_0r9U1 zq%tG1P&|4$w-Y^m03s&EWAib`yC0OnvTeS!f-$hnNdQMcxW6lF>(FZN*D9;pnclG% zB0zV$in8v-ys6vWYB&IKw14@yCP`=ilSx@uBbgkKjbFIZC(|JA(c*sYndMyg+s7?Y zyBGwfa~rQgbtiMB9DqV>9_?$S=TY4-DGyyqQ^_|*nMB3Fj}U8L2fuL6Scs<4x~FRU zwtFt=1d9kr>oTeg&B+&*&2Z^;s01*N&PRiuflK68eQlnN8B$5syD+7MQ4=Be;`{nR zhb;z@K#Z+o90!vF9yN*J0MJBg0lDNVC84(?ke_qiNbai|+{62B($&dOpdmWvy!V_n zHpW-tQO~(ERYM!d+V7i+1PBVu9?H-1F2Zn6;zd(pLq;{E{uYH-y!5NpYs;|Q2H~$o ze;?AFcCpxa+#=!!0zYK-BeBAjG;^3p*A4ZFU&*2Vp*APhUB%5fGUWQDP`UN?&WFSr zb_{qO!%0q*?B$UT2@O7LvNjO)u6(`u^{q#mnF_~3tSPfNH0 z!EI8&z$>^S&{P4$b^L@O?VIb!h>y1?_cNczoRI1mRLWT}e#88`2UPUDL<{rz2-iI1 zJ%ofJ^3R^^V4j(xUm^@Zk69812BQA9aw)u}oTqnx(4F^0`aLMZ%U6g#$ZVg)iE7|( zE#lQjmd-VWh!2ImR(oC()ZinJs^htT7CsiV%7G6L?itA!+L?;aUCMdnSu_J%?2^6! zs8A|xK59dO*wqEAS$&i3{zuXa`yyi3jI+1iUufV3A#a6-twG};_2{m}6sRckEc`Iz zajVAiYSJaja8@aFLwxI5^TI{v^<$J56LxKW4~@sngh>gdY$^DoztO!RiQ*W#z{aw9 z2S%LEPbsW>19R(c(7yC`&GqHR*+w@P8JbCRN7j{%GY?kybKCSi+B1zo;IcN}KcR<+ znniaVfNHKTNYuqyeNihd(A6y%>Pk?1h33@K<9%VV^h;=;=dr;Q!Mwxfw>4K6lEyWM zTx%O{`-{@^f@TQp5uvDEjSN<(q+h2j_Gn{Etm??u<5%&Y;r%-$bHORZjQTSOo2^fL zdpl>@7+|eOheX$ zeJ4q9#1cH8ph34y~%@G#u7H6X3+_95)mRZb!$tip1lVop=V*f2H=zAL&_Lc#!>R2!vq5IVhMe{$w;a7A#74AlJfFyTy~6^z%%& z)B;!Btpp<$*x{7ZmVM0ARNnOEk4R;-B;Ag<0iA|Yua4_f-`JA+D+(h5KJR;XYwhiu z^jhE5+1c~mks2f%%>c-y3R57RA(;zoK*qa`wlkB#vXE*hkG`&xM!N54}G z1ma`dK)Vm`T{gxAJ80|ys6MlZ1^4ku)SqOH&5#E~s}Vk!fSX0I`Z5cFlLRi7PK{Yy z`YmmG^vLZ6F}s?(_dfv`);d3$TCC|MZIjsvz6q^C)q#b_KThaa4M=!g+aAgpIyFwO zcxB|A!F%WHw!0kac`Wzg=j^{w)K7oj!mWX8r!uRUJaBDt)#7o4{QU0=o40&VxJhI^ zzb&Wu#Krfqkavn8yo&p#g~QK=MC4M%qDY%0Y|ny>AtjMxL)iQy*Em&yS1t80IiI6G zXWf&u6(Xd4a|pS#Qi9DBW_Olz0GfP#BtryY=seuyub(n|Rp2G5AWW1fZD;u8%-|#B zTH!Jt=ZFksm{PBd!KI3AXg8|kepn-%u8BOJ8(s|5)C^Gz5-MZAc_C9TdhX@3SNv6^ zEt!^v)b&ZT9IPJ7#cy4qIn6({MLUrc(q=dYU$dKsfAg*6X8N8>J zLF9a}^B5-TeNKjb|6U2^FQzvxP>RQuk$$IDf+hw)dc`-}#3%(c7`iL+*-M##aLY)F zGow&2V{Gt9JxV6I&#*V_*j-Ne9$~TT0(54Unn1QmJ^*>`0dbHxOz_RPF4vIMGZVtF zl^2e8qMwWA-xv72dY01Iryyy|wd-Uo!(r*jrxeC7DaG7;JikLE{Yd;V4LYP zKAe01cAlGZP_@_DEA9r$5%EzeS46pFz6)7V?*SJh$Q#rdpoqrp4#PO1KN&Eeg$12Y zTrxEp3pvdA*a5E=cbC)aAe`sz6g31PaLgfay>C3uA0@?tO5mhcNOZ{@9a3j3s z+v2g-IiD`8@PONps{50RByj*btldWT?H)kIKx;!{e1ZJsi$*SL7;()rk9!{+AAH<- zxCUGM{C$Vd=hH&+N*t&-{JcND=R$~IfHvY zL7pN7Rxvx9At|l$8YI_xE~wWttf}tD%{^Ix%kvGJ%9|yFstpLOnVG%-fSvlJiGm@q zFw9{d==4uJienK0on$0hXBi?h_D%ER7>{6Uj!D%~!zv$V+vb|$L+hnEylk}osVp-j zq)_aup$!XW?J?Tu>|~8kH`K;=w-XOQ0=H|N#==xC_h>X&s}(=_@b-#As$XYSinx!K zU2UvQDq;{_ORb=}F~8uX+oWJEy?I+n1Sx&{)~2Sqv0#(@N>qcpdB8hG0ol~EqXPL6 zeeIIR*%+#@IOnv^eaV4^d2*8klL5s4SKOuq3_o^T2M)Ywd+xxzfDAIXlj%TOM_ z@H}2|y;q^X<8 z!CzjojOVx1^!r5kO>ftDrIakxFuM6^k9UF@-{2!1_^(P^>x zJ}Q?bvZvWEdr#T%UR^8t%;mu2qPyjHcSpfXhpb0o68u=EW zUQkinE`lYrf`giKCN8IToyUI_KDT-0Jf;IPW9kG{(<11%fCuCU#HsWJ4Q}|^(b7B% z`6fU0I@Q1kr@cF$X|G?jrz$t^*i+iuuFs{G$0NG_sDG>BaT1@MdP|S zA}iz#xA-s*4D@85x^gQttGFTgTl`H+ne>=T(~O+93pd~qz`c8Kfn1w3GfHk^nCeHK zuE;wI&q=y&Tr;P88*3wik2ZU~WN%QY(4~N5S|z-T4nXaH(bdQuJ?q2`bHJS3X!iQ! zuUNMvt!wWM-_icod6z5t@TitZ*+X1y-Oxw^a;XG@#l!@OB7FiM8c2V9AL@px?U1B& z)Yc7T&&P1pfe;0DW`ZE6KJfc;dOqUC0qEAE&;e-u(i^8gL~>K*0CZ~cHF7$<8@c~D zK#*;h@o!k<|BMFyXFlBh-?#6J)7>R0B90;3twJHmBEQp2fmwn-R`Erqyhq4Yzt@)^ zd=XP4m?fXgx&4Vfm7)Ajz8A_zKS5C+upXn|EA4&TS+Y1AkmEM z+`aU};ygzx2=FBAZ9bxCbRcWcJ?KYyndPOH82FV5!%I=+BZ5<$qsqI^B^G9#bI3Luk^dhyIoJ4{wAAkg5Hg2s^VxiH2Hg%ah3scskGXu%kq0cvb z6<_QPIvwjeKG4T7XAO6jWo*!C?Jl%9>yKzIVtLYTrPPIXgJ%CM*zDDU6_+}TUuju} zayk|sk~MNy!u#?~4rxD89m544fMy1WxNZ#zx*9MrG$43v^0@6b$6d(H?XZI zIQ!$ZRm-3CfRtpC>{A1`)|J_JpuLbNOz6_a4o8K)s|)2-x;NBQ8Bteu{;A*2g90 zKI!rOtYA##@5Dwffxkqu#&L6Cq(S^pht0@5M2!v)Xs1)#Md0Eqy@YVj%KY-tcR80s z{e!+)OxjLA>-nn(vDVk_PzKo?qXlg&Vv{<-`0$7M*KDPI^3DP0E+iueNl1I+sm)IXwKOGWxu@e{o%pkt{fkQ?8z2a5WTVq__K+sJl@LA_2~j8 z`3C<7a_imRo6Iw{9wv|z`A3qkcYr={4+aP&%REL-ZViC10gq^Mz&5d=3zv99in7`g z^oGt4K>dTX{HH{mL?YW-D)C((dX36gP2~J~6_~pN@Fmnj0s7UrEm!*@AH+u^8Op}8 z7qlR-OfV{XZAOkGas)+G{SXlt5$evYPCT`2lOYRBZSlO1&B}P^B${bJ-(dk$7~n*m z|AO$pEkYFgM7WU+@6a>_G~TvCKh;=d$^JW- z#rkF(mYq5^1nGYR5yTAhPS@}4{3-atk8j;S;qF+&jB3R@ZqZ`rJx?e*{ht07?C#4R zM_&8{0hB}9M-D+g*~BCC$-(7I$-;rws_qjdZAl(ucgltZ6;6KggbxT4()1mIK4KB3ku6I ze`0s2Nxd)b#HUIDmA`rU!I$8Ij4Y-+{Tw5XZbQ=u%*)A!q}EmILu(UP@&2gqa`E%s7M8p0jZ`!ZXuuyb-e6Y6nB^yA15A%gy{TpdVh_}wuqg#CxjA-$ra5gpg6 zoG;3kFP(9$AG5fAuB#SgGq}>niSz&Qihp1cUryzrG@uM0EFm+IwYljcolpTdpMRjI zV4nTfLLBwdJ4at<|1q@uB+C}sB zRF9Hbfcrs{ywYV&toxqy0}&+Ui(}--#&q*D)w+GmVHNU?1Oues5V`oQ$4L3 zP+bO1$~M$tbHdwF`D|?U1H1%gd$KH2uv?ktvvRTApLACt+y|hWV0;My*^Wzx)V5Qg ziFHU0*!t+b60u;6XCwCGPeF5?tTesLE(BYpzr*qCW#RB{T!7yz{?E`P@O$&_kYmiQ zDM)Q*(em?F-Q{y(FLu+U+%7e@&X&V$8tB-2EPUJhi*a;TXu@1NVprB z==W z6Fwte_L0(xB(x*sPweR>*--COY&KhH7O(-!W^%gSY(GJNl-=E`464{QC2)1sD$qso ziofQEZz0cK{9XRpeA9zvfLUdTJ|x*8ft;8{mRnxFfhvKqTkNP2$94LB(i~EIW)CTQ zKDpo=e5~8{kl6T%9kHVz)fq?t4p5p(N614up~=WY^niWeE==OXhdIaBUFUvUpDL2d z{{3Y{x6cJl;!%01nDuP$Sn+PdvMktDs^J7;aeAzrfUB?F7 z*Di~48BKRM-PgO~LH#1voBdPsrh(I1Pz1U=Bo4=Cqz~LOl%hD8q(MjJ8#A}gc}K`= z&RsrYDPZBEaE0x;xAR>K!;{9~6Ug?9I{xtMmGB@&Id5m6@(WEyhQd*3SHy|Tzk~C&A*bC>#%k4L7Aemwr^4|g22!lf%pIA zq`HwYqxb;ytsXH9rs@Si_HX0~NDFt^ln=C^5gN^dm9E%5nXx(b^cFRni9`%m~8GRFbv z(y>_UOH!kRFPFy|=`yEW z7n5Y)19wN~{BB5-o9A^u;Ii3CPFnMD+S9jMF~i)~!7>Zd@z7c{DTsCvHro@9uDRAk zur_TsIzRq;5^P4Xzaj4*nJ{(oVpR?rp`CEVhZ(itpw&3o;%B zrj|DNA3;Uw;RLA*pWaUPzuj;>y-@JLzM($su9)}bc#Cef`^CCS*^Sl^l?KcZ8N#_yEXwbr{`|6OhOO;LVMbLYFv)-orm z3pF!9O(E~~AOU~WOed7gC{L%Gmg4;vRKJE{n+%M~6-xsu47E&OWPLeZ%-*nKYXu*! z-j^~1!9~cq)KK6%5qTWg=!MozrB#Pjz=Mhh2;a!Vk96^VdIr%Qq=IKkGT5DC`p*>a zAAl|dOTfcF;cB<(f)Y!pIOvjo2T}?!pnZBQMi{Ldy1}zZ8qyl}QLB?nxq6JUb?WTO zxU^Pfozt!>Ylgjm6itOWb^xmF-OM7Q;vsy7zC|zW6Rv3mPmJW}5i>E`$DC$2vJjlOjqfM)&rgd~T zgm2!X*44^O%W#z9+BOA|fBRi|sP7y`k211p^XI)L&`n-8VW62Rz(D&H^Td~6IoNK6 z(borWv9>D?S{EC$o~yL4h`nd;yJE>0W4VUYf8Ye5q_~$xS0k4=0DQzc@>CZ%t~o68 z#p?i(_AaN#(^~yJSHD&zst9=OR5;IDK6G@yiD556bl~bBz3B8d0ib{u1bjE2z#`e3 z`@Ktl^ey7Nvb;_&T?&!(S1rb7>bIPZ@8A_;JYkKe4OgQH)6GZ!>?2Dc#+vIZ%fMW) z;tt}lYG70vigZ~Ue<>u#H28x$@16U#0-XHrkA6biZKmC*>x`HA-3K5(=5g3YhojLk z3cPc8Qe8IB`kJx{*2JP{=WgwhX@dBbbp6xI3R7FUf^5IpX=hoG&d^AiuF60g>B4z{ z3?iQxj^H)hD~ygRvwU#xo5hE}65h!d^1wko+VMVpb6RJ)mzWZWc4U1>BF-0@jH`vD zwE7eBN4Ntc5kp7u=Y3~F-WU~ygelYvP}vN6zV<48=84%n+xR<)G{Fj)(G&?LcNt}> zd$Bg;6DqDbxP{QTi%HlM|JM9+%;Sby)j-7}&-1py0iWS++gp3ZH-Gi5wy~UiY&wGF z9t3cKxTAo!DG*e#CLYwA6cYR{Si&)nC>UC(Yjz?(Dk|1Ob=X*R8(P958-I!#M|Fa^ ziWtRhQXA~V!+Ra5)DJE$j9iyMrD!>4dw&6L@8*<=S1>Q$n)6PFv|7fMIoqu2$!*m{ z@E^Jncn+b8>4gfODk@tyXsf+V8MqZ9^=!ahx32c`aK21Ka=)y-$OH6Kz0CuV1w_z@ z7p?+Kl$sXN9m(&|#Hb5C8iy7-Y7BX&=e}BY_BeyMuZT%Xt8x*{H&@8oOM!DExqugilV2Gw>cq1>>*GMIv3zk3xFKXymBO`Lp27sf?E$uGXIOYQ zgrAr?xxmvw?vky0ZsSL`$oed_lzq<8y6VWcpibDs5*i4B2MZt!;2HppQcKiGGBm3M zob1PxaE}Z(yc<4@VdR^ftA%-VGhHMj(z|nHTOT!I1|fHqU-1v2XK+*l-~~B~+6y$% zOn_X6QT5jI%iAQ#`&qp8-MtUd4YsLUkc$cpnYtaad^JwLKcr_~qNx6PXc;`a-43a{ zl3THM0%p_su%7IWAJXkuKl9c6Zn|ei5MECE^m6FHV&)6RDVAM9AVJ&HI2T6g7F>}6 zCLoiS$+=xPwyTPx+rIqN2qABm5=(L2@QmVT@Vb(1z#xQXi#&D_Od?I?{=p-XQwM z;X+2lnG@oL<)u~x$O-)1rI0}0DK5J!IjW(Y7WnzwAkqADFB;`D8==RTz0i|7C_p(A zM{}E7k2HlruGj6zVJ+VsE0v%bNI>$mgJszVGf*eNxm;p>;8LtD*K$Mq_Ovgxf`LW` zWCRjzIyEHy0?8ZQ_$mBuzDpdVZTV{8>qfm*ee5&gzmI*!NPfO%`T6@H{!BFa8aPed zyk~<2i6p3JDdW;yQ@bfjjUV4Phd0Dq8HtC;5>vhXRznJkaHuN z4nVgKK&gdifZa001g_?LS`}S|B0Q{2Y)P}{r@CQIpA1$w_F-6GM>Js>_E{??T!o`y zU6JLZ&Xe`2lE6ka^Xnv}&YYCCEOns^q4;IlY!pjUblW6j0|rh!)HHtcKG)ZI`O3WP z!pO_SZRG6(&>!({u2IT~dtD(C0g-0Z7t6HQg&h}-0#lSStml3b!}1n{9O{jYt{@%^ zpS4;0;}BD5`iL&%34|c?3s}lX5m@xs zChh8H^>*((py{%JAQovH@~qhYb7<{Y28 z#I4cr7Rw-S+L^-pRW;3|JPzJh!jjLxmA`DczAZEmMx^ON3=Gb9k;TkJ!+4@d<~ASxD$UuFCI)Si_`kCpg4Jxyp?hf zowGW1IsK9jr7%M zoYxb5M^NGwuKK&y{xJD=>61VR;iC4Z1{ON9FY2NulJd$px^9F2?>(}P_Y9=`v7!g$cjZ^OaAc|2J^o} zhbbgTFp3Sj;hL1ViI9eyHcnul#<~rhqbnlzgul**?1=ltZkgo{L?^`X)qQv=K63y{ z?D>NG@sxh`0Mw!Vr;?_Mk>F377aVDn2Zh*L;{SOt(%udMfi~N}oss>E^_xiJ41_=J>0K}J3g#4-kyf^^G`;;Aky6pb(meUjqi1&fX z(|8ev06GN?TnT{E&Hn8*3&Z|rhyQzYXbvV#Em^{?^y9_|yR( z)X-8Tp8xEX5een{MV1_gEM$WJt;q`dgLe=M$}FHCQjA<%wr9B<_HX>aogf}&icQxD zU0zp%DTn$u*KN2z`#JxJ8I=F=mg>g7^8bn*Vh~-CMz~_cu&ZK23N~tXnn^<$I!b%tdP3?_qWlkP|u%?lwODps$ zb^cwsHc;r)Fs?SKb5W3fVYD?mkl5l~m+e8prRY`~ z*C^y~hDl83&G(x;%rW71NR&Fl8Do_C?-7T-^JFNB-@ie87#Gc%Uygsb_Ac1l`Buh* z^wvz1H~l@9?@nzmYjp7NMUHedES&#Rz5DU?qL!kv^4;&6W>#|y#HVfuX+rLKq1Qn4xH4-wRvn`?H$V8;R8)yQ^ofvN zcJHYVhEkN11Xg&x;1bfxMhw#En*4HHA@}OX*xlnVm$Z$y*v_3BDZ=z5-!UiI(M*^_ zXfCFX`_NmMQ7_@fvt@}40~e3m6Lo>l^$fE~GJTw1rj-CMaM&F9GQc30e?r$_NDeeZ zx*5P;)=A(&Nx~A~+SUG%cXxs`s)7rZ@mCt`c;v!&KthQ2~f{?Q2aDDdio1E0fUD0mcreh0UR|Tb}CAGf6JKne=Mh`$d z@7k1rp9D|$k&p=T)U`B+sXFc~hpV-Tev{Xo8a4LlHSQUWY;H>Of^5GI3;kYU5ud}l zjF-V-JTAeTt=6vrd*%;UH`v>sS8}8d`CC1e2u=%Omsh}gvS+7DMq+w!v!(?7cBqhl z8z|Ri$}ogDE8mS5hCH8yH2ZVP9iA^ry-*5YH| z$=l-w$_n$eF z<$u}ezbHtOFQtTlZbv2=83JhX>SE`@X-av<9lAz%sa2>)P!NW%-RfzUe(>%0v4WHl z9kzWDGoc~a$c^ld1^y|x4X;UrP8v^TcSa_AJ}l3;G&6?OKu zwJpswR=jH+f!yq*#MuHgGPnaGvTJRic50(5XJ<&UN`2J)L}r96n@fz6toBGXC~D$g zx^)@|$6%VmxqpTEjY+a)Gsd-Ac;u6HP?FdtANP5vcmGp5SmogSg+)sk@LWB z&05ZEzm@v9%wKFxW)b1Z%yV#I^22&VZQ?cFB%FGZ_27?|-5=W6}sllt{JVaq*UQ~6uW^eg@%KTJle zKBcqQpqw;9+@4{sRpSUJzqZN-RlB|IPD9lV+~d9D>b}$BPH+5$fl|c~i9UW~y-{+UfjJN;7 zW_G_hDU*JpbZ%WQvOGC-<3fhCVB^Qkz(&s~XRl9|ryOs3Ug_)9V;kYD*+r!;^0Zzg z4DgF?Fg3qohuE*1<&4-hjjIuAn=;0=u-Yxj^DY)LmB%k}##~re9ceYC=(ihyW8N|4 zkRfZ;#hvW^d>c1R>hCvl-A>uNbK!ZAs9_vBN4iC@K`pZV!ld0$8rMPct=~5f zQ?Dq0S0pALdUwGpP-4)_+i%j$?5;Z~oL4~eG5@etLQGu)J;i`Z#k7v;L0} zSwZoK!?~}PZcaND%=DZevNh5r`{i23Y)l@qjudVj%O%+be|#kW)79->i&k+@c+S-r zoaVXJ7=r-Sg!g~aHD1reduVjy&4@SVEj`&yks&fUTQa@^2d`|w7tMZ2emf8K{ED^ap?LAvsBod(XP>uIVG1s{vuwh` z6rH2uj78pHcqr&zOrq<CycQw6`N{gAC=f&whjlVVj%84msn39- zdla{BX_1uWFH6kfxWC3iSDy++I4%f#M_9D;$G3wDx@|Fw{~xz3SCU8IwWqJnr)g$5DHWTTKY*$QE`TT#2O#=M?PZPLz{&`b z?gNl`*g3jW#c58h*C__M+A)|@y}}p znbl?U>uqP7>Uc`5uKJFwxMFp&vtqss z4DmTDIbKmh=5>1mSL`_*HrC499HEC!LOkmyT0LndFat=OKAsONahp7Mr^5e(fT-*V zZ#po2`t7Tq!e)}3l2%L5_{ke`l?00EkbkS23x1;I3a`HK&@e-#%kt;_!0 zYWwN;6!1Pry_->ZYR7d78x4o3pb6 zGb_s(b?ZwhKu`oJ84<|9aD<*HHg+#5+vT_=)__ph7(_d&}$aw@)lU z*~Z{A%s!}~VYm|MJjG$Dya#g>xMif^?;4#`ge0PPJ6GOS96C~xqQS$r`nOB&P1&>T ze9zfXYeO(-J9q}Ogx*{$hx#ubG1NSk#CY?0FZ+dJQ*)zAL7Ueeze2ovrqNNC4t(*YUvfVJ*aa%NH3 z1BC`9;|bBhEtj2IkDED4=S4U2Xy`6isoWGgqyh-BpQl>8P6k@mztqn)5MAW>{!+77 z=(ibpkLt$whyc^iv@mjhp(FsKMM8yJi-qp?soh-wyD_5>aXazM5rHcLXAh@E+-kEt zCISMB`)dMYJ>Z&=O*_Izo^Fx-V`an;p^b+E0T0LY@kN=@*I>~0T-r7Q887m4s*}n$uxg_vLZZKS5w<)4oVT0eYuo1 z6n&m%3umV!^^BaPi%zzxM%?n}>cohxEy#@@-h5Ir;O|E$Q0uy9A?|>BdfsgJmNA%{ zIkq3Nxl0_uhj-;bu;m$Hm}E^?yvyq(@&TyheSmgWKVV67WDd1SNy~k~TAzwiX;pd+d-N^o@6qxX!Rl&+$J)X1Iyqmqt};gN zTly%iQyDM+dRd>R(W)pTi>m3X~8$DDM z7C0oe4l?qh_>vTf$W$o#ng$5w*6C!=p8^)p*fav4Xv$g9D0*%hcINr-+`(9xVPw(> z2eFwSU)~O3hhJF6C4rA3^y!x42 zOXL>J=@GE(t0U7qj-zl*nit#*a3bT(DdzD;;&Z?awc7(G6cZa>ihJ*aAbz}TBH_iT zis6i2t-zpW_9ymL9N)UgKAL`Vn;P0Y{?4oACEfcyr=>^feU1h|?6!^2KA4Q6`ZB8M z5;Tuang!g1g`eS8BB{U5>tIfFhe%B{P$O0UkM`a>uE}Lx8;*h?MPs2zjfxaOM5&69 zh=>S?fJhgj(witqlaNP6=|w<5LC8|N2$3!|(glP_5hNgxAkrnFga^{TxX<@~=bXLP zx6XRc+54Qe-*^8pfAC`_Gtb=Deb05xGjl(0o;2mQUtK=$cB3`<#4%Ct&N|Pm{bv~u zm?zwkWgX244>m;G9}$)xzz^C5l~DcP)v701H*Xy4YyLiX(dDpnbA?Ae43l?OnFaB( zQ+j}wX5^S(WaOYiUk4?etLncYYSMz=r3~9}eAkRc!2g`|_UX>Y7($vfCki~Vn-n()PV{tBz7L9)xsd^Zk zrSE}e{pEn(7b#+O2W-T%nJrY%#~0GS=N8T58lgZt*8!2t(HEle8#Cmhy~fDWi_ejW0=vKXlEfB29MKPQ8A$EUwmS`SN0?0 zo9jN6T^YW1Kr4)Fq9oixJ3Rg~>s*vqrH=%d&|1Zm9rlki&U-jMzxojh#~(kP1Cf7x z3H#BvKnOHf8RE$&9 z`vY31-XAPI#I_hd{uS9|$aGCTat;@S8=~rc^^>YjJw5O zc=*IMZ;mro-|h25F%Q@}7v~{{kF`RGvmov`5o?}b26{7dLC2Q;4##7**9m#XJbIC! zj@tLj6NVpd+5!UewVKhV3n+AC!7B%tLUbN5u*8@cf{%quhn=tc>>XvW^hP=6RMdkV zHuays?J+Dg+lVSzrXHqDv;#0OkR$+azbj`bptN1A(`{*q zK4@SwwaWXV_7wls?IBRY1l1ED=)bSEh<{L`@wncVxXVz&vt_HS@Qx?o(-mRX+c9;- zsc6S_v0FnBkdOL`ky5Ws6F|wqDrOc3NV`0BD2NBk$D{{Sm(9|DOkAt3sfivsUmvYo z`8-`u*3ClU9p~4|R9xFKe^4DYhJmZso($z~v&Dqb)kqWJ0ak>Of!ve!>ghg`#9tmq z9zK2K*|}J-x99ys9`i*>HAV))8$<9N)nhYSlc4-&QT>)o%^!T3mIyxSIouHQqwe90 zw=Axx-c$|{s3AVw~Jo)#|ht$sLpBB5)g zKJh?1>g&jq%jsXBXm+?7XaTs~7ra4pc9@4(QRc)lMROEYtJZwvuHg8aH)2 z(#gyInQ_M~CLUIzu z`X_GUaJ!-g)td~wXF)(4WO)}|mjZ2V5LrC#1U`B)pSopdGSi;6-&h-;S|}d-@i1=& zz5T3p+z2g$I^3t_M`A%>sH2pbHY5*-`S~$(v6jTnH**dG!RHg_SGfb<)jZ_ZcWYL) zGjQVI=LmbkaBannV5kgmldL{98Q6;03+`_w?21dNH*I^Rhgz90w-)epE6K7L@!^{N z+!?O*!&IxG9%}j-z7su~E-`Z-tw29T0U}70@MPlbn$n)2o6Jxh`pJMpzK%6jd}&5; z85~uE(?Q<3Dfi(ajAuS*E`8#1d@8IQ-`aC-wb=?T)c7=Lzg_sWQia{K;t{8;qsOoP zh)k6ya$GOt_B}V#i*NzHAc!+;_46ge2+XHI?S`-@3-z?ZYi_=IFI5A!4%>EXj^bJvoqj`ezn&loX0gb&8avW3ao^;2b znxK}`+PbYW<*dlqOPi|+xC-ElLOVe2K7tlM*G)6E3=`JGmL;ln@}P>pL>+8<v}FlW;Cx ztvc$I=JLU*b2o<^{tORa1;>ZAiSSfhb>PwsN`@i$`SrXC3J&V~d%kjakf^9j?IqYn zac22{WSUvtv=ut|kY_CWj44M1*=X`900AcR?|^)lhJDttP&WOqwN;iJvso4^Auesw=eb$t@S!!wY zDVr>!{^^sDYyAF#^ey`!7*Rc+CKpsdKfuWF$B5a)$zH7oA{%AZ@7Z@Bu(ZKkd7P8- zJ@H19Q@r9U;{jebp~wf;`)qN)08x^heP}s4n-{bId!GwmqQEi!d1Dplj}-|HdW$LV z+qwH?SWDE70A$Y$lY@rCSm;da=-bgG2Y|Feu>MCHu0`pfbU}@sOC?vg19KB!Mve${m4<{0;9q(@%Rr;&x&>i$Xtpwu>VSiAf&YvCMUwiWx%5( zDtMZvy?_&&{%mEL3Pd`{soz5qTwR_te68Qu_dK9kpI*MVPWj0fUk}E3F7TQKX*$jJ zY`fwM0q;`a((Wg?{E`k=*L}Vbg^m)HPdE#~mZ3yw94K!x_92d_SG@!+$ZuL-B{4sg z^%X0wYn0Ul1bYJ&Fc3DU7C+Rabzn-m1xs z>gN-`+Ld1%nd0R#>2DMvW5dwUpp41}iw??`7^C(*EtrLvoG`Yk} zFR~P~yz5;L%8{l8deP5;N0p*c z{xk)T2@!w1WOqm)Fva74#yM-=KsHHxD0b>&)k@Xk=FT&NSW!JpHzKc(j0v>vZsxk8m1%9j>Wrl!Jj_ol2-zGPnI#Oyy4I27lZnMrSLz0&vMwGP zJbpNS=Tg#Cm$OT}id5(Q;Oi>wo-IpnIwEl%EJ!rLe|eDw38Y|JSP;IRw8!)_*&Y6z z_ijDNw`>1!-|pHEE6)d#YmP5a9fe}RbuA^DR>Cgkpri^T2UpGfgtE`Jafgin&LdQy zbQ5Tx>8A(&SYa+deTO%9u%IBRI+XBiN{A`ALDQrg*MJsN688uS-tIv8h(qLlFY(Q0`97QOhprv5`WZv=P+10}? z@zRO3M^{a?A%a^WG;L<*NxIY^%6$qGnWa?6)|=dr z9~OPwo8e4?ay3*gRwW(C58=ojQTrx8m9o0jns}1AkOkFU%k7}=Z)cKJk~vTP9I@(l>_O!lRoIX3u7yf?(+~r>xkz4|jQHj$=LbB<@i~{&J)L{muQJwiwQXNzv79qLj z106I6*3P63JZ(Pig%y!Xbb-*9%6)$zPVR1snu3MUeHmH$?FkZeIZEj;Teh+wL~Bpn zDAJXtM1X&7hROmNu#^orb9iCH9pMHYnPCd&;mFn3G+7X;EL{O9FcOs3&8~|crK<0u zhK_qVSki$vEmO3-`-p>DYDJz%A%q(~-T^^bUR(z#^HW9?>6r*G)M%Y^d7szaIZ3&t zq@mkg($2g+2Vo)7w?9soxeUP(%w9~n$&!+DPLPHb=sG#t(Vt76j+WB^;i-jc&3_; zUwkNi{OwMWn6`(bNbWNh7H752v?1O?7i;pF9o1DslH%pnLu)wx&ewV*rw=%dPXw{V zyTgzla{as7wH9{<6mT5afPyl3`g7st<*l^_7Nnn+PO(8;MyQJKA1x9<4hH2>4VO`|GU!NEKAK#t-Gk-4c zcgl9LkdTmzR|rGW;d1SQd(XX2ILo~~51Y>11!Mi7z-}dAF|ojo!atli0M>{u~Qp_K7Li_|i{tK!+mLM!w)2 z;G3vlQ2XjQ>GtbW7UJ9b@53wpt0wyf4F^{4!Nh?@2eK=3TH)s%J|c#m7105s3D=9T zAT@@+kqG7wAIUu1kNC!@H)B7~#CaBEpgk9f9R47xPsdb8BNj7eF|Lj5!-d^Jupd`S#Ey6rpUi=cICZ@RQ(3VXabg z!hKmrCetS#S@9^VQGP&}x%uf0+ulrdz|jsG1BkI8?g(DGb{Pd-v#X@8AooZ0G0nI^ zZ^e`(p5vlcHrtMU>X?>N50-Cyh%38(^6z#!_#2XZ70DTdM>3xI(0#}>t3lN`*Y{~B z=i~3vo_l9`?x$tsIPO1gA^506n^RvRm~OgX6HiiPo(Sx>T+BKv0@Z zoX-zV^Jfy)!LP-Sg@@!vIekr$m)KBD-)=%M==*_9Jf4nm;V6haVn@B~a~_8uyY zYT(E7E*e=zvbnj^bfxEr;ruhH8HKfjk~U;K(?oYFfe|y#7Sdz6p#ZYe=RR90W@9Q- zSdeya{nqh)5f^GHKCL=AZavU1Jn@zlN!E+~s;g*AmzwJxvRZfB0BccI&CJF`N3QDI zY4>7ppRZQAkY#Ih!t{v$<$xmfiz1VE&Wc|BjjKfeadB{`q`ePB>~9nRvG0XM9}$dy z)Z|~YBaG`Pv`ANWA39-(72#Jm6pV)+bZmeGIV7@IyCqTrO=e4$nWZMb#l%G_@p-^1 zpi#^dUr>m*6nG7HoSG+yf*Z{XA0{5r;5x)##-rgCZ+TPa6!O_tI&%mmMl1rjg7o#s zak;I-w`Wr=sRr6D&t;z4wU=%to!R$ssoL-4kt73|`TDhDkVFZ z3aI08gwt9#vK5XV3@fmExO0Bzggu)m&mUny?y?~AbYn&eoC~#|BD}aTDdE!!gVt*o z&TFJQ`I`9o=MapwN{pPd^drk*z6K?z3x~|D+^8#Bsn+vJ`8>8=GYdGnBIYr$cG?XG zo@BGHsi#2m2x!HE=%%uzN0^uo^E7e?&~h4$N3I#s71>T{2V<(}(^b+I*IAJBxaJ8^ znoXvs)H)gYk{ts;E4-KmL0FC98vvpgU4aF8*{#QdG{sf3AmZ6fA$&7#OS}R}KQIbV zx2TsGtRcJvLWx{<-?49?7F~YY6lAv+sA_N zPt&x4J|%KBlgA4Hdtih+i!chb2*7{dP+3NTb_iY;WY)J2AUk@qARR}s6g%Si$iB|0 zU4khOI3><~c?dPVum!68Zx1#r(`+v;*vnlZ7ax#_~p(xCPaH&tweH+>T4`-`5 z+-w?X$AWNHA?Pj%psUiz0y7GDj3XO4vO}&Lb0Fb53lbS>$3$amFzjdh>$$Y&dQ8Ie z1!ecbMTWd8eae?s(Vch1nGTCfU#H6*Po2VF6Q$4px~F1h7aB@Vd%%KtV54o79tMmHZxs$FC+RoF*DR(}WYuP3&N~>>wV1 zk@+K`+ibAXSVgZi&3x!M@oo8ijw7odO3&Ya!ZmXf(s|JL-mutT8v!*z0|>SruyXan z8vyS$!q`HVaI|%O@a|@`(hPN_DDsz z8#v57e&PDI>0O~-9p>tn^YErV?N;z zxCq;1;f{<9#B4Ii=1-iKu%9mCf*2`hMj;;I$a*(^x(EwmQ^5Zb*El@4QXt(1ZQxuN}AiVqf@|ypRmx{Vb>^R1z>fW^S_AR@IR! zg9TB*3i*ppc2Kun|FOl2j0`#N8x>{G zj>#7(zUX<9&-r6!A<3`ELdQY>W$JXw9e?cQBYMa2XtNzxw-OQouQm~QGpYK7- zCKfM`?_#@PT2OEAd}{&^O4)VzF3D=+lG@qJX?wIk>Wn=^#E&r)w)SGXcQSdweu;Ba zmJw4C30Jn}PrXd{uOHwn)87^l#}#);%+Lj<)sk*t@Ju1dv2S~7B4L$oMD0l`_}R%Z5AZLF-gPp z!z^Js(%D&Sk4_VJLC)8dHd$xCS^VF~`8~hmhCF}|_-Gcyz7W7ygRs9~SIQ|p$Yg;u9A>I!`-Gf$&bj(3)b(Tb0`mME;7 z{0(~j$B*b^whp!)LT@LmFQ=&w?<~_lc1c3wfU}K_?@p;F`dp2B2iX(gGt#K7{^KH3 zAjsI}=97o23J@LM+xkB|`w=%1HdUdIFjOTr1ZLIdrbk}f(HeU_q+O3W6Rwhxs$Pj> z6OzPrf41U$zV!Q%`|t5pmp^evrT@2VS4ddj2h;*7Xj60tu;PW-jab|-%zX5D3wMY4 z%4EZ21=|JvvdlD&Aa*bw-ee;!y?zWo>5xB8=BD+SkeLNrSEA*x0*q_FdvP_Ak;Q_1 zTSl{C^d+B&W5^GBR+mUoLs*dH1~8iixrqs9LDq`QO6YZ9Llk@QazA;7UjHufTy?CE+&DOx(w;FOZfQhpVwKi)JuvSL+<7bFv^jGxTml*8tf&*#&qY|>|ABAEfb_bOVU332mx_YPJv5Sv=qFbtK00x-k!t%|Ik zvK^yy8YRx202n)pu1RRtk`ZmlVcqZVa7?|=Xyn!vgh9cp=&k*f--HM@9`M0zs$urC z4X59N*$RD&EiIbDjLtBPUD?w}-AkTfV!Y&C$z}5NV{7wruW&~ZT)#CoISV8F|VeqGU$ z1+g5glyP*-Ayl3Gei+qrh(B&(+u)9y9p25mFMs&nMj~F&8d!K`6hM<&l2=%b=|JuQ zyp%>VE?0wz6vUOjMyVi~qr?Qu`1avNtE!W|M9wFZhs(kb>3Ds6veVQkzML8cex#FW`abgGjn;|19+FUsOU%p1>04cd@p-W@pL&G~??*7X(?_zn z&)6NnmZQ#4j9O}En$JLE({{X3wJVlTD?I;5=phGp7BO=2sR+0DzEg!MGASFHCpKec zWw~D1T9q%2t-V%Q&7c}FUNfcX=3rDH5gJn^v~>+F)8E@bOcY0(YbRYZ;>#A#{PuV( zKde%uE_&UEpfnZOirhs%OSXES@Q_M{k)MN;*DfjfYqt+|4SlsqH;(B(z4M#vL9h0q zV<%0Z(#I{GO-^TP!mQ(#LTm}+RKxLm*0kNxbP@&A>O;U&ooo8)ohh!?{pdrW5S1#X zZSdwzV@Jq!SuMlp2No%}Z`%c!bOj_G2yu;Jo&-BCFtA$OCGD>Au1No5QW%-p{!s9_tbQyN`|RITEepRzQD;bJHON<=(ewXdY` zm9@d0Th1oRCl4pabtfj`FAd?Ed<5smH9_4;tf*(3*p=bCA!4J+qKmp}tvpgo4!1S- zKOmHUL)CZq3^^`^CfFgTLnJfw1g>UoyQaUm!Gg$!Q1qE?2(~(yv&^<{xC1Mnpl2?( z!Ds?>4R$oNjSHNfXoVx<5o2i2b%f6BtLP1r_U1owdpquDBJNEMv1JXGop*D$EckL2p*;n}r)4v?M=OwgMqQ`$+hAdhFtRwn^W#{t zKOh_wKdPsUeDC_$avJ7-aL)ztqeq;kw5)nQy_z>Zccy&m_Pbz#Hnw(llkz{)hSwH6P1k|oGB;>}9%0ZQeH++qbB8N{H{vs>ZGxV3<+0I#%LyS-9J+o7+rXrw{Ob9*mIkE%pwXl3fy`;HUEA;k%i=wOI+1UxkS^ z)nOJx{$fDYSChcoFdoh$syDXjJ6M4{imN+bZ#}}+R$|eqqpK@QH2FXfRde<3M6EQmwnarRQJaBoYrF_?m6 zWAnYq);cASnP@kRHejwpG2if3;fRSsI-7`uGV}zjW?dJWe(!E2G8M;wE z1k|3K;0qe+zVwa~njd>>vSJ|Z(p?!pzrCq4=Q{YsAp*M%4p-cjzWe5mzDCQtu4@y! zH;fTAMHs_AB##GBl@_I?;iz6sT7H05>#qn=Q@-{!L(Tu8^mJy~)g5M?()T5LLIcUP zj&Wh|OOW0TkT-Q6=|I}inMC?Si<>fu84VB2u z_^#+pjrTz1M$2*}Owu2BpJ1QaszETfZ`(yH6Z7nj+4m~wRnym+3*YhQ3QX=`Oux93^CAOMmLk@{CCGy+RnS zbzgYZS2Q2eBlx^{K5;f(jajZNBK5X9m6#HA?C`m7{2QmR>Yy+s&0cNl`1+1AE+ zwjMpV3w>^P^~;XT1noAw(|Jz6v|u`*W@tgr*u1eA`K_4gTEb?zGA|v>e;yl2A^S1k zqm|gp|K0g@kH6-O4%}eT)+}n6t@A$AV!K%oL;X25Hsv~pKKNT3!h#h1(kdJ9K+KYG6*Sk)pwTsu!cM z(j?MhJB2aR9;!Ui;vfT>`1^a31S@Y2z4SKwnis2bl4Ik__PS@N8h+jDK^u!cGza#= zUPC#)+60JH(7a_3g6^`da6#)=E6*4AeYbW{Ka=pR_4xEDZZEH|JBxyNql|Io4EN1+ zt-LY|F(elYLOwHxeYxeMhw`CWp+YGWExSzKBl+Nat!?bVWs>t+Rlt4^y~Yk#0ZHrB zV2hnDQa$$Bi7n#l+p8a;^w|^JK~r*L>v6%xL!Ja!>oON%tVy!e(e(yZtlRq55o>yP zfZo|JHw9Eun{GU9w=uL9F_yiHEekytZljqP^WC7^X&jqBlUIc>nZ4q@V&w*k_3Oir9Uuv{n>Fp|MInCjsUV0vpfDpJiiO_n$zW}^eD+6 z(k~~KK0hxnX{r37^zf^sUrJrXovdasOS%PMdHVzm;i~9K^!{jjyt>$CUijYK^qezE zQ25TAR?6|^XNL|xc%gw_Ur=U#nAi`Oo+lVF`*DIZ6nw;*%@9djXy9^$an-w2l@+zl zNG5sjldE~RFIt&i4s9WEzjveGp(GGH+9E3x^JQBms&>4!L!Pkb%h?G@`)DF3gLpSG z*XC*53=L@jq{76E_D6+X7B8*$D#7L?-9DZx#{D7={Vezhbit~q(QR;i}fwL>^1jtQ9H1jDu{|2Ub<`d=u z)IT`aF*_da%#)9-Io5W`EOAW54;ezY1p#QANqCkt=%-B_7;aTpvE@sIWqhj$n@;W? ztE;No{k1#mxrFD;&z+UB(2Ymv!=O|L^Ef4vA_s;NTgl91x7xrj{fDC+g{9*@j`;0Y z-do`sRyV!byjC9WGNX02bw8HNM{CIW?bzsh8xcy({d80Eax+vg zNM@KQ@RnfYS7@_ox#F(8bE&89!>Jt+A8Ouzj2nxlIZgo&8@bVa4r*k~Vt)BcwV@8lAl4jkFT=Q@vw%Hrr}%Aw#CXvq z<&&y0k5aBCrpA#M@TLmiLa<-b-RV0f?KLMlHtqoljS{-jc`2ljGe{YeGGUka@eoIq z<#<)^XwK}|u$B{ti-ldwb z)d8jg2s239(fDv{&}RN*i)zds|GVA$Yo6Y6KhkvYslp3CKrA8#E{pyGaAO+C~|aVaZT`bA*g0cWGa$P-2@Cxbd2?zu|khR9%PM^Rp2kwkR_&P^#c2~2K2VJtr2 ze(zQq*K_K`(J;9zw~J?dw<%OiP8M2jD;o9p8KDlbAU_k&!8L3=NbM6%g!6>+wpR#0 zZ1(9r7ktEY`?ANVdDAW!`9P#ZdTm<-1oeRtz z^B+Xr07F<1K1X6g6kI$MM^j?%^Bd8O>Rc3$}VIh~fH2d8c?AWt(tQEWls z4kTMlI4y4jeXPL;zo6v8CtB0LV{+{nc|Vp&p>IVTktw=oR6an(Tp{99h|2XvB1?|M!(y-gneb9`fPvjS`upq}#m79A0M9Q3fr=q%n z?a~}5RmYQF@U=(UJIS){9`bS*3-WSv;uY%Fu$BfbFerqSS501RMeNqnrd;TU?V9(* z+GgB+Hz+(^m99>E^ss8y*SDyCO>NC50nLR{X8Z!z2*P&2wxeY|vbKTcL|FM8fxdOu zJlN@}0`Hiv+#{o>5w{$lwp(!N92DJBqGmHP*Vt2yB&LJAL+$Ie0oPFPf-fEh+yu!X z(srF22a*ntX1h8ZxwcR2#q~|$1cW0CBJ>rcD#gLLnKIWvK9clwN<&^{;I7y}&43c} zg#wql+Ir}4h zpzFg*GR2cx!bn5Q1c@~xD!9sXQ5VSi@s+14LPBp2joC~Pu3c)9Qtl9awMT>NM#QmS zh%NjQ-aeDC`|wjJOG;WBW+aT%SU3rloU_8`fUzSw3bxwo*sf0P3g(5?r!9i6QPDqm z?e1tVKgKx$k&=hO1R_2fR#Dx$*?8C?2!1Cpd#-9|uX}oEasQL=wVg{n zk~N;5R(B-V+ty)W_;vLxqS)-phD^4CNB@RhV~<^RDg%0oJkf4K2%F??U*@1oFmjaE zu;M`g>B!2+obA%1!$UvLJfjxako4lDAgIkLpZw$v~p{#xe3i5tt1InHS$+2ATO9C2n zXEs&J|GOkPP7CWjNeQG2gb(3cJ-_QrvU!YHkNoM~j>5_x3szpQeXVj8Y4^R)g6!;= z^+ws#E~5Csm^VSR7FdPs`{1Q)%JL&ph|MwV?(WblZQW?%ixg8URM>Z^L*)%N0z+$} zbtbR1UXWhAkdiA}=~S=F9bMgoS%G!Bx7DbyrN!x_pos< z@6&C*f!lf4Irpa1dl{wPT7r|nqX|y$#(nQ=t0O9q!XugL<6U#u^UW}|`e*rpPiv0z z^4Ad14v_cDT7e|&sL_<`V-Tb#65icJ*j?^Vn}YwrKt8)~z6} z%3R3{HP64h_&Z1Cn~#`>C|@Z;ae&!3|jKT|J7%BY)hk+G8=Vzl;$CeQKM7(zRfYb?Njna>C*a zWutXsH+(0G7ko^V>90RZRJ^%yg(BWRVT~8>>(ELjH18An7HDPTaCrL*A)=U9*jNNz1)(nr{xkl%{ooL_h|pIUm2 ztG348I-=p><;4#|r|dAb;xjc2c}5O=zvo1S{=<463isrXa&PYv&}C(~)%IB0^$fcd ze*;rE$MqLdN9FZ*T;>px#FBs!++;+Qmd0x^2o%#TWe!xPk1h#qIlu8c=W;H~=~ijD z)uri+2On+|BnO7$Tw#P;N{<{MwRWDN3M7rDP}>cf=$WDdm&(r-8JP*w6;D2lLb+6J z)NgR{T=7*RT(C?E@Wf%(!50&zMLLGD#2yhnl!k447sJ1*s4gzPt^-pc+h)JNS$JHS zfrWF9858-wS^F#M>(&ZeW;qZe-1<5rZ$Tao^S+*Re}oH$KS*VpxZDBjn%u0syYT|Ry^Z?SqIuetSHrFHL#?@1N@cPf&<+j^BG)s5=f zwc#WXo?=*DPs`zn@*;wrk+W}74-3Mhmb`hf@2xB0aJRSkq<=|1lV_S8U{WS0wiXK6 zETWmzSVi%FJXA>3_PkVTqWt|w*Y^WyhXS<{l?yr#@+S|zu)?!h4z>k*fG)?#q^nFK zVeTx*$i44b8$H^%3;`PFaIzsr>-em1ER_Gw3rSxE9%D^!X>Z^o_2>=x7BLaSTSlq2 z6%|9;NfY?e^<4sH*YfKHr`3U#U?ewUk(CTxIC)OOx_}-A-n2I=vaD#@AD=;!}uC$3qW*!@o zr@(UBxu6FnYVL0iI;xVJ&krB<*+>7VQC9fDo@7Nl3%N=62Wv=5{2mDI#$%x8WOWRk z+ns#V`q*^s=VPc0cU5=JfcBATaV}>`TUQQc4PS+I6*ERA3sQ}9XDCr)DbPsxC^X`3 zl}R+p0O-gogwP zU!_ccb5H}XJBdQ07Zn>j?{GSI#tT=g7&NMy#ypUJaj?nMT3x1&b_Csz5LoM*#Ka?E zE<^P~ix|(+0aZ`7rMFbCH%Vuyq=;}FjNleInB{I(bor=$=BeTVtA&BfI7NdNl3d#b z$-YxEKXNh_>hJb1^myn}#0=VA07scRu!pWLDbK5dn&x;<4U_8 zem3dQ0UM#SS5podxjq2nikPFAQhc}*m{JVR7=uld5~9}oO&>BpSMkr@S0!oR(JJD2&ZE5gbCgNk@lD4_=k6+JC^_;M2&Dck<{`$0g zU&&dqrp;&jbWgyM#XmoKDhXH8_ax#7x>KleIkIy-r3apzJEy*7HTv5_b-rbmPKs= zjS)SD!=L_3J8`c6vJ)5jKfDw7=TFM~&*L@!JYMt9<28Tic+Hl%oE{{tf?<fK`JDxB|VBsYu5H5#r3a>S}MfufSO7``K0{VJilpm0jIdt zt?e&Tj4DuRqK-#Rc69UP{it$dsI!C3DB{Q;y3wq`Xh3`$^T915h)4#)dbq$U>F4=u zthXwDB*yx)8jmHPk)mhI{vL(frEQWmPQ8mEJ2;LEV}KS{bQf;zsw#rcE4cE);DYbd z)8-+V9qrclk~85KtFuS$!HoNm%Kx^Wz`tv>inJ)AC;Wgb&9me3%qZ>o+E>9o0?ynm_xSATx?U_qp4VSn}(f4%y=!Gd1PBUa4l@Cde4KljcUI%U#~iJ7S4 zZo0@63CineEzY$83rpIbzCs>yDZhUKDZwFlFjQfn^X+gu7C-GCT>;!-YW(?^zH*z#f{; zmWrFg7MsA_MTQI;m9r+T+kf-g^l3&T@NEcX!X^N)-M}2Rxv?D^i<|r3yi^* zjOqD!hY&ZN{raR5>`Gl77hm(hKdX!+niE}L|1Qin6aK|K39aatNM>?%$o<04f-Gh#Fi}Jn1n0>V0G#HK zt20mr4M{HMmE%CrWDQvm%qd`*z~;WN5lt)lCVK@z57QOSMMLn+&VJlXFN{XT5%sB; zQ&r_=8FC!&#p7+jNqGiD!$Q*H=!o8?L(*%=SYwE4O^5v1zNVFdts|{Bq&|pAJ4pmEuYO!;U1C) zRA~5E1n~jF6}q`b;bsbI&ajo884JSCLpufF^CJ=D!ePXwawGm#{8gBBAsxRAKk=*K z>eEliF0yA6o^|l&{@XS7lG8vB#w(_cG^!p>Dx+pWF#cNM$NR4Ui-#TiUVd;BAPrzLHH(kRiu|xjAwCQXM=iVp! z@ACW3im)L62ElUw2EDcdrd+_kM=;`F!E5oM&065{_V)vyUguR&mtJ`G%JC|`Y z`w>WTpX@sk1o3;+NC00000 v00000q=9EG003}uWp-(0cP?shWoJ-J1qJ{B000620swLV004Wq0RR91l8brp diff --git a/proposals/nnnn-is-isolated-flow.png b/proposals/nnnn-is-isolated-flow.png index bb86ddf5487b5b3133121eb91a2f8adb4383b9ed..97db91af276480fdef60f67090f87904e26389c5 100644 GIT binary patch literal 84498 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 Gy#FUmc2!sa literal 80747 zcmeFZbyU<(_%9B~s(=_DN<~TqX%LZ)RRpAaX%GeJkXpJFP*6ZxI;BIpQzWFjyKAYX z+!Vl3hTW>6YFMc{oBF`lx&}hN)d9<_WXVK1}vY=srkAHqV zql4$`XpnEeqoKjjiGMw7pi}?O@2QW5`6JJB@E7&(G58PO{_*!r4Epa9V=#W^#>|a5 z^Yi%(6y!!b3eqPBf3VCRD_fwU;ozbEqoajITt!2}z|ogivQ&}~=Xz#p%&4Vp`c#L} z#@Gz?78;KY7kD(*vD6~BF*Y)>;IiSp`7H+*ct-uqbd&sB7E43kn@SSWeY)ve+Y#2-|ZhbH0XE~2_ES{O`n_23cnvkQ))p}}bWyyQzOUhhd z2ecRU8sFU?ul)Jj-}wbhjm^w;EG$s@@BhgE=Wl=Km)0}2GzGFY*MBBrVyR;eUj9+r z&j$X_IewJI!-NvoAL9EyHs5{)gTsf-!}M#Q`LMgO7pc+EplBkG9?09EFOQsa!56Hk zUsu6=A9Ir&1N-%PJE}+Gcg{BNHKU7%3Oah2+;!u5#58 zRhV&@GWbDuCz>LKyt(?;@aNXg=Ts3bt(I^rD`b-0PG}`T(+w^WPsXPYB!4Kt7X~f4+X4rS8qljBT_xmM-M0N$P9u8dD#t}8RK4?+00+66LY;)P5) z6GW8hxXPP9N`#llNpdFk&afNyHsfAnN$8zZw0tVDw6#5CT6&JuCMGVEpXeQCNz{Xy!8^-#-*SuO62$wBnVVUl4_ zYLKe)5pqQHc!Q{~+#bHuDaI7^wf^GIaUu@^Gs`?hYyb=p^vvb?_Slz8orz+-2G zegmv3h66ELY+Nw##c_AS6QX{!Gv-_wv!vJ%q?-N2wRGGKXV?Y(jM`Ff22OFRZN^Z{ zgO|fWiW&@8P>Z%n|Hb%LI>CrL%)CrL|BdfJH`Eoq)$3pC+>mNv~_DI6Ph1ahGWX}-@YEdpEY zz)O68OPCA7**&D|%}`)=a=cR+FEDZRm8sJ5U^!QcS+;bw;$U@kvyES>F<>~9z`{hiL_w2Uxl5)U0;4t<`C>XO_$`CkM{Lp^6HF@s6TWN_f#5OL$ zx+|MI|C7JR+eN<2ihYB^UKK-5+%pQ}!VhA!!?@uldgqS#7C8L{_RG{2cnym!5rg?@ zLt36B!xHQx_=?Jv#MhmYb;(7WlH^CmT&VdGe`_tJ2#P}elcSv-x{N&8q6R@C^@JC$ zPDzp08$=p5S~h(J$l>I?e|-7&lM6YM4!!6y=TSX95V*+sc_?H;+6RJt7$@jm=18$k zs3byD>qbt|21KxIyc)GO;3hvh%eFzNc7AStkgZLI0|7>4jgWPXkbd*bxr7I zrPeEl|A^5~FenjhD7nXRsmTqQyQtF z)v3DBs_CwcSC4x1+Tujm5_>HePcHlEPQ7ElXiLvA!7x6XpHZUnB&LRC=9#PCTl$CS z`uuU5`K2XnIWaE_ZG9d(%J0Mqczy})Q-`aondgY(Y`Gs2`mGZVZ+Vj1B{R{{;TXr_ zUF2TQ9#6Di?#qfUjN*#Dk?*>#JWiKaKWLam(wgf6dihG6C z)U`=Egm=6D){R1!4~63aeYqTt`|_KYJ9(P z*!-()I6mKznPdSGKk>HE!+&pT)G*fw2Q6{JunW&=UMDgg_li-r=1lo;?^ie;d>L9G z>s5!3tWomryJb%K@@zcbeVX+oxN~nVnyi2z@U?%_a!0&y|64a@Hhg-n<&1M;9Kz@< zluIA*3&?=d;AqPz9KF7+j0nz_s-`#8RGE zD$q?U+HqSsf*+gw-L-pPRHfpjqulPvpwwy&AEZ67^Q-t-pVZvfP2v@I+Ojg=rR&Nh ze@zV0xK0#{_Rj5bFLy&*G(Z2cRIom8VOdKf0h!#{{DY0JOk^QikyTom!5KHaXnW3MU`4_S_n&w{eIEPivz;l|f^^<%KVUV0#~ zlriUgyr=8jqoC-{QvZ&aXig?ZvQiT}jz(c8okogr#8@(2x}N$;`jViC^O>y+^E;pI z3I$6ojx*=tlunf7On>ZZ4N+*d7jkt)L{OXBOQLpZnvBDb6fdtkfxU;U_)fG#Coj-C z1f!)8p$NwZmulBo18GH_4~E8S{3`TRHwl#2ZeQ5zpyOp_DP<2zI;N+^P@uU;z`Z&s4Gd^lI20 zQ`~z!Vsw`c`Xie<+j;UoWoFp>_(K}haw6l8ddmA|E95`IR=o#1-NYqpuQH$!FB0}} ztF(04UGp%|dz~_<)>Z+@tyzOEWdzF#;--mTRL>g~lMLu>3%y$_5y{n~zni+Pzx&iO z5>!{C%=92>NqZwbQO#^!h;8H+(UC^tospgXPtPJDGc}lN3-tp+Ki7;oO%>)^ad)B- z7@inctO&cs6fKRLEkp@Sv!ZOx)Xnfja#_0^EhQ~Q)-1`5B4jJp1Kbt47%{vI)ix^l zfKCV}L@M3WH+NK`QLd&;w2=hcMX=H1EY}jn%xdu*=?>U#Jc?6U`4#Ot%fuTKSnzGy z%Y=A9UW3 zYfPw0@t?&E@SWZDnvEBmmGh(P(q*uX;?wQo-9M6%X5*!aDei%(auOSaJH0mkWvI?Ia`v&*5MaOS@jQ(afge#{HSA8*GT4MS5ePw5Pxf+~91Nm2S5b|ST9O>aO5 zjeO|gV9WAkYHA!+YYHdjks+rLWvi45HB+5Q-tlXhn=-O_YRN%|SQJc1cvBi6Qm)sH zC!U7gBp6Vc))z{JfRRHV{DbspV%2#nqpaMM{~njfa$%d6&VV2JR+I_?H{wv9e`B@T z!tRL{xH>lLC;FUjM>$}Wj)pl!q@_zUEKj4nAHQ8hYLNogB@eVilcx26PGk!f0b4v5 znML#6nZ>mIXp2_P4*gi&aExR-s_w50M<0?KIQDs^)vXwaX_Y6ej7Br1GZ}+5Og5Cg z=>m2yj|i|0BkeQsk>cKr@nZ}~<^y1UTwj?a`RRK!qyaak%-rHGYR(lw_P1A-SR+Ks z?eZ|9U`5_AJ2~<@y!j?0Tn<-YW}>`yaa-&4WS$dt9R;KJo2B-$%C`rZjbzYc!)}M4 zqr*JceM>a$szKfT@Tp`fLHTgSYEH;aeCqa8R~cEUe4y*^lai*8huekfBl#d=+VK=2 zjpM48CV~j7Psy3@j9OErrNYx_W;)>`R*HIxxM#$vGL(`@Y;Fk6;MQH08MnDJd{1dp6Pg+s3suZl)RDl90|KAYm|@&(DdXYVJ$*PL0mI zmY6J_pEjswtW*8LZ)}zaXRl|K%~Od(@C&U#n%bb6l2$Y>32vK*4==J?PAkqi|9uo0 zB@Tvr&mq0ul(ElUQww2t0!jrR4F%AIAT)+uyg}8EA4V06%qBgllKU2eRDz^w?0PMI zb3Q#$Pj&d#@D0@O7#Y$1JnAXE? zd_I-zz5y`m=cpMR0;v$>peCygg%HRLxe0wR7 z&yC$W*g=rNLb}}Z79){R>}uRIIGU|U9knz(SWx=8kUk>&$oQ()E%{T%Q8%;D9&)N7u`YyW*u4*dYT-|YlB!sn6qV-{tbC@IvC{uI)3ej1A!$x5ZFx!L zX8ppQ(AfrfJ_3#zp6dIt5vEK9Iqd)Z8?=Fb!k#|-`b>~W+LS~U!nozp5pp8#zcDb~ zP2>7@YcsCuea2R>6Lq{XGGcG5ORBuZ6@M<8-BhE=+9Ae=Ebib_@kd(v###IgHhj9R zS(&rM!B6vZHKzy%wnWR1q{J#l(5KqLjHor| z^I^tX*R+!x9aHKx>U~J2NSzudjpMch4OQ)^dwPp`V`GssGJZnmHQQ7nx79RS|Gc}bLv(t9kAC@fSv3VhW_dz77lEk53> zYHGzc&5Vi0x`&)(N{7I{9?GBdKIFKQ6<75RH^l0eu#fmE<3O8=)<(gQi3Qt<@&ibY zXu*S`7eBUG>N@}*q!q3~VIwignAgSI=);$X^eK5E1frZNx`c##&KP-5V`0hNiyl@I zDzP#;17*fm45=EeeNFLfpF5HB9q}5OnmvLG9~6Qv)_-4%)Fc2|Ozi3%rolMRD(-sr zO0z+zM6Ei73$y@o{<)57;Kq-9lIR}S2z5(k41aF;KdmRwnA;$0kan&`*EdQ3>jU}% zz)rNS*73dn`uV$!Ac9J3d_MQ_CrI^kcLdz^`69AJUo&!K90lF!Blk;1Kpx#-&zXz!y z&czM;_8+a-U<8x5iJOz?`|9{Tc~DQu89+{hO)p6Q+a(w1C}{UgWCYG>AZ#}b426AulWRE>Zx+J z{y^LQRc}Kn%BBmjc<@KRe@-yhK`_@-Gj7cNLJ9vUeOeuKW3;iD{IvcXgZ}rxd^UfU z^k(_K%8w0qV9y-F^j}&P^glmnis!U$ zl;Hpr`TvGt)KeS6~b;D#g0B8(pc%6b_cIY0VY16xBs6$6sz zRM{C2pTlWC{-koSa~J>{BKanrj_K{E9l=^~K1a z8|uHN74!klR{o%VXzVBo)A;YC!q2Pv2Ue=EoCyCdr2ppn@g`IdLx*5Rn+zp95X7R- z3ELmf3v5Ptgt2_5bsz|}dILR94HLOj0bSCr@@oII zj?2@6MA_>XPfNoO1N!2j;g!Xgr!+`91tf~b!O1*ACicU7w%1@);fhxd|Rhxw-dQXbcE+V9alqh{p zr1QxUe6IXbRui@&8Un;}EU_KR0b07czmx?B(IxAH)zU20A~P+Wq)%kObVJNz$h@;= z0$Wu6M?k(4D(w!`0(nuL%No-OS8_uHRMSS<^qpQ~apv1Te zep=sObKZ{@+LkVVso=W?OeS(Qt=RiQ0{kHpcLLaX3*LOwvC&AI$v2X`0dZRZODjR4 z5*LV#M$2rk%I=K6yyQ_k7wufZJs^cyEV zADWd)fK$|F7F*1f-16b5v0ChI%r_qDT>&{L$nj^SD)<5Nnkf~{XHxA3(b_@9T?&#U z!U+qqN)~C8p#F=4dHQmNg9d5EIE+PA3@Ullj6&4~_j{FU8S=YjGj+ZOn}E25^(Fp8 zGY6idmzjxCPfAvS=})pMHn$4wdI~>+84%Sm+`ZbvFxZA74g7n7cW1f0tGam~6CG#L zCOmssb*&*9K5DBmw5?~0bJ>090Kh;;O>|kyAxclN#z6Dax*C z48&GZuH~gUrMBDrPpVwZMge$@P*l-RTq_0$d4+nZ^(cn+-2rzZjjOGDKzfI$=mSIc zGy})Tc+i#~pIcMc^TF(bSU#0(E!S zCSqTMxY-w5`u3R+5M#{Fu(vzjn-d_#k#%F4D7 zVePb{y=ky1x(!8@cr!mc-Ua-vY^)0GTG&|Ejrt&Z~(5!kmpY!|rnZUCm~h-AiWcavDJNaa)VWn{OUmrja( z6K+~ztAtzwf`)gLsel0W+uTuctxn4f>8q4W12d$KTQczVIwIlHno`Ky2qeDuj($(I zp6ZMNM=a7GI}O|5={735G@VcSWI}x>J|Wge#a+6V!nADtOSX9|QWmE^jttC@oGvku zfbx?SQ)lmsiDl9DtHmbE{hwArIQSx7RniUZGrttWcRR)P=4HM46M{;PQbp+{a||$t zlQb<_?hCZtIw<$DXCrak>YzY?(A!F%vTmgL93@=7@1B^gaTLuMSej;o_xsfFJZMsN zL;W*j4HdUK{mPqUyYGn!;KXaAQ)ZDW5(Fhi$%#fg?Wbs(mLr>HI?P0IJluI?+S0W- z)6#Ri`lM^T{5@Dr@_S$eBu_QZTvj@~(NFx-juKUN!5SAUMi#?SMue-|Wg8%&+G#|X z*%62X;gsj{0VTjpVJBY=%TRGY>agC*w6K!=xZrZ;qFGqXQGTBW4qnF2%240Hu*=G;J%59NW$w$;2gx6^K3&#xq&Q}49Iaius}z2 zLevTEv}si3jNw4nFOqZ7n*l&ES?Qz+SdefD!P9|?4Do>m$=c4RA zVqb%e=6M9u(Mw3#Lt9$8G&0Euj=SPjnZ~&4dA22GFxl<`jb37U{1?;jg*{dP5oRAS zMrhMxlDTN4Sl1m{o2ApP(E>zVbs{RL-p>?61g`Lt^?TZ; z|2FeuCa~wdUkFIz&Z!z;jlDrW-2j1Uf%B97wbwC3bt7H~oxiPb4^-=exs;?Rua|0r zSyk_6%f0+z8(k4fDvr`jluNcV1ZZMZ;c9$pVyO2(yQ3nJ~S#oq$V3vP~B%Y!Hg!9gSyy>xX**rNIdd+Gw!=)C1{%F!s%d{7!lo zhz&(pwP}W@n?Kwe0XyGik8OPgXvW!H5K%5=R4;iI>-^r;W1J>hVwyCI^eV~M-cp!C zw{*20U&dlnj|B&Oby!*oC&ztxbG8L%Q&T@*sHI*(x$}nV_0i;m6+l?=Zq1_SKM+%d z(&?!fG&pyO6}~98_-_9jkXP}aHE3COAn(&A&ZjB zpqV`JDQSWrEwO)b_}+gk5pwASplQ7FCX(4sN%I0}qMv$-b^i+z0Lu^{P5QMmzhZ;G zT~~mL0;uq5nnl~+h7WM{-lO2aPLKG(Q_^TqY5(U2FvbT1wKPe@e)*lK;WW4-4J+;9 zz(EQ5I=bn7;|Av?!ux9nbYbV-p`29>%q{lFldIuG28?chjwg~bhKUbog@y{WO4R}O z#7Dn`=z0Njmr3;+`FqHJ#|j$5jAAhgaZBU;%KtkTcoX2YE{_OLORE9QO@*r~P=>#z z;{^obT4QbfQb4yw2H+Z1U)X<*@}ugN{MUqC<65Kj*o$DaKZFD!U!y zDXWlNS`IY+KEW;ipSgc6P%wqd0f_K_-;21=Cm`~X2}g{Y03VMAz6lI&_oF^Q^Xun_ zud2a6UlA^njN~dVFdiy#+#aYe2Oi@(XSDNi@enWt)YD)Y!?I!wGv9cD!1SrF-}_T$ z1(2p3b@Cb11_PlQ&)_@E`1&H=MvSupvrbnTD$$#v%B~2^X~27(Dzb!pI*WUKTEl5i zr*PD6saT`ju2_n1?=y+reC#)8vv9;Z9OaJN&jcwxbP=<~ALiOuulLsi`D$}RW|4{gj0y}=L=xt|^u@XFLik|}imlxmt*k$jM!DqqeKovejcdVW@ zRrev5)Eu&K!18K)?_#I3Qh9Q`3aDM?!1T(@jS02~9(rvLa2)v#*96$Dm;22X6@3{2 zqXlsS>Ku86g;z6;0OYjSxo9E8{7w!I5tr&1sv?x@Mx44ye`ylXJ1;R8axv1uG%e%< znvBvtU~@PEBJC0Sxf|oe>?X^?@2(S^xj@3jx>Y2LNTX&@%B}+b&i--eGoN*UffN*q zOdo~beHK?c;rQ-;@A=K=iObsY$&igT-B)6N`R4S5Kv8-M$0k=M%GsKx5iRa~E;Jfo z5nm*I@31!$QUNUB3b7DIiUupdXE{L8s#UY-Pr#t;YdY=K6&mz3!I%3x#$MEuI8Al+Kord1Et(zf^m>i`ibjy`=0D9|jb0l9 zf6YYKFW2U7-}<4tM49sCo2}d?tr487D5$F!ht9U&7?7k_fm>{K z?|Jii+rdIpM0z1CVs3ZJ7YBa!{a5m!{ z6*l)7Dd4zm>b3;^*o9*3T!ngcDbD?D{UcXZ)AF7H?G+QCuT}xSwZV>D>^T6Sw9flq zX)t&#b$RC(eBJE}wLaN2JQ_Zuh&t+!`VXK@D{v`u3ALruKbS4Pifl$P2Wu`v!>4)M z6z9zAZUdO=sR6^{_k#z}S`b3%SsM!FeiYM<3QW@5nvHMHk^8Gy=6fX8KxcSkavO1GBZp<70{SgY2fXX)K2 z@Ear_R`z`b?wssb`z}->DsKxZ23v{C1gbW)%|9#Q~fXyL_ z3twuvFnO}>>%0qg8%}Nh+0bW)56+PUnlFOm2djOmro1S6YW4|0P>@Lx=3dUTA9N3c zRZSLvc)(Oqa6pWf9|5<;vC`?t0Zg*Px7Y3+MsQjjqKN+}&@8*nPH8ViF6qk*8NhX% z#;aV9!Rzb1_S;+Uh}pNnY!5!EJUOWJn*&_<&9sbyu&8Te`G$&>)n|!6&plrfP_T;N zu{AIHMy0A42C8QfP~+j1ja1>g0O{~JQV6;dxeF*MC~EFL(2rb7fR|5t49L~zJ&mvG z6tx2Poj~Uj0<<ukvt)$!WUb{rdW}=VDXNggdBdJC+x4fYqIQm31kleEAi3A{5}2 zw8?S0O&+@nc1*ou^gMknVfQxyx>Q`blvz5tuf4>H0;7+x>C!K+RstmP7$C(L`usjQ znF2U-4&ae*{N{jSDm?)ZZOx1FXh5f#*nzecT|f>G`L&p-k=lL9*wIqcJ&Ib~Sp^(k z-yKT+=>;jQkiX1FW^_mWTQf@Jdx`9O%9@KSolf!Z*fszuHV1`m))wGu;tb&P$oSp- zfX~{&>C3yV)SqENV50(%gNM?yV28Y*SrjBZ$8J2xdeI1VuEi-OF&JBO_$RQrdy$08 zW@!XZQ|bWUMVbVkS`I3tGjv1f+cr34TIpC+vB(90Q|+F`!@Uqqr}dtm_3YY;yeWTLENbd02tUbw!iHg7%&lBmcb!a2< zH6GlDVClp|U-MOh;}lK+S+20(S&ikR?XnYdkBM$7SuI(5sGQSVfZ=P0vMi49qTB`L2EVkGEkT;GJSp% z1*v^)YC5buIWi?6XlnRk@lp3dHB?>9I0h}O6VQ`x48j2=dmX#VK-JcyWZ|Qk+Ji^N zh`cVzV}K)FKn$YHtlIUhC&3%@C?p9%z>`5e@Zzti9W)Aai}GFIGgq&QL#K_#I}Gx0LftQg%K7olWSQQJzf^`Dwc}APb`U^FQD<}b_vhoy_R=y-XdNiX*iF>bNFX|4 ztooD26^YqWeR9f;<4q_6`gRJtzrPz>6F5yVpRL|;3CSvpNNLhQEmy&$J@Lilm_gdK z^hp%jEG^Ze`QQz;j;x0p@#1^rfNr#4lDmd%2@^7|>2^^(9yp^jbNP`M_NTpEw-yws zd}RY*K^Gt705f%eZ*$JGDmD{Oovt->n<5~`(#!5yN_w)QjLKcUfI0ergN*qPUKkdQ z_U}{d(n(%?zVbo=|A~AX4P-Si2N{tDE}xTUUnQJ z#tTFHp8(z7Bg$?+;==Qz&FGU0bF|q9fJMG!=HA$J=a)`|+yc~NNEg05CNOFAlrR8w zIWCtxICqr1)#IUic~UI{Lf)6(Az;3_a0 z=+y5t#ko)%2_NMIC%^!yKSWXeTJKaND)?gpHgoe{JUTuEiVO}g*5F*Nu=R>Cr|ej7 zNn|dC@p=l|g%0J*bwEpeRhIf_Q@Lou>p8iyb?H70-O=#0HCyz(pm2weaZ9%mf_+{0 zp7VB3&WYo751A?Gx+;LvOMzx8Y*D%M`;Bm7m3h>`E8X($2wZk6!dF(k+;rLNBYr^%&{%9{bcfi23rN&) z2rsp9U0GjZc^2Sq-I`_2+g#A6|Dh#e1JCVj~k8APZy?=tgAPe?v*js$Pt-`1ZvJ%9p`SA4?YC z6JY;_tGt(OoOQ#YlcQxOq9kr2j$(j}N7*gX6xLqke&lH*{M}##gfkW3n?GQ`6oewG zcqu}8tpmI5Z-2nQkS#JWLa1u=ewf4==9{#ojaQb0z#eKu3voNgHcY#9DB5-dlHR$~ zXMF%psa-06M$4^PS9;=-ITWoO-az3AVC`#OX_*&@qpofwa;Me@ zOIVUED#(mW9!x7L$a3Gd*A%ohzInXXF+1#KUEDNC-y|K76K6qd*EY?W)_6n}oicCN z2&5>FikF?gENB}CM`AYX$hI+u_caeBY_`sZSg_4S$b}DOckbrMNPYRrSW3U;Cg1ki zFsr+w zT;xCoI>cOrg->n}2A!jVbve*RQM?5kYUh~`!NzBSeR<%~cq{A}$0{rH0&-GzO|Y6U z{0vQnCbDzDs!u%xHvZ#Ydq3!E7ECyVWG_E zFW|EKC3N;#{bH;+?u`F7WrKIWmiF0W5gPum^aEge`Ro`zHOi3H6UaOSrxp*vR6=Cj5iL3f_QbUf z9hQkQ++ys$!m3w=wy!2P0?5+)0;2Ce6H3f#qM~a{@ChqZJ|t!UW2xBf7V?%QkN zENpq%e$dt6x*$TGNvN=K~N2A5!&A=zquvOjSFzOk@pK zHIBN}1Iii2H3NWBydZ_xr0=LvPgS2IyKtc3foqIY{ZC|?VRD5^hm?qM=1~tMH?XiI zC-4r4C@_l{!$MQ-TPj@m02iS))n`Al(+Vkz)<^Z?lB=rm5?@|T0>eVK&MV>Tw~B9xMUTWhSa#Qsc!|&HcMLNvCSg%sBi^He|Sj^ z-e@PxjX3v+9-z6}fnY??xx+=kPE5uK0nv#Yz|m}?U=;kZj-l^Rl;bbj5kH;FKOIhK zO@JXRibXB`qNe3T@bsN_Awcpc5O=s9@Zu-Y?N7u6 z>WBhEnQSw?|HQt3)GGZ9g`!eTVgB?6e{NhqhY%gp{MNXI9DU+V=?#oSlc2*}Xupb) z=11YPWbn+>?f{U+0VU@{r|?fH*>xXv_^uJ{O1tZ1`gs)J&@kwyOpWMP}374J=n?fz_-&>(~8KbXXonFb|j$LKJgJA-8 z*Pn9yQ9IQ2eEYpL=yf*()~l}D)_1U8<<;mNdw{de7H?e&_ zp&~|qKxAOvU8|LKqRX4w?!{YBXpkNaGESKXmkhB*> zrU#UUttU>D_m4w8{dBo|UNL~OV^A@_piVQ?s-nhrWkD=B!0;IaDX&0dS}}Bj7uC)~ z@V%e|xyJ(!Q^d;qo_)<>uq{|BCrCz>9Dvqw@*C*-mmC9&z@Yr&j8+8LmjCVms52A@ zjzG>(M)8!iWH?wP7@r!Rhr`bW_KSz}HMRq-x4MKw_ZhI86yGBlIl%(Gvbf|?3+ zvaVaD`;^s8{Q{&>9;2BZ{8btF3cZV>dVcJU%RD9R4IntvuAg%m`ejQ0?x>dtSj%_w z39U|1g`#R8?F~QLFyDVQgtR!A1YRlm$#kcrO=7$gJ3KD_Q=k!r^5-w;1Y^gNc7NB% zt`7+TI!RG@(dsnb`D38ef@-SI{5Fz+nRVc<&tGW&lD{&-R6;#)Fo_x)-DoKvd$}_`JiPJ|% zg=wlJt8awlC@WrlM`L7a3R`xiOP`G0{)-X3T7alX0zSmbN9bs?<>I7D_eIhHE35bS^O$D?V`5YX(gA+ zBF?iPZNATYa|*M$NO%dbU59KD7BUWv!F!|j2uR->ygSe9peq8zI_~}tFQ3P7dVkcC zdx9tyl!8y!34173#vVPCN(J&8!5w)1I-J|kBpun*uQizIrrQ;{5I?WC-3+VR9U?w|aQg3MZ2|rq)*Q&4}f`U=>|?P)zKAd;+ht zP%L`J$p6JkB_n{?aX=4V4}m`t+(2CsLhg4C-R}7e`iFmoJD}T`z5O=0eJ9<=FI*R| zSq;1oDZXRs)LDMG`_;q~o%_|ZXQsqU!G@I)OPhs!tBtDBmbtpE)?f2g8Tk;!ciW0{ zgmfrgCyuI%60c@!o%eaiqm^L)eCwV`kCmd8DbJ=y_`!-A`}7wIlaO0*ti9fmr|Nz1 z=!#Vrg-d2rh#QEr5%OY+~a0k60UC4!Fm$_)0z(%7e zWb>giZ6%6?Ydln70&Wa2SsgB3eSOQv3^?-G2ipU>WT?A#zRX;@&e}i%Za+YAIjz8J zncxzYH>!Z9J94j$2XDiuVBqD)O?H=bg|^*F ze%~;tbtPE&`L#lTAC^)Gcoezg5PeZjHCO@=$Cx0JVu4DB5l$#Uqj*CmNPF?7YluZ;Exh`DAk?2L38TU4=`beMV%@0NZ^Qj@RF z$jMtC$QiEbS>Yjz9jpo)toOXek!jf75ByY_1?~L4(P#TE3%ExbQK&1YoGcjsVJ*M5k(rOxOa5JXecMka(D?2s#7g zW8g>0$m<)17t=r-_-jUfuZqc+x7SutG{~cUBu@1waDNV`gZ`j)fW$*)T|mRbeZZ>4={#7qbYW0a*E!;L!dsXz%j&nDfcyz_9y$DbL4(v@uoF0NIaTWd^+tK38XsSoVfo0vov~Vxu;FTHu9Q!c~anDW%lSG?NoYMW5@(C+O&pp9U9&&7gq2KX@r|yqnH5S0 zd)!Yw*Vlk2Tta;EBHsQae<#wdU$n`h)9Ow!<#k0KEr*8Bm;TuQ4anQu@8IVw*gUqn za+S>}H0p|TEiU`#Iwd9=(=;X9@BrH7TxdX{ix@yaq5#ZbHu}t$mvCFPoyJJDs_p~? z-?he2gx>7|BFz(UJBGWXqPmqrzb<-ub_N+L^xk{Wq-q+2f{-Jl07;y~7kM4~K*Me! zF&hymCy6x#wg|7y1n2B0zJ;W^K@}#YD+Oj=i)soLG;$wz#lMPX)#^q&&SoU}7e?u= z$D#tYJBvMERS~J#Z5S_|fa|snFejrTUFBtfk-u=lS$4P2C)L-O6Iy7v<$K}amKctZ z-O|b|L)BHCbr9M%X?XTPFj_^isb*gi2s0IHL}NPWbzaQN}nto@InreI<7Yv$qKyF19@_ zySE}BX~J0PE*TJBj=ylys1d)6RJ2dLb7I7Bj0i3?!OA3FEsEtg?$)2su~6E32OsTc z*U0%)h&6B&y725_<4Ety>=4|TOj9ST5<$>few@EF;cwQGC=^ZjBh_opI{1kO=5kjiKLi>D0xg7zWWuz;|D%x%_o2N0MXW z74s{m!K^4o_7O|DtAi=AAz^vyb9d~^_2!fPje5i~KN=gmHX3~GxleCHU>7Zz_Cdej z-y?Fd;&B~KOywCAoHhce0>h|Sg2|-oInwjxSSb2(yS;2>Jy4^B%h+uNt=E{JK(Cr4 z&&ijUirzlDiymZguK#FND~oK|Dze-pr;lt3ZAHMiEA5%4l^vyAxR3F$AF)T#jG_vk z`0(-iwC{*X{p#$j(~j_^!O@{D>q}~TE?tk-07k$NF<2z>4Bpg|RD?c!Rd{!#UiCua_8$06~_j>o~+tCQjoQd^p`{pHd6$djtQ zbiGic%X}znixY(?2&j2|VFVx%B+)!(&CP)P6`)$kw z|JtdzXV~U~BGu{IUT(Ls>2<==h2M0gl>|nRrRS7g&j}GxUYJ{Q3c|NZrC#tZZ|ZIT z`i_0HU%4%pc{(R9HX!T{-G_8`#eR8WTC*4ze`Fv|mNuVbua!Yp?}tF*dHTe!g}SV+0TI%7M3fE$h6>ncjQe-(A<2{)>dy#lP*r+5SeCLPWWAf~c4I+=*Q;AK#dNGOJSm|Wv3iIzQ~y7&25ydUB;49tBq!38Jv9LRA| zsm1q+oaqLGU?2_}ZaF*1_$=b7AApU{n{Oiug3f@E&C$bo`5%J7Z4JiP3A#d?Wdqq= zmn{{1OV3=C7QRKqZ=t|D#GqPWIaTiq2fJW7V1_>oJydV=cGDiz6lv-?QZO%0NAxn+ zO1_c3|EU|CZ?x~u-!2)@u#)^*px&EN_N9p+cylPLvN#FhG?>xvSZ6a+O+7WlRIx(E z$91=?ccnCQD1L<0WM|46e&_AsCc@*G(Dc&|q1MK3k`V7q#qKx`ysnCFcn;yTN*cB< zEiZ3_C{xje&+mDbbip}C9Cv3ufxlz<&EGM<15VDu3j)6}4x}+L76}rx^i?t#7axGo zuBJNy7Qs~+<}^WXLaoIzcWC4Pi-j@vXp^hnv zro@m&d7^xGs@lF+Yx_A_B0B-DPzkR}06u@#(c2C2_i&)0PKkPPa)fXeXs2gU95P50 z4PT-T)KpikcV{~G6Dc;3qeNE7T*{>uq+=5rDkF+^fwgu&y^LL8@HpL0LH}yHtW{e9 z>_*SzrR!YjEO{7l8g{K+M1jUuMywR|n(hH)zD19*DiZ>N{@?oQ7MpdV#u_N1;B? zD+-n*J1$ha=W*fMKeSm--ps1Wni+yy1aWy^8xUK{X2o8)B~*l>tqmlsQb>R7>BwV= zn{{qty>B|o^S{`8>!_-ms0~yR6;O~gC_zF}L`uK|2+|$r&>-C)Er(E~K|ty54(aBA z5)#rObwKIvPVXG+^?g6TweGri-F5%C_a7I+FJ|VqXV1*u&+}}3#6n5{5~Q{8V7gNL z-xUWzEZ6>M?YX-4KzJ!!4=RpG-)V-RmJ4|+;)_XLfZ>5#s#qwRdtp?6Mdm#7xKG_e zcQjiI1W`B3*>yO~0g z1Q0hNYTOxc+U=sezdKqvgv={2tn%pQ8^-2`SMpkhP9y8?t}a)<8yq}+xGu`I7G%BF zX*6M{zW-&E!>qSsmHWADrj{D9LS;)5Bo6l2ysy;Hc|P3{sd;03mR)=3XzYwT?a^uV zpP3;!0(YB65mOr*ycucr%K@FE7>`goGaL{zD+r5Qv_ZtCS{aiBXKm;HV*g#ze(Nih z&#w@Atr|B!&Ns}0u7{WaE(2xoMQBJ3qO*QF-%&&(!F6%>`g^}^r82m#9ps9eSNO5g z?JFlu^Vg>?9}BLRrNqKGlw8YVVlQIU!dM6V{YM=E#sFv@!V5i5KT~}a&Amnb;$(AT zj_As9{(N{vg1HtWrbrt+(kWWh$^4F+l{?Ef05B0%b+NawK&;oEl%=F-NkoU4HMZ6+ z<=NWtm*0F@@znUh{Bgb<4*$|U3U%jMYABR9zdU=MK`ooTU45`5{}HF>(AdW42B}Iq zB0>F%3;fD!Vc{_6?zT=M!{joxQx>((!Y?ML43ECOT_@iRB<9*eRIF-FTIWA_-eJ(< z$=O>|?t^^Tq`sb889xA1%a+T%9dvAf*zHLgLZ|qgOGtDs$v!c#_m^C4m{>JTeR~ZF@$@Cjb)p;3>tbo7E-VcWt&z}zahRM8C7$%Ambnh?S&ndqe`A*5uP9z+{!~7Y ztYC87esdTFEY)Xvf4k##b}JAm_=jtOi%IRF+IynZ%Q_(`Ns;)0sq<~-`)u!TYQg+m zfZvyy>`^5H6l0k+qGky?7&;u1VIcEciQ1f2S_pOijO9^K%JGoF@VPo$-~6p&PsxwL{e92d@!18%< z9cGa&eedGd2q344fIKO;k*xuDECEYoMYsYd1Vq;)3_TK5Y5E6{KpI&e6+euipuYt2 z^C;zt51iOUsKc)*?VIkWuujtm1QNuQjZ~#*@P5T7% zgu(WwvPdx%07I@kRKWUM%#j?l>c8F~zEb6GN;m%F zg!*d;+*eT9w0C#Ye}i-W2${~vfo9`a)Bi=RMS!9Pl?hlDH~HiG-|zg_4*SpV13qQz zI}l7?fh!RIZ4hx#n9~1KT@(<i<5e41dGK1cbEQz}{m!RWx`{l*~SC zeYhyqYNEF4+t`=0ITWhx;Xc?_uA?v*DCpvs6yYo1@rfufVGHB2T&~3DZt;MX;)ENQ z9$k2JfoALKf)#nT4#q~kcJ{a9&XV!_31(}*c^(If6p)29if}UQ^EsB|)rUYly4ecw zFm<#6-%x1p;+5+MYvVOOu7H|eahu1^7{he27PV(bw1%zn7j)bOnV%;D_3D2~2#Hb9 z^y!m;Z5as0Xdy~dN`ZXtA(65Mt2qu(aYiq`huG;`C`^Pnm#_Dw2Uv}j=cDlWwfv_- z!uC%A0wfJ&+axBR{tv3ErvSW=9?KA${L#bNp7-t-TuTf)8|uIrqZz=v`&cw8@6!ao zQiqi$vYRNhpUsF&^#P41cYpAKpeqepzfH-V^a_9<1-a7$c)AT^4?tOlU12xfnNKVO zL8lrNKY~^|CT(UBC9Zk~5T6QrCI3lM$sGU<#bw5mY6T(iR0^u|%Q{3`WhVU}L7>iY zwkw+3)^NB2Y#kzbKmHcT{xPlH8vr&PI=m{h3XT;xXbAYO4VDH7nBPket68gN-1%I5 zSoYWV0Ue3@z${8Mi~)tOD5MtvN}vL0wkYTXN;q^JV1AZqrJ}wD@f{ftz0<5wi|F{P zp<^gfzKM&|Oq}nCCZM%O1;i9^Oau?EGpjWnYrQzNuLl^%qvGP?H`)XZi7s1hX8>9W zwg5ZH{yEPu&ZD2`3;Zzou17z-;9qQ22{mc`1O(k_LT2_DS&w0m1}7xGOcZ=3t%LiU=s-Z?VWT9KnAF&?B?#@ za!;uAJth}l#rJsr_b~bIe+Xj%1S%lEIg162hC$9JS)BM16qaI+{5Pqu=PUX`^x)T+ zFp~c$38P#VG0IPQkCh{D{TkQbPp1GkViJWzU^V}Jr*S24#l)6lHby_je?a9a zP>J|XT~q<1LM2O6cj-S#Q(>U0PQ`sW!Rmt8uV}qqoSQ5w=#lRy&4sh2Mi__ zzAhkh^&g*|75}ne+$7FRzy#x*@5HM9KL{7Bd^Ij6Y_hK44HZ*E#IXV0SG?_)qEeZD*K_PXphIdP8RU#x?F z9v%QZ)g~Qz_?FggwHt97#V(6Ax9`yUUf6h2`@{_glqYa+f^Ny+iQB z2-0c3dpHuyfraiD4^S))l$HjENgp);l#@dm_CQ!QqBs%zj}a`U-*XEXMX2zrFk?A?bPQ&H%JX>W=x^^l74ju~d^M2}?~NEH1%|>CiI+(!I|;ZFf>~JG zr(Y(!ijCH@_Y>R_s_GF&jt&m(Y&9ip>oV@=&?(NH#}GJ&hMRT$d{dt3+os#!|MybB z2lpnoO*6^-h&=e!9q>?M zv7}sg9RhanB6m2hoKS4>JMuKlR2odNXG@Yz^PqSH$aqbAU%R~~HO#OWUPZr}mBs=T zhkiF~K_5+tj+c91oEM$ProiJ_Z&6JCOZ+a+bn=CDeIeoW| z|MZ%j9+=$!OE)=da^LY8ktor#Wcfwy1f4PYvki>&7 z!)7&6CfyB1+PPF)fM5ObmLEUn2mn*T!reqe8%O_K_=U?NKrq71p2_*@U%oz+;$;-{ zqVMzb?u6$%1H-SEkc-Fb-T0ql?aqfU(6K}%aL-4;`~7oXw?rvdLTT>!I@4OgJU)LVlB=hyXrcH$hG0iHky!xe&{|4fCS7sa@Pkz$)cv;L0@ z_&F2l0>GbDqn@GveX?Ce`3cG!z8C)9GF9;B_6AR?zt|k`kcPmN2Cr5Lkp8`8?I^3b zPD}cG>i??=>=(dHHf+5(^|PV>X}%n4Z7IG#iSa)z6FesA76yeOhtNIT%YScKF~$z# zC!&9iSkDLa+Gs;Dx5#Ki-^;%Si#_BVq=Z;Jv5@kwtzba)0Ph~@A3pn!PXlh&g;6aM zaQ=Plgu&P`G065{e4`Nc~7ChoN(YNq6CTi{`Ja0G!YDBhR!_YRLX0ZYyg4X-pFV0FV`uZb1 zvyjK1w9lp{0Gzn)x#E^uQ(lNK0K@%iJdY15f`$Y%)>TkG>99+joqkmX4Mnl4{1R~f zU?7uk_PWZ`^ZT7vZY5DAakeOC>ljE(BTMrbLR6vWc_>gM3T8IOx++Hib8ZOT)IY1>IR6)d!_w3YxO&Ql9ULE67+D>SpL&R z*$>}PykTywZ~OJ%?8hu?@@tlIa&1=BC%*!;1dd6Lhz3jbLdwR~GoU_i1CIX=^+$sR zIg=KT`Eg6IQYO*Af2>jxchGaH+Cmh}-<#S3WXNq34?B#A@f~W=0c$ImHZUL1Ey^`R zpbk96i{HQ?_j`z1F>a$|p^m3+)Gq)GL{-n%Gf)ABJP2TN)Exks!yQId2$z$GTtGVKghmSx7AtVs}Swf|h;|`iiXH;N|UjfL&8tjqkcmXX#WA8MXTn#Y$ z18V?jIhRoF9oN#u>>X2Q0OGNgg-tHxYM+{J92bAO_i1w#;0he!`x5WXIJQ9$gfmTi z{|U$IlUom;C55V-f?P{IZHn&eySgyy4=g{%2y)()Ug2UUEIdo$9Mrl%cov~lxoW3% zVycR1#9iQchYaZSGzPrSdBy&IZ%LakA7jdA4TGgb1T4{zZx4FCw?j)hk-fua!h z7znG!q;3b3l!>O4x=m4K4-%ui)oghHLpqMHwpFYWRcs3hm_)Ndp#02J6l#eFp*`AM z3xFdsCIEnj7;oX*D{>HrCH7kb>P{u9P?+ZPNiWyEE7wqS){en_$;HrE3;sE%IZW~^ z0Auu?eq{k66&sf9oSOXd(e?t+6XV5jLYPrhvB`?;1HkeXyrfT5biPaFZKItjVqrBT`+gl&s^Vk0a}LXnYq^wPA!E};{QQhj`_Nxo*N^4|uoPE@)XbP) ze7JandVYH~OzfN5`0JqJFGLcRo%61VD}V=j9Tn6%ZoaPGF}6|trX1MXmk+Yb$&(h9 z@fGA(xpm?|{9(d-;v#RXB12^r;DVh7yX{bY^OJRHh7}mXF zg+23iVlH_L7`Xw46%Yy70DS13&vIRuva^WYx-HJ8Zgs2kR*;O^-J}ha_#1{RxPxCSINNOMZ>H@Zp*!L105@{iq#(Ytyl0 zwFB05f^AU$>8Vc6*V0U|V0; zQo${Ne}Ou`j;cv^Kv^`%i=cL3D35s zZ$Jq0&W1dxZnXVUb|$R@;0diTBDS<={hspy@Rxh`%8px5hRTTDs7a>RmWUHx;KbnP zSmsBu#jzkD_`E#K62fxf(p8M^@`P`ttVOM{PuKGA+SA#tdgOOcNN!fODc?gOwyxC@ zeFLb#BUIvWvu?OXGRQp4L-~0-OL#uR6(!3y7Lw|lCq-IWlL-=!@~46tim)%Bwg&l_ zrOuC)n}-C~5lhRG>Xeailbly+5^X@-;3h*0d~s}Oin{MI>9dy=hvFf6t4P2uPi{!^ zKfUI*;UULeQUg(X37ri7=HA=l%++tluRmXwe=}XG zWDOHmqGg;Sc*Z)0J8l~Kk-Z~Mg4nZshJ)fG}72-h>{XSNpJ>_rd;CdkjmJ|VibJa`>Bj5}Re zAfm0T99e%b70~F!K|UZ>q-FhGDg+=hO&=x_QN5a8dqLAz9~qx$HKtyU&>Pb%cO5Sm zHvbe;TH!iT4{(cus+Ax_>$9^^r+7iFyRcJp+M+A{{T=2tx*kC4e|W#=422j)ilr5` zULwcO=ijgDKD7U=+LHS^LM)?Le72l;TsNcG3`_@{Au-Z0ze#KWJspdKJiZ#bLG!`_ zC#^>=f-ZHNp}wr(8u_6V%;hZ|{fjWZ_b%17iM%5g z>qMCK_>}sYHr4>^DAR?iT7?rSEMuyYD+QfsM>KU9Q!{;%*?%d8I2?A7pL7d038=5G zpqjV28PUiz5y^V>bjeN97XQNdWjKG@c(W^J?&c|Bqf&G@;u=lZLV}_ztyV5zJWvOz zb~hIa8{3#Z^b4<}>JYI+?bE7qQEcLY{wa6B)vMw@i*jo`cw` za?%@jo{lh`AW7nlfm>GC7nhRa9o1>UcM>^o6q&T664 z%0!1MCL!q!ktD9tOqn*JfnNY<8n;fNJ$NOfv?T#&R_UQ0O%+$*z1i%BZdi!HT^xTS zScklt1cyiygN+hZi#NX~OZk>EL^fcCE~l z$b%ebA%~o}oDkwu`4fZU#cuK&IUUOhk@coeM5uJ69k8fQy&fe*KFqLHefu!Ms>zCr z(EkhYwCO{Zhe5wl61&#c$h9VmVT7}bq7@^f8vIH7PBmUDl5b{JWsRoN2CLN1+ zt5GW6nROm@>V%V?tep*}8R1uCjP5y&9gWZ`()ntQER#b$U@1cEMRBE+_I{O0K~d?I zi!sJZIBhcfx+{yxz}vf4U8klF^D5BU$Um&KPtRK&`-mQ__k9d3<*d{ z#NSdnTRtUNRdUOIoV}m1LY=WV?diF^KOg6tv~Fv3VGf_o{8_?tf8AOHIrteMH}J6 zTA!+tQ%ScP_?7Ch`lO`Fpr}78^@DfboG$}+9W}kA@@Sgq9__X&o-IORW~qzhEK9Rj zdP}G#HYa)!OazT#ypRC@nkD^BHIj%my<2p=WRVZ>xl5IU1rCe<>sSExNftVL4oTyFTQ1y^og#K~H12SnbkybvGsQWm17nuNXy1?8kL58$K|ANkoL} z>esJ)U|hH1#o|fHx%u#zq&aVAqjH!=9ZaPuLQAzrax{_-MXbsGfk8A4!g`_Y&K3`5 zl`N<1HWBo-0wxQ!$VFiB=JHsnGYAg|k-^M$#SlE(6f`@qIfPG`-g?w?U0e za$T9KK)i7leBT-6yfjnoMt7`e8)CAzp$zG!xLHLvS7%<(=)&^kmfTzbZ$Yqhpi%TJ zYcsFi3|8BYnmf5SyiR(r`^YtEF)UpS<-k8-M;CFzclI(EXP>I%#oiw+C_k>QI9^pA zyD&a>_1Lx0*}2uN41z>-mVObf=3*92mp02bJ67J$Xwy0yN1V2}mAMW;*}|V;2a_0T zr>5d5?ox#Kb%%S0W)DdqcU)p$XkpuMEQME?KGOoKC&_rXP8oL0hUz8|;%R-fn-XIr z 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 G-~R$m4s+!I From 54d5d8f67966555b833323a60da81ffc015f3ad4 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Tue, 18 Mar 2025 13:57:16 -0700 Subject: [PATCH 159/505] Do not generalize Result.flatMapError yet --- proposals/0465-nonescapable-stdlib-primitives.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index 687c0f999e..1d906e306f 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -241,7 +241,7 @@ We generalize `Result` along the same lines as `Optional`, allowing its `success Important convenience APIs such as `Result.init(catching:)` or `Result.map` will need to require escapability until we introduce a way to formally specify lifetime dependencies. This is unfortunate, but it still enables intrepid Swift developers to experiment with defining interfaces that take (or perhaps even return!) `Result` values. -However, we are already able to generalize a small handful of methods: `get` and the two error-mapping utilities, `mapError` and `flatMapError`. +However, we are already able to generalize a couple of methods: `get` and the error-mapping utility `mapError`. ```swift func sample(_ res: Result, E>) -> Int { @@ -525,7 +525,7 @@ extension Result: Escapable where Success: Escapable & ~Copyable {} extension Result: Sendable where Success: Sendable & ~Copyable & ~Escapable {} ``` -We postpone generalizing most of the higher-order functions that make `Result` convenient to use, as we currently lack the means to reason about lifetime dependencies for such functions. But we are already able to generalize the two functions that do not have complicated lifetime semantics: `mapError` and `flatMapError`. +We postpone generalizing most of the higher-order functions that make `Result` convenient to use, as we currently lack the means to reason about lifetime dependencies for such functions. But we are already able to generalize the one function that does not have complicated lifetime semantics: `mapError`. ```swift extension Result where Success: ~Copyable & ~Escapable { @@ -534,16 +534,9 @@ extension Result where Success: ~Copyable & ~Escapable { _ transform: (Failure) -> NewFailure ) -> Result } - -extension Result where Success: ~Copyable & ~Escapable { - @_lifetime(copying self) // Illustrative syntax - consuming func flatMapError( - _ transform: (Failure) -> Result - ) -> Result -} ``` -Both of these functions return a value with the same lifetime as the original `Result` instance. +The returned value has the same lifetime constraints as the original `Result` instance. We can also generalize the convenient `get()` function, which is roughly equivalent to optional unwrapping: @@ -888,5 +881,6 @@ Many people contributed to the discussions that led to this proposal. We'd like - Guillaume Lessard - John McCall - Tony Parker +- Ben Rimmington - Andrew Trick - Rauhul Varma From a88c17732df31776066a2c5a67f55ffe265b4d41 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 18 Mar 2025 20:57:14 +0000 Subject: [PATCH 160/505] Minor wording amendment --- proposals/NNNN-adoption-tooling-for-swift-features.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index e8f9ca34b7..2d750e459a 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -92,7 +92,7 @@ and testing code where a change in behavior is preferable. ## Proposed solution -Introduce the notion of a ***migrate*** mode for individual experimental and +Introduce the notion of a migration mode for individual experimental and upcoming features. The core idea behind migration mode is a declaration of intent that can be leveraged to build better supportive adoption experiences for developers. @@ -150,8 +150,8 @@ be emitted. This warning will belong to the diagnostic group `StrictLanguageFeatures`. In a series of either of these options applied to a given feature, only the last option will be honored. -If an upcoming feature is both implied by the effective language mode and -enabled in migration, the latter will be disregarded. +If a feature is both implied by the effective language mode and enabled in +migration mode, the latter option will be disregarded. ### Diagnostics @@ -241,7 +241,7 @@ of language feature control. The decision around surfacing migration mode in the `PackageDescription` library depends on whether there is a concensus on the value of enabling it as -a persistent setting as opposed to a automated procedure in the long run. +a persistent setting as opposed to an automated procedure in the long run. Here is how an API change could look like for the proposed solution: @@ -288,7 +288,7 @@ The next candidates in line per discussions are ***adopt***, ***audit***, * An important reservation about ***adoption*** of source-breaking features is that it comprises both code migration and integration. It may be more prudent to save this term for a future add-on mode that, - unlike migration mode, implies that the feature is enabled and can be invoked + unlike migration mode, implies that the feature is enabled, and can be invoked in any language mode to aid developers in making better use of new behaviors or rules. To illustrate, this mode could appropriately suggest switching from `any P` From 7069fb5c1faca0d08c21459183c9dfe55ca057d5 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 18 Mar 2025 14:52:24 -0700 Subject: [PATCH 161/505] Accept SE-465 "Standard Library Primitives for Nonescapable Types" --- proposals/0465-nonescapable-stdlib-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index 1d906e306f..1f8bc5fad4 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -3,7 +3,7 @@ * Proposal: [SE-0465](0465-nonescapable-stdlib-primitives.md) * Authors: [Karoy Lorentey](https://github.com/lorentey) * Review Manager: [Doug Gregor](https://github.com/douggregor) -* Status: **Active review (March 5...18, 2025)** +* Status: **Accepted** * Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] * Implementation: https://github.com/swiftlang/swift/pull/73258 * Review: ([Review](https://forums.swift.org/t/se-0465-standard-library-primitives-for-nonescapable-types/78310)) ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) From 61dd6adec716a0f3a61f422f9e1fa930f8085dbb Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Thu, 20 Mar 2025 15:26:53 +0100 Subject: [PATCH 162/505] Update and rename NNNN-exit-tests.md to 0008-exit-tests.md --- .../testing/{NNNN-exit-tests.md => 0008-exit-tests.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/testing/{NNNN-exit-tests.md => 0008-exit-tests.md} (99%) diff --git a/proposals/testing/NNNN-exit-tests.md b/proposals/testing/0008-exit-tests.md similarity index 99% rename from proposals/testing/NNNN-exit-tests.md rename to proposals/testing/0008-exit-tests.md index 29d2ac0775..da116c10f1 100644 --- a/proposals/testing/NNNN-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -1,11 +1,11 @@ # Exit tests -* Proposal: [ST-NNNN](NNNN-exit-tests.md) +* Proposal: [ST-0008](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0008-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) -* Status: **Awaiting review** +* Status: **Active Review (March 21...April 8, 2025)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) -* Review: ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) +* Review: (review), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction From c866493afe9c2c61ef221a0469cbf7762c4507f1 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Thu, 20 Mar 2025 17:18:14 +0100 Subject: [PATCH 163/505] Update 0008-exit-tests.md - Added link to review topic Added link to review topic --- proposals/testing/0008-exit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index da116c10f1..b7b74e1d73 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -5,7 +5,7 @@ * Status: **Active Review (March 21...April 8, 2025)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) -* Review: (review), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) +* Review: ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction From a4419800fe85d8c7f520e6d14207824fb8dbddc1 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 20 Mar 2025 10:57:00 -0700 Subject: [PATCH 164/505] Mark SE-0444 as implemented in Swift 6.1 (#2746) --- proposals/0444-member-import-visibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0444-member-import-visibility.md b/proposals/0444-member-import-visibility.md index a98f0b6857..7904ebc4d5 100644 --- a/proposals/0444-member-import-visibility.md +++ b/proposals/0444-member-import-visibility.md @@ -3,7 +3,7 @@ * Proposal: [SE-0444](0444-member-import-visibility.md) * Authors: [Allan Shortlidge](https://github.com/tshortli) * Review Manager: [Becca Royal-Gordon](https://github.com/beccadax) -* Status: **Accepted** +* Status: **Implemented (Swift 6.1)** * Bug: [apple/swift#46493](https://github.com/apple/swift/issues/46493) * Implementation: [apple/swift#72974](https://github.com/apple/swift/pull/72974), [apple/swift#73063](https://github.com/apple/swift/pull/73063) * Upcoming Feature Flag: `MemberImportVisibility` From 8273f0e7cae43b528a7de267201b97fa776343dc Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 20 Mar 2025 15:07:12 -0400 Subject: [PATCH 165/505] Update attach() -> record() --- proposals/testing/NNNN-attachments.md | 33 +++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/NNNN-attachments.md index 8610d5397e..28aa7947ab 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/NNNN-attachments.md @@ -99,12 +99,15 @@ public struct Attachment: ~Copyable where AttachableValue: Atta /// disk. /// /// An attachment can only be attached once. - public static func attach(_ attachment: consuming Self, sourceLocation: SourceLocation = #_sourceLocation) + public static func record(_ attachment: consuming Self, sourceLocation: SourceLocation = #_sourceLocation) /// Attach a value to the current test. /// /// - Parameters: /// - attachableValue: The value to attach. + /// - preferredName: The preferred name of the attachment when writing it to + /// a test report or to disk. If `nil`, the testing library attempts to + /// derive a reasonable filename for the attached value. /// - sourceLocation: The source location of the call to this function. /// /// When attaching a value of a type that does not conform to both @@ -119,7 +122,7 @@ public struct Attachment: ~Copyable where AttachableValue: Atta /// attaches it to the current test. /// /// An attachment can only be attached once. - public static func attach(_ attachment: consuming AttachableValue, sourceLocation: SourceLocation = #_sourceLocation) + public static func record(_ attachableValue: consuming AttachableValue, named preferredName: String? = nil, sourceLocation: SourceLocation = #_sourceLocation) /// Call a function and pass a buffer representing the value of this /// instance's ``attachableValue-2tnj5`` property to it. @@ -153,10 +156,11 @@ conform: /// A protocol describing a type that can be attached to a test report or /// written to disk when a test is run. /// -/// To attach an attachable value to a test report or test run output, use it to -/// initialize a new instance of ``Attachment``, then call -/// ``Attachment/attach(_:sourceLocation:)``. An attachment can only be attached -/// once. +/// To attach an attachable value to a test, pass it to ``Attachment/record(_:named:sourceLocation:)``. +/// To further configure an attachable value before you attach it, use it to +/// initialize an instance of ``Attachment`` and set its properties before +/// passing it to ``Attachment/record(_:sourceLocation:)``. An attachable +/// value can only be attached to a test once. /// /// The testing library provides default conformances to this protocol for a /// variety of standard library types. Most user-defined types do not need to @@ -245,10 +249,11 @@ that refines `Attachable`: /// written to disk when a test is run and which contains another value that it /// stands in for. /// -/// To attach an attachable value to a test report or test run output, use it to -/// initialize a new instance of ``Attachment``, then call -/// ``Attachment/attach(_:sourceLocation:)``. An attachment can only be attached -/// once. +/// To attach an attachable value to a test, pass it to ``Attachment/record(_:named:sourceLocation:)``. +/// To further configure an attachable value before you attach it, use it to +/// initialize an instance of ``Attachment`` and set its properties before +/// passing it to ``Attachment/record(_:sourceLocation:)``. An attachable +/// value can only be attached to a test once. /// /// A type can conform to this protocol if it represents another type that /// cannot directly conform to ``Attachable``, such as a non-final class or a @@ -452,10 +457,10 @@ version too. allows an implementation (such as that of `Encodable & Attachable`) to add a path extension to the filename specified by the test author if needed. -- Making the `Attachment.attach(_:sourceLocation:)` methods a single instance - method of `Attachment` named `attach()`: this was in the initial pitch but the - community discussed several more ergonomic options and we chose - `Attachment.attach(_:sourceLocation:)` instead. +- Making the `Attachment.record(_:[named:]sourceLocation:)` methods a single + instance method of `Attachment` named `attach()`: this was in the initial + pitch but the community discussed several more ergonomic options and we chose + `Attachment.record(_:sourceLocation:)` instead. ## Acknowledgments From 762a5a076cd065112d696ce14924ade54d86970e Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Thu, 20 Mar 2025 13:47:09 -0700 Subject: [PATCH 166/505] Get ready for moving to active review --- .../testing/{NNNN-attachments.md => 0009-attachments.md} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename proposals/testing/{NNNN-attachments.md => 0009-attachments.md} (99%) diff --git a/proposals/testing/NNNN-attachments.md b/proposals/testing/0009-attachments.md similarity index 99% rename from proposals/testing/NNNN-attachments.md rename to proposals/testing/0009-attachments.md index 28aa7947ab..ad6e16804e 100644 --- a/proposals/testing/NNNN-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -1,8 +1,9 @@ # Attachments -* Proposal: [ST-NNNN](NNNN-attachments.md) +* Proposal: [ST-0009](0009-attachments.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) -* Status: **Awaiting review** +* Review Manager: [Rachel Brindle](https://github.com/younata) +* Status: **Active Review (March 21 - April 8, 2025)** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) * Review: ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) From 7462f2076b0c5a19ada4f8178ad63e859e935b11 Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Thu, 20 Mar 2025 13:59:43 -0700 Subject: [PATCH 167/505] Link to the review thread for ST-0009 --- proposals/testing/0009-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0009-attachments.md b/proposals/testing/0009-attachments.md index ad6e16804e..565c01acc3 100644 --- a/proposals/testing/0009-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -6,7 +6,7 @@ * Status: **Active Review (March 21 - April 8, 2025)** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) -* Review: ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) +* Review: ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) ## Introduction From 1f1cfee5d172cce1b99f87f5cf4c9e814730c00b Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 20 Mar 2025 16:57:52 -0500 Subject: [PATCH 168/505] Add Review Manager field to header of Swift Testing proposal template --- proposal-templates/0000-swift-testing-template.md | 10 +++++++--- proposals/testing/0008-exit-tests.md | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/proposal-templates/0000-swift-testing-template.md b/proposal-templates/0000-swift-testing-template.md index 9e0377961e..642ac7bd53 100644 --- a/proposal-templates/0000-swift-testing-template.md +++ b/proposal-templates/0000-swift-testing-template.md @@ -2,6 +2,7 @@ * Proposal: [ST-NNNN](NNNN-filename.md) * Authors: [Author 1](https://github.com/author1), [Author 2](https://github.com/author2) +* Review Manager: TBD * Status: **Awaiting implementation** or **Awaiting review** * Bug: _if applicable_ [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/issues/NNNNN) * Implementation: [swiftlang/swift-testing#NNNNN](https://github.com/swiftlang/swift-testing/pull/NNNNN) @@ -14,8 +15,10 @@ except for the section headers and the header fields above. For example, you should delete everything from this paragraph down to the Introduction section below. -As a proposal author, you should fill out all of the header fields. Delete any -header fields marked _if applicable_ that are not applicable to your proposal. +As a proposal author, you should fill out all of the header fields except +`Review Manager`. The review manager will set that field and change several +others as part of initiating the review. Delete any header fields marked _if +applicable_ that are not applicable to your proposal. When sharing a link to the proposal while it is still a PR, be sure to share a live link to the proposal, not an exact commit, so that readers will always see @@ -181,4 +184,5 @@ were incorporated into the proposal as it developed, take a moment here to thank them for their contributions. This is a collaborative process, and everyone's input should receive recognition! -Generally, you should not acknowledge anyone who is listed as a co-author. +Generally, you should not acknowledge anyone who is listed as a co-author or as +the review manager. diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index b7b74e1d73..57953ff9ee 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -2,6 +2,7 @@ * Proposal: [ST-0008](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0008-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Review Manager: [Maarten Engels](https://github.com/maartene) * Status: **Active Review (March 21...April 8, 2025)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) From 0a317843f06163de925fb1fd61ff160a8608c3a4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 20 Mar 2025 21:48:27 -0700 Subject: [PATCH 169/505] Global-actor isolated conformances (#2720) * Draft: isolated conformances * Add an introduction, switch to `isolated P` syntax * Turn this into a real proposal with introduction / motivation / etc Also pull in Slava's lovely idea of the SendableMetatype protocol, and narrow the "strict sendable metatypes" check to type parameters that have non-marker protocol requirements. * Future work entry for non-isolated types with isolated conformances * Future direction: consider inference of `isolated` along with `@MainActor` * Add alternative considered for isolated conformance requirements * Discuss using "non-Sendable" terminology instead of "isolated conformances" * [Isolated conformances] Note the need for `nonisolated` if we infer `isolated` * [Isolated conformances] Add alternative for the "@MainActor P" spelling Instead of using `isolated P` for an isolated conformance, we could use the global actor spelling. Document it. * [Isolated conformances] Remove some leftover text This was rewritten and moved in an earlier iteration. * [Isolated conformances] Switch to @GlobalActorName spelling I've gotten a bunch of feedback that `isolated P` is confusing, and `@MainActor P` is both clearer and more extensible. Rework the proposal to use this new syntax, and bring in a few future directions that are enabled by it. * Now that SE-0466 is in review, promote "infer @MainActor conformances" This was in future work, but make this an official part of the proposal now that SE-0466 is in review. * Fix a few inconsistencies and odd wording choices * Introduce a second necessary restriction on dynamic casting Thanks to John for noticing that we need this dynamic check as well. * Add a "Future Direction" for inferring global actor isolation more generally * Address PR comments, thank you Xiaodi! * Add key path example * Improve exposition of rule (2) Instead of solely talking about the metatype being Sendable, be explicit about the two halves of type checking for generic code and what they mean for isolated conformances, how Sendable changes the interface contract, and why we slip SendableMetatype in there. * Bring the upcoming feature InferIsolatedConformances into the proposal * Fix a sentence fragment * Assign SE-0470 --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- proposals/0470-isolated-conformances.md | 662 ++++++++++++++++++++++++ 1 file changed, 662 insertions(+) create mode 100644 proposals/0470-isolated-conformances.md diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md new file mode 100644 index 0000000000..b8c221639a --- /dev/null +++ b/proposals/0470-isolated-conformances.md @@ -0,0 +1,662 @@ +# Global-actor isolated conformances + +* Proposal: [SE-0470](0470-isolated-conformances.md) +* Authors: [Doug Gregor](https://github.com/DougGregor) +* Review Manager: [Xiaodi Wu](https://github.com/xwu) +* Status: **Active review (March 21...April 3, 2025)** +* Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) +* Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. +* Upcoming Feature Flag: `InferIsolatedConformances` +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) + +## Introduction + +Types isolated to a global actor (such as `@MainActor`) are useful for representing data that can only ever be used from a single concurrency context. They occur both in single-threaded programs where all code is expected to run on the main actor as well as larger applications where interaction with the UI occurs through the main actor. Unfortunately, such types are unable to conform to most protocols due to isolation mismatches: + +```swift +@MainActor +class MyModelType: Equatable { + var name: String + + init(name: String) { + self.name = name + } + + // error: main-actor-isolated static function '==' cannot satisfy non-isolated requirement 'Equatable.==' + static func ==(lhs: MyModelType, rhs: MyModelType) -> Bool { + lhs.name == rhs.name + } +} +``` + +This proposal introduces the notion of an *isolated conformance*, which is a conformance that can only be used within the isolation domain of the type. For the code above, the conformance to `Equatable` can be specified as being isolated to the main actor as follows: + +```swift +@MainActor +class MyModelType: @MainActor Equatable { + // unchanged from the above ... +} +``` + +This allows `MyModelType` to provide a conformance to `Equatable` that works like every other conformance, except that it can only be used from the main actor. + +## Motivation + +Types isolated to the global actor are common in single-threaded programs and UI applications, among others, but their inability to conform to protocols without workarounds means that they cannot integrate with any Swift code using generics, cutting them off from interacting with many libraries. The workarounds themselves can be onerous: each operation that is used to satisfy a protocol requirement must be marked as `nonisolated`, e.g., + +```swift + nonisolated static func ==(lhs: MyModelType, rhs: MyModelType) -> Bool { + lhs.name == rhs.name + } +``` + +However, this is incompatible with using types or data on the main actor, and results in an error: + +```swift + 3 | @MainActor + 4 | class MyModelType: Equatable { + 5 | var name: String + | `- note: property declared here + 6 | + 7 | init(name: String) { + : +10 | +11 | nonisolated static func ==(lhs: MyModelType, rhs: MyModelType) -> Bool { +12 | lhs.name == rhs.name + | `- error: main actor-isolated property 'name' can not be referenced from a nonisolated context +13 | } +14 | } +``` + +We can work around this issue by assuming that this function will only ever be called on the main actor using [`MainActor.assumeIsolated`](https://developer.apple.com/documentation/swift/mainactor/assumeisolated(_:file:line:)): + +```swift + nonisolated static func ==(lhs: MyModelType, rhs: MyModelType) -> Bool { + MainActor.assumeIsolated { + lhs.name == rhs.name + } + } +``` + +This is effectively saying that `MyModelType` will only ever be considered `Equatable` on the main actor. Violating this assumption will result in a run-time error detected when `==` is called from outside the main actor. There are two problems with this approach. First, it's dynamically enforcing data-race safety for something that seems like it should be statically verifiable (but can't easily be expressed). Second, this same `nonisolated`/`assumeIsolated` pattern has to be replicated for every function that satisfies a protocol requirement, creating a lot of boilerplate. + +## Proposed solution + +This proposal introduces the notion of an *isolated conformance*. Isolated conformances are conformances whose use is restricted to a particular global actor. This is the same effective restriction as the `nonisolated`/`assumeIsolated` pattern above, but enforced statically by the compiler and without any boilerplate. The following defines an isolated conformance of `MyModelType` to `Equatable`: + +```swift +@MainActor +class MyModelType: @MainActor Equatable { + var name: String + + init(name: String) { + self.name = name + } + + static func ==(lhs: MyModelType, rhs: MyModelType) -> Bool { + lhs.name == rhs.name + } +} +``` + +Any attempt to use this conformance outside of the main actor will result in a compiler error: + +```swift +/*nonisolated*/ func hasMatching(_ value: MyModelType, in modelValues: [MyModelType]) -> Bool { + // error: cannot use main-actor-isolated conformance of 'MyModelType' to 'Equatable' in + // non-isolated function. + return modelValues.contains(value) +} +``` + +Additionally, we need to make sure that generic code cannot take the conformance and send it to another isolation domain. The [`Sequence.contains`](https://developer.apple.com/documentation/swift/sequence/contains(_:)) operation above clearly won't do that, but one could imagine a similar operation that uses concurrency to attempt the search in parallel: + +```swift +extension Sequence { + func parallelContains(_ element: Element) -> Bool where Element: Equatable & Sendable { + // ... + } +} +``` + +This `parallelContains` function can send values of type `Element` to another isolation domain, and from there call the `Equatable.==` function. If the conformance to `Equatable` is isolated, this would violate the data race safety guarantees. Therefore, this proposal specifies that an isolated conformance cannot be used in conjunction with a `Sendable` conformance: + +```swift +@MainActor +func parallelHasMatching(_ value: MyModelType, in modelValues: [MyModelType]) -> Bool { + // error: isolated conformance of 'MyModelType' to 'Equatable' cannot be used to + // satisfy conformance requirement for a `Sendable` type parameter 'Element'. + return modelValues.parallelContains(value) +} +``` + +The corresponding restriction needs to be in place within generic functions, ensuring that they don't leak (potentially) isolated conformances across isolation boundaries. For example, the following code could introduce a data race if the conformance of `T` to `GlobalLookup` were isolated: + +```swift +protocol GlobalLookup { + static func lookupByName(_ name: String) -> Self? +} + +func hasNamed(_: T.Type, name: String) async -> Bool { + return await Task.detached { + return T.lookupByName(name) != nil + }.value +} +``` + +Here, the type `T` itself is not `Sendable`, but because *all* metatypes are `Sendable` it is considered safe to use `T` from another isolation domain within the generic function. The use of `T`'s conformance to `GlobalLookup` within that other isolation domain introduces a data-race problem if the conformance were isolated. To prevent such problems in generic code, this proposal treats conformances within generic code as if they are isolated *unless* the conforming type opts in to being sendable. The above code, which is accepted in Swift 6 today, would be rejected by the proposed changes here with an error message like: + +```swift +error: cannot use potentially-isolated conformance of non-sendable type `T` to `GlobalLookup` in 'sending' closure +``` + +A function like `hasNamed` can indicate that its type parameter `T`'s requires non-isolated conformance by introducing a requirement `T: SendableMetatype`, e.g., + +```swift +func hasNamed(_: T.Type, name: String) async -> Bool { + return await Task.detached { + return T.lookupByName(name) != nil + }.value +} +``` + +As with `Sendable`, an isolated conformance cannot be combined with a `SendableMetatype` constraint: + +```swift +extension MyModelType: isolated GlobalLookup { + static func lookupByName(_ name: String) -> Self? { ... } +} + +// error: isolated conformance of 'MyModelType' to 'MyModelType' cannot be used to +// satisfy conformance requirement for a `SendableMetatype` type parameter 'T'. +if hasNamed(MyModelType.self, "root") { ... } +``` + +Note that `Sendable` inherits from `SendableMetatype`, so any type `T` with a `Sendable` requirement also implies a requirement `T: SendableMetatype`. + +Protocol conformances can also be discovered dynamically with the `as?` and `is` operators. For example, one could try to produce an `any Equatable` from a value of unknown type in any isolation domain: + +```swift +func tryEquatable(_ lhs: Any, rhs: Any) -> Bool { + if let eLHS = lhs as? any Equatable { + // use Equatable.== + } else { + return false + } +} +``` + +The `Any` value could contain `MyModelType`, in which case the conformance to `Equatable` will be isolated. In such cases, the `as?` operation will check whether the code is running on the executor associated with the conformance's isolation. If so, the cast can succeed; otherwise, the case will fail (and produce `nil`). + +## Detailed design + +The proposed solution describes the basic shape of isolated conformances and how they interact with the type system. This section goes into more detail on the data-race safety issues that arise from the introduction of isolated conformances into the language. Then it details three rules that, together, ensure freedom from data race safety issues in the presence of isolated conformances: + +1. An isolated conformance can only be used within its isolation domain. +2. When an isolated conformance is used to satisfy a generic constraint `T: P`, the generic signature must not include either of the following constraints: `T: Sendable` or `T: SendableMetatype`. +3. A value using a conformance isolated to a given global actor is within the same region as that global actor. + +### Data-race safety issues + +An isolated conformance must only be used within its actor's isolation domain. Here are a few examples that demonstrate the kinds of problems that need to be addressed by a design for isolated conformances to ensure that this property holds. + +First, using an isolated conformance outside of its isolation domain creates immediate problems. For example: + +```swift +protocol Q { + static func g() { } +} + +extension C: @MainActor Q { + @MainActor static func g() { } +} + +nonisolated func callQG() { + let qType: Q.Type = C.self + qType.g() // problem: called @MainActor function from nonisolated code +} +``` + +Here, a call to `C.g()` would have been rejected because it's calling a `@MainActor` function from non-isolated code and cannot `await`. However, if we're allowed to use the isolated conformance of `C: Q`, we would subvert the checking because `Q.g()` is non-isolated. + +We can address this specific issue by prohibiting the use of an isolated conformance from outside its isolation domain, i.e., the use of `C: Q` to convert `C.Type` to `Q.Type` in a non-`@MainActor` function would be an error. + +However, this is not sufficient to ensure that this conformance `C: P` will only be used from the main actor. Consider a function like this: + +```swift +@MainActor func badReturn(c: C) -> any Sendable & P { // okay so far + c // uses C: P from the main actor context (okay) + // uses C: Sendable (okay) +} + +@MainActor func useBadReturn(c: C) { + let anyP = badReturn(c: c) + Task.detached { + anyP.f() // PROBLEM: C.f is called from off the main actor + } +} +``` + +Here, the conformance `C: P` is used from within a `@MainActor` function, but a value that stores the conformance (in the `any Sendable & P`) is returned that no longer carries the isolation restriction. The caller is free to copy that value to another isolation domain, and will end up calling `@MainActor` code from outside the main actor. + +The issue is not limited to return values. For example, a generic parameter might escape to another isolation domain: + +```swift +@MainActor func sendMe(_ value: T) { + Task.detached { + value.f() + } +} + +extension C: @unchecked Sendable { } + +@MainActor func doSend(c: C) { + sendMe(c) // uses C: P from the main actor context + // uses C: Sendable +} +``` + +Here, `sendMe` ends up calling `C.f()` from outside the main actor. The combination of an isolated conformance and a `Sendable` requirement on the same type underlies this issue. To address the problem, we can prohibit the use of an isolated conformance if the corresponding type parameter (e.g, `T` in the example above) also has a `Sendable` requirement. + +However, that doesn't address all issues, because region isolation permits sending non-`Sendable` values: + +```swift +@MainActor func badSendingReturn() -> sending any P { // okay so far + C() // uses C: P from the main actor context (okay) + // returned value is in its own region +} + +@MainActor func useBadSendingReturn(c: C) { + let anyP = badSendingReturn() + Task.detached { + anyP.f() // PROBLEM: C.f is called from off the main actor + } +} +``` + +There are similar examples for `sending` parameters, but they're not conceptually different from the return case. This particular issue can be addressed by treating a value that depends on an isolated conformance as being within the region as the actor it's isolated to. So a newly-created value of type `C` is in its own region, but if it's type-erased to an `any P`, its region is merged with the region for the main actor. This would make the return expression in `badSendingReturn` ill-formed, because the returned value is not in its own region. + +Conformances can cross isolation boundaries even if no values cross the boundary: + +```swift +nonisolated func callQGElsewhere(_: T.Type) { + Task.detached { + T.g() + } +} + +@MainActor func isolationWithStatics() { + callQGElsewhere(C.self) +} +``` + +Here, the generic type `T` is used from another isolation domain inside `callQGElsewhere`. When the isolated conformance of `C: Q` is provided to this function, it opens up a data-race safety hole because `C.g()` ends up getting called through generic code. Addressing this problem either means ensuring that there are no operations on the metatype that go through a potentially-isolated protocol conformance or that the metatype is itself does not leave the isolation domain. + +One last issue concerns dynamic casting. Generic code can query a conformance at runtime with a dynamic cast like this: + +```swift +nonisolated func f(_ value: Any) { + if let p = value as? any P { + p.f() + } +} +``` + +If the provided `value` is an instance of `C` , and this code is invoked off the main actor, allowing it to enter the `if` branch would introduce a data race. Therefore, dynamic casting will have to determine when the conformance it depends on is isolated to an actor and check whether the code is running on the executor for that actor. + +Additionally, a dynamic cast that involves a `Sendable` or `SendableMetatype` constraint should not accept an isolated conformance even if the code is running on that global actor, e.g., + +```swift + if let p = value as? any Sendable & P { // never allows an isolated conformance to P + p.f() + } +``` + +### Rule 1: Isolated conformance can only be used within its isolation domain + +Rule (1) is straightforward: the conformance can only be used within a context that is also isolated to the same global actor. This applies to any use of a conformance anywhere in the language. For example: + +```swift +struct S: @MainActor P { } + +struct WrapsP: P { + var value: T + + init(_ value: T) { self.value = value } +} + +func badFunc() -> WrapsP { } // error: non-@MainActor-isolated function uses @MainActor-isolated conformance `S: P` + +func badFunc2() -> any P { + S() // error: non-@MainActor-isolated function uses @MainActor-isolated conformance `S: P` +} + +func acceptsP(_ value: T) { } + +func badFunc3() { + acceptsP(S()) // error: non-@MainActor-isolated function uses @MainActor-isolated conformance `S: P` +} + +protocol P2 { + associatedtype A: P +} + +struct S2: P2 { // error: conformance of S2: P2 depends on @MainActor-isolated conformance `S: P` + // note: fix by making conformance of S2: P2 also @MainActor-isolated + typealias A = S +} + +protocol HasName { + var name: String { get } +} + +@MainActor class Named: @MainActor HasName { + var name: String + // ... +} + +@MainActor +func useName() { + let named = Named() + Task.detached { + named[keyPath: \HasName.name] // error: uses main-actor isolated conformance Named: P + // outside of the main actor + } +} +``` + +Note that the types can have different isolation from their conformances. For example, an `actor` or non-isolated type can have a `@MainActor` conformance: + +```swift +actor MyActor: @MainActor P { + // okay, so long as the declarations satisfying the requirements to P are + // @MainActor or nonisolated +} + +/*nonisolated*/ struct MyStruct: @MainActor P { + // okay, so long as the declarations satisfying the requirements to P are + // @MainActor or nonisolated +} +``` + +### Rule 2: Isolated conformances can only be abstracted away for non-`Sendable` types + +Rule (2) ensures that when information about an isolated conformance is abstracted away by the generics system, the conformance cannot leave its original isolation domain. This requires a way to determine when a given generic function is permitted to pass a conformance it receives across isolation domains. Consider the example above where a generic function uses one of its conformances in different isolation domain: + +```swift +protocol Q { + static func g() { } +} + +nonisolated func callQGElsewhere(_: T.Type) { + Task.detached { + T.g() // use of the conformance T: Q in a different isolation domain + } +} + +extension C: @MainActor Q { ... } + +@MainActor func isolationWithStatics() { + callQGElsewhere(C.self) // passing an isolated conformance +} +``` + +The above code must be rejected to prevent a data race. There are two options for diagnosing this data race: + +1. Reject the definition of `callQGElsewhere` because it is using the conformance from a different isolation domain. +2. Reject the call to `callQGElsewhere` because it does not support isolated conformances. + +This proposal takes option (1): we assume that generic code accepts isolated conformances unless it has indicated otherwise with a `Sendable` constraint (more information on that below). Since most generic code doesn't deal with concurrency at all, it will be unaffected. And generic code that does make use of concurrency should already have `Sendable` constraints that indicate that it will not work with isolated conformances. + +The specific requirement for option (1) is enforced both in the caller to a generic function and in the implementation of that function. The caller can use an isolated conformance to satisfy a conformance requirement `T: P` so long as the generic function does not also contain a requirement `T: Sendable`. This prevents isolated conformances to be used in conjunction with types that can cross isolation domains, preventing the data race from being introduced at the call site. Here are some examples of this rule: + +```swift +func acceptsSendableP(_ value: T) { } +func acceptsAny(_ value: T) { } +func acceptsSendable(_ value: T) { } + +@MainActor func passIsolated(s: S) { + acceptsP(s) // okay: the type parameter 'T' requires P but not Sendable + acceptsSendableP(s) // error: the type parameter 'T' requires Sendable + acceptsAny(s) // okay: no isolated conformance + acceptsSendable(s) // okay: no isolated conformance +} +``` + +The same checking occurs when the type parameter is hidden, for example when dealing with `any` or `some` types: + +```swift +@MainActor func isolatedAnyGood(s: S) { + let a: any P = s // okay: the 'any P' cannot leave the isolation domain +} + +@MainActor func isolatedAnyBad(s: S) { + let a: any Sendable & P = s // error: the (hidden) type parameter for the 'any' is Sendable +} + +@MainActor func returnIsolatedSomeGood(s: S) -> some P { + return s // okay: the 'any P' cannot leave the isolation domain +} + +@MainActor func returnIsolatedSomeBad(s: S) -> some Sendable & P { + return s // error: the (hidden) type parameter for the 'any' is Sendable +} +``` + +Within the implementation, a conformance requirement `T: Q` is considered to be isolated if there is no requirement `T: Sendable`. This mirrors the rule on the caller side, and causes the following code to be ill-formed: + +```swift +protocol Q { + static func g() { } +} + +nonisolated func callQGElsewhere(_: T.Type) { + Task.detached { + T.g() // error: use of potentially-isolated conformance of non-Sendable type T to Q + } +} +``` + +To correct this function, add a constraint `T: Sendable`, which allows the function to send the conformance across isolation domains. As described above, it also prevents the caller from providing an isolated conformance to satisfy the `T: Q` requirement, preventing the data race. + +The `Sendable` requirement described above is a stricter contract than is necessary for a function such as `callQGElsewhere`, which won't ever pass *values* of the type `T` across an isolation domain. Therefore, we introduce a new marker protocol `SendableMetatype` to capture the idea that values of the metatype of `T` (i.e., `T.Type`) will cross isolation domains and take conformances with them. A requirement `T: SendableMetatype` prohibits isolated conformances from being used on type `T`. Now, `callQGElsewhere` can be correctly expressed as follows: + +```swift +nonisolated func callQGElsewhere(_: T.Type) { + Task.detached { + T.g() + } +} +``` + +The `SendableMetatype` protocol is somewhat special, because according to SE-0302 *all* metatypes are `Sendable`. This proposal refines that statement slightly: all concrete types (structs, enums, classes, actors) implicitly conform to `SendableMetatype`, because their metatypes (e.g., `MyModelType.Type`) are all `Sendable`. Therefore, a call to `callQGElsewhere` for any concrete type will succeed so long as that type has a (non-isolated) conformance to `Q`. + +The `Sendable` protocol inherits from the new `SendableMetatype` protocol: + +```swift +/*@marker*/ protocol SendableMetatype { } +/*@marker*/ protocol Sendable: SendableMetatype { } +``` + +This means that a requirement `T: Sendable` implies `T: SendableMetatype`, so a generic function that uses concurrency along with `Sendable` requirements, like this:: + +```swift +func doSomethingElsewhere(_ value: T) { + Task.detached { + value.f() // okay + } +} +``` + +will continue to work with the stricter model for generic functions in this proposal. + +The proposed change for generic functions does have an impact on source compatibility, where functions like `callQGElsewhere` will be rejected. However, the source break is limited to generic code that: + +1. Uses a conformance requirement (`T: P`) of a non-marker protocol `P` in another isolated domain, +2. Does not have a corresponding constraint `T: Sendable` requirement; and +3. Is compiled with strict concurrency enabled (either as Swift 6 or with warnings). + +Experiments with the prototype implementation of this feature uncovered very little code that was affected by this change. The benefit to introducing this source break is that the vast majority of existing generic code will work unmodified with isolated conformances, or (if it's using concurrency) correctly reject the use of isolated conformances in their callers. + +### Rule 3: Isolated conformances are in their global actor's region + +With [region-based isolation](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0414-region-based-isolation.md), values of non-`Sendable` type can be transferred to another isolation domain when it can be proven that they are in their own "region" of code that separate from all other regions. Isolated conformances are considered to be within the region of their global actor, so any value formed that involves an isolated conformance will have its region merged with that of the isolated conformance. For example: + +```swift +@MainActor func acceptSending(_ value: sending any P) { } + +@MainActor func passSending() { + let c1 = C() // in its own region + let ap1: any P = c1 // merges region of c1 with region of the conformance of C: P (MainActor) + acceptSending(ap1) // error: argument to sending parameter is within the MainActor region + + let c2 = C() // in its own region + let wp2 = WrapsP(c2) // merges region of c2 with region of the conformance of C: P (MainActor) + acceptSending(c) // error: argument to sending parameter is within the MainActor region +} +``` + +### Inferring global actor isolation for global-actor-isolated types + +Types that are isolated to a global actor are very likely to want to have their conformances to be isolated to that global actor. This is especially true because the members of global-actor isolated types are implicitly isolated to that global actor, so obvious-looking code is rejected: + +```swift +@MainActor +class MyModelType: P { + func f() { } // error: implements P.f, is implicitly @MainActor + // but conformance to P is not isolated +} +``` + +With this proposal, the fix is to mark the conformance as `@MainActor`: + +```swift +@MainActor +class MyModelType: @MainActor P { + func f() { } // okay: implements P.f, is implicitly @MainActor +} +``` + +However, the inference rule feels uneven: why is the `@MainActor` in one place inferred but not in the other? + +In the future, we'd like to extend the global actor inference rule for global-actor isolated types to also infer global actor isolated on their conformances. This makes the obvious code above also correct: + +```swift +@MainActor +class MyModelType: /*inferred @MainActor*/ P { + func f() { } // implements P.f, is implicitly @MainActor +} +``` + +If this inference is not desired, for example because the code will use `nonisolated` members to satisfy the requirements of the protocol, it can use `nonisolated` on the conformance: + +```swift +@MainActor +class MyModelType: nonisolated P { + nonisolated func f() { } // implements P.f, is non-isolated +} +``` + +This mirrors the rules for global actor inference elsewhere in the language, providing a more consistent answer. + +This proposed change is source-breaking, so it should be staged in via an upcoming feature (`InferIsolatedConformances`) that can be folded into a future language mode. Fortunately, it is mechanically migratable: existing code migrating to `InferIsolatedConformances` could introduce `nonisolated` for each conformance of a global-actor-isolated type. + +### Infer `@MainActor` conformances + +[SE-0466](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md) provides the ability to specify that a given module will infer `@MainActor` on any code that hasn't explicitly stated isolated (or non-isolation, via `nonisolated`). In a module that infers `@MainActor`, the upcoming feature `InferIsolatedConformances` (from the prior section) should also be enabled. This means that types will get main-actor isolation and also have their conformances main-actor isolated, extending the "mostly single-threaded" view of SE-0466 to interactions with generic code: + +```swift +/*implicit @MainActor*/ +class MyClass: /*implicit @MainActor*/P { ... } +``` + +## Source compatibility + +As discussed in the section on rule (2), this proposal introduces a source compatibility break for code that is using strict concurrency and passes uses conformances of non-`Sendable` type parameters in other isolation domains. The overall amount of such code is expected to be small, because it's likely to be rare that the conformances of generic types cross isolation boundaries but values of those types do not. + +Initial testing of an implementation of this proposal found very little code that relied on `Sendable` metatypes where the corresponding type was not also `Sendable`. Therefore, this proposal suggests to accept this as a source-breaking change with strict concurrency (as a warning in Swift 5, error in Swift 6) rather than staging the change through an upcoming feature or alternative language mode. + +## ABI compatibility + +Isolated conformances can be introduced into the Swift ABI without any breaking changes, by extending the existing runtime metadata for protocol conformances. All existing (non-isolated) protocol conformances can work with newer Swift runtimes, and isolated protocol conformances will be usable with older Swift runtimes as well. There is no technical requirement to restrict isolated conformances to newer Swift runtimes. + +However, there is one likely behavioral difference with isolated conformances between newer and older runtimes. In newer Swift runtimes, the functions that evaluate `as?` casts will check of an isolated conformance and validate that the code is running on the proper executor before the cast succeeds. Older Swift runtimes that don't know about isolated conformances will allow the cast to succeed even outside of the isolation domain of the conformance, which can lead to different behavior that potentially involves data races. + +## Future Directions + +### Actor-instance isolated conformances + +Actor-instance isolated conformances are considerably more difficult than global-actor isolated conformances, because the conformance needs to be associated with a specific instance of that actor. Even enforcing rule (1) is nonobvious. As with `isolated` parameters, we could spell actor-instance isolation to a protocol `P` with `isolated P`. The semantics would need to be similar to what follows: + +```swift +actor A: isolated P { + func f() { } // implements P.f() +} + +func instanceActors(a1: isolated A, a2: A) { + let anyP1: any P = a1 // okay: uses isolated conformance 'A: P' only on a1, to which this function is isolated + let anyP2: any P = a2 // error: uses isolated conformance 'A: P' on a2, which is not the actor to which this function is isolated + + let a3 = a1 + let anyP3: any P = a3 // okay? requires dataflow analysis to determine that a3 and + // a1 are in the isolation domain of this function + + let wrappedA1: WrapsP // error? isolated conformance 'A: P' used without being + // anchored to the actor instance a1 + var wrappedA2: WrapsP = .init(a1) // okay? isolated conformance 'A: P' is used with a1 + wrappedA2.value = a3 // error: isolated conformance 'A: P' used in the type is + // in a different isolation domain than 'a1' +} +``` + +It's possible that these problems can be addressed by relying more heavily on region-based isolation akin to rule (3). This can be revisited in the future if the need justifies the additional complexity and we find a suitable implementation strategy. + +## Alternatives considered + +### "Non-Sendable" terminology instead of isolated conformances + +Isolated conformances are a lot like non-`Sendable` types, in that they can be freely used within the isolation domain in which they are created, but can't necessarily cross isolation domain boundaries. We could consider using "sendable" terminology instead of "isolation" terminology, e.g., all existing conformances are "Sendable" conformances (you can freely share them across isolation domain boundaries) and these new conformances are "non-Sendable" conformances. Trying to send such a conformance across an isolation domain boundary is, of course, an error. + +However, the "sendable" analogy breaks down or causes awkwardness in a few places: + +* Values of non-`Sendable` type can be sent across isolation domain boundaries due to [region-based isolation](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0414-region-based-isolation.md), but the same cannot be said of isolated conformances, so they are more non-Sendable than most non-Sendable things. + +* Global-actor-isolated types are usually `Sendable`, but their conformances would generally need to be non-`Sendable`. + +* Usually things are non-`Sendable` but have to be explicitly opt-in to being `Sendable`, whereas conformances would be the opposite. + +* Diagnostics for invalid conformance declarations that could be addressed with isolated conformances are necessarily described in terms of isolation, e.g., + ```` + error: main-actor isolated method 'f' cannot satisfy non-isolated requirement `f` of protocol P + ```` + + It wouldn't make sense to recast that diagnostic in terms of "sendable", and would also be odd for the fix to an isolation-related error message to be "add non-Sendable." + +* There is no established spelling for "not Sendable" that would work well on a conformance. + +### Isolated conformance requirements + +This proposal introduces the notion of isolated conformances, which can satisfy a conformance requirement only when the corresponding type isn't `Sendable`. There is no way for a generic function to express that some protocol requirements are intended to allow isolated conformances while others are not. That could be made explicit, for example by allowing requirements of the form `T: isolated P` (which would work with both isolated and non-isolated conformances) and `T: nonisolated P` (which only allows non-isolated conformances). One could combine these in a given generic signature: + +```swift +func mixedConformances(_ x: [T]) { + for item in x { + item.foo() // Can use requirements of P + print(x.id) // Can use requirements of Identifiable + } + + Task.detached { + for item in x { + item.foo() // error: cannot capture isolated conformance of 'T' to 'P' in a closure in a different isolation domain + print(x.id) // okay: conformance to Identifable is nonisolated + } + } +} +``` + +This is a generalization of the proposed rules that makes more explicit when conformances can cross isolation domains within generic code, as well as allowing mixing of isolated and non-isolated conformances as in the example. One can explain this proposal's rule involving `SendableMetatype` requirements and isolated conformances in terms of (non)-isolated requirements. For a given conformance requirement `T: P` : + +* If `T: SendableMetatype`, `T: P` is interpreted as `T: nonisolated P`. +* If not `T: SendableMetatype`, `T: P` is interepreted as `T: isolated P`. + +The main down side of this alternative is the additional complexity it introduces into generic requirements. It should be possible to introduce this approach later if it proves to be necessary, by treating it as a generalization of the existing rules in this proposal. From be55df54147e25ed2a35885af6060d57a729da17 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Thu, 20 Mar 2025 22:02:18 -0700 Subject: [PATCH 170/505] Add link to review thread (#2749) --- proposals/0470-isolated-conformances.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index b8c221639a..91c87b8b53 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -7,7 +7,7 @@ * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` -* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ## Introduction From 9232e2ff1f540f023ead85c7fe1cd6e7f3e56470 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 25 Mar 2025 11:08:48 -0600 Subject: [PATCH 171/505] Update UTF8Span proposal --- .../0464-utf8span-safe-utf8-processing.md | 96 ++++++++++++------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/proposals/0464-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md index a2b09f6528..dc7b5d7d5f 100644 --- a/proposals/0464-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -121,16 +121,6 @@ extension Unicode.UTF8 { errors (including overlong encodings, surrogates, and invalid code points), it will produce an error per byte. - Since overlong encodings, surrogates, and invalid code points are erroneous - by the second byte (at the latest), the above definition produces the same - ranges as defining such a sequence as a truncated scalar error followed by - unexpected continuation byte errors. The more semantically-rich - classification is reported. - - For example, a surrogate count point sequence `ED A0 80` will be reported - as three `.surrogateCodePointByte` errors rather than a `.truncatedScalar` - followed by two `.unexpectedContinuationByte` errors. - Other commonly reported error ranges can be constructed from this result. For example, PEP 383's error-per-byte can be constructed by mapping over the reported range. Similarly, constructing a single error for the longest @@ -208,6 +198,25 @@ extension UTF8Span { /// /// The resulting UTF8Span has the same lifetime constraints as `codeUnits`. public init(validating codeUnits: Span) throws(UTF8.EncodingError) + + /// Creates a UTF8Span unsafely containing `uncheckedBytes`, skipping validation. + /// + /// `uncheckedBytes` _must_ be valid UTF-8 or else undefined behavior may + /// emerge from any use of the resulting UTF8Span, including any use of a + /// `String` created by copying the resultant UTF8Span + @unsafe + public init(unsafeAssumingValidUTF8 uncheckedCodeUnits: Span) +} +``` + +Similarly, `String`s can be created from `UTF8Span`s without re-validating their contents. + +```swift +extension String { + /// Create's a String containing a copy of the UTF-8 content in `codeUnits`. + /// Skips + /// validation. + public init(copying codeUnits: UTF8Span) } ``` @@ -217,7 +226,7 @@ We propose a `UTF8Span.UnicodeScalarIterator` type that can do scalar processing ```swift extension UTF8Span { - /// Returns an iterator that will decode the code units into + /// Returns an iterator that will decode the code units into /// `Unicode.Scalar`s. /// /// The resulting iterator has the same lifetime constraints as `self`. @@ -315,7 +324,7 @@ extension UTF8Span { We similarly propose a `UTF8Span.CharacterIterator` type that can do grapheme-breaking forwards and backwards. -The `CharacterIterator` assumes that the start and end of the `UTF8Span` is the start and end of content. +The `CharacterIterator` assumes that the start and end of the `UTF8Span` is the start and end of content. Any scalar-aligned position is a valid place to start or reset the grapheme-breaking algorithm to, though you could get different `Character` output if resetting to a position that isn't `Character`-aligned relative to the start of the `UTF8Span` (e.g. in the middle of a series of regional indicators). @@ -342,7 +351,7 @@ extension UTF8Span { /// Return the `Character` starting at `currentCodeUnitOffset`. After the /// function returns, `currentCodeUnitOffset` holds the position at the /// end of the `Character`, which is also the start of the next - /// `Character`. + /// `Character`. /// /// Returns `nil` if at the end of the `UTF8Span`. public mutating func next() -> Character? @@ -350,7 +359,7 @@ extension UTF8Span { /// Return the `Character` ending at `currentCodeUnitOffset`. After the /// function returns, `currentCodeUnitOffset` holds the position at the /// start of the returned `Character`, which is also the end of the - /// previous `Character`. + /// previous `Character`. /// /// Returns `nil` if at the start of the `UTF8Span`. public mutating func previous() -> Character? @@ -394,7 +403,7 @@ extension UTF8Span { /// /// Note: This is only for very specific, low-level use cases. If /// `codeUnitOffset` is not properly scalar-aligned, this function can - /// result in undefined behavior when, e.g., `next()` is called. + /// result in undefined behavior when, e.g., `next()` is called. /// /// If `i` is scalar-aligned, but not `Character`-aligned, you may get /// different results from running `Character` iteration. @@ -444,13 +453,6 @@ extension UTF8Span { } ``` -We also support literal (i.e. non-canonical) pattern matching against `StaticString`. - -```swift -extension UTF8Span { - static func ~=(_ lhs: UTF8Span, _ rhs: StaticString) -> Bool -} -``` #### Canonical equivalence and ordering @@ -466,7 +468,7 @@ extension UTF8Span { /// Whether `self` orders less than `other` under Unicode Canonical /// Equivalence using normalized code-unit order (in NFC). - public func isCanonicallyLessThan( + public func canonicallyPrecedes( _ other: UTF8Span ) -> Bool } @@ -482,17 +484,17 @@ Slicing a `UTF8Span` is nuanced and depends on the caller's desired use. They ca ```swift extension UTF8Span { - /// Returns whether contents are known to be all-ASCII. A return value of - /// `true` means that all code units are ASCII. A return value of `false` + /// Returns whether contents are known to be all-ASCII. A return value of + /// `true` means that all code units are ASCII. A return value of `false` /// means there _may_ be non-ASCII content. /// /// ASCII-ness is checked and remembered during UTF-8 validation, so this - /// is often equivalent to is-ASCII, but there are some situations where + /// is often equivalent to is-ASCII, but there are some situations where /// we might return `false` even when the content happens to be all-ASCII. /// - /// For example, a UTF-8 span generated from a `String` that at some point - /// contained non-ASCII content would report false for `isKnownASCII`, even - /// if that String had subsequent mutation operations that removed any + /// For example, a UTF-8 span generated from a `String` that at some point + /// contained non-ASCII content would report false for `isKnownASCII`, even + /// if that String had subsequent mutation operations that removed any /// non-ASCII content. public var isKnownASCII: Bool { get } @@ -620,16 +622,24 @@ extension UTF8Span { ``` - ### More alignments and alignment queries Future API could include word iterators (either [simple](https://www.unicode.org/reports/tr18/#Simple_Word_Boundaries) or [default](https://www.unicode.org/reports/tr18/#Default_Word_Boundaries)), line iterators, etc. Similarly, we could add API directly to `UTF8Span` for testing whether a given code unit offset is suitably aligned (including scalar or grapheme-cluster alignment checks). +### `~=` and other operators + +`UTF8Span` supports both binary equivalence and Unicode canonical equivalence. For example, a textual format parser using `UTF8Span` might operate in terms of binary equivalence for processing the textual format itself and then in terms of Unicode canonical equivalnce when interpreting the content of the fields. + +We are deferring making any decision on what a "default" comparison semantics should be as future work, which would include defining a `~=` operator (which would allow one to switch over a `UTF8Span` and match against literals). + +It may also be the case that it makes more sense for a library or application to define wrapper types around `UTF8Span` which can define `~=` with their preferred comparison semantics. + + ### Creating `String` copies -We could add an initializer to `String` that makes an owned copy of a `UTF8Span`'s contents. Such an initializer can skip UTF-8 validation. +We could add an initializer to `String` that makes an owned copy of a `UTF8Span`'s contents. Such an initializer can skip UTF-8 validation. Alternatively, we could defer adding anything until more of the `Container` protocol story is clear. @@ -639,7 +649,7 @@ Future API could include checks for whether the content is in a particular norma ### UnicodeScalarView and CharacterView -Like `Span`, we are deferring adding any collection-like types to non-escapable `UTF8Span`. Future work could include adding view types that conform to a new `Container`-like protocol. +Like `Span`, we are deferring adding any collection-like types to non-escapable `UTF8Span`. Future work could include adding view types that conform to a new `Container`-like protocol. See "Alternatives Considered" below for more rationale on not adding `Collection`-like API in this proposal. @@ -694,6 +704,26 @@ Many printing and logging protocols and facilities operate in terms of `String`. ## Alternatives considered +### Problems arising from the unsafe init + +The combination of the unsafe init on `UTF8Span` and the copying init on `String` creates a new kind of easily-accesible backdoor to `String`'s security and safety, namely the invariant that it holds validly encoded UTF-8 when in native form. + +Currently, String is 100% safe outside of crazy custom subclass shenanigans (only on ObjC platforms) or arbitrarily scribbling over memory (which is true of all of Swift). Both are highly visible and require writing many lines of advanced-knowledge code. + +Without these two API, it is in theory possible to skip validation and produce a String instance of the [indirect contiguous UTF-8](https://forums.swift.org/t/piercing-the-string-veil/21700) flavor through a custom subclass of NSString. But, it is only available on Obj-C platforms and involves creating a custom subclass of `NSString`, having knowledge of lazy bridging internals (which can and sometimes do change from release to release of Swift), and writing very specialized code. The product would be an unsafe lazily bridged instance of `String`, which could more than offset any performance gains from the workaround itself. + +With these two API, you can get to UB via a: + +```swift +let codeUnits = unsafe UTF8Span(unsafeAssumingValidUTF8: bytes) +... +String(copying: codeUnits) +``` + +We are (very) weakly in favor of keeping the unsafe init, because there are many low-level situations in which the valid-UTF8 invariant is held by the system itself (such as a data structure using a custom allocator). + + + ### Invalid start / end of input UTF-8 encoding errors Earlier prototypes had `.invalidStartOfInput` and `.invalidEndOfInput` UTF8 validation errors to communicate that the input was perhaps incomplete or not slices along scalar boundaries. In this scenario, `.invalidStartOfInput` is equivalent to `.unexpectedContinuation` with the range's lower bound equal to 0 and `.invalidEndOfInput` is equivalent to `.truncatedScalar` with the range's upper bound equal to `count`. @@ -764,7 +794,7 @@ Scalar-alignment can still be checked and managed by the caller through the `res #### View Collections -Another forumulation of these operations could be to provide a collection-like API phrased in terms of indices. Because `Collection`s are `Escapable`, we cannot conform nested `View` types to `Collection` so these would not benefit from any `Collection`-generic code, algorithms, etc. +Another forumulation of these operations could be to provide a collection-like API phrased in terms of indices. Because `Collection`s are `Escapable`, we cannot conform nested `View` types to `Collection` so these would not benefit from any `Collection`-generic code, algorithms, etc. A benefit of such `Collection`-like views is that it could help serve as adapter code for migration. Existing `Collection`-generic algorithms and methods could be converted to support `UTF8Span` via copy-paste-edit. That is, a developer could interact with `UTF8Span` ala: From 3f2e465ee76b61a621876375718d401c852ea13d Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Tue, 25 Mar 2025 13:06:06 -0700 Subject: [PATCH 172/505] Update 0459-enumerated-collection.md (#2754) --- proposals/0459-enumerated-collection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0459-enumerated-collection.md b/proposals/0459-enumerated-collection.md index a2df267080..e9044be172 100644 --- a/proposals/0459-enumerated-collection.md +++ b/proposals/0459-enumerated-collection.md @@ -3,10 +3,10 @@ * Proposal: [SE-0459](0459-enumerated-collection.md) * Author: [Alejandro Alonso](https://github.com/Azoy) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Active review (January 28 – February 7, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift#78092](https://github.com/swiftlang/swift/pull/78092) * Previous Proposal: [SE-0312](0312-indexed-and-enumerated-zip-collections.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-add-collection-conformance-for-enumeratedsequence/76680)) ([review](https://forums.swift.org/t/se-0459-add-collection-conformances-for-enumerated/77509)) +* Review: ([pitch](https://forums.swift.org/t/pitch-add-collection-conformance-for-enumeratedsequence/76680)) ([review](https://forums.swift.org/t/se-0459-add-collection-conformances-for-enumerated/77509)) ([acceptance](https://forums.swift.org/t/accepted-with-modification-se-0459-add-collection-conformances-for-enumerated/78082)) ## Introduction From b7cf8c0d72f72ff4ef92a117f85e2556359eaa70 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Tue, 25 Mar 2025 16:06:38 -0400 Subject: [PATCH 173/505] Update 0460-specialized.md (#2755) --- proposals/0460-specialized.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0460-specialized.md b/proposals/0460-specialized.md index 6f0979f9e7..ff54c65de9 100644 --- a/proposals/0460-specialized.md +++ b/proposals/0460-specialized.md @@ -3,7 +3,7 @@ * Proposal: [SE-0460](0460-specialized.md) * Authors: [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Active Review (January 29 ... February 11, 2025)** +* Status: **Accepted** * Implementation: Available in nightly toolchains using the underscored `@_specialize` * Review: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967)) ([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) From a22bf6d4f2e8428e74b2d40c23f7aa3a2232c6e1 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Tue, 25 Mar 2025 16:12:49 -0400 Subject: [PATCH 174/505] Update 0460-specialized.md (#2756) --- proposals/0460-specialized.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0460-specialized.md b/proposals/0460-specialized.md index ff54c65de9..e39ffc84c8 100644 --- a/proposals/0460-specialized.md +++ b/proposals/0460-specialized.md @@ -5,7 +5,7 @@ * Review Manager: [Steve Canon](https://github.com/stephentyrone) * Status: **Accepted** * Implementation: Available in nightly toolchains using the underscored `@_specialize` -* Review: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967)) ([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) +* Review: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967)) ([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) ([acceptance](https://forums.swift.org/t/accepted-se-0460-explicit-specialization/78583)) ## Introduction From ae330664dc9d9dfc0f891eeb7299aadc7d5676d3 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 25 Mar 2025 14:31:45 -0700 Subject: [PATCH 175/505] Mark metatype keypaths and swift language mode proposals as implemented (#2757) * SE-0438: Mark proposal as implemented in Swift 6.1 * SE-0441: Mark proposal as implemented in Swift 6.1 New SwiftPM build settings are available in Swift 6.0 but `-language-mode` was introduced in 6.1 compiler. --- proposals/0438-metatype-keypath.md | 2 +- proposals/0441-formalize-language-mode-terminology.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0438-metatype-keypath.md b/proposals/0438-metatype-keypath.md index 94b2bdb954..e12bd4afb6 100644 --- a/proposals/0438-metatype-keypath.md +++ b/proposals/0438-metatype-keypath.md @@ -3,7 +3,7 @@ * Proposal: [SE-0438](0438-metatype-keypath.md) * Authors: [Amritpan Kaur](https://github.com/amritpan), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: [Joe Groff](https://github.com/jckarter) -* Status: **Accepted** +* Status: **Implemented (Swift 6.1)** * Implementation: [apple/swift#73242](https://github.com/apple/swift/pull/73242) * Review: ([pitch](https://forums.swift.org/t/pitch-metatype-keypaths/70767)) ([review](https://forums.swift.org/t/se-0438-metatype-keypaths/72172)) ([acceptance](https://forums.swift.org/t/accepted-se-0438-metatype-keypaths/72878)) diff --git a/proposals/0441-formalize-language-mode-terminology.md b/proposals/0441-formalize-language-mode-terminology.md index dcfbc9d2d6..d34b6eeacf 100644 --- a/proposals/0441-formalize-language-mode-terminology.md +++ b/proposals/0441-formalize-language-mode-terminology.md @@ -3,7 +3,7 @@ * Proposal: [SE-0441](0441-formalize-language-mode-terminology.md) * Author: [James Dempsey](https://github.com/dempseyatgithub) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Accepted** +* Status: **Implemented (Swift 6.1)** * Implementation: [swiftlang/swift-package-manager#7620](https://github.com/swiftlang/swift-package-manager/pull/7620), [swiftlang/swift#75564](https://github.com/swiftlang/swift/pull/75564) * Review: ([first pitch](https://forums.swift.org/t/pitch-formalize-swift-language-mode-naming-in-tools-and-api/71733)) ([second pitch](https://forums.swift.org/t/pitch-2-formalize-language-mode-naming-in-tools-and-api/72136)) ([review](https://forums.swift.org/t/se-0441-formalize-language-mode-terminology/73182)) ([acceptance](https://forums.swift.org/t/accepted-se-0441-formalize-language-mode-terminology/73716)) From 836695b49ec40bfd95cfb03b075d2eaa19d0a71f Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Tue, 25 Mar 2025 15:57:29 -0700 Subject: [PATCH 176/505] Update the epoch name to systemEpoch and add some prose about how it is system relative and not globally relative --- proposals/NNNN-ClockEpochs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md index 88d77fe96c..b79cb30084 100644 --- a/proposals/NNNN-ClockEpochs.md +++ b/proposals/NNNN-ClockEpochs.md @@ -19,17 +19,17 @@ Not all clocks have a starting point, however in these cases they do. Generally, ## Proposed solution -Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. Both of these properties will be the epoch for which all `Instant` types are derived from; practically speaking this is the "zero" point for these clocks. +Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. Both of these properties will be the epoch for which all `Instant` types are derived from; practically speaking this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on (albeit many may implement them literally as zero) they are named in accordance to reflect that they are designed to be representative of the system's sense of an epoch and should not be expected to be serializable across systems. ## Detailed design ```swift extension ContinousClock { - public var epoch: Instant { get } + public var systemEpoch: Instant { get } } extension SuspendingClock { - public var epoch: Instant { get } + public var systemEpoch: Instant { get } } ``` @@ -37,14 +37,14 @@ These can be used to gather information like for example the uptime of a system, ```swift let clock = ContinousClock() -let uptime = clock.now - clock.epoch +let uptime = clock.now - clock.systemEpoch ``` Or likewise; ```swift let clock = SuspendingClock() -let activeTime = clock.now - clock.epoch +let activeTime = clock.now - clock.systemEpoch ``` ## ABI compatibility From 30ab4bf0ab604860e14d51613f9ca409a57d6c5d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 26 Mar 2025 08:18:23 +0900 Subject: [PATCH 177/505] Add why not tri-state return --- proposals/NNNN-SerialExecutor-isIsolated.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/NNNN-SerialExecutor-isIsolated.md index 0125b5baf3..053475c69b 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/NNNN-SerialExecutor-isIsolated.md @@ -172,6 +172,25 @@ This would be ideal, however also problematic since changing a protocol requirem In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. +### Offer a tri-state return value rather than `Bool` + +We briefly considered offering a tri-state `enum DetectedSerialExecutorIsolation` as the return value of `isIsolatingCurrentContext`, however could not find many realistic use-cases for it. + +The return type could be defined as: + +```swift +// not great name +enum DetectedSerialExecutorIsolation { + case isolated // returned when isolated by this executor + case notIsolated // returned when definitely NOT isolated by this executor + case unknown // when the isIsolatingCurrentContext could not determine if the caller is isolated or not +} +``` + +If we used the `.unknown` as default implementation of the new protocol requirement, this would allow for programatic detection if we called the default implementation, or an user provided implementation which could check a proper isolated/not-isolated state of the executing context. + +Technically there may exist new implementations which return the `.unknown` however it would have to be treated defensively as `.notIsolated` in any asserting APIs or other use-cases which rely on this check for runtime correctness. We are uncertain if introducing this tri-state is actually helpful in real situations and therefore the proposal currently proposes the use of a plain `Bool` value. + ## Changelog - removed the manual need to signal to the runtime that the specific executor supports the new checking mode. It is now detected by the compiler and runtime, checking for the presence of a non-default implementation of the protocol requirement. From e6f3aa93664df15ed68fdb713e8c5e7e46487b9c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 18 Mar 2025 15:00:48 -0700 Subject: [PATCH 178/505] Acceptance link for SE-0465 --- proposals/0465-nonescapable-stdlib-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index 1f8bc5fad4..2f0c6540d8 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -6,7 +6,7 @@ * Status: **Accepted** * Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] * Implementation: https://github.com/swiftlang/swift/pull/73258 -* Review: ([Review](https://forums.swift.org/t/se-0465-standard-library-primitives-for-nonescapable-types/78310)) ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) +* Review: ([Acceptance](https://forums.swift.org/t/accepted-se-0465-standard-library-primitives-for-nonescapable-type/78637)) ([Review](https://forums.swift.org/t/se-0465-standard-library-primitives-for-nonescapable-types/78310)) ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) [Roadmap]: https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206 [Pitch]: https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253 From f8846c3e939f93b4525d5450b0f2c4eea69485ed Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 25 Mar 2025 21:27:25 -0700 Subject: [PATCH 179/505] Initiate review of SE-0471: Improved Custom SerialExecutor isolation checking for Concurrency Runtime --- ...olated.md => 0471-SerialExecutor-isIsolated.md} | 13 +++++-------- ...-flow.graffle => 0471-is-isolated-flow.graffle} | Bin ...isolated-flow.png => 0471-is-isolated-flow.png} | Bin 3 files changed, 5 insertions(+), 8 deletions(-) rename proposals/{NNNN-SerialExecutor-isIsolated.md => 0471-SerialExecutor-isIsolated.md} (97%) rename proposals/{nnnn-is-isolated-flow.graffle => 0471-is-isolated-flow.graffle} (100%) rename proposals/{nnnn-is-isolated-flow.png => 0471-is-isolated-flow.png} (100%) diff --git a/proposals/NNNN-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md similarity index 97% rename from proposals/NNNN-SerialExecutor-isIsolated.md rename to proposals/0471-SerialExecutor-isIsolated.md index 053475c69b..79227eea99 100644 --- a/proposals/NNNN-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -1,14 +1,11 @@ # Improved Custom SerialExecutor isolation checking for Concurrency Runtime -* Proposal: [SE-NNNN](...) +* Proposal: [SE-0471](0471-SerialExecutor-isIsolated.md) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) -* Review Manager: TBD -* Status: Implemented - * https://github.com/swiftlang/swift/pull/79788 - * https://github.com/swiftlang/swift/pull/79946 - +* Review Manager: [Doug Gregor](https://github.com/DougGregor) +* Status: **Active Review (March 25...April 8, 2025) +* Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 * Pitch: [[Pitch][SerialExecutor] Improved Custom SerialExecutor isolation checking](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/) -* Review: TODO ## Introduction @@ -102,7 +99,7 @@ In most cases implementing this new API is preferable to implementing `checkIsol The newly proposed `isIsolatingCurrentContext()` function participates in the previously established runtime isolation checking flow, and happens _before_ any calls to `checkIsolated()` are attempted. The following diagram explains the order of calls issued by the runtime to dynamically verify an isolation when e.g. `assumeIsolated()` is called: -![diagram illustrating which method is called when](nnnn-is-isolated-flow.png) +![diagram illustrating which method is called when](0471-is-isolated-flow.png) diff --git a/proposals/nnnn-is-isolated-flow.graffle b/proposals/0471-is-isolated-flow.graffle similarity index 100% rename from proposals/nnnn-is-isolated-flow.graffle rename to proposals/0471-is-isolated-flow.graffle diff --git a/proposals/nnnn-is-isolated-flow.png b/proposals/0471-is-isolated-flow.png similarity index 100% rename from proposals/nnnn-is-isolated-flow.png rename to proposals/0471-is-isolated-flow.png From bd892637a7685658bbb4df243ce0b42e48924d87 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 25 Mar 2025 21:32:30 -0700 Subject: [PATCH 180/505] Link SE-0471 to the review thread --- proposals/0471-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index 79227eea99..dcbb66db9f 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -5,7 +5,7 @@ * Review Manager: [Doug Gregor](https://github.com/DougGregor) * Status: **Active Review (March 25...April 8, 2025) * Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 -* Pitch: [[Pitch][SerialExecutor] Improved Custom SerialExecutor isolation checking](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/) +* Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834) ## Introduction From a27f65da3f90ba8ad1faf144bf910fb43f89ca45 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 26 Mar 2025 22:14:07 +0900 Subject: [PATCH 181/505] Apply suggestions from code review Co-authored-by: Tony Allevato --- ...k-start-synchronously-on-caller-context.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md index ccb621e83f..557189546f 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -11,7 +11,7 @@ Swift Concurrency's primary means of entering an asynchronous context is creating a Task (structured or unstructured), and from there onwards it is possible to call asynchronous functions, and execution of the current work may _suspend_. -Entering the asynchronous context today incurs the creating and scheduling of a task to be executed at some later point in time. This initial delay may be wasteful for tasks which perform minimal or none (!) work at all. +Entering the asynchronous context today incurs the creating and scheduling of a task to be executed at some later point in time. This initial delay may be wasteful for tasks which perform minimal or no (!) work at all. This initial delay may also be problematic for some situations where it is known that we are executing on the "right actor" however are *not* in an asynchronous function and therefore in order to call some different asynchronous function we must create a new task and introduce subtle timing differences as compared to just being able to call the target function–which may be isolated to the same actor we're calling from–immediately. @@ -51,7 +51,7 @@ func synchronousFunction() { } ``` -The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation... it still would not allow us to call arbitrary async functions, as we are still in a synchronous context. +The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation, it still would not allow us to call arbitrary async functions, as we are still in a synchronous context. The proposed `Task.startSynchronously` API forms an async context on the calling thread/task/executor, and therefore allows us to call into async code, at the risk of overhanging on the calling executor. So while this should be used sparingly, it allows entering an asynchronous context *synchronously*. @@ -102,18 +102,18 @@ extension Task { @discardableResult public static func startSynchronously( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here if accepted priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - operation: sending @escaping async throws(Failure) -> Success, + operation: sending @escaping async throws(Failure) -> Success ) -> Task @discardableResult public static func startSynchronouslyDetached( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here if accepted priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - operation: sending @escaping async throws(Failure) -> Success, + operation: sending @escaping async throws(Failure) -> Success ) -> Task } ``` @@ -125,41 +125,41 @@ extension (Throwing)TaskGroup { // Same add semantics as 'addTask'. func startTaskSynchronously( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, - operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + operation: sending @escaping () async throws -> ChildTaskResult ) // Same add semantics as 'addTaskUnlessCancelled'. func startTaskSynchronouslyUnlessCancelled( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, - operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + operation: sending @escaping () async throws -> ChildTaskResult ) } extension (Throwing)DiscardingTaskGroup { // Same add semantics as 'addTask'. func startTaskSynchronously( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, - operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + operation: sending @escaping () async throws -> ChildTaskResult ) // Same add semantics as 'addTaskUnlessCancelled'. func startTaskSynchronouslyUnlessCancelled( - // SE-NNNN's proposed 'name: String? = nil' would be here + // SE-0469's proposed 'name: String? = nil' would be here priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, - operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult + operation: sending @escaping () async throws -> ChildTaskResult ) } ``` -The `startTaskSynchronously` mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled. +The `startTaskSynchronously` function mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled. ### Isolation rules @@ -256,7 +256,7 @@ After the suspension point though, there may have been other tasks executed on t Synchronously started tasks behave exactly the same as their fully asynchronous equivalents. -In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual; +In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual. The only difference in behavior is where these synchronously started tasks _begin_ their execution. From 8fa35dc01fbfe166b9de916d384d6aeefd2b5e8d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 26 Mar 2025 22:14:46 +0900 Subject: [PATCH 182/505] Apply suggestions from code review --- proposals/NNNN-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/NNNN-task-start-synchronously-on-caller-context.md index 557189546f..f9f7f27359 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/NNNN-task-start-synchronously-on-caller-context.md @@ -349,7 +349,7 @@ Using a combination of (a) `Task/startSynchronously`, (b) `Actor/assumeIsolated` ```swift func tryRunSynchronouslyOrAsynchronouslyOtherwise( - operation: sending @escaping @isolated(any) () async -> Success + operation: sending @escaping () async -> Success ) -> Task { guard let actor = operation.isolation else { // no specific isolation, just run async @@ -377,7 +377,7 @@ Or even better we could build the same API with structured concurrency: ```swift func tryRunSynchronouslyOrAsynchronouslyOtherwise( - operation: sending @escaping @isolated(any) () async throws -> Success + operation: sending @escaping () async throws -> Success ) async rethrows -> Success { /* same, but use TaskGroup inside */ } ``` From 4c523525549c2077307b7e4b7f1680e0a5d1511c Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 26 Mar 2025 08:15:55 -0700 Subject: [PATCH 183/505] Proposal revisions for SE-0461. (#2751) * [SE-0461] Rename `@execution(concurrent)` to `@concurrent`. * [SE-0461] Remove the migration-related warning in favor of automatic migration tooling. * [SE-0461] Add a section about removing `noasync` from the `assumeIsolated` API family. * [SE-0461] Add a section about region isolation rules. * [SE-0461] Update table of contents. --- proposals/0461-async-function-isolation.md | 238 ++++++++++++++------- 1 file changed, 159 insertions(+), 79 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index aecc52bea4..5ba6c142e1 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -26,22 +26,25 @@ async function always switches off of an actor to run. - [Motivation](#motivation) - [Proposed solution](#proposed-solution) - [Detailed design](#detailed-design) - - [The `@execution` attribute](#the-execution-attribute) + - [The `@execution` and `@concurrent` attributes](#the-execution-and-concurrent-attributes) - [`@execution(caller)` functions](#executioncaller-functions) - - [`@execution(concurrent)` functions](#executionconcurrent-functions) + - [`@concurrent` functions](#concurrent-functions) - [Task isolation inheritance](#task-isolation-inheritance) - [`#isolation` macro expansion](#isolation-macro-expansion) - [Isolation inference for closures](#isolation-inference-for-closures) - [Function conversions](#function-conversions) + - [Non-`@Sendable` function conversions](#non-sendable-function-conversions) + - [Region isolation rules](#region-isolation-rules) - [Executor switching](#executor-switching) + - [Dynamic actor isolation APIs in async contexts](#dynamic-actor-isolation-apis-in-async-contexts) - [Import-as-async heuristic](#import-as-async-heuristic) - [Source compatibility](#source-compatibility) - [ABI compatibility](#abi-compatibility) - [Implications on adoption](#implications-on-adoption) - [Alternatives considered](#alternatives-considered) - [Changing isolation inference behavior to implicitly capture isolated parameters](#changing-isolation-inference-behavior-to-implicitly-capture-isolated-parameters) - - [Use `nonisolated` instead of a separate `@execution(concurrent)` attribute](#use-nonisolated-instead-of-a-separate-executionconcurrent-attribute) - - [Use "isolation" terminology instead of "execution"](#use-isolation-terminology-instead-of-execution) + - [Use `nonisolated` instead of a separate `@concurrent` attribute](#use-nonisolated-instead-of-a-separate-concurrent-attribute) + - [Alternative syntax choices](#alternative-syntax-choices) - [Deprecate `nonisolated`](#deprecate-nonisolated) - [Don't introduce a type attribute for `@execution`](#dont-introduce-a-type-attribute-for-execution) - [Revisions](#revisions) @@ -201,7 +204,7 @@ behavior of existing code, so the change is gated behind the `AsyncCallerExecution` upcoming feature flag. To help stage in the new behavior, a new `@execution` attribute can be used to explicitly specify the execution semantics of an async function in any language mode. The -`@execution(concurrent)` attribute is an explicit spelling for the behavior of +`@concurrent` attribute is an explicit spelling for the behavior of async functions in language modes <= Swift 6, and the `@execution(caller)` attribute is an explicit spelling for async functions that run on the caller's actor. @@ -215,7 +218,7 @@ class NotSendable { @execution(caller) func performAsync() async { ... } - @execution(concurrent) + @concurrent func alwaysSwitch() async { ... } } @@ -232,34 +235,28 @@ actor MyActor { } ``` -`@execution(concurrent)` is the current default for nonisolated async +`@concurrent` is the current default for nonisolated async functions. `@execution(caller)` will become the default for async functions when the `AsyncCallerExecution` upcoming feature is enabled. ## Detailed design -The sections below will explicitly use `@execution(concurrent)` and +The sections below will explicitly use `@concurrent` and `@execution(caller)` to demonstrate examples that will behave consistently independent of upcoming features or language modes. However, note that the end state under the `AsyncCallerExecution` upcoming feature will mean that `@execution(caller)` is not necessary to explicitly write, and -`@execution(concurrent)` will likely be used sparingly because it has far +`@concurrent` will likely be used sparingly because it has far stricter data-race safety requirements. -### The `@execution` attribute +### The `@execution` and `@concurrent` attributes -`@execution` is a declaration and type attribute that specifies the execution -semantics of an async function. `@execution` must be written with an argument -of either `caller` or `concurrent`. The details of each argument are specified -in the following sections. +`@execution(caller)` and `@concurrent` are both declaration and type attributes +that specify the execution semantics of an async function. The details of +each attribute are specified in the following sections. -> _Naming rationale_: The term `concurrent` in `@execution(concurrent)` was -> chosen because the colloquial phrase "runs concurrently with actors" is a -> good way to describe the semantics of the function execution. Similarly, the -> async function can be described as running on the concurrent executor. - -Only (implicitly or explicitly) `nonisolated` functions can be marked with the -`@execution` attribute; it is an error to use the `@execution` attribute with +Only (implicitly or explicitly) `nonisolated` functions can be marked with +`@execution(caller)` or `@concurrent`; it is an error to use the these attributes with an isolation other than `nonisolated`, including global actors, isolated parameters, and `@isolated(any)`: @@ -280,13 +277,15 @@ actor MyActor { } ``` -The `@execution` attribute can be used together with `@Sendable` or `sending`. +`@execution(caller)` and `@concurrent` can be used together with `@Sendable` or +`sending`. -The `@execution` attribute is preserved in the type system so that the execution -semantics can be distinguished for function vales. +`@execution(caller)` and `@concurrent` are preserved in the type system so that +the execution semantics can be distinguished for function vales. -The `@execution` attribute cannot be applied to synchronous functions. This is -an artificial limitation that could later be lifted if use cases arise. +`@execution(caller)` and `@concurrent` cannot be applied to synchronous +functions. This is an artificial limitation that could later be lifted if use +cases arise. #### `@execution(caller)` functions @@ -349,23 +348,23 @@ In the above code, the calls to `closure` from `callSendableClosure` run on the main actor, because `closure` is `@execution(caller)` and `callSendableClosure` is main actor isolated. -#### `@execution(concurrent)` functions +#### `@concurrent` functions Async functions can be declared to always switch off of an actor to run using -the `@execution(concurrent)` attribute: +the `@concurrent` attribute: ```swift struct S: Sendable { - @execution(concurrent) + @concurrent func alwaysSwitch() async { ... } } ``` -The type of an `@execution(concurrent)` function declaration is an -`@execution(concurrent)` function type. Details on function conversions are +The type of an `@concurrent` function declaration is an +`@concurrent` function type. Details on function conversions are covered in a [later section](#function-conversions). -When an `@execution(concurrent)` function is called from a context that can +When an `@concurrent` function is called from a context that can run on an actor, including `@execution(caller)` functions or actor-isolated functions, sendable checking is performed on the argument and result values. Either the argument and result values must have a type that conforms to @@ -375,7 +374,7 @@ outside of the actor: ```swift class NotSendable {} -@execution(concurrent) +@concurrent func alwaysSwitch(ns: NotSendable) async { ... } actor MyActor { @@ -395,7 +394,7 @@ actor MyActor { Unstructured tasks created in nonisolated functions never run on an actor unless explicitly specified. This behavior is consistent for all nonisolated functions, including synchronous functions, `@execution(caller)` async -functions, and `@execution(concurrent)` async functions. +functions, and `@concurrent` async functions. For example: @@ -483,7 +482,7 @@ struct Program { } ``` -In an `@execution(concurrent)` function, the `#isolation` macro expands to +In an `@concurrent` function, the `#isolation` macro expands to `nil`. ### Isolation inference for closures @@ -617,21 +616,21 @@ conversion rules for synchronous `nonisolated` functions and asynchronous `@execution(caller) nonisolated` functions are the same; they are both represented under the "Nonisolated" category in the table: -| Old isolation | New isolation | Crosses Boundary | -|--------------------------|----------------------------|------------------| -| Nonisolated | Actor isolated | No | -| Nonisolated | `@isolated(any)` | No | -| Nonisolated | `@execution(concurrent)` | Yes | -| Actor isolated | Actor isolated | Yes | -| Actor isolated | `@isolated(any)` | No | -| Actor isolated | Nonisolated | Yes | -| Actor isolated | `@execution(concurrent)` | Yes | -| `@isolated(any)` | Actor isolated | Yes | -| `@isolated(any)` | Nonisolated | Yes | -| `@isolated(any)` | `@execution(concurrent)` | Yes | -| `@execution(concurrent)` | Actor isolated | Yes | -| `@execution(concurrent)` | `@isolated(any)` | No | -| `@execution(concurrent)` | Nonisolated | Yes | +| Old isolation | New isolation | Crosses Boundary | +|----------------------|------------------------|------------------| +| Nonisolated | Actor isolated | No | +| Nonisolated | `@isolated(any)` | No | +| Nonisolated | `@concurrent` | Yes | +| Actor isolated | Actor isolated | Yes | +| Actor isolated | `@isolated(any)` | No | +| Actor isolated | Nonisolated | Yes | +| Actor isolated | `@concurrent` | Yes | +| `@isolated(any)` | Actor isolated | Yes | +| `@isolated(any)` | Nonisolated | Yes | +| `@isolated(any)` | `@concurrent` | Yes | +| `@concurrent` | Actor isolated | Yes | +| `@concurrent` | `@isolated(any)` | No | +| `@concurrent` | Nonisolated | Yes | #### Non-`@Sendable` function conversions @@ -671,7 +670,7 @@ if the original function must leave the actor in order to be called: ```swift @execution(caller) func convert( - fn1: @escaping @execution(concurrent) () async -> Void, + fn1: @escaping @concurrent () async -> Void, ) async { let fn2: @MainActor () async -> Void = fn1 // error @@ -709,6 +708,45 @@ func call(_ closure: () -> NotSendable) -> NotSendable { } ``` +### Region isolation rules + +`@execution(caller)` functions have the same region isolation rules as +synchronous `nonisolated` functions. When calling an `@execution(caller)` +function, all non-`Sendable` parameter and result values are merged into +the same region, but they are only merged into the caller's actor region if +one of those non-`Sendable` values is already in the actor's region. + +For example: + +```swift +class NotSendable {} + +@execution(caller) +nonisolated func identity(_ t: T) async -> T { + return t +} + +actor MyActor { + func isolatedToSelf() async -> sending NotSendable { + let ns = NotSendable() + return await identity(ns) + } +} +``` + +The above code is valid; the implementation of `identity` can't access the +actor's state unless isolated state is passed in via one of the parameters. +Note that this code would be invalid if `identity` accepted an isolated +parameter, because the non-`Sendable` parameters and results would always be +merged into the actor's region. + +This proposal allows you to access `#isolation` in the implementation of an +`@execution(caller)` function for the purpose of forwarding it along to a +method that accepts an `isolated (any Actor)?`. This is still safe, because +there's no way to access the actor's isolated state via the `Actor` protocol, +and dynamic casting to a concrete actor type will not result in a value that +the function is known to be isolated to. + ### Executor switching Async functions switch executors in the implementation when entering the @@ -717,7 +755,7 @@ functions do not have the ability to switch executors. If a call to a synchronous function crosses an isolation boundary, the call must happen in an async context and the executor switch happens at the caller. -`@execution(concurrent)` async functions switch to the generic executor, and +`@concurrent` async functions switch to the generic executor, and all other async functions switch to the isolated actor's executor. ```swift @@ -729,7 +767,7 @@ all other async functions switch to the isolated actor's executor. // switch to main actor executor } -@execution(concurrent) func runOnGenericExecutor() async { +@concurrent func runOnGenericExecutor() async { // switch to generic executor await Task { @MainActor in @@ -785,6 +823,14 @@ Otherwise, the code will risk a data-race, because the task executor preference does not apply to actor-isolated methods with custom executors, and the nonisolated async method can be passed mutable state from the actor. +### Dynamic actor isolation APIs in async contexts + +Because nonisolated async functions may now execute on a specific actor at +runtime, the APIs in the Concurrency library for enforcing actor isolation +assertions and preconditions are now useful in these contexts. As such, the +`noasync` attribute will be removed from `assertIsolated`, `assumeIsolated`, +and `preconditionIsolated` on `Actor` and `MainActor`. + ### Import-as-async heuristic Nonisolated functions imported from Objective-C that match the import-as-async @@ -803,14 +849,14 @@ not change -- it will not be gated behind the upcoming feature. This proposal changes the semantics of nonisolated async functions when the upcoming feature flag is enabled. Without the upcoming feature flag, the default -for nonisolated async functions is `@execution(concurrent)`. When the upcoming +for nonisolated async functions is `@concurrent`. When the upcoming feature flag is enabled, the default for nonisolated async functions changes to `@execution(caller)`. This applies to both function declarations and function values that are nonisolated (either implicitly or explicitly). Changing the default execution semantics of nonisolated async functions has minor source compatibility impact if the implementation calls an -`@execution(concurrent)` function and passes non-Sendable state in the actor's +`@concurrent` function and passes non-Sendable state in the actor's region. In addition to the source compatibility impact, the change can also regress performance of existing code if, for example, a specific async function relied on running off of the main actor when called from the main actor to @@ -824,25 +870,14 @@ flag, but means something different. Many programmers have internalized the SE-0338 semantics, and making this change several years after SE-0338 was accepted creates an unfortunate intermediate state where it's difficult to understand the semantics of a nonisolated async function without understanding -the build settings of the module you're writing code in. To mitigate these -consequences, the compiler will emit warnings in all language modes -that do not enable this upcoming feature to prompt programmers to explicitly -specify the execution semantics of a nonisolated async function. - -Without the upcoming feature enabled, the compiler will warn if neither -attribute is specified on a nonisolated async function. With the -upcoming feature enabled, the default for a nonisolated async -function is `@execution(caller)`. Packages that must support older Swift tools -versions can use `#if hasAttribute(execution)` to silence the warning while -maintaining compatibility with tools versions back to Swift 5.8 when -`hasAttribute` was introduced: +the build settings of the module you're writing code in. -```swift -#if hasAttribute(execution) -@execution(concurrent) -#endif -public func myAsyncAPI() async { ... } -``` +To make it easy to discover what kind of async function you're working with, +SourceKit will surface the implicit `@execution(caller)` or `@concurrent` +attribute for IDE inspection features like Quick Help in Xcode and Hover in +VSCode. To ease the transition to the upcoming feature flag, [migration +tooling][adoption-tooling] will provide fix-its to preserve behavior by +annotating nonisolated async functions with `@concurrent`. ## ABI compatibility @@ -863,7 +898,7 @@ public func myAsyncFunc() async { // original implementation } -@execution(concurrent) +@concurrent @_silgen_name(...) // to preserve the original symbol name @usableFromInline internal func abi_myAsyncFunc() async { @@ -880,7 +915,7 @@ can be made inlinable. `@execution(caller)` functions must accept an implicit actor parameter. This means that adding `@execution(caller)` to a function that is actor-isolated, or -changing a function from `@execution(concurrent)` to `@execution(caller)`, is +changing a function from `@concurrent` to `@execution(caller)`, is not a resilient change. ## Alternatives considered @@ -895,7 +930,7 @@ potential compromise is to keep the current isolation inference behavior, and offer fix-its to capture the actor if there are any data-race safety errors from capturing state in the actor's region. -### Use `nonisolated` instead of a separate `@execution(concurrent)` attribute +### Use `nonisolated` instead of a separate `@concurrent` attribute It's tempting to not introduce a new attribute to control where an async function executes, and instead control this behavior with an explicit @@ -906,9 +941,43 @@ reasons: `nonisolated` by default, regardless of whether it's applied to synchronous or async functions. 2. This approach cuts off the future direction of allowing - `@execution(concurrent)` on synchronous functions. - -### Use "isolation" terminology instead of "execution" + `@concurrent` on synchronous functions. + +### Alternative syntax choices + +This proposal was originally pitched using the `@concurrent` syntax, and many +reviewers surfaced objects about why `@concurrent` may be misleading, such as: + +* `@concurrent` is not the only source of concurrency; concurrency can arise from + many other things. +* The execution of an `@concurrent` function is not concurrent from the local + perspective of the current task. + +It's true that concurrency can only arise if there are multiple "impetuses" +(such as tasks or event sources) in the program that are running with different +isolation. But for the most part, we can assume that there are multiple +impetuses; and while those impetuses might otherwise share isolation, +`@concurrent` is the only isolation specification under this proposal that +guarantees that they do not and therefore forces concurrency. Indeed, we expect +that programmers will be reaching for `@concurrent` exactly for that reason: +they want the current function to run concurrently with whatever else might +happen in the process. So, this proposal uses `@concurrent` because out of the +other alternatives we explored, it best reflects the programmer's intent for +using the attribute. + +A previous iteration of this proposal used the syntax `@execution(concurrent)` +instead of `@concurrent`. The review thread explored several variations of +this syntax, including `@executor(concurrent)` and `@executor(global)`. + +However, `@execution` or `@executor` encourages +thinking about async function semantics in terms of the lower level model of +executors and threads, and we should be encouraging programmers to think about +these semantics at the higher abstraction level of actor isolation and tasks. +Trying to understand the semantics in proposal in terms of executors can also +be misleading, both because isolation does not always map naively to executor +requests and because executors are used for other things than isolation. +For example, an `@executor(global)` function could end up running on some +executor other than the global executor via task executor preferences. Another possibility is to use isolation terminology instead of `@execution` for the syntax. This direction does not accomplish the goal of having a @@ -954,6 +1023,15 @@ function reference instead of when the function is called. ## Revisions +The proposal was revised with the following changes after the first review: + +* Renamed `@execution(concurrent)` back to `@concurrent`. +* Removed the unconditional warning about nonisolated async functions that + don't explicitly specify `@execution(caller)` or `@concurrent`. +* Removed `noasync` from the `assumeIsolated` API family. +* Specified the region isolation rules for `@execution(caller)` functions [as + discussed in the first review][region-isolation]. + The proposal was revised with the following changes after the pitch discussion: * Gate the behavior change behind an `AsyncCallerExecution` upcoming feature @@ -970,3 +1048,5 @@ The proposal was revised with the following changes after the pitch discussion: [SE-0297]: /proposals/0297-concurrency-objc.md [SE-0338]: /proposals/0338-clarify-execution-non-actor-async.md [SE-0421]: /proposals/0421-generalize-async-sequence.md +[adoption-tooling]: https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936 +[region-isolation]: https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987/36 \ No newline at end of file From 11f0e9e8c319a0e37a2ccdd8dedcceddd24260df Mon Sep 17 00:00:00 2001 From: Dmitrii Galimzianov Date: Wed, 19 Mar 2025 02:51:46 +0100 Subject: [PATCH 184/505] Warning Control Settings for SwiftPM --- proposals/NNNN-swiftpm-warning-control.md | 285 ++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 proposals/NNNN-swiftpm-warning-control.md diff --git a/proposals/NNNN-swiftpm-warning-control.md b/proposals/NNNN-swiftpm-warning-control.md new file mode 100644 index 0000000000..622b8c9971 --- /dev/null +++ b/proposals/NNNN-swiftpm-warning-control.md @@ -0,0 +1,285 @@ +# Warning Control Settings for SwiftPM + +* Proposal: [SE-NNNN](NNNN-swiftpm-warning-control.md) +* Authors: [Dmitrii Galimzianov](https://github.com/DmT021) +* Review Manager: TBD +* Status: **Awaiting review** +* Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) +* Review: ([Pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) +* Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) + +## Introduction + +This proposal adds new settings to SwiftPM to control how the Swift, C, and C++ compilers treat warnings during the build process. It builds on [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md), which introduced warning control flags for the Swift compiler but left SwiftPM support as a future direction. + +## Motivation + +The Swift Package Manager currently lacks a unified way to control warnings across Swift, C, and C++ compilation. This limitation forces developers to either use `unsafeFlags` or accept the default warning settings. + +## Proposed solution + +This proposal introduces new methods to SwiftPM's build settings API, allowing fine-grained control over warnings. + +### API + +#### Cross-language API (Swift, C, and C++) + +```swift +/// The level at which a compiler warning should be treated. +public enum WarningLevel: String { + /// Treat as a warning. + /// + /// Warnings will be displayed during compilation but will not cause the build to fail. + case warning + + /// Treat as an error. + /// + /// Warnings will be elevated to errors, causing the build to fail if any such warnings occur. + case error +} + +public static func treatAllWarnings( + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil +) -> SwiftSetting // or CSetting or CXXSetting + +public static func treatWarning( + _ name: String, + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil +) -> SwiftSetting // or CSetting or CXXSetting +``` + +#### C/C++-specific API + +In C/C++ targets, we can also enable or disable specific warning groups, in addition to controlling their severity. + +```swift +public static func enableWarning( + _ name: String, + _ condition: BuildSettingCondition? = nil +) -> CSetting // or CXXSetting + +public static func disableWarning( + _ name: String, + _ condition: BuildSettingCondition? = nil +) -> CSetting // or CXXSetting +``` +_The necessity of these functions is also explained below in the Alternatives considered section._ + +### Example usage + +```swift +.target( + name: "MyLib", + swiftSettings: [ + .treatAllWarnings(as: .error), + .treatWarning("DeprecatedDeclaration", as: .warning), + ], + cSettings: [ + .enableWarning("all"), + .disableWarning("unused-function"), + + .treatAllWarnings(as: .error), + .treatWarning("unused-variable", as: .warning), + ], + cxxSettings: [ + .enableWarning("all"), + .disableWarning("unused-function"), + + .treatAllWarnings(as: .error), + .treatWarning("unused-variable", as: .warning), + ] +) +``` + +## Detailed design + +### Settings and their corresponding compiler flags + +| Method | Swift | C/C++ | +|--------|-------|-------| +| `treatAllWarnings(as: .error)` | `-warnings-as-errors` | `-Werror` | +| `treatAllWarnings(as: .warning)` | `-no-warnings-as-errors` | `-Wno-error` | +| `treatWarning("XXXX", as: .error)` | `-Werror XXXX` | `-Werror=XXXX` | +| `treatWarning("XXXX", as: .warning)` | `-Wwarning XXXX` | `-Wno-error=XXXX` | +| `enableWarning("XXXX")` | N/A | `-WXXXX` | +| `disableWarning("XXXX")` | N/A | `-Wno-XXXX` | + +### Order of settings evaluation + +The order in which warning control settings are specified in a target's settings array directly affects the order of the resulting compiler flags. This is critical because when multiple flags affect the same warning group, compilers apply them sequentially with the last flag taking precedence. + +For example, consider these two different orderings for C++ settings: + +```swift +// Example 1: "unused-variable" in front of "unused" +cxxSettings: [ + .treatWarning("unused-variable", as: .error), + .treatWarning("unused", as: .warning), +] + +// Example 2: "unused" in front of "unused-variable" +cxxSettings: [ + .treatWarning("unused", as: .warning), + .treatWarning("unused-variable", as: .error), +] +``` + +In Example 1, the compiler will receive flags in this order: +``` +-Werror=unused-variable -Wno-error=unused +``` +Since "unused-variable" is a specific subgroup of the broader "unused" group, and the "unused" flag is applied last, all unused warnings (including unused-variable) will be treated as warnings. + +In Example 2, the compiler will receive flags in this order: +``` +-Wno-error=unused -Werror=unused-variable +``` +Due to the "last one wins" rule, unused-variable warnings will be treated as errors, while other unused warnings remain as warnings. + +The same principle applies when combining any of the new build settings: + +```swift +cxxSettings: [ + .enableWarning("all"), // Enable the "all" warning group + .enableWarning("extra"), // Enable the "extra" warning group + .disableWarning("unused-parameter"), // Disable the "unused-parameter" warning group + .treatAllWarnings(as: .error), // Treat all warnings as errors + .treatWarning("unused", as: .warning), // Keep warnings of the "unused" group as warnings +] +``` + +This will result in compiler flags: +``` +-Wall -Wextra -Wno-unused-parameter -Werror -Wno-error=unused +``` + +When configuring warnings, be mindful of the order to achieve the desired behavior. + +### Remote targets behavior + +When a target is remote (pulled from a package dependency rather than defined in the local package), the warning control settings specified in the manifest do not apply to it. SwiftPM will strip all of the warning control flags for remote targets and substitute them with options for suppressing warnings (`-w` for Clang and `-suppress-warnings` for Swift). + +This behavior is already in place but takes into account only `-warnings-as-errors` (for Swift) and `-Werror` (for Clang) flags. We expand this list to include the following warning-related flags: + +**For C/C++:** +* `-Wxxxx` +* `-Wno-xxxx` +* `-Werror` +* `-Werror=xxxx` +* `-Wno-error` +* `-Wno-error=xxxx` + +**For Swift:** +* `-warnings-as-errors` +* `-no-warnings-as-errors` +* `-Wwarning xxxx` +* `-Werror xxxx` + +This approach ensures that warning control settings are applied only to the targets you directly maintain in your package, while dependencies remain buildable without warnings regardless of their warning settings. + +### Interaction with command-line flags + +SwiftPM allows users to pass additional flags to the compilers using the `-Xcc`, `-Xswiftc`, and `-Xcxx` options with the `swift build` command. These flags are appended **after** the flags generated from the package manifest. + +This ordering enables users to modify or override package-defined warning settings without modifying the package manifest. + +#### Example + +```swift +let package = Package( + name: "MyExecutable", + targets: [ + // C target with warning settings + .target( + name: "cfoo", + cSettings: [ + .enableWarning("all"), + .treatAllWarnings(as: .error), + .treatWarning("unused-variable", as: .warning), + ] + ), + // Swift target with warning settings + .executableTarget( + name: "swiftfoo", + swiftSettings: [ + .treatAllWarnings(as: .error), + .treatWarning("DeprecatedDeclaration", as: .warning), + ] + ), + ] +) +``` + +When built with additional command-line flags: + +```sh +swift build -Xcc -Wno-error -Xswiftc -no-warnings-as-errors +``` + +The resulting compiler invocations will include both sets of flags: + +``` +# C compiler invocation +clang ... -Wall -Werror -Wno-error=unused-variable ... -Wno-error ... + +# Swift compiler invocation +swiftc ... -warnings-as-errors -Wwarning DeprecatedDeclaration ... -no-warnings-as-errors -Xcc -Wno-error ... +``` + +Flags are processed from left to right, and since `-no-warnings-as-errors` and `-Wno-error` apply globally to all warnings, they override the warning treating flags defined in the package manifest. + +#### Limitations + +This approach has a limitation when used with `-suppress-warnings`, which is mutually exclusive with other warning control flags: + +```sh +swift build -Xswiftc -suppress-warnings +``` + +Results in compiler errors: + +``` +error: conflicting options '-warnings-as-errors' and '-suppress-warnings' +error: conflicting options '-Wwarning' and '-suppress-warnings' +``` + + +## Security + +This change has no impact on security, safety, or privacy. + +## Impact on existing packages + +The proposed API will only be available to packages that specify a tools version equal to or later than the SwiftPM version in which this functionality is implemented. + +## Alternatives considered + +### Disabling a warning via a treat level + +Clang allows users to completely disable a specific warning, so for C/C++ settings we could implement that as a new case in the `WarningLevel` enum: + +```swift +public enum WarningLevel { + case warning + case error + case ignored +} +``` + +_(Since Swift doesn't allow selective warning suppression, we would actually have to split the enum into two: `SwiftWarningLevel` and `CFamilyWarningLevel`)_ + +But some warnings in Clang are disabled by default. If we simply pass `-Wno-error=unused-variable`, the compiler won't actually produce a warning for an unused variable. It only makes sense to use it if we have enabled the warning: `-Wunused-variable -Werror -Wno-error=unused-variable`. + +This necessitates separate functions to enable and disable warnings. Therefore, instead of `case ignored`, we propose the functions `enableWarning` and `disableWarning`. + +## Future directions + +### Package-level settings + +It has been noted that warning control settings are often similar across all targets. It makes sense to declare them at the package level while allowing target-level customizations. However, many other settings would also likely benefit from such inheritance, and SwiftPM doesn't currently provide such an option. Therefore, it was decided to factor this improvement out and look at all the settings holistically in the future. + +## Acknowledgments + +Thank you to [Doug Gregor](https://github.com/douggregor) for the motivation, and to both [Doug Gregor](https://github.com/douggregor) and [Holly Borla](https://github.com/hborla) for their guidance during the implementation of this API. From 89c8849dbd83059250087eef8471784de66a40b3 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Thu, 27 Mar 2025 12:01:28 -0400 Subject: [PATCH 185/505] Assign SE-0472. --- ...d => 0472-task-start-synchronously-on-caller-context.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/{NNNN-task-start-synchronously-on-caller-context.md => 0472-task-start-synchronously-on-caller-context.md} (98%) diff --git a/proposals/NNNN-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md similarity index 98% rename from proposals/NNNN-task-start-synchronously-on-caller-context.md rename to proposals/0472-task-start-synchronously-on-caller-context.md index f9f7f27359..a5c4701336 100644 --- a/proposals/NNNN-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -1,11 +1,11 @@ # Starting tasks synchronously from caller context -* Proposal: [SE-NNNN](NNNN-task-start-synchronously-on-caller-context.md) +* Proposal: [SE-0472](0472-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) -* Review Manager: TBD +* Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Partially implemented on `main`** * Implementation: [TODO](https://github.com/swiftlang/swift/pull/79608) -* Review: ... +* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ## Introduction From cf5f862af80a58b1041046a67b5325507dd910de Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Thu, 27 Mar 2025 12:05:41 -0400 Subject: [PATCH 186/505] Add review thread link to SE-0472. --- proposals/0472-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index a5c4701336..4e9daacd9f 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -4,8 +4,8 @@ * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Partially implemented on `main`** -* Implementation: [TODO](https://github.com/swiftlang/swift/pull/79608) -* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) +* Implementation: https://github.com/swiftlang/swift/pull/79608 +* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ## Introduction From 8521e61fea904c5c4953e52a5d57ffa5b66ab96c Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 27 Mar 2025 13:24:13 -0700 Subject: [PATCH 187/505] Prepare SE-0461 for re-review focused on naming. (#2752) * [SE-0461] Rename `@execution(caller)` to `nonisolated(nonsending)`. * [SE-0461] Elaborate on the alternative syntax choices. --- proposals/0461-async-function-isolation.md | 342 +++++++++++++-------- 1 file changed, 214 insertions(+), 128 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index 5ba6c142e1..8fd24a5b28 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -26,9 +26,8 @@ async function always switches off of an actor to run. - [Motivation](#motivation) - [Proposed solution](#proposed-solution) - [Detailed design](#detailed-design) - - [The `@execution` and `@concurrent` attributes](#the-execution-and-concurrent-attributes) - - [`@execution(caller)` functions](#executioncaller-functions) - - [`@concurrent` functions](#concurrent-functions) + - [`nonisolated(nonsending)` functions](#nonisolatednonsending-functions) + - [`@concurrent` functions](#concurrent-functions) - [Task isolation inheritance](#task-isolation-inheritance) - [`#isolation` macro expansion](#isolation-macro-expansion) - [Isolation inference for closures](#isolation-inference-for-closures) @@ -45,8 +44,13 @@ async function always switches off of an actor to run. - [Changing isolation inference behavior to implicitly capture isolated parameters](#changing-isolation-inference-behavior-to-implicitly-capture-isolated-parameters) - [Use `nonisolated` instead of a separate `@concurrent` attribute](#use-nonisolated-instead-of-a-separate-concurrent-attribute) - [Alternative syntax choices](#alternative-syntax-choices) + - [No explicit spelling for `nonisolated(nonsending)`](#no-explicit-spelling-for-nonisolatednonsending) + - [Justification for `@concurrent`](#justification-for-concurrent) + - [`@executor`](#executor) + - [`@isolated`](#isolated) + - [`nonisolated` argument spelling](#nonisolated-argument-spelling) - [Deprecate `nonisolated`](#deprecate-nonisolated) - - [Don't introduce a type attribute for `@execution`](#dont-introduce-a-type-attribute-for-execution) + - [Don't introduce a type attribute for `@concurrent`](#dont-introduce-a-type-attribute-for-concurrent) - [Revisions](#revisions) ## Motivation @@ -202,22 +206,35 @@ actor MyActor { Changing the default execution semantics of async functions can change the behavior of existing code, so the change is gated behind the `AsyncCallerExecution` upcoming feature flag. To help stage in the new -behavior, a new `@execution` attribute can be used to explicitly specify the -execution semantics of an async function in any language mode. The -`@concurrent` attribute is an explicit spelling for the behavior of -async functions in language modes <= Swift 6, and the `@execution(caller)` -attribute is an explicit spelling for async functions that run on the caller's -actor. +behavior, new syntax can be used to explicitly specify the +execution semantics of an async function in any language mode. -For example: +A new `nonsending` argument can be written with `nonisolated` to indicate +that by default, the argument and result values are not sent over an +isolation boundary when the function is called: ```swift class NotSendable { - func performSync() { ... } - - @execution(caller) + nonisolated(nonsending) func performAsync() async { ... } +} + +actor MyActor { + let x: NotSendable + + func call() async { + await x.performAsync() // okay + } +} +``` +The `@concurrent` attribute is an explicit spelling for the behavior of +async functions in language modes <= Swift 6. `@concurrent` indicates +that calling the function always switches off of an actor to run, so +the function will run concurrently with other tasks on the caller's actor: + +```swift +class NotSendable { @concurrent func alwaysSwitch() async { ... } } @@ -226,77 +243,35 @@ actor MyActor { let x: NotSendable func call() async { - x.performSync() // okay - - await x.performAsync() // okay - await x.alwaysSwitch() // error } } ``` `@concurrent` is the current default for nonisolated async -functions. `@execution(caller)` will become the default for async functions +functions. `nonisolated(nonsending)` will become the default for async functions when the `AsyncCallerExecution` upcoming feature is enabled. ## Detailed design The sections below will explicitly use `@concurrent` and -`@execution(caller)` to demonstrate examples that will behave consistently +`nonisolated(nonsending)` to demonstrate examples that will behave consistently independent of upcoming features or language modes. However, note that the end state under the `AsyncCallerExecution` upcoming feature will mean that -`@execution(caller)` is not necessary to explicitly write, and +`(nonsending)` is not necessary to explicitly write, and `@concurrent` will likely be used sparingly because it has far stricter data-race safety requirements. -### The `@execution` and `@concurrent` attributes - -`@execution(caller)` and `@concurrent` are both declaration and type attributes -that specify the execution semantics of an async function. The details of -each attribute are specified in the following sections. - -Only (implicitly or explicitly) `nonisolated` functions can be marked with -`@execution(caller)` or `@concurrent`; it is an error to use the these attributes with -an isolation other than `nonisolated`, including global actors, isolated -parameters, and `@isolated(any)`: - -```swift -actor MyActor { - var value = 0 - - // error: '@execution(caller)' can only be used with 'nonisolated' methods - @execution(caller) - func isolatedToSelf() async { - value += 1 - } - - @execution(caller) - nonisolated func canRunAnywhere() async { - // cannot access 'value' or other actor-isolated state - } -} -``` - -`@execution(caller)` and `@concurrent` can be used together with `@Sendable` or -`sending`. +### `nonisolated(nonsending)` functions -`@execution(caller)` and `@concurrent` are preserved in the type system so that -the execution semantics can be distinguished for function vales. - -`@execution(caller)` and `@concurrent` cannot be applied to synchronous -functions. This is an artificial limitation that could later be lifted if use -cases arise. - -#### `@execution(caller)` functions - -Async functions annotated with `@execution(caller)` will always run on the +Async functions annotated with `nonisolated(nonsending)` will always run on the caller's actor: ```swift class NotSendable { func performSync() { ... } - @execution(caller) + nonisolated(nonsending) func performAsync() async { ... } } @@ -313,27 +288,29 @@ actor MyActor { In the above code, the call to `x.performAsync()` continues running on the `self` actor instance. The code does not produce a data-race safety error, -because the `NotSendable` instance `x` does not leave the actor. +because the `NotSendable` instance `x` does not leave the actor. In other +words, the arguments are not send across an isolation boundary when calling +`performAsync` by default. This behavior is accomplished by implicitly passing an optional actor parameter to the async function. The function will run on this actor's executor. See the [Executor switching](#executor-switching) section for more details on why the actor parameter is necessary. -The type of an `@execution(caller)` function declaration is an -`@execution(caller)` function type. For example: +The type of an `nonisolated(nonsending)` function declaration is an +`nonisolated(nonsending)` function type. For example: ```swift class NotSendable { ... } @MainActor let global: NotSendable = .init() -@execution(caller) +nonisolated(nonsending) func runOnActor(ns: NotSendable) async {} @MainActor func callSendableClosure() async { - // the type of 'closure' is '@Sendable @execution(caller) (NotSendable) -> Void' + // the type of 'closure' is '@Sendable nonisolated(nonsending) (NotSendable) -> Void' let closure = runOnActor(ns:) let ns = NotSendable() @@ -345,10 +322,10 @@ callSendableClosure() ``` In the above code, the calls to `closure` from `callSendableClosure` run on the -main actor, because `closure` is `@execution(caller)` and `callSendableClosure` +main actor, because `closure` is `nonisolated(nonsending)` and `callSendableClosure` is main actor isolated. -#### `@concurrent` functions +### `@concurrent` functions Async functions can be declared to always switch off of an actor to run using the `@concurrent` attribute: @@ -360,12 +337,40 @@ struct S: Sendable { } ``` +Only (implicitly or explicitly) `nonisolated` functions can be marked with +`@concurrent`; it is an error to use the these attributes with +an isolation other than `nonisolated`, including global actors, isolated +parameters, and `@isolated(any)`: + +```swift +actor MyActor { + var value = 0 + + // error: '@concurrent' can only be used with 'nonisolated' methods + @concurrent + func isolatedToSelf() async { + value += 1 + } + + @concurrent + nonisolated func canRunAnywhere() async { + // cannot access 'value' or other actor-isolated state + } +} +``` + +`@concurrent` can be used together with `@Sendable` or `sending`. + +`@concurrent` cannot be applied to synchronous +functions. This is an artificial limitation that could later be lifted if use +cases arise. + The type of an `@concurrent` function declaration is an `@concurrent` function type. Details on function conversions are covered in a [later section](#function-conversions). When an `@concurrent` function is called from a context that can -run on an actor, including `@execution(caller)` functions or actor-isolated +run on an actor, including `nonisolated(nonsending)` functions or actor-isolated functions, sendable checking is performed on the argument and result values. Either the argument and result values must have a type that conforms to `Sendable`, or the values must be in a disconnected region so they can be sent @@ -393,7 +398,7 @@ actor MyActor { Unstructured tasks created in nonisolated functions never run on an actor unless explicitly specified. This behavior is consistent for all nonisolated -functions, including synchronous functions, `@execution(caller)` async +functions, including synchronous functions, `nonisolated(nonsending)` async functions, and `@concurrent` async functions. For example: @@ -403,7 +408,7 @@ class NotSendable { var value = 0 } -@execution(caller) +nonisolated(nonsending) func createTask(ns: NotSendable) async { Task { // This task does not run on the same actor as `createTask` @@ -444,7 +449,7 @@ struct Program { This behavior allows async function calls that use `#isolation` as a default isolated argument to run on the same actor when called from an -`@execution(caller)` function. For example, the following code is valid because +`nonisolated(nonsending)` function. For example, the following code is valid because the call to `explicitIsolationInheritance` does not cross an isolation boundary: @@ -456,7 +461,7 @@ func explicitIsolationInheritance( isolation: isolated (any Actor)? = #isolation ) async { ... } -@execution(caller) +nonisolated(nonsending) func printIsolation(ns: NotSendable) async { await explicitIsolationInheritance(ns: ns) // okay } @@ -575,29 +580,29 @@ actor MyActor { } func invalidResult(a: MyActor) async -> NotSendable { - let grabActorState: @execution(caller) () async -> NotSendable = a.getState // error + let grabActorState: nonisolated(nonsending) () async -> NotSendable = a.getState // error return await grabActorState() } ``` In the above code, the conversion from the actor-isolated method `getState` -to a `@execution(caller) nonisolated` function is invalid, because the +to a `nonisolated(nonsending)` function is invalid, because the result type does not conform to `Sendable` and the result value could be actor-isolated state. The `nonisolated` function can be called from anywhere, which would allow access to actor state from outside the actor. Not all function conversions cross an isolation boundary, and function conversions that don't can safely pass non-`Sendable` arguments and results. -For example, a `@execution(caller)` function type can always be converted to an -actor-isolated function type, because the `@execution(caller)` function will +For example, a `nonisolated(nonsending)` function type can always be converted to an +actor-isolated function type, because the `nonisolated(nonsending)` function will simply run on the actor: ```swift class NotSendable {} -@execution(caller) -nonisolated func performAsync(_ ns: NotSendable) async { ... } +nonisolated(nonsending) +func performAsync(_ ns: NotSendable) async { ... } @MainActor func convert(ns: NotSendable) async { @@ -613,7 +618,7 @@ which function conversions cross an isolation boundary. Function conversions that cross an isolation boundary require `Sendable` argument and result types, and the destination function type must be `async`. Note that the function conversion rules for synchronous `nonisolated` functions and asynchronous -`@execution(caller) nonisolated` functions are the same; they are both +`nonisolated(nonsending)` functions are the same; they are both represented under the "Nonisolated" category in the table: | Old isolation | New isolation | Crosses Boundary | @@ -646,7 +651,7 @@ class NotSendable { var value = 0 } -@execution(caller) +nonisolated(nonsending) func convert(closure: () -> Void) async { let ns = NotSendable() let disconnectedClosure = { @@ -668,7 +673,7 @@ Converting a non-`@Sendable` function type to an actor-isolated one is invalid if the original function must leave the actor in order to be called: ```swift -@execution(caller) +nonisolated(nonsending) func convert( fn1: @escaping @concurrent () async -> Void, ) async { @@ -710,8 +715,8 @@ func call(_ closure: () -> NotSendable) -> NotSendable { ### Region isolation rules -`@execution(caller)` functions have the same region isolation rules as -synchronous `nonisolated` functions. When calling an `@execution(caller)` +`nonisolated(nonsending)` functions have the same region isolation rules as +synchronous `nonisolated` functions. When calling an `nonisolated(nonsending)` function, all non-`Sendable` parameter and result values are merged into the same region, but they are only merged into the caller's actor region if one of those non-`Sendable` values is already in the actor's region. @@ -721,8 +726,8 @@ For example: ```swift class NotSendable {} -@execution(caller) -nonisolated func identity(_ t: T) async -> T { +nonisolated(nonsending) +func identity(_ t: T) async -> T { return t } @@ -741,7 +746,7 @@ parameter, because the non-`Sendable` parameters and results would always be merged into the actor's region. This proposal allows you to access `#isolation` in the implementation of an -`@execution(caller)` function for the purpose of forwarding it along to a +`nonisolated(nonsending)` function for the purpose of forwarding it along to a method that accepts an `isolated (any Actor)?`. This is still safe, because there's no way to access the actor's isolated state via the `Actor` protocol, and dynamic casting to a concrete actor type will not result in a value that @@ -780,7 +785,7 @@ all other async functions switch to the isolated actor's executor. } ``` -`@execution(caller)` functions will switch to the executor of the implicit +`nonisolated(nonsending)` functions will switch to the executor of the implicit actor parameter passed from the caller instead of switching to the generic executor: @@ -835,10 +840,10 @@ and `preconditionIsolated` on `Actor` and `MainActor`. Nonisolated functions imported from Objective-C that match the import-as-async heuristic from [SE-0297: Concurrency Interoperability with Objective-C][SE-0297] -will implicitly be imported as `@execution(caller)`. Objective-C async +will implicitly be imported as `nonisolated(nonsending)`. Objective-C async functions already have bespoke code generation that continues running on the caller's actor to match the semantics of the original completion handler -function, so `@execution(caller)` already better matches the semantics of these +function, so `nonisolated(nonsending)` already better matches the semantics of these imported `async` functions. This change will eliminate many existing data-race safety issues that happen when calling an async function on an Objective-C class from the main actor. Because the only effect of this change is @@ -851,7 +856,7 @@ This proposal changes the semantics of nonisolated async functions when the upcoming feature flag is enabled. Without the upcoming feature flag, the default for nonisolated async functions is `@concurrent`. When the upcoming feature flag is enabled, the default for nonisolated async functions changes to -`@execution(caller)`. This applies to both function declarations and function +`nonisolated(nonsending)`. This applies to both function declarations and function values that are nonisolated (either implicitly or explicitly). Changing the default execution semantics of nonisolated async functions has @@ -873,7 +878,7 @@ understand the semantics of a nonisolated async function without understanding the build settings of the module you're writing code in. To make it easy to discover what kind of async function you're working with, -SourceKit will surface the implicit `@execution(caller)` or `@concurrent` +SourceKit will surface the implicit `nonisolated(nonsending)` or `@concurrent` attribute for IDE inspection features like Quick Help in Xcode and Hover in VSCode. To ease the transition to the upcoming feature flag, [migration tooling][adoption-tooling] will provide fix-its to preserve behavior by @@ -913,9 +918,9 @@ can be made inlinable. ## Implications on adoption -`@execution(caller)` functions must accept an implicit actor parameter. This -means that adding `@execution(caller)` to a function that is actor-isolated, or -changing a function from `@concurrent` to `@execution(caller)`, is +`nonisolated(nonsending)` functions must accept an implicit actor parameter. This +means that adding `nonisolated(nonsending)` to a function that is actor-isolated, or +changing a function from `@concurrent` to `nonisolated(nonsending)`, is not a resilient change. ## Alternatives considered @@ -945,6 +950,41 @@ reasons: ### Alternative syntax choices +Several different options for the spelling of `nonisolated(nonsending)` +and `@concurrent` were explored. An earlier iteration of this proposal +used the same base attribute for both annotations. However, these two +annotations serve very different purposes. `@concurrent` is the long-term +right way to move functions and closures off of actors. +`nonisolated(nonsending)` is necessary for the transition to the new behavior, +but it's not a syntax that will stick around long term in Swift codebases; the +ideal end state is that this is expressed via the default behavior for +(explicitly or implicitly) `nonisolated` async functions. + +Note that it is well understood that there is no perfect syntax which will +explain the semantics without other context such as educational material or +documentation. This is true for all syntax design decisions. + +#### No explicit spelling for `nonisolated(nonsending)` + +It's reasonable to question whether `nonisolated(nonsending)` is necessary +at all given that its only purpose is transitioning to the new behavior +for async functions. An explicit spelling that has consistent behavior +independent of upcoming features and language modes is valuable when +undertaking a transition that changes the meaning of existing code. + +An explicit, transitory attribute is valuable because there will be a period of +time where it is not immediately clear from source what kind of async function +a programmer is working with. It's necessary to be able to discover that +information from source, such as by showing an inferred attribute explicitly +in SourceKit's cursor info request (surfaced by "Quick Help" in Xcode and +"Hover" in LSP / VSCode). An explicit spelling that has consistent behavior +independent of language mode is also valuable for code generation tools like +macros, so that they do not have to consider build settings to determine the +right code to generate, it's valuable for posting code snippets on the forums +during the transition period, etc. + +#### Justification for `@concurrent` + This proposal was originally pitched using the `@concurrent` syntax, and many reviewers surfaced objects about why `@concurrent` may be misleading, such as: @@ -965,6 +1005,8 @@ happen in the process. So, this proposal uses `@concurrent` because out of the other alternatives we explored, it best reflects the programmer's intent for using the attribute. +#### `@executor` + A previous iteration of this proposal used the syntax `@execution(concurrent)` instead of `@concurrent`. The review thread explored several variations of this syntax, including `@executor(concurrent)` and `@executor(global)`. @@ -979,28 +1021,38 @@ requests and because executors are used for other things than isolation. For example, an `@executor(global)` function could end up running on some executor other than the global executor via task executor preferences. -Another possibility is to use isolation terminology instead of `@execution` -for the syntax. This direction does not accomplish the goal of having a -section to have a consistent meaning for `nonisolated` across synchronous and -async functions. If the attribute were spelled `@isolated(caller)` and -`@isolated(concurrent)`, presumably that attribute would not work together with -`nonisolated`; it would instead be an alternative kind of actor isolation. -`@isolated(concurrent)` also doesn't make much sense because the concurrent -executor does not provide isolation at all - isolation is only provided by -actors and tasks. - -Having `@execution(caller)` as an attribute that is used together with -`nonisolated` leads to a simpler programming model because after the upcoming -feature is enabled, programmers will simply write `nonisolated` on an `async` -function in the same way that `nonisolated` is applied to synchronous -functions. If we choose a different form of isolation like `@isolated(caller)`, -programmers have to learn a separate syntax for `async` functions that -accomplishes the same effect as a `nonisolated` synchronous function. - -### Deprecate `nonisolated` +#### `@isolated` + +An alternative to `nonisolated(nonsending)` is to use the "isolated" +terminology, such as `@isolated(caller)`. However, this approach has very +unsatisfying answers for how it interacts with `nonisolated`. There are +two options: + +1. `@isolated(caller)` must be written together with `nonisolated`, + + This approach leads to the verbose and oxymoronic spelling + `@isolated(caller) nonisolated`. Though there + exists a perfectly reasonable explanation about how `nonisolated` is the + static isolation while `@isolated(caller)` is the dynamic isolation, most + programmers do not have this deep of an understanding of actor isolation, + and they should not have to in order to make basic use of nonisolated async + functions. +2. `@isolated(caller)` implies `nonisolated` and can be written alone as an + alternative. + + This direction means that programmers would sometimes write + `nonisolated` and sometimes write `@isolated(caller)`, which is not a good + end state to be in because programmers have to learn a separate syntax for + `async` functions that accomplishes the same effect as a `nonisolated` + synchronous function. Or, if we view `@isolated(caller)` as only used for + the transition to the new behavior, then the assumption is that some day + people will remove `@isolated(caller)` if it is written in source. If + `@isolated(caller)` implies `nonisolated`, then the code could change + behavior if it's in a context where global or instance actor isolation would + otherwise be inferred. Going in the oppose direction, this proposal could effectively deprecate -`nonisolated` and allow you to use `@execution(caller)` everywhere that +`nonisolated` and allow you to use `@isolated(caller)` everywhere that `nonisolated` is currently supported, including synchronous methods, stored properties, type declarations, and extensions. This direction was not chosen for the following reasons: @@ -1010,26 +1062,60 @@ for the following reasons: necessary to solve the major usability problem with async functions on non-`Sendable` types, because it's painful both to transition code and to re-learn parts of the model that have already been internalized. -2. `nonisolated` is nicer to write than `@execution(caller)`, - `@isolated(caller)`, or any other alternative attribute + argument syntax. - -### Don't introduce a type attribute for `@execution` - -There are a lot of existing type attributes for concurrency and it's -unfortunate to introduce another one. However, without `@execution` as a type -attribute, referencing nonisolated async functions unapplied is very restrictive, -because sendable checking would need to be performed at the point of the -function reference instead of when the function is called. +2. `nonisolated` is nicer to write than `@isolated(caller)` + or any other alternative attribute + argument syntax. + +#### `nonisolated` argument spelling + +An argument to `nonisolated` is more compelling than a separate attribute +to specify that an async function runs on the caller's actor because it +defines away the problem of whether this annotation implies `nonisolated` when +written alone. + +A few different options for the argument to `nonisolated` were explored. + +**`nonisolated(nosend)`**. +`nonisolated(nosend)` effectively the same as `nonisolated(nonsending)` as +proposed, but it states that the call itself does not constitute a "send", +rather than stating that the call is not "sending" its argument and result +values over an isolation boundary. `nonisolated(nosend)` is shorter, but +`nonisolated(nonsending)` is more consistent with existing Swift naming +conventions. + +**`nonisolated(caller)`**. +`nonisolated(caller)` is meant to indicate that the function is statically +`nonisolated` and dynamically isolated to the caller. However, putting those +terms together into one `nonisolated(caller)` attribute is misleading, because +it appears the mean exactly the opposite of what it actually means; +`nonisolated(caller)` reads "not isolated to the caller". + +**`nonisolated(nonconcurrent)`**. +If `@concurrent` is applied to a function, then the function must run +concurrently with the caller's actor (assuming multiple isolated tasks +in the program). `nonconcurrent` conveys the inverse; if `nonconcurrent` is +applied to an async function, then the function must not run concurrently +with the caller's actor. However, this statement isn't quite true, because the +implementation of the function can perform work concurrently, though that work +cannot involve the non-`Sendable` parameter values. + +**`nonisolated(static)`**. +`nonisolated(static)` is meant to convey that a function is only `nonisolated` +statically, but it may be dynamically isolated to a specific actor at runtime. +However, we have not yet introduced "static" into the language surface to mean +"at compile time". `static` also has an existing, different meaning; +`nonisolated static func` would mean something quite different from +`nonisolated(static) func`, despite having extremely similar spelling. ## Revisions The proposal was revised with the following changes after the first review: * Renamed `@execution(concurrent)` back to `@concurrent`. +* Renamed `@execution(caller)` to `nonisolated(nonsending)` * Removed the unconditional warning about nonisolated async functions that - don't explicitly specify `@execution(caller)` or `@concurrent`. + don't explicitly specify `nonisolated(nonsending)` or `@concurrent`. * Removed `noasync` from the `assumeIsolated` API family. -* Specified the region isolation rules for `@execution(caller)` functions [as +* Specified the region isolation rules for `nonisolated(nonsending)` functions [as discussed in the first review][region-isolation]. The proposal was revised with the following changes after the pitch discussion: From e37fb650638a550fc82f7c830c53fb9d77011216 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Thu, 27 Mar 2025 15:47:34 -0700 Subject: [PATCH 188/505] Update proposals/NNNN-ClockEpochs.md Co-authored-by: Ben Rimmington --- proposals/NNNN-ClockEpochs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md index b79cb30084..65ed3f626a 100644 --- a/proposals/NNNN-ClockEpochs.md +++ b/proposals/NNNN-ClockEpochs.md @@ -24,7 +24,7 @@ Two new properties will be added, one to `SuspendingClock` and another to `Conti ## Detailed design ```swift -extension ContinousClock { +extension ContinuousClock { public var systemEpoch: Instant { get } } From 9095dcdced0646591a392e2a2bf80700c858e158 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Thu, 27 Mar 2025 15:47:42 -0700 Subject: [PATCH 189/505] Update proposals/NNNN-ClockEpochs.md Co-authored-by: Ben Rimmington --- proposals/NNNN-ClockEpochs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md index 65ed3f626a..2820db62fc 100644 --- a/proposals/NNNN-ClockEpochs.md +++ b/proposals/NNNN-ClockEpochs.md @@ -36,7 +36,7 @@ extension SuspendingClock { These can be used to gather information like for example the uptime of a system, or the active time of a system; ```swift -let clock = ContinousClock() +let clock = ContinuousClock() let uptime = clock.now - clock.systemEpoch ``` From d65c66a2cc0537ade9ea95e02aadf7bc5225e6af Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Thu, 27 Mar 2025 15:47:58 -0700 Subject: [PATCH 190/505] Update proposals/NNNN-ClockEpochs.md Co-authored-by: Ben Rimmington --- proposals/NNNN-ClockEpochs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md index 2820db62fc..61c6741eed 100644 --- a/proposals/NNNN-ClockEpochs.md +++ b/proposals/NNNN-ClockEpochs.md @@ -1,6 +1,6 @@ # Clock Epochs -* Proposal: [SE-NNNN](NNNN-ClockEpochs.md) +* Proposal: [SE-NNNN](NNNN-clock-epochs.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: TBD * Status: **Awaiting implementation** From 897d6d3168a7b03e381edfcb238f31f609f04b08 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 27 Mar 2025 19:56:12 -0400 Subject: [PATCH 191/505] Wording updates --- proposals/NNNN-ClockEpochs.md | 58 -------------------------------- proposals/NNNN-clock-epochs.md | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 58 deletions(-) delete mode 100644 proposals/NNNN-ClockEpochs.md create mode 100644 proposals/NNNN-clock-epochs.md diff --git a/proposals/NNNN-ClockEpochs.md b/proposals/NNNN-ClockEpochs.md deleted file mode 100644 index 61c6741eed..0000000000 --- a/proposals/NNNN-ClockEpochs.md +++ /dev/null @@ -1,58 +0,0 @@ -# Clock Epochs - -* Proposal: [SE-NNNN](NNNN-clock-epochs.md) -* Authors: [Philippe Hausler](https://github.com/phausler) -* Review Manager: TBD -* Status: **Awaiting implementation** -* Implementation: - -* Previous Proposal: *if applicable* [SE-0329](0329-clock-instant-duration.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) - -## Introduction - -[The proposal for Clock, Instant and Duration](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) brought in two primary clock types: `SuspendingClock` and `ContinuousClock`. These both have a concept of a reference point for their `Instant` types. - -## Motivation - -Not all clocks have a starting point, however in these cases they do. Generally, it cannot required for a clock's instant definition to have a start or the start may not be a fixed point. However it can be useful that a given instant can be constructed to determine the elapsed duration from the starting point of that clock if it does have it. - -## Proposed solution - -Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. Both of these properties will be the epoch for which all `Instant` types are derived from; practically speaking this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on (albeit many may implement them literally as zero) they are named in accordance to reflect that they are designed to be representative of the system's sense of an epoch and should not be expected to be serializable across systems. - -## Detailed design - -```swift -extension ContinuousClock { - public var systemEpoch: Instant { get } -} - -extension SuspendingClock { - public var systemEpoch: Instant { get } -} -``` - -These can be used to gather information like for example the uptime of a system, or the active time of a system; - -```swift -let clock = ContinuousClock() -let uptime = clock.now - clock.systemEpoch -``` - -Or likewise; - -```swift -let clock = SuspendingClock() -let activeTime = clock.now - clock.systemEpoch -``` - -## ABI compatibility - -This is a purely additive change and provides no direct impact to existing ABI. It only carries the ABI impact of new properties being added to an existing type. - -## Alternatives considered - -It was considered to add a constructor or static member to the `SuspendingClock.Instant` and `ContinousClock.Instant` however the home on the clock itself provides a more discoverable and nameable location. - -It is suggested that this be used as an informal protocol for other clocks. It was considered as an additional protocol but that was ultimately rejected because no generic function made much sense that would not be better served with generic specialization or explicit clock parameter types. \ No newline at end of file diff --git a/proposals/NNNN-clock-epochs.md b/proposals/NNNN-clock-epochs.md new file mode 100644 index 0000000000..4ef36495f7 --- /dev/null +++ b/proposals/NNNN-clock-epochs.md @@ -0,0 +1,60 @@ +# Clock Epochs + +* Proposal: [SE-NNNN](NNNN-clock-epochs.md) +* Authors: [Philippe Hausler](https://github.com/phausler) +* Review Manager: [John McCall](https://github.com/rjmccall) +* Status: **Awaiting implementation** +* Implementation: +* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) + +## Introduction + +[SE-0329: Clock, Instant, and Duration](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) introduced three concrete clock types: `SuspendingClock`, `ContinuousClock`, and `UTCClock`. While not all clocks have a meaningful concept of a reference or zero instant, `SuspendingClock` and `ContinuousClock` do, and having access to it can be useful. + +## Motivation + +The `Instant` type of a `Clock` represents a moment in time as measured by that clock. `Clock` intentionally imposes very few requirements on `Instant` because different kinds of clocks can have very different characteristics. Just because something does not belong on the generic `Clock` protocol, however, does not mean it shouldn't be exposed in the interface of a concrete clock type. + +Many clocks have a concept of a reference instant, also called an "epoch", that has special meaning for the clock. For example, the Unix `gettimeofday` function measures the nominal elapsed time since 00:00 UTC on January 1st, 1970, an instant often called the "Unix epoch". Swift's `SuspendingClock` and `ContinuousClock` are defined using system facilities that similarly measure time relative to an epoch, and while the exact definition of the epoch is system-specific, it is at least consistent for any given system. This means that durations since the epoch can be meaningfully compared within the system, even with code in other processes or written in other languages (as long as it uses the same system facilities). + +## Proposed solution + +Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. These properties define the system epoch that all `Instant` types for the clock are derived from; practically speaking, this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on, their names reflect that they are representative of the system's sense of an epoch and should not be expected to be meaningfully comparable (or serializable) across systems. + +## Detailed design + +```swift +extension ContinuousClock { + public var systemEpoch: Instant { get } +} + +extension SuspendingClock { + public var systemEpoch: Instant { get } +} +``` + +On both Darwin and Linux, the system epochs of these clocks is set at boot time, and so measurements relative to the epoch can used to gather information such as the uptime or active time of a system: + +```swift +let clock = ContinousClock() +let uptime = clock.now - clock.systemEpoch +``` + +Likewise: + +```swift +let clock = SuspendingClock() +let activeTime = clock.now - clock.systemEpoch +``` + +Swift will make an effort to maintain this property on other supported systems when possible. However, it cannot be guaranteed for all systems, such as when the concept of uptime either doesn't apply or is intentionally not exposed to the programming environment for privacy reasons. + +## ABI compatibility + +This is a purely additive change and provides no direct impact to existing ABI. It only carries the ABI impact of new properties being added to an existing type. + +## Alternatives considered + +We considered adding a constructor or static member to `SuspendingClock.Instant` and `ContinousClock.Instant` instead of on the clock. However, placing it on the clock itself provides a more discoverable and nameable location. + +As proposed, `systemEpoch` is an informal protocol that works across multiple clock implementations. We consider formalizing it as a new protocol, but ultimately we decided not to because no generic function made much sense that would not be better served with generic specialization or explicit clock parameter types. From d1fbc32a41cf6669b12af97c19dbe1c4afecc8ad Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Fri, 28 Mar 2025 15:20:30 +0000 Subject: [PATCH 192/505] [SE-0471] Amend the status field --- proposals/0471-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index dcbb66db9f..539f1adc84 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -3,7 +3,7 @@ * Proposal: [SE-0471](0471-SerialExecutor-isIsolated.md) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Active Review (March 25...April 8, 2025) +* Status: **Active Review (March 25...April 8, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 * Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834) From 8df1b2b9132a257575f170f4a74b5fb108e43fb0 Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Fri, 28 Mar 2025 15:26:24 +0000 Subject: [PATCH 193/505] [SE-0472] Amend the status field --- proposals/0472-task-start-synchronously-on-caller-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 4e9daacd9f..ae636da68c 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -3,7 +3,7 @@ * Proposal: [SE-0472](0472-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Partially implemented on `main`** +* Status: **Active Review (March 27...April 10, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79608 * Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) From 150133f0c0aecb7344a079a5d88edde6d87325c9 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:21:44 -0400 Subject: [PATCH 194/505] Update SE-0461 for focused re-review (#2765) --- proposals/0461-async-function-isolation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index 8fd24a5b28..755fa646d0 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -3,12 +3,12 @@ * Proposal: [SE-0461](0461-async-function-isolation.md) * Authors: [Holly Borla](https://github.com/hborla), [John McCall](https://github.com/rjmccall) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (February 20...March 2, 2025)** +* Status: **Active review (March 28...April 4, 2025)** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` * Upcoming Feature Flag: `AsyncCallerExecution` * Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([first review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) ([acceptance with focused re-review](https://forums.swift.org/t/accepted-with-modifications-and-focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78920)) ([second review](https://forums.swift.org/t/focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78921)) ## Introduction @@ -1135,4 +1135,4 @@ The proposal was revised with the following changes after the pitch discussion: [SE-0338]: /proposals/0338-clarify-execution-non-actor-async.md [SE-0421]: /proposals/0421-generalize-async-sequence.md [adoption-tooling]: https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936 -[region-isolation]: https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987/36 \ No newline at end of file +[region-isolation]: https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987/36 From a89b64fad71766571d6c2b32858a581720723c60 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 28 Mar 2025 18:47:27 -0400 Subject: [PATCH 195/505] Assign SE-0473 to the clocks proposal and put it into review Also some more assorted wording updates --- .../{NNNN-clock-epochs.md => 0473-clock-epochs.md} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename proposals/{NNNN-clock-epochs.md => 0473-clock-epochs.md} (76%) diff --git a/proposals/NNNN-clock-epochs.md b/proposals/0473-clock-epochs.md similarity index 76% rename from proposals/NNNN-clock-epochs.md rename to proposals/0473-clock-epochs.md index 4ef36495f7..bc2981752a 100644 --- a/proposals/NNNN-clock-epochs.md +++ b/proposals/0473-clock-epochs.md @@ -1,9 +1,9 @@ # Clock Epochs -* Proposal: [SE-NNNN](NNNN-clock-epochs.md) +* Proposal: [SE-0473](0473-clock-epochs.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Awaiting implementation** +* Status: **Active Review (March 28th...April 9th, 2025)** * Implementation: * Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) @@ -15,11 +15,11 @@ The `Instant` type of a `Clock` represents a moment in time as measured by that clock. `Clock` intentionally imposes very few requirements on `Instant` because different kinds of clocks can have very different characteristics. Just because something does not belong on the generic `Clock` protocol, however, does not mean it shouldn't be exposed in the interface of a concrete clock type. -Many clocks have a concept of a reference instant, also called an "epoch", that has special meaning for the clock. For example, the Unix `gettimeofday` function measures the nominal elapsed time since 00:00 UTC on January 1st, 1970, an instant often called the "Unix epoch". Swift's `SuspendingClock` and `ContinuousClock` are defined using system facilities that similarly measure time relative to an epoch, and while the exact definition of the epoch is system-specific, it is at least consistent for any given system. This means that durations since the epoch can be meaningfully compared within the system, even with code in other processes or written in other languages (as long as it uses the same system facilities). +Many clocks have a concept of a reference instant, also called an "epoch", that has special meaning for the clock. For example, the Unix `gettimeofday` function measures the nominal elapsed time since 00:00 UTC on January 1st, 1970, an instant often called the "Unix epoch". Swift's `SuspendingClock` and `ContinuousClock` are defined using system facilities that similarly measure time relative to an epoch, and while the exact definition of the epoch is system-specific, it is at least consistent for any given system. This means that durations since the epoch can be meaningfully compared within the system, even across multiple processes or with code written in other languages (as long as they use the same system facilities). ## Proposed solution -Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. These properties define the system epoch that all `Instant` types for the clock are derived from; practically speaking, this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on, their names reflect that they are representative of the system's sense of an epoch and should not be expected to be meaningfully comparable (or serializable) across systems. +Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. These properties define the system epoch that all `Instant` types for the clock are derived from; practically speaking, this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on, their names reflect that they are a system-specific definition and should not be expected to be consistent (or meaningfully serializable) across systems. ## Detailed design @@ -33,7 +33,7 @@ extension SuspendingClock { } ``` -On both Darwin and Linux, the system epochs of these clocks is set at boot time, and so measurements relative to the epoch can used to gather information such as the uptime or active time of a system: +On most platforms, including Apple platforms, Linux, and Windows, the system epoch of these clocks is set at boot time, and so measurements relative to the epoch can used to gather information such as the uptime or active time of a system: ```swift let clock = ContinousClock() @@ -47,7 +47,7 @@ let clock = SuspendingClock() let activeTime = clock.now - clock.systemEpoch ``` -Swift will make an effort to maintain this property on other supported systems when possible. However, it cannot be guaranteed for all systems, such as when the concept of uptime either doesn't apply or is intentionally not exposed to the programming environment for privacy reasons. +However, this cannot be guaranteed for all possible platforms. A platform may choose to use a different instant for its system epoch, perhaps because the concept of uptime doesn't apply cleanly on the platform or because it is intentionally not exposed to the programming environment for privacy reasons. ## ABI compatibility From 3ba7dede6c42589206ea1d3e4ad653a03dade17d Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 28 Mar 2025 18:52:33 -0400 Subject: [PATCH 196/505] Link SE-0473 to its review thread --- proposals/0473-clock-epochs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0473-clock-epochs.md b/proposals/0473-clock-epochs.md index bc2981752a..4565338dcc 100644 --- a/proposals/0473-clock-epochs.md +++ b/proposals/0473-clock-epochs.md @@ -5,7 +5,7 @@ * Review Manager: [John McCall](https://github.com/rjmccall) * Status: **Active Review (March 28th...April 9th, 2025)** * Implementation: -* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) +* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) ([review](https://forums.swift.org/t/se-0473-clock-epochs/78923)) ## Introduction From b5bf19dd29385f7d647d4e7a41290323d1765940 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Fri, 28 Mar 2025 22:08:21 -0400 Subject: [PATCH 197/505] Update 0466-control-default-actor-isolation.md (#2767) --- proposals/0466-control-default-actor-isolation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 81f289408c..51ffc99c7c 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -3,10 +3,10 @@ * Proposal: [SE-0466](0466-control-default-actor-isolation.md) * Authors: [Holly Borla](https://github.com/hborla) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Active Review (March 5...19, 2025)** +* Status: **Accepted** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Implementation: On `main` behind the `UnspecifiedMeansMainActorIsolated` experimental feature. -* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321)) +* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321))([acceptance](https://forums.swift.org/t/accepted-se-0466-control-default-actor-isolation-inference/78926)) ## Introduction From a00d4eee3d5b848dffd8e7388aecd0948cc8de98 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 31 Mar 2025 11:03:24 -0700 Subject: [PATCH 198/505] [SE-0467] incorporate review feedback (#2737) * [se0467] extract slicing from future directions * [se0467] clean up element constraints * [se0467] fix another typo * [se0467] fix a typo and parameter name --- proposals/0467-MutableSpan.md | 36 +++++++---------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/proposals/0467-MutableSpan.md b/proposals/0467-MutableSpan.md index 0ed4faecc7..4ee89aeb13 100644 --- a/proposals/0467-MutableSpan.md +++ b/proposals/0467-MutableSpan.md @@ -84,7 +84,7 @@ This lifetime relationship will apply to all the safe `var mutableSpan: MutableS An important category of use cases for `MutableSpan` and `MutableRawSpan` consists of bulk copying operations. Often times, such bulk operations do not necessarily start at the beginning of the span, thus having a method to select a sub-span is necessary. This means producing an instance derived from the callee instance. We adopt the nomenclature already introduced in [SE-0437][SE-0437], with a family of `extracting()` methods. ```swift -extension MutableSpan where Element: ~Copyable & ~Escapable { +extension MutableSpan where Element: ~Copyable { @_lifetime(inout self) public mutating func extracting(_ range: Range) -> Self } @@ -114,12 +114,12 @@ As established in [SE-0437][SE-0437], the instance returned by the `extracting() ````swift @frozen -public struct MutableSpan: ~Copyable, ~Escapable { +public struct MutableSpan: ~Copyable, ~Escapable { internal var _start: UnsafeMutableRawPointer? internal var _count: Int } -extension MutableSpan: @unchecked Sendable where Element: Sendable {} +extension MutableSpan: @unchecked Sendable where Element: Sendable & ~Copyable {} ```` We store a `UnsafeMutableRawPointer` value internally in order to explicitly support reinterpreted views of memory as containing different types of `BitwiseCopyable` elements. Note that the the optionality of the pointer does not affect usage of `MutableSpan`, since accesses are bounds-checked and the pointer is only dereferenced when the `MutableSpan` isn't empty, when the pointer cannot be `nil`. @@ -127,7 +127,7 @@ We store a `UnsafeMutableRawPointer` value internally in order to explicitly sup Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#initializers)" in the [future directions](#Directions) section. ```swift -extension MutableSpan where Element: ~Copyable & ~Escapable { +extension MutableSpan where Element: ~Copyable { /// The number of initialized elements in this `MutableSpan`. var count: Int { get } @@ -172,7 +172,7 @@ We include functions to perform bulk copies of elements into the memory represen ```swift extension MutableSpan where Element: Copyable { - /// Updates every element of this span's to the given value. + /// Updates every element of this span to the given value. mutating func update( repeating repeatedValue: Element ) @@ -224,7 +224,7 @@ extension MutableSpan where Element: Copyable { These functions extract sub-spans of the callee. The first two perform strict bounds-checking. The last four return prefixes or suffixes, where the number of elements in the returned sub-span is bounded by the number of elements in the parent `MutableSpan`. ```swift -extension MutableSpan where Element: ~Copable & ~Escapable { +extension MutableSpan where Element: ~Copyable { /// Returns a span over the items within the supplied range of /// positions within this span. @_lifetime(inout self) @@ -427,7 +427,7 @@ extension MutableRawSpan { /// Updates the span's bytes with the bytes of the elements from the source mutating func update( - from elements: inout some IteratorProtocol + from source: inout some IteratorProtocol ) -> Int /// Updates the span's bytes with every byte of the source. @@ -669,28 +669,6 @@ Note: The future directions stated in [SE-0447](https://github.com/swiftlang/swi These annotations have been [pitched][PR-2305-pitch] and, after revision, are expected to be pitched again soon. `MutableSpan` initializers using lifetime annotations will be proposed alongside the annotations themselves. -#### Functions providing variants of `MutableRawSpan` to `MutableSpan` - -`MutableSpan`s representing subsets of consecutive elements could be extracted out of a larger `MutableSpan` with an API similar to the `extracting()` functions recently added to `UnsafeBufferPointer` in support of non-copyable elements: - -```swift -extension MutableSpan where Element: ~Copyable { - public mutating func extracting(_ bounds: Range) -> Self -} -``` - -These functions would require a lifetime dependency annotation. - -Similarly, a `MutableRawSpan` could provide a function to mutate a range of its bytes as a typed `MutableSpan`: - -```swift -extension MutableRawSpan { - @unsafe - public mutating func unsafeMutableView(as type: T.Type) -> MutableSpan -} -``` -We are subsetting functions that require lifetime annotations until such annotations are [proposed][PR-2305]. - #### Splitting `MutableSpan` instances – `MutableSpan` in divide-and-conquer algorithms It is desirable to have a way to split a `MutableSpan` in multiple parts, for divide-and-conquer algorithms or other reasons: From e82773fbe6f5158d9b6114c6e4d33082eac8f133 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Mon, 31 Mar 2025 14:05:12 -0400 Subject: [PATCH 199/505] Update 0467-MutableSpan.md (#2769) --- proposals/0467-MutableSpan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0467-MutableSpan.md b/proposals/0467-MutableSpan.md index 4ee89aeb13..75bb7f7b1e 100644 --- a/proposals/0467-MutableSpan.md +++ b/proposals/0467-MutableSpan.md @@ -3,10 +3,10 @@ * Proposal: [SE-0467](0467-MutableSpan.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Joe Groff](https://github.com/jckarter) -* Status: **Active review (March 11...25, 2025)** +* Status: **Accepted** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) -* Review: [Pitch](https://forums.swift.org/t/pitch-mutablespan/77790) +* Review: ([Pitch](https://forums.swift.org/t/pitch-mutablespan/77790)) ([Review](https://forums.swift.org/t/se-0467-mutablespan/78454)) ([Acceptance](https://forums.swift.org/t/accepted-se-0467-mutablespan/78875)) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md From 06d3b8f3737b83d234ad53c03e8db38530b1d2fa Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 31 Mar 2025 11:07:37 -0700 Subject: [PATCH 200/505] [SE-0447] Span proposal edits (#2738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [se0447] reorder future-direction sections - “Index Validation Utilites” was mistakenly inserted between two other sections that should remain contiguous. * [se0447] use the indices property in an example * [se0447] add omitted `Sendable` conformances - while these were discussed in the form threads and were in the prototype implementations, they weren’t in this document. * [se0447] fix typos * [se0447] address telemetry domain’s Span naming * [se0447] discuss sendability of RawSpan --- ...7-span-access-shared-contiguous-storage.md | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/proposals/0447-span-access-shared-contiguous-storage.md b/proposals/0447-span-access-shared-contiguous-storage.md index 95d5c8346b..71b3ff8aa4 100644 --- a/proposals/0447-span-access-shared-contiguous-storage.md +++ b/proposals/0447-span-access-shared-contiguous-storage.md @@ -66,10 +66,12 @@ A `RawSpan` can be obtained from containers of `BitwiseCopyable` elements, as we ```swift @frozen -public struct Span: Copyable, ~Escapable { +public struct Span: Copyable, ~Escapable { internal var _start: UnsafeRawPointer? internal var _count: Int } + +extension Span: Sendable where Element: Sendable & ~Copyable {} ``` We store a `UnsafeRawPointer` value internally in order to explicitly support reinterpreted views of memory as containing different types of `BitwiseCopyable` elements. Note that the the optionality of the pointer does not affect usage of `Span`, since accesses are bounds-checked and the pointer is only dereferenced when the `Span` isn't empty, and the pointer cannot be `nil`. @@ -95,7 +97,7 @@ Like `UnsafeBufferPointer`, `Span` uses a simple offset-based indexing. The firs As a side-effect of not conforming to `Collection` or `Sequence`, `Span` is not directly supported by `for` loops at this time. It is, however, easy to use in a `for` loop via indexing: ```swift -for i in 0..Sendability of `RawSpan` + +This proposal makes `RawSpan` a `Sendable` type. We believe this is the right decision. The sendability of `RawSpan` could be used to unsafely transfer a pointer value across an isolation boundary, despite the non-sendability of pointers. For example, suppose a `RawSpan` were obtained from an existing `Array` variable. We could send the `RawSpan` across the isolation boundary, and there extract the pointer using `rawSpan.unsafeLoad(as: UnsafeRawPointer.self)`. While this is an unsafe outcome, a similar operation can be done encoding a pointer as an `Int`, and then using `UnsafeRawPointer(bitPattern: mySentInt)` on the other side of the isolation boundary. + ##### A more sophisticated approach to indexing This is discussed more fully in the [indexing appendix](#Indexing) below. @@ -444,7 +454,7 @@ This proposal includes some `_read` accessors, the coroutine version of the `get #### Extensions to Standard Library and Foundation types -The standard library and Foundation has a number of types that can in principle provide access to their internal storage as a `Span`. We could provide `withSpan()` and `withBytes()` closure-taking functions as safe replacements for the existing `withUnsafeBufferPointer()` and `withUnsafeBytes()` functions. We could also also provide lifetime-dependent `span` or `bytes` properties. For example, `Array` could be extended as follows: +The standard library and Foundation has a number of types that can in principle provide access to their internal storage as a `Span`. We could provide `withSpan()` and `withBytes()` closure-taking functions as safe replacements for the existing `withUnsafeBufferPointer()` and `withUnsafeBytes()` functions. We could also provide lifetime-dependent `span` or `bytes` properties. For example, `Array` could be extended as follows: ```swift extension Array { @@ -466,10 +476,6 @@ extension Array where Element: BitwiseCopyable { Of these, the closure-taking functions can be implemented now, but it is unclear whether they are desirable. The lifetime-dependent computed properties require lifetime annotations, as initializers do. We are deferring proposing these extensions until the lifetime annotations are proposed. -#### Index Validation Utilities - -This proposal originally included index validation utilities for `Span`. such as `boundsContain(_: Index) -> Bool` and `boundsContain(_: Range) -> Bool`. After review feedback, we believe that the utilities proposed would also be useful for index validation on `UnsafeBufferPointer`, `Array`, and other similar `RandomAccessCollection` types. `Range` already a single-element `contains(_: Bound) -> Bool` function which can be made even more efficient. We should add an additional function that identifies whether a `Range` contains the _endpoints_ of another `Range`. Note that this is not the same as the existing `contains(_: some Collection) -> Bool`, which is about the _elements_ of the collection. This semantic difference can lead to different results when examing empty `Range` instances. - #### A `ContiguousStorage` protocol An earlier version of this proposal proposed a `ContiguousStorage` protocol by which a type could indicate that it can provide a `Span`. `ContiguousStorage` would form a bridge between generically-typed interfaces and a performant concrete implementation. It would supersede the rejected [SE-0256](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0256-contiguous-collection.md). @@ -495,6 +501,10 @@ Two issues prevent us from proposing it at this time: (a) the ability to suppres Many of the standard library collections could conform to `ContiguousStorage`. +#### Index Validation Utilities + +This proposal originally included index validation utilities for `Span`. such as `boundsContain(_: Index) -> Bool` and `boundsContain(_: Range) -> Bool`. After review feedback, we believe that the utilities proposed would also be useful for index validation on `UnsafeBufferPointer`, `Array`, and other similar `RandomAccessCollection` types. `Range` already a single-element `contains(_: Bound) -> Bool` function which can be made even more efficient. We should add an additional function that identifies whether a `Range` contains the _endpoints_ of another `Range`. Note that this is not the same as the existing `contains(_: some Collection) -> Bool`, which is about the _elements_ of the collection. This semantic difference can lead to different results when examining empty `Range` instances. + #### Support for `Span` in `for` loops This proposal does not define an `IteratorProtocol` conformance, since an iterator for `Span` would need to be non-escapable. This is not compatible with `IteratorProtocol`. As such, `Span` is not directly usable in `for` loops as currently defined. A `BorrowingIterator` protocol for non-escapable and non-copyable containers must be defined, providing a `for` loop syntax where the element is borrowed through each iteration. Ultimately we should arrive at a way to iterate through borrowed elements from a borrowed view: From 2ea525f6fa27f96f712701b7dd2020b8d864be98 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 1 Apr 2025 14:14:37 -0700 Subject: [PATCH 201/505] SE-0446 is implemented. --- proposals/0446-non-escapable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0446-non-escapable.md b/proposals/0446-non-escapable.md index 854394b9cb..ab78724fd4 100644 --- a/proposals/0446-non-escapable.md +++ b/proposals/0446-non-escapable.md @@ -3,7 +3,7 @@ * Proposal: [SE-0446](0446-non-escapable.md) * Authors: [Andrew Trick](https://github.com/atrick), [Tim Kientzle](https://github.com/tbkka) * Review Manager: [Joe Groff](https://github.com/jckarter) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [BufferView Language Requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview) * Implementation: **Implemented** in `main` branch * Upcoming Feature Flag: `NonescapableTypes` From 5055d9a00facd435682db199a1bef3d5c8e72e1c Mon Sep 17 00:00:00 2001 From: Mykola Pokhylets Date: Wed, 2 Apr 2025 19:16:07 +0200 Subject: [PATCH 202/505] Proposal to unban weak let bindings --- proposals/NNNN-weak-let.md | 106 +++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 proposals/NNNN-weak-let.md diff --git a/proposals/NNNN-weak-let.md b/proposals/NNNN-weak-let.md new file mode 100644 index 0000000000..e91230bd47 --- /dev/null +++ b/proposals/NNNN-weak-let.md @@ -0,0 +1,106 @@ +# Feature name + +* Proposal: [SE-NNNN](NNNN-weak-let.md) +* Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) +* Review Manager: TBD +* Status: **Awaiting implementation** +* Implementation: [swiftlang/swift#80440](https://github.com/swiftlang/swift/pull/80440) +* Upcoming Feature Flag: `WeakLet` +* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) + +## Introduction + +Currently Swift requires weak stored variables to be mutable. +This restriction is rather artificial, and causes friction with sendability checking. + +## Motivation + +Currently swift classes with weak stored properties cannot be `Sendable`, +because weak properties have to be mutable, and mutable properties are +not allowed in `Sendable` classes. + +Similarly, closures with `weak` captures cannot be `@Sendable`, +because such captures are implicitly made mutable. + +Usually developers are not aware of this implicit mutability and have no intention to modify the captured variable. +Implicit mutability of weak captures is inconsistent with `unowned` or default captures. + +Wrapping weak reference into a single-field struct, allows stored properties and captures to be immutable. + +```swift +final class C: Sendable {} + +struct WeakRef { + weak var ref: C? +} + +final class User: Sendable { + weak let ref1: C? // error: 'weak' must be a mutable variable, because it may change at runtime + let ref2: WeakRef // ok +} + +func makeClosure() -> @Sendable () -> Void { + let c = C() + return { [weak c] in + c?.foo() // error: reference to captured var 'c' in concurrently-executing code + c = nil // nobody does this + } + return { [c = WeakRef(ref: c)] in + c.ref?.foo() // ok + } +} +``` + +Existence of this workaround shows that ban on `weak let` variables is artificial, and can be lifted. + +Note that resetting weak references on object destruction is different from regular variable modification. +Resetting on destruction is implemented in a thread-safe manner, and can safely coexist with concurrent reads or writes. +But regular writing to a variable requires exclusive access to that memory location. + +## Proposed solution + +Allow `weak let` declarations for local variables and stored properties. + +Proposal maintains status quo regarding use of `weak` on function arguments and computed properties: +* there is no valid syntax to indicate that function argument is a weak reference; +* `weak` on computed properties is allowed, but has not effect. + +Weak captures are immutable under this proposal. If mutable capture is desired, +mutable variable need to be explicit declared and captured. + +```swift +func makeClosure() -> @Sendable () -> Void { + let c = C() + // Closure is @Sendable + return { [weak c] in + c?.foo() + c = nil // error: cannot assign to value: 'c' is an immutable capture + } + + weak var explicitlyMutable: C? = c + // Closure cannot be @Sendable anymore + return { + explicitlyMutable?.foo() + explicitlyMutable = nil // but assigned is ok + } +} +``` + +## Source compatibility + +Allowing `weak let` bindings is a source-compatible change +that makes previously invalid code valid. + +Treating weak captures as immutable is a source-breaking change. +Any code that attempts to write to the capture will stop compiling. +The overall amount of such code is expected to be small. + +## ABI compatibility + +This is an ABI-compatible change. + +## Implications on adoption + +This feature can be freely adopted and un-adopted in source +code with no deployment constraints and without affecting source or ABI +compatibility. From fda62f8240e22a276d161a4d14c1480c3931c1ea Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 3 Apr 2025 12:41:10 +0100 Subject: [PATCH 203/505] Clean up wording and links in `visions/webassembly.md` --- visions/webassembly.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 3ae48a47af..6f5cac3344 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -14,7 +14,7 @@ Wasm modules. An application compiled to a Wasm module can run on any platform that has a Wasm runtime available. Despite its origins in the browser, it is a general-purpose technology that has use cases in client-side and server-side applications and services. WebAssembly support in Swift makes the language more appealing in those settings, and also brings it to the -browser where it previously wasn't available at all. It facilitates a broader adoption of Swift in more environments +browser where it previously wasn't available at all[^1]. It facilitates a broader adoption of Swift in more environments and contexts. The WebAssembly instruction set has useful properties from a security perspective, as it has no interrupts or @@ -42,7 +42,7 @@ In the last few years, the W3C WebAssembly Working Group considered multiple pro [type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined [Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on -[WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/preview2/README.md), which served as playground for +[WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/preview2/README.md), which served as playground for the new design. The Component Model defines these core concepts: @@ -83,7 +83,7 @@ overhead of new process setup and IPC infrastructure. ## Goals -As of March 2024 all patches necessary for basic Wasm and WASI Preview 1 support have been merged to the Swift +As of March 2024 all patches necessary for basic Wasm and WASI Preview 1 support have been merged to the Swift toolchain and core libraries. Based on this, we propose a high-level roadmap for WebAssembly support and adoption in the Swift ecosystem: @@ -126,13 +126,13 @@ engine is necessary for debugging. The current state of debugging tools in the Wasm ecosystem is not as mature as other platforms, but there are two main directions: -1. LLDB debugger with Wasm runtime supporting GDB Remote Serial Protocol [1] -2. Wasm runtime with a built-in debugger [2] +1. [LLDB debugger with Wasm runtime](https://github.com/llvm/llvm-project/pull/77949) supporting GDB Remote Serial Protocol; +2. [Wasm runtime with a built-in debugger](https://book.swiftwasm.org/getting-started/debugging.html#enhanced-dwarf-extension-for-swift). The first approach provides an almost equivalent experience to existing debugging workflows on other platforms. It can utilize LLDB's Swift support, remote metadata inspection, and serialized Swift module information. However, since Wasm is a Harvard architecture and has no way to allocate executable memory space at runtime, implementing expression -evaluation with JIT in user space is challenging. In other words, gdb stub in Wasm engines need tricky implementations +evaluation with JIT in user space is challenging. In other words, GDB stub in Wasm engines need tricky implementations or need to extend the GDB Remote Serial Protocol. The second approach embeds the debugger within the Wasm engine. In scenarios where the Wasm engine is embedded as a @@ -146,9 +146,6 @@ debuggers in some way. In summary, debugging in the browser and outside of the browser context are sufficiently different activities to require separate implementation approaches. -[1]: https://github.com/llvm/llvm-project/pull/77949 -[2]: https://github.com/ChromeDevTools/devtools-frontend/blob/main/extensions/cxx_debugging - ### Multi-threading and Concurrency WebAssembly has [atomic operations in the instruction set](https://github.com/WebAssembly/threads) (only sequential @@ -193,6 +190,7 @@ The latter approach cannot fully replace the former, as it is unable to handle d runtime, but it is more portable way to distribute programs linked with shared libraries, as it does not require the host environment to provide any special capabilities except for Component Model support. -Support for shared libraries in Swift for Wasm is mostly about making sure that Swift programs can be compiled in +Support for shared libraries in Swift means ensuring that Swift programs can be compiled in position-independent code mode and linked with shared libraries by following the corresponding dynamic linking ABI. +[^1]: We aim to address browser-specific use cases in a separate future document. From 726445345def1372b0dca0bc65cff7639a7a02b2 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 3 Apr 2025 15:42:36 +0100 Subject: [PATCH 204/505] Fix broken `wasip2` link in `webassembly.md` --- visions/webassembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visions/webassembly.md b/visions/webassembly.md index 6f5cac3344..95aa29f884 100644 --- a/visions/webassembly.md +++ b/visions/webassembly.md @@ -42,7 +42,7 @@ In the last few years, the W3C WebAssembly Working Group considered multiple pro [type system](https://github.com/webassembly/interface-types) and [module linking](https://github.com/webassembly/module-linking). These were later subsumed into a combined [Component Model](https://component-model.bytecodealliance.org) proposal thanks to the ongoing work on -[WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/preview2/README.md), which served as playground for +[WASI Preview 2](https://github.com/WebAssembly/WASI/blob/main/wasip2/README.md), which served as playground for the new design. The Component Model defines these core concepts: From 24d39d1c13908f98ac8054ece1e182bd965ddc32 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Sat, 5 Apr 2025 13:12:42 -0400 Subject: [PATCH 205/505] Accept SE-0468 (#2773) --- .../0468-async-stream-continuation-hashable-conformance.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0468-async-stream-continuation-hashable-conformance.md b/proposals/0468-async-stream-continuation-hashable-conformance.md index 00791b140f..e276c80235 100644 --- a/proposals/0468-async-stream-continuation-hashable-conformance.md +++ b/proposals/0468-async-stream-continuation-hashable-conformance.md @@ -3,9 +3,9 @@ * Proposal: [SE-0468](0468-async-stream-continuation-hashable-conformance.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active review (March 12...25, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift#79457](https://github.com/swiftlang/swift/pull/79457) -* Review: ([pitch](https://forums.swift.org/t/pitch-add-hashable-conformance-to-asyncstream-continuation/77897)) +* Review: ([pitch](https://forums.swift.org/t/pitch-add-hashable-conformance-to-asyncstream-continuation/77897)) ([review](https://forums.swift.org/t/se-0468-hashable-conformance-for-async-throwing-stream-continuation/78487)) ([acceptance](https://forums.swift.org/t/accepted-se-0468-hashable-conformance-for-async-throwing-stream-continuation/79116)) ## Introduction From 8991630f5a7d0a896bdadddb2b5b2f0db943e525 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Sat, 5 Apr 2025 13:22:14 -0400 Subject: [PATCH 206/505] Accept SE-0461 (#2774) * Accept SE-0461 * Fixup decision link --- proposals/0461-async-function-isolation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index 755fa646d0..f8712cde7d 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -3,12 +3,12 @@ * Proposal: [SE-0461](0461-async-function-isolation.md) * Authors: [Holly Borla](https://github.com/hborla), [John McCall](https://github.com/rjmccall) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (March 28...April 4, 2025)** +* Status: **Accepted with modifications** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` * Upcoming Feature Flag: `AsyncCallerExecution` * Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([first review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) ([acceptance with focused re-review](https://forums.swift.org/t/accepted-with-modifications-and-focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78920)) ([second review](https://forums.swift.org/t/focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78921)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([first review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) ([acceptance with focused re-review](https://forums.swift.org/t/accepted-with-modifications-and-focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78920)) ([second review](https://forums.swift.org/t/focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78921)) ([second acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0461-run-nonisolated-async-functions-on-the-caller-s-actor-by-default/79117)) ## Introduction From 6c9a5a0eba8f1bf34bd22cf18290a3603e3facfd Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 8 Apr 2025 12:59:01 -0700 Subject: [PATCH 207/505] [Pitch] `yielding` coroutine accessors (#2697) * [CoroutineAccessors] Pitch. * Revisions based on feedback from second pitch thread - Provide links to the accessors vision - Use the names `yielding borrow` and `yielding mutate` for the coroutine based accessors - Add discussion of when to favor these accessors over `get` and `set` under implications for adoption * update credits * Update and rename NNNN-yielding-accessors.md to 0474-yielding-accessors.md --------- Co-authored-by: Nate Chandler Co-authored-by: Stephen Canon --- proposals/0474-yielding-accessors.md | 668 +++++++++++++++++++++++++++ 1 file changed, 668 insertions(+) create mode 100644 proposals/0474-yielding-accessors.md diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md new file mode 100644 index 0000000000..d9fb323da2 --- /dev/null +++ b/proposals/0474-yielding-accessors.md @@ -0,0 +1,668 @@ +# Yielding accessors + +* Proposal: [SE-0474](0474-yielding-accessors.md) +* Authors: [Ben Cohen](https://github.com/airspeedswift), [Nate Chandler](https://github.com/nate-chandler), [Joe Groff](https://github.com/jckarter/) +* Review Manager: [Steve Canon](https://github.com/stephentyrone) +* Status: **Active Review (Apr 8...22)** +* Vision: [A Prospective Vision for Accessors in Swift](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) +* Implementation: Partially available on main behind the frontend flag `-enable-experimental-feature CoroutineAccessors` +* Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), (review) + +## Introduction + +We propose the introduction of two new accessors, `yielding mutate` and `yielding borrow`, for implementing computed properties and subscripts alongside the current `get` and `set`. + +By contrast with `get` and `set`, whose bodies behave like traditional methods, the body of a `yielding` accessor will be a coroutine, using a new contextual keyword `yield` to pause the coroutine and lend access of a value to the caller. +When the caller ends its access to the lent value, the coroutine's execution will continue after `yield`. + +These `yielding` accessors enable values to be accessed and modified without requiring a copy. +This is essential for noncopyable types and often desirable for performance even with copyable types. + +This feature has been available (but not supported) since Swift 5.0 via the `_modify` and `_read` keywords. +Additionally, the feature is available via `read` and `modify` on recent builds from the compiler's `main` branch using the flag `-enable-experimental-feature CoroutineAccessors`. + +## Motivation + +### `yielding mutate` + +Swift's `get`/`set` syntax allows users to expose computed properties and subscripts that behave as l-values. +This powerful feature allows for the creation of succinct idiomatic APIs, such as this use of `Dictionary`'s defaulting subscript: + +```swift +var wordFrequencies: [String:Int] = [:] +wordFrequencies["swift", default: 0] += 1 +// wordFrequencies == ["swift":1] +``` + +While this provides the illusion of "in-place" mutation, it actually involves three separate operations: +1. a `get` of a copy of the value +2. the mutation, performed on that returned value +3. finally, a `set` replacing the original value with the mutated temporary value. + +This can be seen by performing side effects inside of the getter and setter; for example: + +```swift +struct GetSet { + var x: String = "👋🏽 Hello" + + var property: String { + get { print("Getting",x); return x } + set { print("Setting",newValue); x = newValue } + } +} + +var getSet = GetSet() +getSet.property.append(", 🌍!") +// prints: +// Getting 👋🏽 Hello +// Setting 👋🏽 Hello, 🌍! +``` + +#### Performance + +When the property or subscript is of copyable type, this simulation of in-place mutation works well for user ergonomics but has a major performance shortcoming, which can be seen even in our simple `GetSet` type above. +Strings in Swift aren't bitwise-copyable types; once they grow beyond a small fixed size, they allocate a reference-counted buffer to hold their contents. +Mutation is handled via the copy-on-write technique: +When you make a copy of a string, only the reference to the buffer is copied, not the buffer itself. +Then, when either copy of the string is mutated, the mutation operation checks if the buffer is uniquely referenced. +If it isn't (because the string has been copied), it first duplicates the buffer before mutating it, preserving the value semantics of `String` while avoiding unnecessary eager copies. + +Given this, we can see a performance problem when appending to `GetSet.property` in our example above: + +- `GetSet.property { get }` is called and returns a copy of `x`. +- Because a copy is returned, the buffer backing the string is no longer uniquely referenced. +- The append operation must therefore duplicate the buffer before mutating it. +- `GetSet.property { set }` writes this copy back over the top of `x`, destroying the original string. +- The original buffer's reference count drops to zero, and it's destroyed too. + +So, despite looking like in-place mutation, every mutating operation on `x` made through `property` is actually causing a full copy of `x`'s backing buffer. +This is a linear-time operation. +If we appended to this property in a loop, that loop would end up being quadratic in complexity. +This is likely very surprising to the developer and is a frequent performance pitfall. + +[An accessor](#design-modify) which _lends_ a value to the caller in place, without producing a temporary copy, is desirable to avoid this quadratic time complexity while preserving Swift's ability for computed properties to provide expressive and ergonomic APIs. + +#### Non-`Copyable` types + +When the value being mutated is noncopyable, the common `get`/`set` pattern often becomes impossible to implement: +the very first step of mutation makes a copy! +Thus, `get` and `set` can't be used to wrap access to a noncopyable value: + +```swift +struct UniqueString : ~Copyable {...} + +struct UniqueGetSet : ~Copyable { + var x: UniqueString + + var property: UniqueString { + get { // error: 'self' is borrowed and cannot be consumed + x + } + set { x = newValue } + } +} +``` + +`get` borrows `self` but then tries to _give_ ownership of `x` to its caller. Since `self` is only borrowed, it cannot give up ownership of its `x` value, and since `UniqueString` is not `Copyable`, `x` cannot be copied either, making `get` impossible to implement. +Therefore, to provide computed properties on noncopyable types with comparable expressivity, we again need [an accessor](#design-modify) that borrows `self` and _lends_ access to `x` to its caller without implying independent ownership. + +### `yielding borrow` + +For properties and subscripts of noncopyable type, the current official accessors are insufficient not only for mutating, but even for _inspecting_. +Even if we remove `set` from our `UniqueGetSet` type above, we still hit the same error in its getter: + +```swift +struct UniqueString : ~Copyable {...} + +struct UniqueGet : ~Copyable { + var x: UniqueString + + var property: UniqueString { + get { // error: 'self' is borrowed and cannot be consumed + return x + } + } +} +``` + +As discussed above, `UniqueGet.property { get }` borrows `self` but attempts to transfer ownership of `self.x` to the caller, which is impossible. + +This particular error could be addressed by marking the getter `consuming`: + +```swift +struct UniqueString : ~Copyable {...} + +struct UniqueConsumingGet : ~Copyable { + var x: UniqueString + + var property: UniqueString { + consuming get { + return x + } + } +} +``` + +This allows the getter to take ownership of the `UniqueConsumingGet`, +allowing it to destructively extract `x` and transfer ownership to the caller. +Here's how that looks in the caller: + +```swift +let container = UniqueConsumingGet() +let x = container.property // consumes container! +// container is no longer valid +``` + +This might sometimes be desirable, but for many typical uses of properties and subscripts, it is not. If a container holds a number of noncopyable fields, it should be possible to inspect each field in turn, but doing so wouldn't be possible if inspecting one consumes the container. + +Similar to the mutating case, what's needed here is [an accessor](#design-read) which _borrows_ `self` and which _lends_ `x`--this time immutably--to the caller. + +## Proposed solution + +We propose two new accessor kinds: +- `yielding mutate`, to enable mutating a value without first copying it +- `yielding borrow`, to enable inspecting a value without copying it. + +## Detailed design + +### `yielding borrow` + +[`UniqueGet`](#read-motivation) can now allow its clients to inspect its field non-destructively with `yielding borrow`: + +```swift +struct UniqueString : ~Copyable {...} + +struct UniqueBorrow : ~Copyable { + var x: UniqueString + + var property: UniqueString { + yielding borrow { + yield x + } + } +} +``` + +The `UniqueBorrow.property { yielding borrow }` accessor is a "yield-once coroutine". +When called, it borrows `self`, and then runs until reaching a `yield`, at which point it suspends, lending the yielded value back to the caller. +Once the caller is finished accessing the value, it resumes the accessor's execution. +The accessor continues running where it left off after the `yield`. + +If a a property or subscript provides a `yielding borrow`, it cannot also provide a `get`. + +#### `yielding borrow` as a protocol requirement + +Such accessors should be usable on values of generic and existential type. +To indicate that a protocol provides immutable access to a property or subscript via a `yielding borrow` coroutine, we propose allowing `yielding borrow` to appear where `get` does today: + +```swift +protocol Containing { + var property: UniqueString { yielding borrow } +} +``` + +A protocol requirement cannot specify both `yielding borrow` and `get`. + +A `yielding borrow` requirement can be witnessed by a stored property, a `yielding borrow` accessor, or a getter. + +#### `get` of noncopyable type as a protocol requirement + +Property and subscript requirements in protocols have up to this point only been able to express readability in terms of `get` requirements. +This becomes insufficient when the requirement has a noncopyable type: + +```swift +protocol Producing { + var property: UniqueString { get } +} +``` + +To fulfill such a requirement, the conformance must provide a getter, meaning its implementation must be able to produce a value whose ownership can be transferred to the caller. +In practical terms, this means that the requirement cannot be witnessed by a stored property or a `yielding borrow` accessor when the result is of noncopyable type,[^2] since the storage of a stored property is owned by the containing aggregate and the result of a `yielding borrow` is owned by the suspended coroutine, and it would be necessary to copy to provide ownership to the caller. +However, if the type of the `get` requirement is copyable, the compiler can synthesize the getter from the other accessor kinds by introducing copies as necessary. + +[^2]: While the compiler does currently accept such code currently, it does so by interpreting that `get` as a `yielding borrow`, which is a bug. + +### `yielding mutate` + +The `GetSet` type [above](#modify-motivation) could be implemented with `yielding mutate` as follows: + +```swift +struct GetMutate { + var x: String = "👋🏽 Hello" + + var property: String { + get { print("Getting", x); return x } + yielding mutate { + print("Yielding", x) + yield &x + print("Post yield", x) + } + } +} + +var getMutate = GetMutate() +getMutate.property.append(", 🌍!") +// prints: +// Yielding 👋🏽 Hello +// Post yield 👋🏽 Hello, 🌍! +``` + +Like `UniqueBorrow.property { yielding borrow }` above, `GetMutate.property { yielding mutate }` is a yield-once coroutine. +However, the `yielding mutate` accessor lends `x` to the caller _mutably_. + +Things to note about this example: +* `get` is never called — the property access is handled entirely by the `yielding mutate` accessor +* the `yield` is similar to a `return`, but control returns to the `yielding mutate` after the `append` completes +* there is no more `newValue` – the yielded value is modified by `append` +* because it's granting _mutable_ access to the caller, `yield` uses the `&` sigil, similar to passing an argument `inout` + +Unlike the `get`/`set` pair, the `yielding mutate` accessor is able to safely provide access to the yielded value without copying it. +This can be done safely because the accessor preserves ownership of the value until it has completely finished running: +When it yields the value, it only lends it to the caller. +The caller is exclusively borrowing the value yielded by the coroutine. + +`get` is still used when only fetching, not modifying, the property: + +```swift +_ = getMutate.property +// prints: +// Getting 👋🏽 Hello, 🌍! +``` + +`yielding mutate` is sufficient to allow assignment to a property: + +``` +getMutate.property = "Hi, 🌍, 'sup?" +// prints: +// Yielding 👋🏽 Hello, 🌍! +// Post yield Hi, 🌍, 'sup? +``` + +It is, however, also possible to supply _both_ a `yielding mutate` and a `set` accessor. +The `set` accessor will be favored in the case of a whole-value reassignment, which may be more efficient than preparing and yielding a value to be overwritten: + +```swift +struct GetSetMutate { + var x: String = "👋🏽 Hello" + + var property: String { + get { x } + yielding mutate { yield &x } + set { print("Setting",newValue); x = newValue } + } +} +var getSetMutate = GetSetMutate() +getSetMutate.property = "Hi 🌍, 'sup?" +// prints: +// Setting Hi 🌍, 'sup? +``` + +#### Pre- and post-processing in `yielding mutate` + +As with `set`, `yielding mutate` gives the property or subscript implementation an opportunity to perform some post-processing on the new value after assignment. Even in these cases, `yielding mutate` can often allow for a more efficient implementation than a traditional `get`/`set` pair would provide. +Consider the following implementation of an enhanced version of `Array.first` that allows the user to modify the first value of the array: + +```swift +extension Array { + var first: Element? { + get { isEmpty ? nil : self[0] } + yielding mutate { + var tmp: Optional + if isEmpty { + tmp = nil + yield &tmp + if let newValue = tmp { + self.append(newValue) + } + } else { + tmp = self[0] + yield &tmp + if let newValue = tmp { + self[0] = newValue + } else { + self.removeFirst() + } + } + } + } +} +``` + +This implementation takes a similar approach to `Swift.Dictionary`'s key-based subscript: +if there is no `first` element, the accessor appends one. +If `nil` is assigned, the element is removed. +Otherwise, the element is updated to the value from the assigned `Optional`'s payload. + +Because the fetch and update code are all contained in one block, the `isEmpty` check is not duplicated; if the same logic were implemented with a `get`/`set` pair, `isEmpty` would need to be checked independently in both accessors. With `yielding mutate`, whether the array was initially empty is part of the accessor's state, which remains present until the accessor is resumed and completed. + +#### Taking advantage of exclusive access + +The optional return value of `first` in the code above means that, despite using `yielding mutate`, we have reintroduced the problem of triggering copy-on-write when mutating through the `first` property. +That act of placing the value in the array inside of an `Optional` (namely, `tmp = self[0]`) creates a copy. + +Like a `set` accessor, a `yielding mutate` accessor in a `struct` or `enum` property is `mutating` by default (unless explicitly declared a `nonmutating yielding mutate`). +This means that the `yielding mutate` accessor has exclusive access to `self`, and that exclusive access extends for the duration of the accessor's execution, including its suspension after `yield`-ing. +Since the implementation of `Array.first { yielding mutate }` has exclusive access to its underlying buffer, it can move the value of `self[0]` directly into the `Optional`, yield it, and then move the result back after being resumed: + +```swift +extension Array { + var first: Element? { + yielding mutate { + var tmp: Optional + if isEmpty { + // Unchanged + } else { + // Illustrative code only, Array's real internals are fiddlier. + // _storage is an UnsafeMutablePointer to the Array's storage. + + // Move first element in _storage into a temporary, leaving that slot + // in the storage buffer as uninintialized memory. + tmp = _storage.move() + + // Yield that moved value to the caller + yield &tmp + + // Once the caller returns, restore the array to a valid state + if let newValue = tmp { + // Re-initialize the storage slot with the modified value + _storage.initialize(to: newValue) + } else { + // Element removed. Slide other elements down on top of the + // uninitialized first slot: + _storage.moveInitialize(from: _storage + 1, count: self.count - 1) + self.count -= 1 + } + } + } +} +``` + +While the `yielding mutate` coroutine is suspended after yielding, the `Array` is left in an invalid state: the memory location where the first element is stored is left uninitialized, and must not be accessed. +However, this is safe thanks to Swift's rules preventing conflicting access to memory. +Unlike a `get`, the `yielding mutate` is guaranteed to have an opportunity to put the element back (or to remove the invalid memory if the entry is set to `nil`) after the caller resumes it, restoring the array to a valid state in all circumstances before any other code can access it. + +### The "yield once" rule + +Notice that there are _two_ yields in this `Array.first { yielding mutate }` implementation, for the empty and non-empty branches. +Nonetheless, exactly one `yield` is executed on any path through the accessor. +In general, the rules for yields in yield-once coroutines are similar to those of deferred initialization of `let` variables: +it must be possible for the compiler to guarantee there is exactly one yield on every path. +In other words, there must not be a path through the yield-once coroutine's body with either zero[^1] or more than one yield. +The `Array.first` example is valid since there is a `yield` in both the `if` and the `else` branch. +In cases where the compiler cannot statically guarantee this, refactoring or use of `fatalError()` to assert unreachable code paths may be necessary. + +[^1]: Note that it is legal for a path without any yields to terminate in a `fatalError`. Such a path is not _through_ the function. + +### Throwing callers + +The `Array.first { yielding mutate }` implementation above is correct even if the caller throws while the coroutine is suspended. + +```swift +try? myArray.first?.throwingMutatingOp() +``` + +Thanks to Swift's rule that `inout` arguments be initialized at function exit, the element must be a valid value when `throwingMutatingOp` throws. +When `throwingMutatingOp` does throw, control returns back to the caller. +The body of `Array.first { yielding mutate }` is resumed, and `tmp` is a valid value. +Then the code after the `yield` executes. +The coroutine cleans up as usual, writing the updated temporary value in `tmp` back into the storage buffer. + +## Source compatibility + +The following code is legal today: + +```swift +func borrow(_ c : () -> T) -> T { c() } +var reader : Int { + borrow { + fatalError() + } +} +``` + +Currently, the code declares a property `reader` with an implicit getter. +The implicit getter has an implicit return. +The expression implicitly returned is a call to the function `borrow` with a trailing closure. + +An analogous situation exists for `mutate`. + +This proposal takes the identifiers `borrow` and `mutate` as contextual keywords +as part of the `yielding borrow` and `yielding mutate` accessor declarations. +By themselves, these two new accessor forms do not immediately require a source break; however, as the [accessors vision](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) lays out, we will more than likely want to introduce non-`yielding` variants of `borrow` and `mutate` in the near future as well. + +Therefore, we propose an alternate interpretation for this code: +that it declare a property `reader` with a `borrow` accessor. +Although such an accessor does not yet exist, making the syntax change now will prepare the language for subsequent accessors we introduce in the near future. + +If this presents an unacceptable source compatibility break, the change may have to be gated on a language version. + +## ABI compatibility + +Adding a `yielding mutate` accessor to an existing read-only subscript or computed property has the same ABI implications as adding a setter; it must be guarded by availability on ABI-stable platforms. +The stable ABI for mutable properties and subscripts provides `get`, `set`, and `_modify` coroutines, deriving `set` from `_modify` or vice versa if one is not explicitly implemented. +Therefore, adding or removing `yielding mutate`, adding or removing `set`, replacing a `set` with a `yielding mutate`, or replacing `yielding mutate` with `set` are all ABI-compatible changes, so long as the property or subscript keeps at least one of `set` or `yielding mutate`, and those accessors agree on whether they are `mutating` or `nonmutating` on `self`. + +By contrast, `yielding borrow` and `get` are mutually exclusive. Replacing one with the other is always an ABI-breaking change. +Replacing `get` with `yielding borrow` is also an API-breaking change for properties or subscripts of noncopyable type. + +Renaming the current `_modify` (as used by the standard library, e.g.) to `yielding mutate` is an ABI additive change: a new `yielding mutate` symbol will be added. +When the compiler sees a `yielding mutate` with an early enough availability, the compiler will synthesize a corresponding `_modify` whose body will just forward to `yielding mutate`. +This is required for ABI stability: code compiled against an older standard library which calls `_modify` will continue to do so. +Meanwhile, code compiled against a newer standard library will call the new `yielding mutate`. +The same applies to renaming `_read` to `yielding borrow`. + +## Implications on adoption + +### Runtime support + +The new ABI will require runtime support which would need to be back deployed in order to be used on older deployment targets. + +### When to favor coroutines over `get` and `set` + +Developers will need to understand when to take advantage of `yielding` accessors, and we should provide some guidance: + +#### `yielding mutate` + +`yielding mutate` is desirable when the value of a property or subscript element is likely to be subject to frequent in-place modifications, especially when the value's type uses copy-on-write and the temporary value created by a `get`-update-`set` sequence is likely to trigger full copies of the buffer that could otherwise be avoided. +Additionally, if the mutation operation involves complex setup and teardown that requires persisting state across the operation, `yielding mutate` allows for arbitrary state to be preserved across the access. + +For noncopyable types, implementing `yielding mutate` is necessary to provide in-place mutation support if the value of the property or subscript cannot be read using a `get`. + +Even in cases where `yielding mutate` is beneficial, it is often still profitable to also provide a `set` accessor for whole-value reassignment. `set` may be able to avoid setup necessary to support an arbitrary in-place mutation and can execute as a standard function call, which may be more efficient than a coroutine. + +#### `yielding borrow` + +For read-only operations on `Copyable` types, the performance tradeoffs between `get` and `yielding borrow` are more subtle. +`borrowing yield` can avoid copying a result value that is stored as part of the originating value. +On the other hand, `get` can execute as a normal function without the overhead of a coroutine. +(As part of the implementation work for this proposal, we are implementing a more efficient coroutine ABI that should be significantly faster than the implementation used by `_read` and `_modify` today; however, a plain function call is likely to remain somewhat faster.) +`yielding borrow` may nonetheless be preferable for providing access to large value types in memory that would be expensive to copy as part of returning from a `get`. + +`yielding borrow` also introduces the ability to perform both setup work before and teardown work after the caller has accessed the value, whereas `get` can at best perform setup work before returning control to the caller. +Particularly in conjunction with non-`Escapable` types, which could eventually be lifetime-bound to their access, a `yielding borrow` accessor producing a non-`Escapable` value could provide limited access to a resource in a similar manner to `withSomething { }` closure-based APIs, without the "pyramid of doom" or scoping limitations of closure-based APIs. + +For properties and subscripts with noncopyable types, the choice between `yielding borrow` and `get` will often be forced by whether the API contract specifies a borrowed or owned result. +An operation that provides temporary borrowed access to a component of an existing value without transferring ownership, when that value is expected to persist after the access is complete, must be implemented using `yielding borrow`. +An operation that computes a new value every time is best implemented using `get`. +(Such an operation can in principle also be implemented using `yielding borrow`; it would compute the temporary value, yield a borrow to the caller, and then destroy the temporary value when the coroutine is resumed. +This would be inefficient, and would furthermore prevent the caller from being able to perform consuming operations on the result.) + +For polymorphic interfaces such as protocol requirements and overridable class members that are properties or subscripts of noncopyable type, the most general requirement is `yielding borrow`, since a `yielding borrow` requirement can be satisfied by either a `yielding borrow` or a `get` implementation (in the latter case, by wrapping the getter in a synthesized `yielding borrow` that invokes the getter, yields a borrow the result, then destroys the value on resume). +Using `yielding borrow` in polymorphic or ABI-stable interfaces may thus desirable to allow for maximum evolution flexibility if being able to consume the result is never expected to be part of the API contract. + +## Future directions + +### Yield-once functions + +Further ergonomic enhancements to the language may be needed over time to make the most of this feature. +For example, coroutine accessors do not compose well with functions because functions cannot themselves currently yield values. +In the future, it may be desirable to also support yield-once functions: + +```swift +var value: C { yielding mutate { ... } } +yielding func updateValue(...) -> inout C { + yield &self.value + additionalWork(value) +} +``` + +### Forwarding both consuming and borrowing accesses to the same declaration + +When a property or subscript has a `consuming get`, a caller can take ownership of the field at the expense of also destroying the rest of object. +When a property or subscript has a `yielding borrow` accessor, a caller can borrow the field to inspect it without taking ownership of it. + +As proposed here, it's not yet possible for a single field to provide both of these behaviors to different callers. +Since both of these behaviors have their uses, and many interfaces want to provide "perfect forwarding" where any of consuming, mutating, or borrowing operations on a wrapper can be performed by passing through the same operation to an underlying value, it may be desirable in the future to allow a single field to provide both a `yielding borrow` and a `consuming get`: + +```swift +subscript(index: Int) -> Value { + consuming get {...} + yielding borrow {...} +} +``` + +The rules that Swift currently uses to determine what accessor(s) to use in order to evaluate an expression are currently only defined in terms of whether the access is mutable or not, so these rules would need further elaboration to distinguish non-mutating accesses by whether they are consuming or borrowing in order to determine which accessor to favor. + +### Transitioning between owned and borrowed accessors for API evolution + +When a noncopyable API first comes into existence, its authors may not want to commit to it producing an owned value. As discussed [above](#read-implications), providing a `yielding borrow` accessor is often the most conservative API choice for noncopyable properties and subscripts: + +```swift +subscript(index: Int) -> Value { + yielding borrow {...} +} +``` + +As their module matures, however, the authors may decide that committing to providing a consumable value is worthwhile. +To support this use-case, in the future, it may be desirable to allow for forward-compatible API and ABI evolution by promoting a `yielding borrow` accessor to `get`: + +```swift +subscript(index: Int) -> Value { + // Deprecate the `yielding borrow` + @available(*, deprecated) + yielding borrow {...} + + // Favor the `get` for new code + get {...} +} +``` + + +That would enable the module to evolve to a greater commitment while preserving ABI. + +For APIs of copyable type, the reverse evolution is also a possibility; an API could originally be published using a `get` and later decide that a `yielding borrow` accessor is overall more efficient. + +Since it would typically be ambiguous whether the `yielding borrow` or `get` should be favored at a use site, it would make sense to require that one or the other accessor be deprecated or have earlier availability than the other in order to show that one is unambiguously preferred over the other for newly compiled code with recent enough availability. + +### Non-`yielding` `borrow` and `mutate` accessors + +A `yielding` accessor lends the value it yields to its caller. +The caller only has access to that value until it resumes the coroutine. +After the coroutine is resumed, it has the opportunity to clean up. +This enables a `yielding borrow` or `mutate` to do interesting work such as constructing aggregates from its base object's fields: + +```swift +struct Pair : ~Copyable { + var left: Left + var right: Right + + var reversed: Pair { + yielding borrow { + let result = Pair(left: right, right: left) + yield result + self = .init(left: result.right, right: result.left) + } + } +} +``` + +That the borrow ends when the coroutine is resumed means that the lifetime of the lent value is strictly shorter than that of the base value. +In the example above, the lifetime of `reversed` is shorter than that of the `Pair` it is called on. + +As discussed in the [accessors vision](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md), when a value is merely being projected from the base object and does not need any cleanup after being accessed, this is undesirably limiting: +a value projected from a base naturally has _the same_ lifetime as the base. + +This is especially problematic in the context of composition with non-`Escapable` types. +Consider the following wrapper type[^3]: + +[^3]: This example involves writing out a `yielding borrow` accessor. The same issue exists when the compiler synthesizes a `yielding borrow` accessor for a stored property exported from a resilient module. + +```swift +struct Wrapper : ~Copyable & ~Escapable { + var _stuffing: Stuffing + + var stuffing: Stuffing { + yielding borrow { + yield _stuffing + } + } +} +``` + +When the instance of `Wrapper` is local to a function, the strict nesting of lifetimes may not immediately be a problem: + +```swift +{ + let wrapper: Wrapper = ... + borrowStuffing(wrapper.stuffing) + // lifetime of wrapper.stuffing ends (at coroutine resumption) + // lifetime of wrapper ends +} +``` + +But when `Wrapper` is a parameter, or otherwise nonlocal to the function, it is natural to expect to return the `Stuffing` back to the source of the `Wrapper`, but the `yielding borrow` accessor artificially limits its lifetime: + +```swift +@lifetime(borrow wrapper) +func getStuffing(from wrapper: borrowing Wrapper) -> Stuffing { + return wrapper.stuffing // error +} +``` + +The issue is that the lifetime of `stuffing` ends _within_ `getStuffing`, when the `yielding borrow` coroutine is resumed, which prevents `stuffing` from being returned. + +To address use cases like this, in the future, it may be desirable to introduce a variant of `borrow` and `mutate` accessors that immediately `return`s the borrowed or mutable value without involving a coroutine: + +```swift +var stuffing: Stuffing { + borrow { + return _stuffing + } +} +``` + +A non-`yielding` `borrow` or `mutate` accessor would be limited to returning values that can be accessed immediately and which do not require any cleanup (implicit or explicit) when the access ends. As such, the `yielding` variants would still provide the most flexibility in implementation, at the cost of the additional lifetime constraint of the coroutine. Similar to the [discussion around evolving `yielding borrow` accessors into `get` accessors](#ownership-evolution), there is also likely to be a need to allow for APIs initially published in terms of `yielding` accessors to transition to their corresponding non-`yielding` accessors in order to trade stronger implementation guarantees for more flexibility in the lifetime of derived `~Escapable` values. + +## Alternatives considered + +### Unwinding the accessor when an error is thrown in the caller + +A previous version of this proposal specified that if an error is thrown in a coroutine caller while a coroutine is suspended, the coroutine is to "unwind" and the code after the `yield` is not to run. +In the [example above](#throwing-callers), the code after the `yield` would not run if `throwingMutatingOp` threw an error. + +This approach was tied up with the idea that a `yielding mutate` accessor might clean up differently if an error was thrown in the caller. +The intervening years of experience with the feature have not borne out the need for this. +If an error is thrown in a caller into which a value has been yielded, the _caller_ must put the yielded mutable value back into a consistent state. +As with `inout` function arguments, the compiler enforces this: +it is an error to consume the value yielded from a `yielding mutate` accessor without reinitializing it before resuming the `yielding mutate` accessor. +When there are higher-level invariants which the value being modified must satisfy, in general, only the caller will be in a position to ensure that they are satisfied on the throwing path. + +Once that basis has been removed, there is no longer a reason to enable a coroutine to "unwind" when an error was thrown in the caller. +It should always finish execution the same way. + +### Naming scheme + +These coroutine accessors have been a long-standing "unofficial" feature of the Swift compiler under the names `_read` and `_modify`. +Previous revisions of this proposal merely dropped the underscore and proposed the coroutine accessors be provided under the name `read` and `modify`. +However, as we have continued to build out Swift's support for ownership and lifetime dependencies with `~Copyable` and `~Escapable` types, we have since identified the need for non-coroutine accessors that can produce borrowed and/or mutable values without imposing a lifetime dependency on a coroutine access. + +In order to avoid a proliferation of unrelated-seeming accessor names, this revision of the proposal uses the name `yielding borrow` instead of `read` and `yielding mutate` instead of `modify`. +We feel these names better connect the accessors to what ownership of the result is given: +a `borrow` accessor gives `borrowing` access to its result, and a `mutate` accessor gives `mutating` (in other words, `inout`) access. +Using `yielding` as an added modifier relates these accessors to potential non-coroutine variants of the accessors that could exist in the future; a `borrow` accessor (without `yielding`) would in the future be an accessor that returns a borrow without involving a coroutine. +The same `yielding` modifier could also be used in other places in the future, such as `func` declarations, to allow for yield-once coroutines to be defined as regular functions outside of accessors. + +## Acknowledgments + +John McCall and Arnold Schwaighofer provided much of the original implementation of accessor coroutines. Tim Kientzle and John McCall authored the accessors vision document this proposal serves as part of the implementation of. + From badc7558e01ee2f43f247043504a4a792b5723e0 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Tue, 8 Apr 2025 16:06:15 -0400 Subject: [PATCH 208/505] Update 0474-yielding-accessors.md (#2778) Add link back to forums review. --- proposals/0474-yielding-accessors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index d9fb323da2..2e9f24d22d 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -6,7 +6,7 @@ * Status: **Active Review (Apr 8...22)** * Vision: [A Prospective Vision for Accessors in Swift](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) * Implementation: Partially available on main behind the frontend flag `-enable-experimental-feature CoroutineAccessors` -* Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), (review) +* Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), ([review](https://forums.swift.org/t/se-0474-yielding-accessors/79170)) ## Introduction From e2b1b4d4ee4a9585a280e4ba434aface11f205ea Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 8 Apr 2025 13:08:39 -0700 Subject: [PATCH 209/505] [SE-0470] Reinstate sendable-metatype model for type checking generics (#2763) * [SE-0470] Reinstate sendable-metatype model for type checking generics Based on discussions in the review thread, reinstate the sendable-metatype model for type checking generic definitions rather than the potentially-isolated-conformance model. While slightly less expressive, the sendable-metatype model is easier to reason about and teach. It's still possible to generalize the model toward the potentially-isolated-conformance model, as is already captured in Future Directions. * [SE-0470] Tighten up requirements within generic functions Close a potential data race with my attempt to loosen the rules. In essence, if we're allowed to pass a metatype `T.Type` across isolation boundaries when there are no constraints of the form `T: P`, then we will incorrectly allow a dynamic cast `as? any T & P` to bind to an isolated conformance (because `T` is not `SendableMetatype`). --- proposals/0470-isolated-conformances.md | 50 ++++++++++++++----------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index 91c87b8b53..0809817d2d 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -82,7 +82,7 @@ This is effectively saying that `MyModelType` will only ever be considered `Equa ## Proposed solution -This proposal introduces the notion of an *isolated conformance*. Isolated conformances are conformances whose use is restricted to a particular global actor. This is the same effective restriction as the `nonisolated`/`assumeIsolated` pattern above, but enforced statically by the compiler and without any boilerplate. The following defines an isolated conformance of `MyModelType` to `Equatable`: +This proposal introduces the notion of an *isolated conformance*. Isolated conformances are conformances whose use is restricted to a particular global actor. This is the same effective restriction as the `nonisolated`/`assumeIsolated` pattern above, but enforced statically by the compiler and without any boilerplate. The following defines a main-actor-isolated conformance of `MyModelType` to `Equatable`: ```swift @MainActor @@ -144,10 +144,10 @@ func hasNamed(_: T.Type, name: String) async -> Bool { } ``` -Here, the type `T` itself is not `Sendable`, but because *all* metatypes are `Sendable` it is considered safe to use `T` from another isolation domain within the generic function. The use of `T`'s conformance to `GlobalLookup` within that other isolation domain introduces a data-race problem if the conformance were isolated. To prevent such problems in generic code, this proposal treats conformances within generic code as if they are isolated *unless* the conforming type opts in to being sendable. The above code, which is accepted in Swift 6 today, would be rejected by the proposed changes here with an error message like: +Here, the type `T` itself is not `Sendable`, but because *all* metatypes are `Sendable` it is considered safe to use `T` from another isolation domain within the generic function. The use of `T`'s conformance to `GlobalLookup` within that other isolation domain introduces a data-race problem if the conformance were isolated. To prevent such problems in generic code, this proposal introduces a notion of *non-sendable metatypes*. Specifically, if a type parameter `T` does not conform to either `Sendable` or to a new protocol, `SendableMetatype`, then its metatype, `T.Type`, is not considered `Sendable` and cannot cross isolation boundaries. The above code, which is accepted in Swift 6 today, would be rejected by the proposed changes here with an error message like: ```swift -error: cannot use potentially-isolated conformance of non-sendable type `T` to `GlobalLookup` in 'sending' closure +error: cannot capture non-sendable type 'T.Type' in 'sending' closure ``` A function like `hasNamed` can indicate that its type parameter `T`'s requires non-isolated conformance by introducing a requirement `T: SendableMetatype`, e.g., @@ -379,7 +379,7 @@ actor MyActor: @MainActor P { } ``` -### Rule 2: Isolated conformances can only be abstracted away for non-`Sendable` types +### Rule 2: Isolated conformances can only be abstracted away for non-`SendableMetatype` types Rule (2) ensures that when information about an isolated conformance is abstracted away by the generics system, the conformance cannot leave its original isolation domain. This requires a way to determine when a given generic function is permitted to pass a conformance it receives across isolation domains. Consider the example above where a generic function uses one of its conformances in different isolation domain: @@ -406,20 +406,20 @@ The above code must be rejected to prevent a data race. There are two options fo 1. Reject the definition of `callQGElsewhere` because it is using the conformance from a different isolation domain. 2. Reject the call to `callQGElsewhere` because it does not support isolated conformances. -This proposal takes option (1): we assume that generic code accepts isolated conformances unless it has indicated otherwise with a `Sendable` constraint (more information on that below). Since most generic code doesn't deal with concurrency at all, it will be unaffected. And generic code that does make use of concurrency should already have `Sendable` constraints that indicate that it will not work with isolated conformances. +This proposal takes option (1): we assume that generic code accepts isolated conformances unless it has indicated otherwise with a `SendableMetatype` constraint. Since most generic code doesn't deal with concurrency at all, it will be unaffected. And generic code that does make use of concurrency should already have `Sendable` constraints (which imply `SendableMetatype` constraints) that indicate that it will not work with isolated conformances. -The specific requirement for option (1) is enforced both in the caller to a generic function and in the implementation of that function. The caller can use an isolated conformance to satisfy a conformance requirement `T: P` so long as the generic function does not also contain a requirement `T: Sendable`. This prevents isolated conformances to be used in conjunction with types that can cross isolation domains, preventing the data race from being introduced at the call site. Here are some examples of this rule: +The specific requirement for option (1) is enforced both in the caller to a generic function and in the implementation of that function. The caller can use an isolated conformance to satisfy a conformance requirement `T: P` so long as the generic function does not also contain a requirement `T: SendableMetatype`. This prevents isolated conformances to be used in conjunction with types that can cross isolation domains, preventing the data race from being introduced at the call site. Here are some examples of this rule: ```swift -func acceptsSendableP(_ value: T) { } +func acceptsSendableMetatypeP(_ value: T) { } func acceptsAny(_ value: T) { } -func acceptsSendable(_ value: T) { } +func acceptsSendableMetatype(_ value: T) { } @MainActor func passIsolated(s: S) { - acceptsP(s) // okay: the type parameter 'T' requires P but not Sendable - acceptsSendableP(s) // error: the type parameter 'T' requires Sendable - acceptsAny(s) // okay: no isolated conformance - acceptsSendable(s) // okay: no isolated conformance + acceptsP(s) // okay: the type parameter 'T' requires P but not SendableMetatype + acceptsSendableMetatypeP(s) // error: the type parameter 'T' requires SendableMetatype + acceptsAny(s) // okay: no isolated conformance + acceptsSendableMetatype(s) // okay: no isolated conformance } ``` @@ -431,19 +431,19 @@ The same checking occurs when the type parameter is hidden, for example when dea } @MainActor func isolatedAnyBad(s: S) { - let a: any Sendable & P = s // error: the (hidden) type parameter for the 'any' is Sendable + let a: any SendableMetatype & P = s // error: the (hidden) type parameter for the 'any' is SendableMetatype } @MainActor func returnIsolatedSomeGood(s: S) -> some P { return s // okay: the 'any P' cannot leave the isolation domain } -@MainActor func returnIsolatedSomeBad(s: S) -> some Sendable & P { +@MainActor func returnIsolatedSomeBad(s: S) -> some SendableMetatype & P { return s // error: the (hidden) type parameter for the 'any' is Sendable } ``` -Within the implementation, a conformance requirement `T: Q` is considered to be isolated if there is no requirement `T: Sendable`. This mirrors the rule on the caller side, and causes the following code to be ill-formed: +Within the implementation, we ensure that a conformance that could be isolated cannot cross an isolation boundary. This is done by making the a metatype `T.Type` `Sendable` only when there existing a constraint `T: SendableMetatype`. Therefore, the following program is ill-formed: ```swift protocol Q { @@ -452,14 +452,14 @@ protocol Q { nonisolated func callQGElsewhere(_: T.Type) { Task.detached { - T.g() // error: use of potentially-isolated conformance of non-Sendable type T to Q + T.g() // error: non-sendable metatype of `T` captured in 'sending' closure } } ``` -To correct this function, add a constraint `T: Sendable`, which allows the function to send the conformance across isolation domains. As described above, it also prevents the caller from providing an isolated conformance to satisfy the `T: Q` requirement, preventing the data race. +To correct this function, add a constraint `T: SendableMetatype`, which allows the function to send the metatype (along with its conformances) across isolation domains. As described above, it also prevents the caller from providing an isolated conformance to satisfy the `T: Q` requirement, preventing the data race. -The `Sendable` requirement described above is a stricter contract than is necessary for a function such as `callQGElsewhere`, which won't ever pass *values* of the type `T` across an isolation domain. Therefore, we introduce a new marker protocol `SendableMetatype` to capture the idea that values of the metatype of `T` (i.e., `T.Type`) will cross isolation domains and take conformances with them. A requirement `T: SendableMetatype` prohibits isolated conformances from being used on type `T`. Now, `callQGElsewhere` can be correctly expressed as follows: +`SendableMetatype` is a new marker protocol that captures the idea that values of the metatype of `T` (i.e., `T.Type`) will cross isolation domains and can take conformances with them. It is less restrictive than a `Sendable` requirement, which specifies that *values* of a type can be sent across isolation boundaries. All concrete types (structs, enums, classes, actors) conform to `SendableMetatype` implicitly, so fixing `callQGElsewhere` will not affect any non-generic code: ```swift nonisolated func callQGElsewhere(_: T.Type) { @@ -467,9 +467,10 @@ nonisolated func callQGElsewhere(_: T.Type) { T.g() } } -``` -The `SendableMetatype` protocol is somewhat special, because according to SE-0302 *all* metatypes are `Sendable`. This proposal refines that statement slightly: all concrete types (structs, enums, classes, actors) implicitly conform to `SendableMetatype`, because their metatypes (e.g., `MyModelType.Type`) are all `Sendable`. Therefore, a call to `callQGElsewhere` for any concrete type will succeed so long as that type has a (non-isolated) conformance to `Q`. +struct MyTypeThatConformsToQ: Q { ... } +callQGElsewhere(MyTypeThatConformsToQ()) // still works +``` The `Sendable` protocol inherits from the new `SendableMetatype` protocol: @@ -492,7 +493,7 @@ will continue to work with the stricter model for generic functions in this prop The proposed change for generic functions does have an impact on source compatibility, where functions like `callQGElsewhere` will be rejected. However, the source break is limited to generic code that: -1. Uses a conformance requirement (`T: P`) of a non-marker protocol `P` in another isolated domain, +1. Passes the metatype `T.Type` of a generic parameter `T` across isolation boundaries; 2. Does not have a corresponding constraint `T: Sendable` requirement; and 3. Is compiled with strict concurrency enabled (either as Swift 6 or with warnings). @@ -580,7 +581,7 @@ Initial testing of an implementation of this proposal found very little code tha Isolated conformances can be introduced into the Swift ABI without any breaking changes, by extending the existing runtime metadata for protocol conformances. All existing (non-isolated) protocol conformances can work with newer Swift runtimes, and isolated protocol conformances will be usable with older Swift runtimes as well. There is no technical requirement to restrict isolated conformances to newer Swift runtimes. -However, there is one likely behavioral difference with isolated conformances between newer and older runtimes. In newer Swift runtimes, the functions that evaluate `as?` casts will check of an isolated conformance and validate that the code is running on the proper executor before the cast succeeds. Older Swift runtimes that don't know about isolated conformances will allow the cast to succeed even outside of the isolation domain of the conformance, which can lead to different behavior that potentially involves data races. +However, there is one likely behavioral difference with isolated conformances between newer and older runtimes. In newer Swift runtimes, the functions that evaluate `as?` casts will check of an isolated conformance and validate that the code is running on the proper executor before the cast succeeds. Older Swift runtimes that don't know about isolated conformances will allow the cast to succeed even outside of the isolation domain of the conformance, which can lead to different behavior that potentially involves data races. It should be possible to provide (optional) warnings when running on newer Swift runtimes when a cast fails due to isolated conformances but would incorrectly succeed on older platforms. ## Future Directions @@ -660,3 +661,8 @@ This is a generalization of the proposed rules that makes more explicit when con * If not `T: SendableMetatype`, `T: P` is interepreted as `T: isolated P`. The main down side of this alternative is the additional complexity it introduces into generic requirements. It should be possible to introduce this approach later if it proves to be necessary, by treating it as a generalization of the existing rules in this proposal. + +## Revision history + +* Changes in review: + * Within a generic function, use sendability of metatypes of generic parameters as the basis for checking, rather than treating specific conformances as potentially isolated. This model is easier to reason about and fits better with `SendableMetatype`, and was used in earlier drafts of this proposal. From 964afd9798792975becaa77d411c63b32110d567 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 9 Apr 2025 11:24:43 -0400 Subject: [PATCH 210/505] Accept SE-0470 (#2780) --- proposals/0470-isolated-conformances.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index 0809817d2d..146dcd95bd 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -3,11 +3,11 @@ * Proposal: [SE-0470](0470-isolated-conformances.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (March 21...April 3, 2025)** +* Status: **Accepted** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` -* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ## Introduction From cd7fec5c2294947a27c2f4948f73b75ae775aa8b Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Wed, 9 Apr 2025 12:42:27 -0700 Subject: [PATCH 211/505] Mark ST-0009: Attachments as accepted Apply the modifications of AttachableContainer -> AttachableWrapper and update other corresponding text. --- proposals/testing/0009-attachments.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/proposals/testing/0009-attachments.md b/proposals/testing/0009-attachments.md index 565c01acc3..80225a2f75 100644 --- a/proposals/testing/0009-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -3,10 +3,10 @@ * Proposal: [ST-0009](0009-attachments.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Rachel Brindle](https://github.com/younata) -* Status: **Active Review (March 21 - April 8, 2025)** +* Status: **Accepted** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) -* Review: ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) +* Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0009-attachments/79193)), ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) ## Introduction @@ -170,8 +170,8 @@ conform: /// A type should conform to this protocol if it can be represented as a /// sequence of bytes that would be diagnostically useful if a test fails. If a /// type cannot conform directly to this protocol (such as a non-final class or -/// a type declared in a third-party module), you can create a container type -/// that conforms to ``AttachableContainer`` to act as a proxy. +/// a type declared in a third-party module), you can create a wrapper type +/// that conforms to ``AttachableWrapper`` to act as a proxy. public protocol Attachable: ~Copyable { /// An estimate of the number of bytes of memory needed to store this value as /// an attachment. @@ -242,12 +242,12 @@ conformances, Foundation must be imported because `JSONEncoder` and Some types cannot conform directly to `Attachable` because they require additional information to encode correctly, or because they are not directly -`Sendable` or `Copyable`. A second protocol, `AttachableContainer`, is provided +`Sendable` or `Copyable`. A second protocol, `AttachableWrapper`, is provided that refines `Attachable`: ```swift /// A protocol describing a type that can be attached to a test report or -/// written to disk when a test is run and which contains another value that it +/// written to disk when a test is run and which wraps another value that it /// stands in for. /// /// To attach an attachable value to a test, pass it to ``Attachment/record(_:named:sourceLocation:)``. @@ -259,7 +259,7 @@ that refines `Attachable`: /// A type can conform to this protocol if it represents another type that /// cannot directly conform to ``Attachable``, such as a non-final class or a /// type declared in a third-party module. -public protocol AttachableContainer: Attachable, ~Copyable { +public protocol AttachableWrapper: Attachable, ~Copyable { /// The type of the attachable value represented by this type. associatedtype AttachableValue @@ -267,13 +267,13 @@ public protocol AttachableContainer: Attachable, ~Copyable { var attachableValue: AttachableValue { get } } -extension Attachment where AttachableValue: AttachableContainer & ~Copyable { +extension Attachment where AttachableValue: AttachableWrapper & ~Copyable { /// The value of this attachment. /// - /// When the attachable value's type conforms to ``AttachableContainer``, the - /// value of this property equals the container's underlying attachable value. + /// When the attachable value's type conforms to ``AttachableWrapper``, the + /// value of this property equals the wrappers's underlying attachable value. /// To access the attachable value as an instance of `T` (where `T` conforms - /// to ``AttachableContainer``), specify the type explicitly: + /// to ``AttachableWrapper``), specify the type explicitly: /// /// ```swift /// let attachableValue = attachment.attachableValue as T @@ -286,7 +286,7 @@ The cross-import overlay with Foundation also provides the following convenience interface for attaching the contents of a file or directory on disk: ```swift -extension Attachment where AttachableValue == _AttachableURLContainer { +extension Attachment where AttachableValue == _AttachableURLWrapper { /// Initialize an instance of this type with the contents of the given URL. /// /// - Parameters: @@ -307,7 +307,7 @@ extension Attachment where AttachableValue == _AttachableURLContainer { } ``` -`_AttachableURLContainer` is a type that conforms to `AttachableContainer` and +`_AttachableURLWrapper` is a type that conforms to `AttachableWrapper` and encloses the URL and corresponding mapped data. As an implementation detail, it is omitted from this proposal for brevity. From cc52603f2f57222aa9e1e2b4c9ef66de5d4a66aa Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 10 Apr 2025 05:33:52 +0900 Subject: [PATCH 212/505] [SE-0317] fix minor typo (#2779) --- proposals/0317-async-let.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0317-async-let.md b/proposals/0317-async-let.md index 6720edf791..245dd4e7e0 100644 --- a/proposals/0317-async-let.md +++ b/proposals/0317-async-let.md @@ -148,7 +148,7 @@ func asynchronous() async { and inside asynchronous closures: ```swift -func callMe(_ maybe: () async -> String) async -> String +func callMe(_ maybe: () async -> String) async -> String { return await maybe() } From 5ff0900999e537b5c086146686ab49d304ab09f4 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 9 Apr 2025 17:32:43 -0400 Subject: [PATCH 213/505] Adjustments to ST-0009. This PR makes some further adjustments to ST-0009 to ensure the rename from `AttachableContainer` to `AttachableWrapper` is also applied to its associated type (i.e. `AttachableValue` -> `Wrapped`) and corresponding property (i.e. `attachableValue` -> `wrappedValue`). --- proposals/testing/0009-attachments.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/testing/0009-attachments.md b/proposals/testing/0009-attachments.md index 80225a2f75..e8442b2a81 100644 --- a/proposals/testing/0009-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -3,7 +3,7 @@ * Proposal: [ST-0009](0009-attachments.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Rachel Brindle](https://github.com/younata) -* Status: **Accepted** +* Status: **Accepted with revisions** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) * Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0009-attachments/79193)), ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) @@ -259,12 +259,12 @@ that refines `Attachable`: /// A type can conform to this protocol if it represents another type that /// cannot directly conform to ``Attachable``, such as a non-final class or a /// type declared in a third-party module. -public protocol AttachableWrapper: Attachable, ~Copyable { - /// The type of the attachable value represented by this type. - associatedtype AttachableValue +public protocol AttachableWrapper: Attachable, ~Copyable { + /// The type of the underlying value represented by this type. + associatedtype Wrapped - /// The attachable value represented by this instance. - var attachableValue: AttachableValue { get } + /// The underlying value represented by this instance. + var wrappedValue: Wrapped { get } } extension Attachment where AttachableValue: AttachableWrapper & ~Copyable { @@ -278,7 +278,7 @@ extension Attachment where AttachableValue: AttachableWrapper & ~Copyable { /// ```swift /// let attachableValue = attachment.attachableValue as T /// ``` - public var attachableValue: AttachableValue.AttachableValue { get } + public var attachableValue: AttachableValue.Wrapped { get } } ``` From 81787427101d6f8c944fe31e377c48233af70421 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Thu, 10 Apr 2025 08:44:50 +0200 Subject: [PATCH 214/505] ST-0008: add link to second review topic --- proposals/testing/0008-exit-tests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index 57953ff9ee..4256c976ab 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -3,10 +3,10 @@ * Proposal: [ST-0008](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0008-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Maarten Engels](https://github.com/maartene) -* Status: **Active Review (March 21...April 8, 2025)** +* Status: **Active Review (April 10...April 21, 2025)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) -* Review: ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) +* Review: ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)), ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction From 406db1e2db3c6fa2dfb5dd3540436e8dda29630a Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Thu, 10 Apr 2025 15:43:28 -0400 Subject: [PATCH 215/505] Accept SE-0464. --- proposals/0464-utf8span-safe-utf8-processing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0464-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md index dc7b5d7d5f..bfc006ac3e 100644 --- a/proposals/0464-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -3,10 +3,10 @@ * Proposal: [SE-0464](0464-utf8span-safe-utf8-processing.md) * Authors: [Michael Ilseman](https://github.com/milseman), [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Active review (March 5–19, 2025)** +* Status: **Accepted** * Bug: rdar://48132971, rdar://96837923 * Implementation: [swiftlang/swift#78531](https://github.com/swiftlang/swift/pull/78531) -* Review: ([first pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([second pitch](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([third pitch](https://forums.swift.org/t/pitch-utf8span-safe-utf-8-processing-over-contiguous-bytes/77483)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) +* Review: ([first pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([second pitch](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([third pitch](https://forums.swift.org/t/pitch-utf8span-safe-utf-8-processing-over-contiguous-bytes/77483)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0464-safe-utf-8-processing-over-contiguous-bytes/79218)) ## Introduction From 941cfbc08f1f297edae0064ee02bc56a22394b97 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 10 Apr 2025 16:45:19 -0400 Subject: [PATCH 216/505] Accept SE-0473 --- proposals/0473-clock-epochs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0473-clock-epochs.md b/proposals/0473-clock-epochs.md index 4565338dcc..0eebef737b 100644 --- a/proposals/0473-clock-epochs.md +++ b/proposals/0473-clock-epochs.md @@ -3,9 +3,9 @@ * Proposal: [SE-0473](0473-clock-epochs.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active Review (March 28th...April 9th, 2025)** +* Status: **Accepted** * Implementation: -* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) ([review](https://forums.swift.org/t/se-0473-clock-epochs/78923)) +* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) ([review](https://forums.swift.org/t/se-0473-clock-epochs/78923)) ([acceptance](https://forums.swift.org/t/accepted-se-0473-clock-epochs/79221)) ## Introduction From 986a981ad41cf52ecd1f5ca19902d00b07eb9163 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 10 Apr 2025 16:50:19 -0400 Subject: [PATCH 217/505] Add an implementation link to SE-0473 --- proposals/0473-clock-epochs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0473-clock-epochs.md b/proposals/0473-clock-epochs.md index 0eebef737b..c674352d3c 100644 --- a/proposals/0473-clock-epochs.md +++ b/proposals/0473-clock-epochs.md @@ -4,7 +4,7 @@ * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [John McCall](https://github.com/rjmccall) * Status: **Accepted** -* Implementation: +* Implementation: [PR #80409](https://github.com/swiftlang/swift/pull/80409) * Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) ([review](https://forums.swift.org/t/se-0473-clock-epochs/78923)) ([acceptance](https://forums.swift.org/t/accepted-se-0473-clock-epochs/79221)) ## Introduction From c956aac190ff3d6f6d3d45e6d25c04a6a7984793 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Thu, 10 Apr 2025 18:54:52 -0700 Subject: [PATCH 218/505] [Observation] Proposal to add a transactional observation of values (#2726) * Proposal to add a transactional observation of values * Fix the placeholder SE# * Update the interfaces to use `@isolated(any)` instead of `isolated` parameters * Add a number of example cases to describe in more detail expected behaviors and potential edge cases * Fix some spellings to the new behavioral section * Transition to a non-optional construction and add a Iteration return version for explicitly constructing Observed untilFinished * Observed is SE-0475 --------- Co-authored-by: Freddy Kellison-Linn --- proposals/0475-observed.md | 529 +++++++++++++++++++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 proposals/0475-observed.md diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md new file mode 100644 index 0000000000..488cebc102 --- /dev/null +++ b/proposals/0475-observed.md @@ -0,0 +1,529 @@ +# Transactional Observation of Values + +* Proposal: [SE-0475](0475-observed.md) +* Authors: [Philippe Hausler](https://github.com/phausler) +* Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) +* Status: **Active Review (Apr 10...24)** +* Implementation: https://github.com/swiftlang/swift/pull/79817 +* Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) + +## Introduction + +Observation was introduced to add the ability to observe changes in graphs of +objects. The initial tools for observation afforded seamless integration into +SwiftUI, however aiding SwiftUI is not the only intent of the module - it is +more general than that. This proposal describes a new safe, ergonomic and +composable way to observe changes to models using an AsyncSequence, starting +transactions at the first willSet and then emitting a value upon that +transaction end at the first point of consistency by interoperating with +Swift Concurrency. + +## Motivation + +Observation was designed to allow future support for providing an `AsyncSequence` +of values, as described in the initial [Observability proposal](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0395-observability.md). +This follow-up proposal offers tools for enabling asynchronous sequences of +values, allowing non-SwiftUI systems to have the same level of "just-the-right-amount-of-magic" +as when using SwiftUI. + +Numerous frameworks in the Darwin SDKs provide APIs for accessing an +`AsyncSequence` of values emitted from changes to a property on a given model +type. For example, DockKit provides `trackingStates` and Group Activities +provides `localParticipantStates`. These are much like other APIs that provide +`AsyncSequence` from a model type; they hand crafted to provide events from when +that object changes. These manual implementations are not trivial and require +careful book-keeping to get right. In addition, library and application code +faces the same burden to use this pattern for observing changes. Each of these +uses would benefit from having a centralized and easy mechanism to implement +this kind of sequence. + +Observation was built to let developers avoid the complexity inherent when +making sure the UI is updated upon value changes. For developers using SwiftUI +and the `@Observable` macro to mark their types, this principle is already +realized; directly using values over time should mirror this ease of use, +providing the same level of power and flexibility. That model of tracking changes +by a graph allows for perhaps the most compelling part of Observation; it +can track changes by utilizing naturally written Swift code that is written just +like the logic of other plain functions. In practice that means that any solution +will also follow that same concept even for disjoint graphs that do not share +connections. The solution will allow for iterating changed values for applications +that do not use UI as seamlessly as those that do. + +## Proposed solution + +This proposal adds a straightforward new tool: a closure-initialized `Observed` +type that acts as a sequence of closure-returned values, emitting new values +when something within that closure changes. + +This new type makes it easy to write asynchronous sequences to track changes +but also ensures that access is safe with respect to concurrency. + +The simple `Person` type declared here will be used for examples in the +remainder of this proposal: + +```swift +@Observable +final class Person { + var firstName: String + var lastName: String + + var name: String { firstName + " " + lastName } + + init(firstName: String, lastName: String) { + self.firstName = firstName + self.lastName = lastName + } +} +``` + +Creating an `Observed` asynchronous sequence is straightforward. This example +creates an asynchronous sequence that yields a value every time the composed +`name` property is updated: + +```swift +let names = Observed { person.name } +``` + +However if the example was more complex and the `Person` type in the previous +example had a `var pet: Pet?` property which was also `@Observable` then the +closure can be written with a more complex expression. + +```swift +let greetings = Observed { + if let pet = person.pet { + return "Hello \(person.name) and \(pet.name)" + } else { + return "Hello \(person.name)" + } +} +``` + +In that example it would track both the assignment of a new pet and then consequently +that pet's name. + +## Detailed design + +There a few behaviors that are prerequisites to understanding the requirements +of the actual design. These two key behaviors are how the model handles tearing +and how the model handles sharing. + +Tearing is where a value that is expected to be assigned as a singular +transactional operation can potentially be observed in an intermediate and +inconsistent state. The example `Person` type shows this when a `firstName` is +set and then the `lastName` is set. If the observation was triggered just on the +trailing edge (the `didSet` operation) then an assignment to both properties +would garner an event for both properties and potentially get an inconsistent +value emitted from `name`. Swift has a mechanism for expressing the grouping of +changes together: isolation. When an actor or an isolated type is modified it is +expected (enforced by the language itself) to be in a consistent state at the +next suspension point. This means that if we can utilize the isolation that is +safe for the type then the suspensions on that isolation should result in safe +(and non torn values). This means that the implementation must be transactional +upon that suspension; starting the transaction on the first trigger of a leading +edge (the `willSet`) and then completing the transaction on the next suspension +of that isolation. + +The simple example of tearing would work as the following: + +```swift +let person = Person(firstName: "", lastName: "") +// willSet \.firstName - start a transaction +person.firstName = "Jane" +// didSet \.firstName +// willSet \.lastName - the transaction is still dirty +person.lastName = "Appleseed" +// didSet \.lastName +// the next suspension the `name` property will be valid +``` + +Suspensions are any point where a task can be calling out to something where +they `await`. Swift concurrency enforces safety around these by making sure that +isolation is respected. Any time a function has a suspension point data +associated with the type must be ready to be read by the definitions of actor +isolation. In the previous example of the `Person` instance the `firstName` and +`lastName` properties are mutated together in the same isolation, that means +that no other access in that isolation can read those values when they are torn +without the type being `Sendable` (able to be read from multiple isolations). +That means that in the case of a non-`Sendable` type the access must be +constrained to an isolation, and in the `Sendable` cases the mutation is guarded +by some sort of mechanism like a lock, In either case it means that the next +time one can read a safe value is on that same isolation of the safe access to +start with and that happens on that isolations next suspension. + +Observing at the next suspension point means that we can also address the second +issue too; sharing. The expectation of observing a property from a type as an +AsyncSequence is that multiple iterations of the same sequence from multiple +tasks will emit the same values at the same iteration points. The following code +is expected to emit the same values in both tasks. + +```swift + +let names = Observed { person.firstName + " " + person.lastName } + +Task.detached { + for await name in names { + print("Task1: \(name)") + } +} + +Task.detached { + for await name in names { + print("Task2: \(name)") + } +} +``` + +In this case both tasks will get the same values upon the same events. This can +be achieved without needing an extra buffer since the suspension of each side of +the iteration are continuations resuming all together upon the accessor's +execution on the specified isolation. This facilitates subject-like behavior +such that the values are sent from the isolation for access to the iteration's +continuation. + +The previous initialization using the closure is a sequence of values of the computed +properties as a `String`. This has no sense of termination locally within the +construction. Making the return value of that closure be a lifted `Optional` suffers +the potential conflation of a terminal value and a value that just happens to be nil. +This means that there is a need for a second construction mechanism that offers a +way of expressing that the `Observed` sequence iteration will run until finished. + +For the example if `Person` then has a new optional field of `homePage` which +is an optional URL it then means that the construction can disambiguate +by returning the iteration as the `next` value or the `finished` value. + +``` +@Observable +final class Person { + var firstName: String + var lastName: String + var homePage: URL? + + var name: String { firstName + " " + lastName } + + init(firstName: String, lastName: String) { + self.firstName = firstName + self.lastName = lastName + } +} + +let hosts = Observed.untilFinished { [weak person] in + if let person { + .next(person.homePage?.host) + } else { + .finished + } +} +``` + +Putting this together grants a signature as such: + +```swift +public struct Observed: AsyncSequence, Sendable { + public init( + @_inheritActorContext _ emit: @escaping @isolated(any) @Sendable () throws(Failure) -> Element + ) + + public enum Iteration: Sendable { + case next(Element) + case finished + } + + public static func untilFinished( + @_inheritActorContext _ emit: @escaping @isolated(any) @Sendable () throws(Failure) -> Iteration + ) -> Observed +} +``` + +Picking the initializer apart first captures the current isolation of the +creation of the `Observed` instance. Then it captures a `Sendable` closure that +inherits that current isolation. This means that the closure may only execute on +the captured isolation. That closure is run to determine which properties are +accessed by using Observation's `withObservationTracking`. So any access to a +tracked property of an `@Observable` type will compose for the determination of +which properties to track. + +The closure is not run immediately it is run asynchronously upon the first call +to the iterator's `next` method. This establishes the first tracking state for +Observation by invoking the closure inside a `withObservationTracking` on the +implicitly specified isolation. Then upon the first `willSet` it will enqueue on +to the isolation a new execution of the closure and finishing the transaction to +prime for the next call to the iterator's `next` method. + +The closure has two other features that are important for common usage; firstly +the closure is typed-throws such that any access to that emission closure will +potentially throw an error if the developer specifies. This allows for complex +composition of potentially failable systems. Any thrown error will mean that the +`Observed` sequence is complete and loops that are currently iterating will +terminate with that given failure. Subsequent calls then to `next` on those +iterators will return `nil` - indicating that the iteration is complete. + +## Behavioral Notes + +There are a number of scenarios of iteration that can occur. These can range from production rate to iteration rate differentials to isolation differentials to concurrent iterations. Enumerating all possible combinations is of course not possible but the following explanations should illustrate some key usages. `Observed` does not make unsafe code somehow safe - the concepts of isolation protection or exclusive access are expected to be brought to the table by the types involved. It does however require the enforcements via Swift Concurrency particularly around the marking of the types and closures being required to be `Sendable`. The following examples will only illustrate well behaved types and avoid fully unsafe behavior that would lead to crashes because the types being used are circumventing that language safety. + +The most trivial case is where a single produce and single consumer are active. In this case they both are isolated to the same isolation domain. For ease of reading; this example is limited to the `@MainActor` but could just as accurately be represented in some other actor isolation. + +```swift +@MainActor +func iterate(_ names: Observed) async { + for await name in names { + print(name) + } +} + +@MainActor +func example() async throws { + let person = Person(firstName: "", lastName: "") + + // note #2 + let names = Observed { + person.name + } + + Task { + await iterate(names) + } + + for i in 0..<5 { + person.firstName = "\(i)" + person.lastName = "\(i)" + try await Task.sleep(for: .seconds(0.1)) // note #1 + } +} + +try await example() + +``` + +The result of the observation will print the following output. + +``` +0 0 +1 1 +2 2 +3 3 +4 4 +``` + +The values are by the virtue of the suspension at `note #1` are all emitted, the first name and last name are conjoined because they are both mutated before the suspension. The type `Person` does not need to be `Sendable` because `note #2` is implicitly picking up the `@MainActor` isolation of the enclosing isolation context. That isolation means that the person is always safe to access in that scope. + +Next is the case where the mutation of the properties out-paces the iteration. Again the example is isolated to the same domain. + +```swift +@MainActor +func iterate(_ names: Observed) async { + for await name in names { + print(name) + try? await Task.sleep(for: .seconds(0.095)) + } +} + +@MainActor +func example() async throws { + let person = Person(firstName: "", lastName: "") + + // @MainActor is captured here as the isolation + let names = Observed { + person.name + } + + Task { + await iterate(names) + } + + for i in 0..<5 { + person.firstName = "\(i)" + person.lastName = "\(i)" + try await Task.sleep(for: .seconds(0.1)) + } +} + +try await example() + +``` + +The result of the observation may print the following output, but the primary property is that the values are conjoined to the same consistent view. It is expected that some values may not be represented during the iteration because the transaction has not yet been handled by the iteration. + +``` +0 0 +1 1 +2 2 +3 3 +``` + +This case dropped the last value of the iteration because the accumulated differential exceeded the production; however the potentially confusing part here is that the sleep in the iterate competes with the scheduling in the emitter. This becomes clearer of a relationship when the boundaries of isolation are crossed. + +Observed can be used across boundaries of concurrency. This is where the iteration is done on a different isolation than the mutations. The types however are accessed always in the isolation that the creation of the Observed closure is executed. This means that if the `Observed` instance is created on the main actor then the subsequent calls to the closure will be done on the main actor. + +```swift +@globalActor +actor ExcplicitlyAnotherActor: GlobalActor { + static let shared = ExcplicitlyAnotherActor() +} + +@ExcplicitlyAnotherActor +func iterate(_ names: Observed) async { + for await name in names { + print(name) + } +} + +@MainActor +func example() async throws { + let person = Person(firstName: "", lastName: "") + + // @MainActor is captured here as the isolation + let names = Observed { + person.name + } + + Task.detached { + await iterate(names) + } + + for i in 0..<5 { + person.firstName = "\(i)" + person.lastName = "\(i)" + try await Task.sleep(for: .seconds(0.1)) + } +} + +``` + +The values still will be conjoined as expected for their changes, however just like the out-paced case there is a potential in which an alteration may slip between the isolations and only a subsequent value is represented during the iteration. However since is particular example has no lengthy execution (greater than 0.1 seconds) it means that it does not get out paced by production and returns all values. + +``` +0 0 +1 1 +2 2 +3 3 +4 4 +``` + +If the `iterate` function was altered to have a similar `sleep` call that exceeded the production then it would result in similar behavior of the previous producer/consumer rate case. + +The next behavioral illustration is the value distribution behaviors; this is where two or more copies of an `Observed` are iterated concurrently. + +```swift + +@MainActor +func iterate1(_ names: Observed) async { + for await name in names { + print("A", name) + } +} + + +@MainActor +func iterate2(_ names: Observed) async { + for await name in names { + print("B", name) + } +} + +@MainActor +func example() async throws { + let person = Person(firstName: "", lastName: "") + + // @MainActor is captured here as the isolation + let names = Observed { + person.name + } + + Task.detached { + await iterate1(names) + } + + Task.detached { + await iterate2(names) + } + + for i in 0..<5 { + person.firstName = "\(i)" + person.lastName = "\(i)" + try await Task.sleep(for: .seconds(0.1)) + } +} + +try await example() +``` + +This situation commonly comes up when the asynchronous sequence is stored as a property of a type. By vending these as a shared instance to a singular source of truth it can provide both a consistent view and reduce overhead for design considerations. However when the sequences are then combined with other isolations the previous caveats come in to play. + +``` +A 0 0 +B 1 1 +A 1 1 +B 2 2 +A 2 2 +A 3 3 +B 3 3 +A 4 4 +B 4 4 +``` + +The same rate commentary applies here as before but an additional wrinkle is that the delivery between the A and B sides is non-determinstic (in some cases it can deliver as A then B and other cases B then A). + +## Effect on ABI stability & API resilience + +This provides no alteration to existing APIs and is purely additive. However it +does have a few points of interest about future source compatibility; namely +the initializer does ferry the inherited actor context as a parameter and if +in the future Swift develops a mechanism to infer this without a user +overridable parameter then there may be a source breaking ambiguity that would +need to be disambiguated. + +## Notes to API authors + +This proposal does not change the fact that the spectrum of APIs may range from +favoring `AsyncSequence` properties to purely `@Observable` models. They both +have their place. However the calculus of determining the best exposition may +be slightly more refined now with `Observed`. + +If a type is representative of a model and is either transactional in that +some properties may be linked in their meaning and would be a mistake to read +in a disjoint manner (the tearing example from previous sections), or if the +model interacts with UI systems it now more so than ever makes sense to use +`@Observable` especially with `Observed` now as an option. Some cases may have +previously favored exposing those `AsyncSequence` properties and would now +instead favor allowing the users of those APIs compose things by using `Observed`. +The other side of the spectrum will still exist but now is more strongly +relegated to types that have independent value streams that are more accurately +described as `AsyncSequence` types being exposed. The suggestion for API authors +is that now with `Observed` favoring `@Observable` perhaps should take more +of a consideration than it previously did. + +## Alternatives Considered + +Both initialization mechanisms could potentially be collapsed into an optional, +however that creates potential ambiguity of valid nil elements versus termination. + +There have been many iterations of this feature so far but these are some of the +highlights of alternative mechanisms that were considered. + +Just expose a closure with `didSet`: This misses the mark with regards to concurrency +safety but also faces a large problem with regards to transactionality. This would also +be out sync with the expected behavior of existing observation uses like SwiftUI. +The one benefit of that approach is that each setter call would have a corresponding +callback and would be more simple to implement with the existing infrastructure. It +was ultimately rejected because that would fall prey to the issue of tearing and +the general form of composition was not as ergonomic as other solutions. + +Expose an AsyncSequence based on `didSet`: This also falls to the same issues with the +closure approach except is perhaps slightly more ergonomic to compose. This was also +rejected due to the tearing problem stated in the proposal. + +Expose an AsyncSequence property extension based on `KeyPath`: This could be adapted +to the `willSet` and perhaps transactional models, but faces problems when attempting +to use `KeyPath` across concurrency domains (since by default they are not Sendable). +The implementation of that approach would require considerable improvement to handling +of `KeyPath` and concurrency (which may be an optimization path that could be considered +in the future if the API merits it). As it stands however the `KeyPath` approach in +comparison to the closure initializer is considerably less easy to compose. + +The closure type passed to the initializer does not absolutely require @Sendable in the +cases where the initialization occurs in an isolated context, if the initializer had a +parameter of an isolation that was non-nullable this could be achieved for that restriction +however up-coming changes to Swift's Concurrency will make this approach less appealing. +If this route would be taken it would restrict the potential advanced uses cases where +the construction would be in an explicitly non-isolated context. From 89c39cbaa68b7687ec0caab527868638f354c249 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Thu, 10 Apr 2025 21:57:26 -0400 Subject: [PATCH 219/505] Link review thread for SE-0475 (#2786) --- proposals/0475-observed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index 488cebc102..2df388465f 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -5,7 +5,7 @@ * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) * Status: **Active Review (Apr 10...24)** * Implementation: https://github.com/swiftlang/swift/pull/79817 -* Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) +* Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) ## Introduction From 8f1c1e3efd9223fc3264ba2562d5d3568b8d3de6 Mon Sep 17 00:00:00 2001 From: David Catmull Date: Fri, 11 Apr 2025 09:12:45 -0600 Subject: [PATCH 220/505] [ST-0010] Add ConditionTrait.evaluate() (#2740) * Proposal for ConditionTrait.evaluate(), moved from swift-testing * Include "extension ConditionTrait" in code exerpts * Remove mentions of EvaluationResult, since it now uses Bool * Add myself as review manager * Note the associated issue * Assign proposal ST number 0010 and update state to Active Review --------- Co-authored-by: Stuart Montgomery --- proposals/testing/0010-evaluate-condition.md | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 proposals/testing/0010-evaluate-condition.md diff --git a/proposals/testing/0010-evaluate-condition.md b/proposals/testing/0010-evaluate-condition.md new file mode 100644 index 0000000000..d490a4b5ba --- /dev/null +++ b/proposals/testing/0010-evaluate-condition.md @@ -0,0 +1,65 @@ +# Public API to evaluate ConditionTrait + +* Proposal: [ST-0010](0010-evaluate-condition.md) +* Authors: [David Catmull](https://github.com/Uncommon) +* Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) +* Status: **Active review (April 11...April 22, 2025)** +* Bug: [swiftlang/swift-testing#903](https://github.com/swiftlang/swift-testing/issues/903) +* Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909) +* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)) + +## Introduction + +This adds an `evaluate()` method to `ConditionTrait` to evaluate the condition +without requiring a `Test` instance. + +## Motivation + +Currently, the only way a `ConditionTrait` is evaluated is inside the +`prepare(for:)` method. This makes it difficult for third-party libraries to +utilize these traits because evaluating a condition would require creating a +dummy `Test` to pass to that method. + +## Proposed solution + +The proposal is to add a `ConditionTrait.evaluate()` method which returns the +result of the evaluation. The existing `prepare(for:)` method is updated to call +`evaluate()` so that the logic is not duplicated. + +## Detailed design + +The `evaluate()` method is as follows, containing essentially the same logic +as was in `prepare(for:)`: + +```swift +extension ConditionTrait { + /// Evaluate this instance's underlying condition. + /// + /// - Returns: The result of evaluating this instance's underlying condition. + /// + /// The evaluation is performed each time this function is called, and is not + /// cached. + public func evaluate() async throws -> Bool +} +``` + +## Source compatibility + +This change is purely additive. + +## Integration with supporting tools + +This change allows third-party libraries to apply condition traits at other +levels than suites or whole test functions, for example if tests are broken up +into smaller sections. + +## Future directions + +This change seems sufficient for third party libraries to make use of +`ConditionTrait`. Changes for other traits can be tackled in separate proposals. + +## Alternatives considered + +Exposing `ConditionTrait.Kind` and `.kind` was also considered, but it seemed +unnecessary to go that far, and it would encourage duplicating the logic that +already exists in `prepare(for:)`. From 94fd1f5786d7f960c118737ab18bef06408591e6 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 11 Apr 2025 10:29:31 -0500 Subject: [PATCH 221/505] Link to review topic (#2787) --- proposals/testing/0010-evaluate-condition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0010-evaluate-condition.md b/proposals/testing/0010-evaluate-condition.md index d490a4b5ba..577b991d3b 100644 --- a/proposals/testing/0010-evaluate-condition.md +++ b/proposals/testing/0010-evaluate-condition.md @@ -6,7 +6,7 @@ * Status: **Active review (April 11...April 22, 2025)** * Bug: [swiftlang/swift-testing#903](https://github.com/swiftlang/swift-testing/issues/903) * Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909) -* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)) +* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)) ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)) ## Introduction From 8fdd34add87beabe36fb533837dc80d193852820 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Fri, 11 Apr 2025 08:51:38 -0700 Subject: [PATCH 222/505] Add `@abi` proposal (#2768) * Add `@abi` proposal * Take corrections from Ben Rimmington Co-authored-by: Ben Rimmington * Assign SE-0476 and put into active review. --------- Co-authored-by: Ben Rimmington Co-authored-by: Holly Borla --- proposals/0476-abi-attr.md | 946 +++++++++++++++++++++++++++++++++++++ 1 file changed, 946 insertions(+) create mode 100644 proposals/0476-abi-attr.md diff --git a/proposals/0476-abi-attr.md b/proposals/0476-abi-attr.md new file mode 100644 index 0000000000..a4e409cd26 --- /dev/null +++ b/proposals/0476-abi-attr.md @@ -0,0 +1,946 @@ +# Controlling the ABI of a function, initializer, property, or subscript + +* Proposal: [SE-0476](0476-abi-attr.md) +* Authors: [Becca Royal-Gordon](https://github.com/beccadax) +* Review Manager: [Holly Borla](https://github.com/hborla) +* Status: **Active Review (April 11 - April 25, 2025)** +* Implementation: behind experimental feature `ABIAttribute` (refinements in [swiftlang/swift#80383](https://github.com/swiftlang/swift/pull/80383)) +* Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) + +## Introduction + +We propose introducing the `@abi` attribute, which provides an alternate +version of the declaration used for name mangling. This feature would allow +developers of ABI-stable libraries to make minor changes, such as changing +the sendability of a parameter or renaming a declaration (so long as source +compatibility is preserved in a backwards-deployable way), without requiring +deep knowledge of compiler implementation details. + +## Motivation + +Maintainers of ABI-stable libraries sometimes need to update or correct +existing declarations for various reasons: + +1. To adopt new language features, like changing `@Sendable` to `sending`, + in an existing declaration. + +2. To replace an existing declaration with a source-compatible but ABI-breaking + equivalent, like replacing a `rethrows` method with one using typed + `throws`. + +3. To correct a mistake, like removing an unnecessary `@escaping` attribute or + adding a `Sendable` generic constraint. + +4. To rename an API whose name is felt to be catastrophically confusing. + +Many revisions will cause fundamental changes in how an API will be used at the +machine code level that clients must account for; for instance, changing `` +to `` requires callers to generate code that will pass the witness +table for `T`'s `Hashable` conformance. However, some features are designed to +have little or no impact on the code generated by the caller. For example, +these two declarations: + +```swift +// `T` must be `Sendable` +func fn(_: T) {} + +// `T` parameter must be `sending` +func fn(_: borrowing sending T) {} // note: 'borrowing sending' is currently banned, + // pending a decision on whether it should have the + // meaning we want it to have here +``` + +Have identical parameter signatures at the IR level, with one pointer to the +argument and another pointer to `T`'s value witness table, and use the same +result type and calling convention too: + +```text +define hidden swiftcc void @"$s4main2fnyyxs8SendableRzlF"(ptr noalias %0, ptr %T) + ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~ +define hidden swiftcc void @"$s4main2fnyyxlF"(ptr noalias %0, ptr %T) + ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~ +``` + +Other details, such as the parameter ownership conventions, also line up to +make this work; suffice it to say, the function generated when you use +`borrowing sending` is perfectly capable of handling the arguments passed by +callers that think the parameter is `Sendable`. The only differences between +them are the compile-time checks applied by the compiler and the part of their +mangled names that indicates the feature being used: + +```text +define hidden swiftcc void @"$s4main2fnyyxs8SendableRzlF"(ptr noalias %0, ptr %T) + ^~~~~~~~~~~~~ 'T: Sendable' +define hidden swiftcc void @"$s4main2fnyyxlF"(ptr noalias %0, ptr %T) + ^ 'T' ('sending' is not indicated by the mangled name) +``` + +Thus, if there was a way to tell the compiler to continue using the mangled +name for `fn(_: T)`, a library designer could actually change the +declaration to be treated like `fn(_: borrowing sending T)` when compiling +with the new version of the library *without* breaking ABI compatibility. + +This is part of how the `@preconcurrency` attribute works. `@preconcurrency` +has two effects: It instructs the type checker to permit Swift 5 code to use +the declaration in ways that would violate the rules of certain concurrency +annotations, and it causes those annotations to be omitted from the +declaration's mangled name. That makes it perfect for retrofitting sendability +checking onto APIs that were created before Swift Concurrency was introduced. +However, it is designed specifically for that exact task, which makes it +inflexible: It cannot be used to suppress some concurrency features but not +others (for instance, to amend a mistake in one parameter without affecting +other parts of the declaration), and it cannot be applied to adopt +non-concurrency features which have the same property of being ABI-compatible +except for a different mangled name. + +For everything else, there's the compiler-internal `@_silgen_name` attribute. +`@_silgen_name` is an internal hack that overrides name mangling at specific +points in the compiler, replacing the mangled name with an arbitrary string. +If you know the original mangled name, therefore, you can use this attribute +to keep that name stable even if the declaration has evolved enough that it +would normally use a different name. That makes `@_silgen_name` enormously +flexible—it can be used to handle an arbitrary set of changes, and the +standard library uses it extensively for this purpose. For example, when the +standard library introduced a new `Collection.map(_:)` that used typed +`throws` in [SE-0413][], it continued to support clients expecting the old +`rethrows`-based `map` by using a `@_silgen_name` hack and +`@usableFromInline internal`: + +```swift +extension Collection { + // New `map(_:)` using typed `throws`: + @inlinable + @backDeployed(...) // slight lie, but that's irrelevant here + public func map( + _ transform: (Element) throws(E) -> T + ) throws(E) -> [T] { + // ...actual implementation of `map` omitted... + } + + // Wrapper with the same ABI as the old `map(_:)` which used `rethrows`: + @_silgen_name("$sSlsE3mapySayqd__Gqd__7ElementQzKXEKlF") + // ^-- func map<$T>(_: (Self.Element) throws -> $T) rethrows -> Swift.Array<$T> + // in Swift.Collection extension from module Swift + @usableFromInline + func __rethrows_map( + _ transform: (Element) throws -> T + ) throws -> [T] { // 'throws' and 'rethrows' have the same ABI + try map(transform) // calls through to the new `map(_:)` + } +} +``` + +This creates a declaration which is written in Swift source code as +`__rethrows_map(_:)`, but which has the mangled name of a function named +`map(_:)`. When a module is compiled against this new version of the standard +library, calls to `map(_:)` will use the new method directly; if a module is +compiled against an older standard library, though, it will end up calling the +`__rethrows_map(_:)` compatibility wrapper instead. + +Although it is a powerful tool, `@_silgen_name` has its own set of serious +drawbacks: + +* It has absolutely no compile-time safety checking. +* It works only with functions and is incompatible with certain function + features like opaque return types and `@backDeployed`.[1] +* It requires deep knowledge of the name mangling and calling convention to use + correctly. + +In practice, you basically need to be a Swift compiler or runtime engineer to +use it correctly. For this reason `@_silgen_name` has never been proposed to +Swift Evolution or recommended for general use. + +Library maintainers need a tool that is much more flexible than +`@preconcurrency` but also much safer and more ergonomic than `@_silgen_name`. + +> *[1] This is because the name mangling has facilities to create multiple +> symbols that are all related to the same declaration, but `@_silgen_name` +> only provides an override for the name of the main symbol. Any declaration +> that requires more than one symbol—such as a type declaration, a function +> with an opaque return type, or a function with a back-deployment +> thunk—would have no way to generate a mangled name for these additional +> symbols.* + + [SE-0413]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md#effect-on-abi-stability + +## Proposed solution + +We propose a new attribute, called `@abi`, which specifies an alternate +declaration that provides its ABI for name mangling purposes. This alternate +declaration is enclosed within the argument parentheses; it has no body or +initializer expression but is otherwise a syntactically complete declaration. + +For example, the `@_silgen_name`-using `__rethrows_map(_:)` method shown in the +Motivation section could be written much more clearly by using `@abi`: + +```swift +extension Collection { + // Wrapper with the same ABI as the old `map(_:)` which used `rethrows`: + @abi( + func map( + _ transform: (Element) throws -> T + ) rethrows -> [T] + ) + @usableFromInline + func __rethrows_map( + _ transform: (Element) throws -> T + ) throws -> [T] { // 'throws' and 'rethrows' have the same ABI + try map(transform) // calls through to the new `map(_:)` + } +} +``` + +Notice how the `@abi` attribute basically contains the original version of the +declaration. When Swift is performing name mangling, this declaration is what +it will use; for all other functions, it will use the outer `__rethrows_map` +declaration. In particular, the `map(_:)` call in the body doesn't get resolved +to the `map(_:)` function in the `@abi` attribute; it looks for other +implementations and eventually finds the new typed-throws `map(_:)`. + +What's more, the ABI declaration can be checked against the original one to +make sure they're compatible. For example, at the ABI level `throws` and +`rethrows` are interchangeable, but a non-`throws`/`rethrows` method handles +its return values differently from them. If the maintainer accidentally dropped +the `throws` effect while implementing this function, the compiler would +complain about the mismatch: + +```swift +extension Collection { + @abi( + func map( + _ transform: (Element) throws -> T + ) rethrows -> [T] // error: 'rethrows' doesn't match API + ) + @usableFromInline + func __rethrows_map( + _ transform: (Element) throws -> T + ) -> [T] { // Whoops, should be 'throws' or 'rethrows'! + try map(transform) + } +} +``` + +This checking also makes sure that the details specified in the `@abi` +attribute are actually relevant. For example, the `@abi` attribute +automatically inherits the access control, availability, and `@objc`-ness of +the API it's attached to, so these are omitted from the `@abi` attribute. +Default arguments, too, are left out because they're irrelevant to ABI. The +compiler will diagnose this unnecessary information and suggest removing it. + +All sorts of precision changes are possible. Here's another use for a +`@_silgen_name` hack in the standard library: The maintainers discovered a data +race safety bug in an API that had already shipped and needed to add an +`@Sendable` attribute to prevent it, but `@preconcurrency` alone would have +also suppressed the `@Sendable` attribute on the parameter that had been +correctly annotated. `@abi` makes it easy to fix this sort of problem: + +```swift +public struct AsyncStream { + // ...other declarations omitted... + + @abi( + init( + unfolding produce: @escaping /* not @Sendable */ () async -> Element?, + onCancel: (@Sendable () -> Void)? = nil + ) + ) + @preconcurrency + public init( + unfolding produce: @escaping @Sendable () async -> Element?, + onCancel: (@Sendable () -> Void)? = nil + ) { + // Implementation omitted + } +} +``` + +Because `@preconcurrency` is applied to the outer declaration, but not to the +one inside the `@abi` attribute, its typechecking effects will be applied +(improving source compatibility for code written before the second `@Sendable` +was added) but its name mangling effects will not (keeping the mangled name +stable to preserve ABI compatibility). + +This feature goes beyond what `@_silgen_name` could do, however. For example, +it can be applied to `var` and `let` declarations: + +```swift +@abi(var oldName: Int) +public var newName: Int +``` + +The mangled name of an accessor includes the mangled name of the variable or +subscript it belongs to; thanks to `@abi`, the accessors for this variable will +have `oldName` mangled into their names. + +### Supported changes (and unsupported uses of them) + +This feature can be used to override the mangling of a declaration's: + +* Name, argument labels, and (for unary operator functions) fixity (`prefix` + vs. `postfix`) + +* Preconcurrency status, actor isolation (where this does not affect calling + convention), and execution environment + +* Generic constraints to marker protocols (`BitwiseCopyable`, `Copyable`, + `Escapable`, `Sendable`) + +* Certain aspects of parameter and `self` behavior (variadic (vs. `Array`); + `@autoclosure`; `sending`; ownership specifiers as long as the behavior is + compatible) + +* Certain aspects of argument, result, and thrown types (marker protocols in + existentials; tuple element labels; `@escaping`, `@Sendable`, and `sending` + results on closures) + +Note that some of these changes relate to safety properties of your code, such +as data race safety and escapability. When you use `@abi` to maintain ABI +compatibility with older versions of your library while tightening safety +constraints for new clients, you must take special care to remember that +clients compiled without those changes may violate the new constraints. In +practice, this means that you should probably only use `@abi` to make +retroactive changes to safety constraints when you know that violating the +constraint was *always* unsafe and it simply wasn't enforced until now. + +For instance, the `AsyncStream.init(unfolding:onCancel:)` example above adds +`@Sendable` to a closure parameter that previously didn't have the attribute. +This is appropriate because the closure was *always* run concurrently; code +that passed a non-`@Sendable` closure was already buggy, so this change merely +made the bug easier to detect. It would have been inappropriate if the closure +was originally run synchronously and was changed to run concurrently, because +code that previously worked fine would now have new data races. + +(`@abi` can still be used to help implement behavior changes, but the pattern +is different: you make the original version `@usableFromInline internal` and +change its API name to something you won't use by accident, applying `@abi` to +keep its mangled name the same as always. Then you create a new declaration +with the old API name and the behavior changes, using `@backDeployed` to ensure +that new binaries can interoperate with old versions of your library. +`__rethrows_map(_:)` is a good example of this pattern.) + +In short: Much like when `@inlinable` is used, **it is the developer's +responsibility to ensure that the current behavior of the declaration is +compatible with clients built against older versions of it. The compiler +doesn't understand the history of your codebase and cannot detect some +mistakes.** + +## Detailed design + +### Grammar + +An `@abi` attribute's argument list must have exactly one argument, which in +this proposal must be one of the following productions: + +* *function-declaration* +* *initializer-declaration* +* *constant-declaration* +* *variable-declaration* +* *subscript-declaration* + +This argument must *not* include any of the following sub-productions: + +* *code-block* +* *getter-setter-block* +* *getter-setter-keyword-block* +* *willSet-didSet-block* +* *initializer* (initial value expression) + +To that end, we amend the following productions in the Swift grammar to make +code blocks optional: + +```diff + initializer-declaration → initializer-head generic-parameter-clause? + parameter-clause async? throws-clause? +- generic-where-clause? initializer-body ++ generic-where-clause? initializer-body? + + initializer-declaration → initializer-head generic-parameter-clause? + parameter-clause async? 'rethrows' +- generic-where-clause? initializer-body ++ generic-where-clause? initializer-body? + + subscript-declaration → subscript-head subscript-result generic-where-clause? +- code-block ++ code-block? +``` + +We don't need to worry about ambiguity in terminating these productions because +the block-less forms always occur in `@abi` attributes; its closing parenthesis serves as a terminator for the declaration. + +> **Note**: If future development of the `@abi` attribute requires additional +> information to be added to it, this can be done by adding new productions at +> the beginning of the argument list, terminated by a comma or colon to +> distinguish them from declaration modifiers: +> +> ```swift +> @abi(unchecked, func liveDangerously(_: AnyObject)) // Future direction +> func liveDangerously(_ object: AnyObject?) { ... } +> ``` + +### Terminology and basic concepts + +Syntactically, an `@abi` attribute involves two declarations. The *ABI-only +declaration* is the one in the attribute's argument list; the *API-only +declaration* is the one the attribute is attached to. + +```swift +@abi(func abiOnlyDeclaration()) +func apiOnlyDeclaration() {} +``` + +A declaration which does not involve an `@abi` attribute at all—that is, which +is neither API-only nor ABI-only—is called a *normal declaration*. + +There are two *ABI roles*: + +* An *API-providing declaration* determines the behavior of the declaration in + source code: what name developers write to address it, what constraints and + behaviors are applied at use sites, how it is implemented (its body, + accessors, or members), etc. + +* An *ABI-providing declaration* determines how the declaration affects mangled + symbol names--both its own name and any names derived from it. + +Every declaration has at least one of these roles. Every declaration also has a +*counterpart* which fulfills the roles it does not. When the compiler wants to +compute some aspect of a declaration pertaining to a role that declaration does +not have, it automatically substitutes the declaration's counterpart. + +Roles and counterparts work as follows: + +| Declaration is… | ABI-providing | API-providing | Counterpart | +| --------------- | ------------- | ------------- | ------------------------------------------- | +| Normal | ✅ | ✅ | Is its own counterpart | +| ABI-only | ✅ | | Declaration `@abi` attribute is attached to | +| API-only | | ✅ | Declaration in `@abi` attribute | + +### Declaration checking + +When you use the `@abi` attribute, Swift validates various aspects of the +ABI-providing declaration in light of its API counterpart. An *aspect* is any +way in which the external appearance of a declaration might vary. Attributes +and modifiers are aspects, but so are the declaration's name, its result or +value types, its generic signature (if it has one), its parameter list (if it +has one), its effects (if it has any), and so on. + +#### Aspects with no ABI impact must be omitted + +Many aspects of a declaration only matter for an API-providing declaration; +they're irrelevant on a declaration that's ABI-only. These include: + +* Default arguments for parameters + +* Attributes which only affect compile-time checking or behavior, such as + `@unsafe`, `@discardableResult`, or result builder attributes + +* Certain attributes and modifiers which have ABI effects, but where the + compiler has been designed to inherit the ABI-providing declaration's + behavior from its API counterpart where needed: + + * `@objc` (and its ilk) and `dynamic`, including inference behaviors + * Access control modifiers and `@usableFromInline` + * `@inlinable` and other attributes controlling inlining + * `@available` and `@backDeployed` + * `override` + +These aspects are generally *forbidden* on an ABI-providing declaration. If +they are present, the compiler will diagnose an error and suggest they be +removed. + +In practice, this means that an `@abi` attribute is often significantly shorter +than the declaration it's attached to because it doesn't need to specify as +much information: + +```swift +@abi( + // Same signature as below, except `T` is not `Sendable`. + static + func assumeIsolated( + _ operation: @MainActor () throws -> T, + file: StaticString, + line: UInt + ) rethrows -> T +) +@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) // not needed in @abi +@usableFromInline // not needed in @abi +internal // not needed in @abi +static +func assumeIsolated( + _ operation: @MainActor () throws -> T, + file: StaticString = #fileID, // default argument not needed in @abi + line: UInt = #line // default argument not needed in @abi +) rethrows -> T { + ... +} +``` + +The intended workflow is that a developer can paste the entire original +declaration into an `@abi` attribute and the compiler will then tell them which +parts of it they should remove. + +#### Call compatibility + +For aspects which *do* have ABI impact, the compiler enforces that the +ABI-providing declaration is *call-compatible* with its API-providing +counterpart. Broadly, "call compatibility" means that, other than the mangled +names, the machine code generated to call the ABI-providing declaration would +be equally able to call its API counterpart. For instance: + +* Declarations are of the same fundamental kind (a `func` for a `func`, a `var` + for a `var`, etc.), so they expose the same basic capabilities and entry + points. + +* Effects match closely enough that the caller and callee will agree on which + stack should be used and which implicit parameters will be passed. + +* Inputs and outputs are passed similarly enough to ensure type and memory + safety, including compatible memory management behavior, and including the + implicit inputs and outputs used for generic parameters, `self`, and + throwing. + +However, call compatibility does *not* require aspects of the declaration +that only change the mangled name and/or compile-time checking to match: + +* Names, argument labels, or other name-like traits of a declaration (such + as the fixity modifiers for operator functions) may vary. + +* Aspects which affect only syntax (and possibly mangling) may vary. For + instance, a regular closure may be used instead of an `@autoclosure`; tuple + types with different element labels may be used; an array parameter may be + used instead of a variadic parameter; ordinary optionals may be used instead + of implicitly-unwrapped optionals; `throws` and `rethrows` may be used + interchangeably. + +* Concurrency safety and lifetime restrictions which don't affect the ability + to call the declaration may vary. For instance, a non-escaping closure may be + used instead of an `@escaping` closure; `sending` modifiers, `Sendable` + constraints, or neither may be used interchangeably so long as memory + management isn't affected; isolation may vary so long as extra data does not + need to be passed; `~Copyable` and `~Escapable` constraints may vary. + +#### Impact on redeclaration checking + +A declaration must have a unique signature in each of its roles. That is, an +API-only declaration is checked against API-providing declarations; an +ABI-only declaration is checked against ABI-providing declarations; a normal +declaration is checked twice, first against API-providing declarations and then +against ABI-providing declarations. + +In general, name lookup will return declarations with the API-providing role +and will ignore declarations with the ABI-providing role. Even when you're +writing an ABI-only declaration, you should use the API names of other +declarations, not the ABI names. + +#### Declaring multiple variables + +When `var` or `let` is used, the ABI-providing declaration must bind the same +number of patterns, each of which has the same number of variables, as its API +counterpart. That is, the first of these is valid, while the others are not: + +```swift +// OK: +@abi(var x, y: Int) +var a, b: Int + +// Mismatched: +@abi(var x, y, z: Int) +var a, b: Int + +// Also mismatched: +@abi(var x, y: Int) +var a: Int, (b1, b2): (Int, Int) + +// Mismatched even though the total adds up: +@abi(var x, y, z: Int) +var a: Int, (b1, b2): (Int, Int) +``` + +An ABI-providing declaration does *not* infer missing types from its API +counterpart. In practice, this means that an ABI-providing declaration +may need to explicitly declare types that its API counterpart infers from an +initial value expression. + +An ABI-providing `var` or `let` does not have a list of accessors or specify +anything about them; in a sense, it can be thought of as inferring its +accessors from its API counterpart. + +### Limitations on feature scope + +#### Supported declaration kinds + +In this proposal, `@abi` may be applied only to `func`, `init`, `var`, `let`, +and `subscript` declarations. Other declarations are less straightforward to +support in various ways; see the future directions section for details. + +#### Language features with auxiliary declarations + +`@abi` can neither contain, nor be applied alongside, `lazy` or a property +wrapper. These features implicitly create auxiliary declarations, and it isn't +clear how those should interact with `@abi`. + +#### Limited support for macros + +Neither attached nor freestanding macros can be used inside an `@abi` +attribute. None of the attached macro roles would be useful since ABI-providing +declarations do not have bodies, members, accessors, or extensions; the +freestanding macro roles, on the other hand, expand to complete declarations, +while some of the future directions involve supporting special stub syntax +which would be incompatible here. + +`@abi` can still be applied *alongside* an attached macro or *to* a +freestanding macro, although in practice many macros will need to handle `@abi` +attributes specially. + +### Non-normative: Precise rules as currently implemented + +To help evaluate how these principles will work in practice, we've listed the +current implementation's rules below. **However, we do not guarantee that the +rules listed here will exactly match the final behavior of the feature.** +Basically, we don't want to put every bug fix through an amendment or every +tiny, straightforward expansion of capabilities through a proposal. + +#### Must be omitted (no ABI impact or inheritance in place) + +* Default arguments on parameters +* Result builder attributes on parameters or declarations +* `@available` +* `@inlinable`, `@inline`, `@backDeployed`, `@usableFromInline`, + `@_alwaysEmitIntoClient`, `@_transparent` +* Objective-C opt-in attributes (`@objc`, `@IBAction`, `@IBDesignable`, + `@IBInspectable`, `@IBOutlet`, `@IBSegueAction`, `@GKInspectable`, + `@NSManaged`, `@nonobjc`) +* `optional` modifier in `@objc` protocols +* `@NSCopying` +* `@_expose` and `@_cdecl` +* `@LLDBDebuggerFunction` +* `dynamic` modifier and `@_dynamicReplacement` +* `@specialize` on functions and initializers +* `override` modifier +* Access control (`open`, `public`, `package`, `internal`, `fileprivate`, + `private`) +* Setter access control (`open(set)`, `public(set)`, `package(set)`, + `internal(set)`, `fileprivate(set)`, `private(set)`) +* `@_spi` and `@_spi_available` +* Reference ownership (`weak`, `unowned`, `unowned(unsafe)`) +* `@warn_unqualified_access` +* `@discardableResult` +* `@implementation` on functions +* `@differentiable`, `@derivative`, `@transpose` +* `@noDerivative` on declarations other than parameters +* `@exclusivity` +* `@safe` and `@unsafe` +* `@abi` +* Unsupported features (`lazy`, property wrapper attributes, attached macro + attributes) + +#### Must be specified and must match + +* Declaration kind (`func`, `var`, etc.) +* `convenience` and `required` modifiers on initializers +* `distributed` modifier +* Result type of functions +* Failability of initializers +* Value type of subscripts and variables +* Number of parameters on functions, initializers, and subscripts +* Parameter types +* `inout` on parameters and `mutating`/`nonmutating` modifiers on members +* `@noDerivative` on parameters +* `@_addressable` on parameters and `@_addressableSelf` on members +* `@lifetime` attributes (NOTE: this probably ought to be "vary with + constraints", but an interaction with `@_addressableForDependencies` needs + to be worked out) +* `async` effect +* Aspects of types which are not listed elsewhere + +#### Allowed to vary, but with constraints + +* `throws` effect and thrown type (`rethrows` is equivalent to `throws`) +* Generic signature of functions, initializers, and subscripts (marker + protocols may vary) +* Variadic parameter types (`T...` and `Array` are treated as equivalent) +* Parameter ownership specifiers and `self` ownership modifiers (ones with + equivalent memory management behavior may be substituted for one another) +* `sending` on parameter and result types (so long as its ownership behavior + is preserved) +* `static`, `class`, and `final` modifiers (`class final` is equivalent to + `static`) +* Actor isolation (other than `@isolated(any)`, which is incompatible with + the others) + +#### Allowed to vary arbitrarily + +* Base names of functions and variables +* Argument labels and parameter names +* `prefix` and `postfix` modifiers on operator functions +* Whether optionals are implicitly unwrapped +* Element labels in tuple types +* `@autoclosure` on parameters +* `@escaping` on closures +* `@Sendable` on closures +* `isolated` on parameters +* `_const` on parameters and variables +* Generic parameter names +* Use of type sugar (e.g. `Optional` and `T?` are equivalent) +* Use of generic types that have a same-type constraint (e.g. in the + presence of `T == Int`, `T` and `Int` are equivalent) +* Use of marker protocols in existential types +* `@Sendable` on functions and initializers +* `@preconcurrency` +* `@execution` +* Aspects of declarations which are not listed elsewhere + +## Source compatibility + +This feature is additive and affects only the ABI. However, many of the changes +that can be effected using it can be source-breaking unless done with care. For +example: + +* When renaming a declaration, make sure there's a declaration with the + original name that can be called in the same situations, and consider using + `@backDeployed` to ensure recompiled clients don't have to raise their + minimum deployment target. + +* When a type changes, make sure that it will either become more broad, or that + you are willing to accept any breakage that results. For example, switching + from a `Sendable` constraint to a `(borrowing) sending` parameter strictly + increases the set of valid callers, so that's probably always okay; switching + from no constraint to a `Sendable` constraint, on the other hand, will break + some callers, but might be acceptable if the missing `Sendable` constraint + created an opportunity for data races. + +## ABI compatibility + +This feature is intended to give libraries additional options to evolve APIs +without breaking the corresponding ABIs. + +We are currently evaluating adoption in `stdlib/public`. So far, it looks like +we can replace all uses of `@_silgen_name` to specify mangled Swift names with +uses of `@abi`, and in some cases remove hacks; this will be roughly 75 +declarations. + +Note that this feature does not subsume the use of `@_silgen_name` with an +arbitrary, C-style symbol name to either declare a function implemented in +C++ using the Swift calling convention, or to generate a symbol that's easy to +access from C-family code or a compiler intrinsic. About 200 of the uses of +`@_silgen_name` in `stdlib/public` are of this type; we expect these to remain +as-is. + +## Implications on adoption + +This feature is intended to help ease the adoption of other new features by +allowing a declaration's ABI to be "pinned" to its original form even as it +continues to evolve. Note that there is only ever a need to specify the +*original* form of the declaration, not any revisions that may have occurred +between then and the current form; there is therefore never a reason you would +need to specify more than one `@abi` attribute, nor to tie an `@abi` attribute +to a specific platform version. + +In module interfaces, the `@abi` attribute is partially suppressible. +Specifically, for `func`s that do not use `@backDeployed` and do not have +opaque result types, the compiler emits a module interface that falls back to +using an equivalent `@_silgen_name` attribute. For other declarations, however, +the compiler falls back to an `@available(*, unavailable)` attribute instead, +with a message indicating that the developer will need a newer compiler to use +the declaration. + +## Future directions + +### Unchecked mode + +There may be situations where a skilled engineer knows that a specific use of +`@abi` is compatible, but the compiler does not know how to prove that. While +that can often be considered a compiler bug—the checker *should* be able to +tell that the code is safe—it may be useful, either as a workaround or to +handle extreme edge cases, to be able to turn off `@abi`'s compatibility +checking: + +```swift +@abi(unchecked, func liveDangerously(_: AnyObject)) +func liveDangerously(_ object: AnyObject?) { ... } +``` + +### Support for types and extensions + +It ought to be possible to use `@abi` with types: + +```swift +@abi(struct Buffer: ~Copyable) +public struct FrameBuffer: ~Copyable { ... } + +@available(*, unavailable, renamed: "FrameBuffer") +@abi(typealias FrameBuffer) // keeps `typealias Buffer` from colliding with `struct Buffer` +typealias Buffer = FrameBuffer +``` + +Here, the library maintainer discovered after shipping that the name `Buffer` +is too vague—clients didn't understand what it meant, and some of them even +had another type named `Buffer`. When they rebuild with the new version of the +library, they will get an error with a fix-it to change `Buffer` to +`FrameBuffer`, but it will still use the name `Buffer` at the ABI level so +that existing binaries don't break. This will apply not only to the type +itself, but also to its members and even to functions with a `FrameBuffer` in +their overload signature. + +Type renaming may create challenges for module interface source stability, +since a module interfaces could refer to a type by an older or newer name than +its current one. It might be possible to address this by making module +interfaces always refer to types by their ABI name. (This should be +non-breaking as long as it's introduced at the same time as `@abi` for types.) + +This could also be used to affect the inference of properties of other +declarations. Consider this example: + +```swift +@abi(protocol Component) +@preconcurrency @MainActor // Added after shipping +public protocol Component { ... } + +extension Component { + public func onEvent(_ handler: @Sendable @escaping () -> Void) -> some Component { ... } +} +``` + +The library maintainer decided after the fact that `Component`s should be +isolated to the main actor, but that broke some Swift 5 code, so they added +`@preconcurrency` for its typechecking effects. However, `@preconcurrency` then +got applied to `onEvent(_:)`, suppressing its `@Sendable` attribute, which +changed its ABI. Using `@abi` on `Component` should override the ABI effects of +`@preconcurrency` not just for `Component` itself, but for every declaration +nested inside it. + +To support this kind of inference, the compiler may need to add an inferred +`@abi` attribute when a declaration with both roles depends on one which +provides only one role. For instance, if a type conforms to a protocol whose +`@abi` attribute specifies different actor isolation or different marker +protocols, Swift may need to add an inferred `@abi` attribute so the type's ABI +will be compatible with the protocol's ABI while its API will be compatible +with the protocol's ABI. + +### Support for enum cases + +It would probably be possible to allow `@abi` to be attached to a `case` +declaration, allowing it to backwards-compatibly rename or otherwise control +the ABI of enum cases. + +### Support for auxiliary declarations + +It might be possible to allow `@abi` to be used with `lazy` and property +wrappers either by coming up with rules to derive an `@abi` attribute for those +declarations, or by creating a syntax that can specify them: + +```swift +@abi(nonisolated var currentValue: Int) +@abi(for: projection, nonisolated var $currentValue: Binding) +@abi(for: storage, nonisolated var _currentValue: Binding) +@MainActor @Binding var currentValue: Int +``` + +### Support for accessors + +It might be possible to allow `@abi` to be attached to individual accessors. + +### Support for context changes + +It might be possible to allow an ABI-providing declaration to belong to a +different context than its counterpart—for instance, turning a global variable +into a static property, or moving a method to a single-property `@frozen` +wrapper struct. + +A particularly interesting one might be allowing an extension member to +be mangled as a member of the main type declaration, or vice versa, since users +may not be aware of the ABI impact of moving a declaration from one to the +other. + +### Equivalent type attribute + +Many uses of `@abi` only change one or two types in a complicated declaration. +It might be possible to provide an `@abi` *type* attribute that can be applied +on the spot as a shorthand: + +```swift +public func runConcurrently( + _ body: @escaping @abi(() -> Void) @Sendable () -> Void +) { ... } + +// Equivalent to: +@abi(func runConcurrently(_: @escaping () -> Void)) +public func runConcurrently( + _ body: @escaping @Sendable () -> Void +) { ... } +``` + +### Support for moving declarations to a different module + +It might be possible to roll some of the functionality of the compiler-internal +`@_originallyDefinedIn` attribute into this attribute. + +## Alternatives considered + +### Many narrow features + +The original motivation for this proposal involved fairly narrow cases where +`@preconcurrency` was too blunt an instrument, such as suppressing the ABI +impact of one sendability annotation while leaving others intact. One could +imagine designing individual type or decl attributes for each specific change +one might wish to make, but this would require both a lot of effort from +compiler engineers to design a specific tool for each problem, and a lot of +effort from library maintainers to figure out which tool to apply to a given +task and how to use it. + +### An argument that describes the differences + +Rather than creating many totally separate features, one could imagine an +`@abi` declaration attribute with an argument list which somehow described the +differences between the API and ABI. However, we see use cases for changing +virtually every aspect of an API—its name; adding or removing declaration +attributes, modifiers, and effects; adding or removing inherited protocols and +generic constraints; changing parameter, result, and error types; changing type +attributes and modifiers; even changing individual sub-types within generic +types, function types, and protocol compositions at any position in the +declaration—and a mini-language to address and edit all of these different +aspects of a declaration seems difficult to design and tedious to learn. +By contrast, re-specifying the entire declaration in the argument reuses the +developer's existing knowledge of how to read and write declarations and gives +them an easy way to adopt it (just copy the existing declaration into an `@abi` +attribute before you start editing in new features). + +### Syntax where the two declarations are peers + +We could design this differently such that the API-only and ABI-only +declarations are peers in the same context: + +```swift +// This declaration provides the ABI... +@abi(for: __rethrows_map(_:)) @usableFromInline func map( + _ transform: (Element) throws -> T +) rethrows -> [T] + +// ...for this declaration +@usableFromInline func __rethrows_map( + _ transform: (Element) throws -> T +) throws -> [T] { + try map(transform) +} +``` + +In theory, this design could simplify parsing, since the `@abi` attribute's +argument might just be an ordinary expression. However, it introduces several +complications: + +1. Merely giving the name of a declaration may not be specific enough in the + presence of overloads, or even when the API and ABI have the same name but + slight type differences. We might normally tell developers to work around + this by using more specific names, but that's not really an appropriate + answer for a tool which is designed to allow fine control of API and ABI + naming. +2. A lot of compiler logic would have to be modified to filter out ABI-only or + API-only declarations when it walked through lists of top-level decls or + members. The current design, where the ABI-only declarations are tucked away + in attributes, keeps them from being accessed by accident. +3. If the future direction for `@abi` on type declarations is taken, the + productions for full type declarations will not be suitable, as they require + member blocks. + +## Acknowledgments + +Thanks to Holly Borla for recognizing the need for an `@abi` attribute. From 4b0e497abab19d0e548c3732c63450170a9fa0a9 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 11 Apr 2025 08:59:34 -0700 Subject: [PATCH 223/505] Link to review thread in SE-0476. (#2788) --- proposals/0476-abi-attr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0476-abi-attr.md b/proposals/0476-abi-attr.md index a4e409cd26..e7bea6bf57 100644 --- a/proposals/0476-abi-attr.md +++ b/proposals/0476-abi-attr.md @@ -5,7 +5,7 @@ * Review Manager: [Holly Borla](https://github.com/hborla) * Status: **Active Review (April 11 - April 25, 2025)** * Implementation: behind experimental feature `ABIAttribute` (refinements in [swiftlang/swift#80383](https://github.com/swiftlang/swift/pull/80383)) -* Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) +* Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) ([review](https://forums.swift.org/t/se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79233)) ## Introduction From fdfc7867df4e35e29b2a24edee34ea4412ec15b0 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 11 Apr 2025 13:58:53 -0400 Subject: [PATCH 224/505] Add missing conformances to `CustomStringConvertible` and `Equatable` in exit tests proposal. This PR adds a couple of missing protocol conformances to types in the exit tests proposal. --- proposals/testing/0008-exit-tests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index 4256c976ab..1145e3df17 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -274,7 +274,7 @@ extension ExitTest { /// - ``failure`` /// - ``exitCode(_:)`` /// - ``signal(_:)`` - public struct Condition: Sendable { + public struct Condition: Sendable, CustomStringConvertible { /// A condition that matches when a process terminates successfully with exit /// code `EXIT_SUCCESS`. /// @@ -351,7 +351,7 @@ by the `StatusAtExit` enumeration: #if SWT_NO_PROCESS_SPAWNING @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif -public enum StatusAtExit: Sendable { +public enum StatusAtExit: Sendable, Equatable, CustomStringConvertible { /// The process terminated with the given exit code. /// /// [...] From 15edadc8cdeed87393ffafd837aef3b5a8a2aeed Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 15 Apr 2025 11:26:50 -0400 Subject: [PATCH 225/505] [ST-0008] Update proposal for second review round. This PR incorporates feedback we have received so far (up to and past the start of the second/focused round of review.) --- proposals/testing/0008-exit-tests.md | 224 ++++++++++++++++++--------- 1 file changed, 153 insertions(+), 71 deletions(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index 1145e3df17..1950c173f4 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -6,6 +6,7 @@ * Status: **Active Review (April 10...April 21, 2025)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) +* Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/fdfc7867df4e35e29b2a24edee34ea4412ec15b0/proposals/testing/0008-exit-tests.md) * Review: ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)), ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction @@ -60,7 +61,7 @@ The function from earlier can then be tested using either of the new overloads: ```swift -await #expect(exitsWith: .failure) { +await #expect(processExitsWith: .failure) { var taco = Taco() taco.isDelicious = false eat(taco) // should trigger a precondition failure and process termination @@ -81,7 +82,7 @@ the testing library: /// - expectedExitCondition: The expected exit condition. /// - observedValues: An array of key paths representing results from within /// the exit test that should be observed and returned by this macro. The -/// ``ExitTest/Result/statusAtExit`` property is always returned. +/// ``ExitTest/Result/exitStatus`` property is always returned. /// - comment: A comment describing the expectation. /// - sourceLocation: The source location to which recorded expectations and /// issues should be attributed. @@ -96,7 +97,7 @@ the testing library: /// the test passes or fails. For example, to test that calling `fatalError()` /// causes a process to terminate: /// -/// await #expect(exitsWith: .failure) { +/// await #expect(processExitsWith: .failure) { /// fatalError() /// } /// @@ -128,7 +129,7 @@ the testing library: /// these streams, you can pass its key path in the `observedValues` argument: /// /// let result = await #expect( -/// exitsWith: .failure, +/// processExitsWith: .failure, /// observing: [\.standardOutputContent] /// ) { /// print("Goodbye, world!") @@ -157,7 +158,7 @@ the testing library: /// /// @Test(arguments: 100 ..< 200) /// func sellIceCreamCones(count: Int) async { -/// await #expect(exitsWith: .failure) { +/// await #expect(processExitsWith: .failure) { /// precondition( /// count < 10, // ERROR: A C function pointer cannot be formed from a /// // closure that captures context @@ -172,7 +173,7 @@ the testing library: #endif @discardableResult @freestanding(expression) public macro expect( - exitsWith expectedExitCondition: ExitTest.Condition, + processExitsWith expectedExitCondition: ExitTest.Condition, observing observedValues: [any PartialKeyPath & Sendable] = [], _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, @@ -188,7 +189,7 @@ the testing library: #endif @discardableResult @freestanding(expression) public macro require( - exitsWith expectedExitCondition: ExitTest.Condition, + processExitsWith expectedExitCondition: ExitTest.Condition, observing observedValues: [any PartialKeyPath & Sendable] = [], _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, @@ -202,7 +203,8 @@ the testing library: > support exit tests (generally because it does not support spawning or awaiting > child processes), then we define `SWT_NO_EXIT_TESTS` when we build it. > -> `SWT_NO_EXIT_TESTS` is not defined during test target builds. +> `SWT_NO_EXIT_TESTS` is not defined during test target builds and is presented +> here for illustrative purposes only. ### Representing an exit test in Swift @@ -212,9 +214,9 @@ A new type, `ExitTest`, represents an exit test: /// A type describing an exit test. /// /// Instances of this type describe exit tests you create using the -/// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or -/// ``require(exitsWith:observing:_:sourceLocation:performing:)`` macro. You -/// don't usually need to interact directly with an instance of this type. +/// ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` or +/// ``require(processExitsWith:observing:_:sourceLocation:performing:)`` macro. +/// You don't usually need to interact directly with an instance of this type. #if SWT_NO_EXIT_TESTS @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -260,8 +262,8 @@ extension ExitTest { /// /// Values of this type are used to describe the conditions under which an /// exit test is expected to pass or fail by passing them to - /// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or - /// ``require(exitsWith:observing:_:sourceLocation:performing:)``. + /// ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` or + /// ``require(processExitsWith:observing:_:sourceLocation:performing:)``. /// /// ## Topics /// @@ -287,7 +289,7 @@ extension ExitTest { /// exit code other than `EXIT_SUCCESS` or with any signal. public static var failure: Self { get } - public init(_ statusAtExit: StatusAtExit) + public init(_ exitStatus: ExitStatus) /// Creates a condition that matches when a process terminates with a given /// exit code. @@ -337,7 +339,7 @@ extension ExitTest { ### Exit status The set of possible status codes reported by the child process are represented -by the `StatusAtExit` enumeration: +by the `ExitStatus` enumeration: ```swift /// An enumeration describing possible status a process will yield on exit. @@ -346,12 +348,12 @@ by the `StatusAtExit` enumeration: /// ``ExitTest/Condition`` using ``ExitTest/Condition/init(_:)``. That value /// can then be used to describe the condition under which an exit test is /// expected to pass or fail by passing it to -/// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or -/// ``require(exitsWith:observing:_:sourceLocation:performing:)``. +/// ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` or +/// ``require(processExitsWith:observing:_:sourceLocation:performing:)``. #if SWT_NO_PROCESS_SPAWNING @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif -public enum StatusAtExit: Sendable, Equatable, CustomStringConvertible { +public enum ExitStatus: Sendable, Equatable, CustomStringConvertible { /// The process terminated with the given exit code. /// /// [...] @@ -378,15 +380,15 @@ extension ExitTest { /// A type representing the result of an exit test after it has exited and /// returned control to the calling test function. /// - /// Both ``expect(exitsWith:observing:_:sourceLocation:performing:)`` and - /// ``require(exitsWith:observing:_:sourceLocation:performing:)`` return - /// instances of this type. + /// Both ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` + /// and ``require(processExitsWith:observing:_:sourceLocation:performing:)`` + /// return instances of this type. public struct Result: Sendable { /// The status of the process hosting the exit test at the time it exits. /// /// When the exit test passes, the value of this property is equal to the /// exit status reported by the process that hosted the exit test. - public var statusAtExit: StatusAtExit { get set } + public var exitStatus: ExitStatus { get set } /// All bytes written to the standard output stream of the exit test before /// it exited. @@ -407,8 +409,8 @@ extension ExitTest { /// /// To enable gathering output from the standard output stream during an /// exit test, pass `\.standardOutputContent` in the `observedValues` - /// argument of ``expect(exitsWith:observing:_:sourceLocation:performing:)`` - /// or ``require(exitsWith:observing:_:sourceLocation:performing:)``. + /// argument of ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` + /// or ``require(processExitsWith:observing:_:sourceLocation:performing:)``. /// /// If you did not request standard output content when running an exit test, /// the value of this property is the empty array. @@ -429,7 +431,7 @@ These macros can be used within a test function: ```swift @Test func `We only eat delicious tacos`() async { - await #expect(exitsWith: .failure) { + await #expect(processExitsWith: .failure) { var taco = Taco() taco.isDelicious = false eat(taco) @@ -444,13 +446,14 @@ exit condition, this is treated as a successful test. It is often interesting to examine what is written to the standard output and standard error streams by code running in an exit test. Callers can request that either or both stream be captured and included in the result of the call to -`#expect(exitsWith:)` or `#require(exitsWith:)`. Capturing these streams can be -a memory-intensive operation, so the caller must explicitly opt in: +`#expect(processExitsWith:)` or `#require(processExitsWith:)`. Capturing these +streams can be a memory-intensive operation, so the caller must explicitly opt +in: ```swift @Test func `We only eat delicious tacos`() async throws { let result = try await #require( - exitsWith: .failure, + processExitsWith: .failure, observing: [\.standardErrorContent]) ) { ... } let stdout = result.standardOutputContent @@ -497,12 +500,12 @@ extension ExitTest { /// observed and returned to the caller. /// /// The testing library sets this property to match what was passed by the - /// developer to the `#expect(exitsWith:)` or `#require(exitsWith:)` macro. - /// If you are implementing an exit test handler, you can check the value of - /// this property to determine what information you need to preserve from your - /// child process. + /// developer to the `#expect(processExitsWith:)` or `#require(processExitsWith:)` + /// macro. If you are implementing an exit test handler, you can check the + /// value of this property to determine what information you need to preserve + /// from your child process. /// - /// The value of this property always includes ``ExitTest/Result/statusAtExit`` + /// The value of this property always includes ``ExitTest/Result/exitStatus`` /// even if the test author does not specify it. /// /// Within a child process running an exit test, the value of this property is @@ -512,9 +515,9 @@ extension ExitTest { /// Call the exit test in the current process. /// /// This function invokes the closure originally passed to - /// `#expect(exitsWith:)` _in the current process_. That closure is expected - /// to terminate the process; if it does not, the testing library will - /// terminate the process as if its `main()` function returned naturally. + /// `#expect(processExitsWith:)` _in the current process_. That closure is + /// expected to terminate the process; if it does not, the testing library + /// will terminate the process as if its `main()` function returned naturally. public consuming func callAsFunction() async -> Never /// Find the exit test function at the given source location. @@ -538,11 +541,11 @@ extension ExitTest { /// the exit test. /// /// This handler is invoked when an exit test (i.e. a call to either - /// ``expect(exitsWith:observing:_:sourceLocation:performing:)`` or - /// ``require(exitsWith:observing:_:sourceLocation:performing:)``) is started. - /// The handler is responsible for initializing a new child environment - /// (typically a child process) and running the exit test identified by - /// `sourceLocation` there. + /// ``expect(processExitsWith:observing:_:sourceLocation:performing:)`` or + /// ``require(processExitsWith:observing:_:sourceLocation:performing:)``) is + /// started. The handler is responsible for initializing a new child + /// environment (typically a child process) and running the exit test + /// identified by `sourceLocation` there. /// /// In the child environment, you can find the exit test again by calling /// ``ExitTest/find(at:)`` and can run it by calling @@ -587,6 +590,11 @@ Android _does_ have `posix_spawn()` and related API and may be able to use the same implementation as Linux. Android support is an ongoing area of research for Swift Testing's core team. +> [!NOTE] +> In the event we can add support for exit tests on a new platform _without_ any +> changes to the feature's public interface, the Testing Workgroup has agreed +> that an additional Swift Evolution proposal will not be necessary. + ### Recursive exit tests The technical constraints preventing recursive exit test invocation can be @@ -610,9 +618,9 @@ could leverage closures' capture list syntax. Subjectively, capture lists ought to be somewhat intuitive for developers in this context: ```swift -let (lettuce, cheese, crema) = taco.addToppings() -await #expect(exitsWith: .failure) { [taco, plant = lettuce, cheese, crema] in - try taco.removeToppings(plant, cheese, crema) +let (lettuce, cheese) = taco.addToppings() +await #expect(processExitsWith: .failure) { [taco, plant = lettuce, cheese] in + try taco.removeToppings(plant, cheese) } ``` @@ -624,7 +632,7 @@ explicit or implicit `main() throws` function: the process terminates abnormally and control returns to the test function that is awaiting the exit test: ```swift -await #expect(exitsWith: .failure) { +await #expect(processExitsWith: .failure) { throw TacoError.noTacosFound } ``` @@ -671,6 +679,24 @@ let result = try await #require(process, exitsWith: .success) #expect(result.standardOutputContent.contains("Build went well!").utf8) ``` +### Conformance of ExitStatus to ExpressibleByIntegerLiteral + +A contributor on the Swift forums suggested having `ExitStatus` conform to +[`ExpressibleByIntegerLiteral`](https://developer.apple.com/documentation/swift/expressiblebyintegerliteral) +and interpreting an integer literal as an exit code, such that a test author +could write: + +```swift +await #expect(processExitsWith: EX_CANTCREAT) { + ... +} +``` + +This would be convenient for test authors who are dealing with a variety of exit +codes, but is beyond the scope of this proposal. Adding conformance to this +protocol also requires some care to ensure that signal constants such as +`SIGABRT` cannot be accidentally interpreted as exit codes. + ## Alternatives considered - Doing nothing. @@ -729,7 +755,35 @@ let result = try await #require(process, exitsWith: .success) sound "right" when the entire expression is read out loud. For example, you probably wouldn't say "exits due to success" in English. -- Combining `StatusAtExit` and `ExitTest.Condition` into a single type: + A contributor in the Swift forums suggested `#expect(crashes:)`: + + ```swift + await #expect(crashes: { + ... + }) + ``` + + This would preclude the possibility of writing an exit test that is expected + to exit successfully—a scenario for which we have real-world use cases. It was + also not clear that the word "crash" applied to every failing exit status. For + example, a process that exits with the POSIX-defined exit code `EX_TEMPFAIL` + likely has not _crashed_; it has just reported that the requested operation + has failed. + + This signature would also be subject to label elision when used with trailing + closure syntax, resulting in: + + ```swift + await #expect { + ... + } + ``` + + The lack of any distinguishing label here would unacceptably impact the test's + readability as it gives no indication that the code is running out-of-process + or is expected to terminate its process. + +- Combining `ExitStatus` and `ExitTest.Condition` into a single type: ```swift enum ExitCondition { @@ -743,35 +797,46 @@ let result = try await #require(process, exitsWith: .success) exit conditions complicated and necessitated a `==` operator that did not satisfy the requirements of the `Equatable` protocol. -- Naming `StatusAtExit` something else such as: +- Naming `ExitStatus` something else such as: - - `ExitStatus`, which could be too easily confusable with exit _codes_ such as - `EXIT_SUCCESS`; + - `StatusAtExit`, which might avoid some confusion with exit _codes_ but which + is not idiomatic Swift; - `ProcessStatus`, but we don't say "process" in our API surface elsewhere; - `Status`, which is too generic, - `ExitReason`, but "status" is a more widely-used term of art for this concept; or - - `terminationStatus` (which Foundation to represent approximately the same - concept), but we don't use "termination" in Swift Testing's API anywhere. - - I settled on `StatusAtExit` because it was distinct and makes it clear that it - represents the status of a process _at exit time_. `ExitStatus` could be - interpreted as the status of the exit itself, i.e.: - - ```swift - enum ExitStatus { - case running - case suspended - case exiting - case exited - } - ``` + - `TerminationStatus` (which Foundation uses to represent approximately the + same concept), but we don't use "termination" in Swift Testing's API + anywhere. + + In particular, there was some interest in using "termination" instead of + "exit" for consistency with Foundation. Foundation and the upcoming + `Subprocess` package use both terms interchangeably, so there is precedent for + either. "Exit" is more concise; "terminate" may be read to imply that the + process was _forced_ to stop running. + +- Naming `ExitStatus.exitCode(_:)` just `.code(_:)`. Some contributors on the + forums felt that the use of "exit" here was redundant given the proposed + `exitsWith:` and `processExitsWith:` labels. However, "code" is potentially + ambiguous: does it refer to an exit code, a signal code, the code the test + author is writing, etc.? + + We certainly don't want the exit test interface to be redundant. However, + given that: + + - We _expect_ (no pun intended) most uses of exit tests will check for + `.failure` rather than a specific exit code; + - "Exit code" is an established term of art; and + - `.exitCode(_:)` may appear in other contexts (not just as an argument to + `#expect(processExitsWith:)`) + + We have opted to keep the full case name. - Using parameter packs to specify observed values and return types: ```swift @freestanding(expression) public macro require( - exitsWith expectedExitCondition: ExitTest.Condition, + processExitsWith expectedExitCondition: ExitTest.Condition, observing observedValues: (repeat (KeyPath)) = (), _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, @@ -785,17 +850,17 @@ let result = try await #require(process, exitsWith: .success) ```swift let (status, stderr) = try await #expect( - exitsWith: .failure, - observing: (\.statusAtExit, \.standardErrorContent) + processExitsWith: .failure, + observing: (\.exitStatus, \.standardErrorContent) ) { ... } #expect(status == ...) #expect(stderr.contains(...)) ``` - Unfortunately, the `#expect(exitsWith:)` and `#require(exitsWith:)` macros do - not have enough information at compile time to correctly infer the types of - the key paths passed as `observedValues` above, so we end up with rather - obscure errors: + Unfortunately, the `#expect(processExitsWith:)` and `#require(processExitsWith:)` + macros do not have enough information at compile time to correctly infer the + types of the key paths passed as `observedValues` above, so we end up with + rather obscure errors: > 🛑 Cannot convert value of type 'KeyPath<_, _>' to expected argument type > 'KeyPath' @@ -820,6 +885,23 @@ let result = try await #require(process, exitsWith: .success) Modifying the C or C++ standard library, or modifying the Objective-C runtime, would be well beyond the scope of this proposal. +- Skipping test functions containing exit tests on platforms that do not support + exit tests. + + This would avoid the need to write `if os(...)`, `@available(...)`, or + `if #available(...)` in a cross-platform test function before using exit + tests. Swift Testing does not currently support skipping a test that has + already started executing, and the implementation of such a feature is beyond + the scope of this proposal. + + Even if the library supported this sort of action, it would likely be + surprising to test authors that they could write a test that compiles for e.g. + iOS but doesn't run and doesn't report any problems. + + Further, in general this is not a pattern that is used in the Swift ecosystem + for platform-specific functionality; instead, `#if os(...)` and availability + checks are the normal way to mark code as platform-specific. + ## Acknowledgments Many thanks to the XCTest and Swift Testing team. Thanks to @compnerd for his From 1ca81dcb3e50efe1af9c89768c07dc29c05c1309 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Tue, 15 Apr 2025 11:59:06 -0700 Subject: [PATCH 226/505] Test Issue Warnings --- .../testing/XXXX-issue-severity-warning.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 proposals/testing/XXXX-issue-severity-warning.md diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md new file mode 100644 index 0000000000..4aa5f4b4a2 --- /dev/null +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -0,0 +1,99 @@ +# [DRAFT] Test Issue Warnings + +* Proposal: [ST-XXXX](XXXX-issue-severity-warning.md) +* Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) +* Review Manager: TBD +* Status: **Pitched** +* Bug: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) +* Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) + +## Introduction + +I propose introducing a new API to Swift Testing that allows developers to record issues with a specified severity level. By default, all issues will have severity level “error”, and a new “warning” level will be added to represent less severe issues. The effects of the warning recorded on a test will not cause a failure but will be included in the test results for inspection after the run is complete. + +## Motivation + +Currently, when an issue arises during a test, the only possible outcome is to mark the test as failed. This presents a challenge for users who want a deeper insight into the events occurring within their tests. By introducing a dedicated mechanism to record issues that do not cause test failure, users can more effectively inspect and diagnose problems at runtime and review results afterward. This enhancement provides greater flexibility and clarity in test reporting, ultimately improving the debugging and analysis process. + +## Proposed solution +We propose introducing a new property on Issues in Swift Testing called `Severity`, that represents if an issue is a warning or an error. +The default Issue severity will still be error and users can create set the severity when they record an issue. + +Test authors will be able to inspect if the issue is a failing issue and will be able to check the severity. + +## Detailed design + +*Severity Enum* + +We introduce a Severity enum to categorize issues detected during testing. This enum is crucial for distinguishing between different levels of test issues and is defined as follows: + +The `Severity` enum is defined as follows: + +```swift + public enum Severity: Sendable { + /// The severity level for an issue which should be noted but is not + /// necessarily an error. + /// + /// An issue with warning severity does not cause the test it's associated + /// with to be marked as a failure, but is noted in the results. + case warning + + /// The severity level for an issue which represents an error in a test. + /// + /// An issue with error severity causes the test it's associated with to be + /// marked as a failure. + case error + } +``` + +*Recording Non-Failing Issues* +To enable test authors to log non-failing issues without affecting test results, we provide a method for recording such issues: + +```swift +Issue.record("My comment", severity: .warning) +``` + +*Issue Type Enhancements* +The Issue type is enhanced with two new properties to better handle and report issues: +- `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. + +```swift +/// The severity of the issue. +public var severity: Severity + +``` +- `isFailure`: A boolean property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. +```swift + + /// Whether or not this issue should cause the test it's associated with to be + /// considered a failure. + /// + /// The value of this property is `true` for issues which have a severity level of + /// ``Issue/Severity/error`` or greater and are not known issues via + /// ``withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)``. + /// Otherwise, the value of this property is `false.` + /// + /// Use this property to determine if an issue should be considered a failure, instead of + /// directly comparing the value of the ``severity`` property. +public var isFailure: Bool +``` + +For more details, refer to the [Issue Documentation](https://developer.apple.com/documentation/testing/issue). + +This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. + +## Alternatives considered + +- Doing Nothing: Although there have been recurring requests over the years to support non-failing issues, we did not have a comprehensive solution until now. This year, we finally had the necessary components to implement this feature effectively. + +- Separate Issue Creation and Recording: We considered providing a mechanism to create issues independently before recording them, rather than passing the issue details directly to the `record` method. This approach was ultimately set aside in favor of simplicity and directness in usage. + +- Naming of `isFailure` vs. `isFailing`: We evaluated whether to name the property `isFailing` instead of `isFailure`. The decision to use `isFailure` was made to adhere to naming conventions and ensure clarity and consistency within the API. + +- Severity-Only Checking: We deliberated not exposing `isFailure` and relying solely on `severity` checks. However, this was rejected because it would require test authors to overhaul their code should we introduce additional severity levels in the future. By providing `isFailure`, we offer a straightforward way to determine test outcome impact, complementing the severity feature. + +## Acknowledgments + +Thanks to Stuart Montgomery for creating and implementing severity in Swift Testing. + +Thanks to Brian Croom and Jonathan Grynspan for feedback on warnings along the way. From dbcea32f69f5d4fb24162536b9e1945f4c48b51f Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Wed, 16 Apr 2025 08:48:20 -0500 Subject: [PATCH 227/505] Add a proposal for a string interpolation default parameter (#2772) * Add a proposal for the string interpolation default parameter * Claim SE-0477 and prepare for review --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- .../0477-default-interpolation-values.md | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 proposals/0477-default-interpolation-values.md diff --git a/proposals/0477-default-interpolation-values.md b/proposals/0477-default-interpolation-values.md new file mode 100644 index 0000000000..8856ea150f --- /dev/null +++ b/proposals/0477-default-interpolation-values.md @@ -0,0 +1,171 @@ +# Default Value in String Interpolations + +* Proposal: [SE-0477](0477-default-interpolation-values.md) +* Authors: [Nate Cook](https://github.com/natecook1000) +* Review Manager: [Xiaodi Wu](https://github.com/xwu) +* Status: **Active review (April 16...29, 2025)** +* Implementation: [swiftlang/swift#80547](https://github.com/swiftlang/swift/pull/80547) +* Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) + +## Introduction + +A new string interpolation syntax for providing a default string +when interpolating an optional value. + +## Motivation + +String interpolations are a streamlined and powerful way to include values within a string literal. +When one of those values is optional, however, +interpolating is not so simple; +in many cases, a developer must fall back to unpalatable code +or output that exposes type information. + +For example, +placing an optional string in an interpolation +yields an important warning and two suggested fixes, +only one of which is ideal: + +```swift +let name: String? = nil +print("Hello, \(name)!") +// warning: string interpolation produces a debug description for an optional value; did you mean to make this explicit? +// print("Hello, \(name)!") +// ^~~~ +// note: use 'String(describing:)' to silence this warning +// print("Hello, \(name)!") +// ^~~~ +// String(describing: ) +// note: provide a default value to avoid this warning +// print("Hello, \(name)!") +// ^~~~ +// ?? <#default value#> + +``` + +The first suggestion, adding `String(describing:)`, +silences the warning but includes `nil` in the output of the string — +maybe okay for a quick shell script, +but not really appropriate result for anything user-facing. + +The second suggestion is good, +allowing us to provide whatever default string we'd like: + +```swift +let name: String? = nil +print("Hello, \(name ?? "new friend")!") +``` + +However, the nil-coalescing operator (`??`) +only works with values of the same type as the optional value, +making it awkward or impossible to use when providing a default for non-string types. +In this example, the `age` value is an optional `Int`, +and there isn't a suitable integer to use when it's `nil`: + +```swift +let age: Int? = nil +print("Your age: \(age)") +// warning, etc.... +``` + +To provide a default string when `age` is missing, +we have to write some gnarly code, +or split out the missing case altogether: + +```swift +let age: Int? = nil +// Optional.map +print("Your age: \(age.map { "\($0)" } ?? "missing")") +// Ternary expression +print("Your age: \(age != nil ? "\(age!)" : "missing")") +// if-let statement +if let age { + print("Your age: \(age)") +} else { + print("Your age: missing") +} +``` + +## Proposed solution + +The standard library should add a string interpolation overload +that lets you write the intended default as a string, +no matter what the type of value: + +```swift +let age: Int? = nil +print("Your age: \(age, default: "missing")") +// Prints "Your age: missing" +``` + +This addition will improve the clarity of code that uses string interpolations +and encourage developers to provide sensible defaults +instead of letting `nil` leak into string output. + +## Detailed design + +The implementation of this new interpolation overload looks like this, +added as an extension to the `DefaultStringInterpolation` type: + +```swift +extension DefaultStringInterpolation { + mutating func appendInterpolation( + _ value: T?, + default: @autoclosure () -> String + ) { + if let value { + self.appendInterpolation(value) + } else { + self.appendInterpolation(`default`()) + } + } +} +``` + +The new interpolation's `default:` parameter name +matches the one in the `Dictionary` subscript that has a similar purpose. + +You can try this out yourself by copy/pasting the snippet above into a project or playground, +or by experimenting with [this Swift Fiddle](https://swiftfiddle.com/nxttprythnfbvlm4hwjyt2jbjm). + +## Source compatibility + +This proposal adds one new API to the standard library, +which should not be source-breaking for any existing projects. +If a project or a dependency has added a similar overload, +it will take precedence over the new standard library API. + +## ABI compatibility + +This proposal is purely an extension of the ABI of the +standard library and does not change any existing features. + +## Implications on adoption + +The new API will be included in a new version of the Swift runtime, +and is marked as backward deployable. + +## Future directions + +There are [some cases][reflecting] where a `String(reflecting:)` conversion +is more appropriate than the `String(describing:)` normally used via string interpolation. +Additional string interpolation overloads could make it easier to use that alternative conversion, +and to provide a default when working with optional values. + +[reflecting]: https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381/58 + +## Alternatives considered + +**An interpolation like `"\(describing: value)"`** +This alternative would provide a shorthand for the first suggested fix, +using `String(describing:)`. +Unlike the solution proposed, +this kind of interpolation doesn't make it clear that you're working with an optional value, +so you could end up silently including `nil` in output without expecting it +(which is the original reason for the compiler warnings). + +**Extend `StringInterpolationProtocol` instead** +The proposed new interpolation works with _any_ optional value, +but some types only accept a limited or constrained set of types interpolations. +If the new `\(_, default:)` interpolation proves to be a useful pattern, +other types can add it as appropriate. + From 93037c0f5dfefd5dfcdbf40f4e609f57fb713037 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:52:16 -0400 Subject: [PATCH 228/505] SE-0477: Add link to review thread (#2791) --- proposals/0477-default-interpolation-values.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0477-default-interpolation-values.md b/proposals/0477-default-interpolation-values.md index 8856ea150f..60248240ab 100644 --- a/proposals/0477-default-interpolation-values.md +++ b/proposals/0477-default-interpolation-values.md @@ -5,7 +5,7 @@ * Review Manager: [Xiaodi Wu](https://github.com/xwu) * Status: **Active review (April 16...29, 2025)** * Implementation: [swiftlang/swift#80547](https://github.com/swiftlang/swift/pull/80547) -* Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) +* Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) ([review](https://forums.swift.org/t/se-0477-default-value-in-string-interpolations/79302)) ## Introduction From 7f16311d11a01b95fd48b6e33d22f03dfcb2de9c Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 16 Apr 2025 10:02:55 -0700 Subject: [PATCH 229/505] Mark SE-0452 and SE-0453 as implemented --- proposals/0452-integer-generic-parameters.md | 2 +- proposals/0453-vector.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0452-integer-generic-parameters.md b/proposals/0452-integer-generic-parameters.md index faa05bb4d7..b2ca7b2083 100644 --- a/proposals/0452-integer-generic-parameters.md +++ b/proposals/0452-integer-generic-parameters.md @@ -3,7 +3,7 @@ * Proposal: [SE-0452](0452-integer-generic-parameters.md) * Authors: [Alejandro Alonso](https://github.com/Azoy), [Joe Groff](https://github.com/jckarter) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#75518](https://github.com/swiftlang/swift/pull/75518), [swiftlang/swift#78248](https://github.com/swiftlang/swift/pull/78248) * Review: ([pitch](https://forums.swift.org/t/integer-generic-parameters/74181)) ([first review](https://forums.swift.org/t/se-0452-integer-generic-parameters/75844)) ([second review](https://forums.swift.org/t/second-review-se-0452-integer-generic-parameters/77043)) ([acceptance](https://forums.swift.org/t/accepted-se-0452-integer-generic-parameters/77507)) diff --git a/proposals/0453-vector.md b/proposals/0453-vector.md index 7d143f7413..d755bf66f1 100644 --- a/proposals/0453-vector.md +++ b/proposals/0453-vector.md @@ -3,7 +3,7 @@ * Proposal: [SE-0453](0453-vector.md) * Authors: [Alejandro Alonso](https://github.com/Azoy) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [Approaches for fixed-size arrays](https://forums.swift.org/t/approaches-for-fixed-size-arrays/58894) * Implementation: [swiftlang/swift#76438](https://github.com/swiftlang/swift/pull/76438) * Review: ([pitch](https://forums.swift.org/t/vector-a-fixed-size-array/75264)) ([first review](https://forums.swift.org/t/se-0453-vector-a-fixed-size-array/76004)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0453-vector-a-fixed-size-array/76411)) ([second review](https://forums.swift.org/t/second-review-se-0453-vector-a-fixed-size-array/76412)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0453-inlinearray-formerly-vector-a-fixed-size-array/77678)) From 48728ee0a8f491b84f501455d49352367891f069 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 16 Apr 2025 14:46:37 -0400 Subject: [PATCH 230/505] Return SE-0472 for revision. --- proposals/0472-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index ae636da68c..836920fce3 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -3,9 +3,9 @@ * Proposal: [SE-0472](0472-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Active Review (March 27...April 10, 2025)** +* Status: **Returned for revision** * Implementation: https://github.com/swiftlang/swift/pull/79608 -* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) +* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ## Introduction From a1fcbcbc51e3ef4f313cf29ce51c7c5a5d39c695 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 17 Apr 2025 14:51:29 -0700 Subject: [PATCH 231/505] Clean up format --- proposals/testing/XXXX-issue-severity-warning.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 4aa5f4b4a2..823c19e846 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -1,4 +1,4 @@ -# [DRAFT] Test Issue Warnings +# Test Issue Severity * Proposal: [ST-XXXX](XXXX-issue-severity-warning.md) * Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) @@ -16,8 +16,8 @@ I propose introducing a new API to Swift Testing that allows developers to recor Currently, when an issue arises during a test, the only possible outcome is to mark the test as failed. This presents a challenge for users who want a deeper insight into the events occurring within their tests. By introducing a dedicated mechanism to record issues that do not cause test failure, users can more effectively inspect and diagnose problems at runtime and review results afterward. This enhancement provides greater flexibility and clarity in test reporting, ultimately improving the debugging and analysis process. ## Proposed solution -We propose introducing a new property on Issues in Swift Testing called `Severity`, that represents if an issue is a warning or an error. -The default Issue severity will still be error and users can create set the severity when they record an issue. +We propose introducing a new property on `Issue` in Swift Testing called `Severity`, that represents if an issue is a `warning` or an `error`. +The default Issue severity will still be `error` and users can set the severity when they record an issue. Test authors will be able to inspect if the issue is a failing issue and will be able to check the severity. @@ -27,7 +27,7 @@ Test authors will be able to inspect if the issue is a failing issue and will be We introduce a Severity enum to categorize issues detected during testing. This enum is crucial for distinguishing between different levels of test issues and is defined as follows: -The `Severity` enum is defined as follows: +The `Severity` enum: ```swift public enum Severity: Sendable { @@ -54,16 +54,20 @@ Issue.record("My comment", severity: .warning) ``` *Issue Type Enhancements* + The Issue type is enhanced with two new properties to better handle and report issues: - `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. ```swift +// ... + /// The severity of the issue. public var severity: Severity ``` - `isFailure`: A boolean property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. ```swift +// ... /// Whether or not this issue should cause the test it's associated with to be /// considered a failure. @@ -78,7 +82,7 @@ public var severity: Severity public var isFailure: Bool ``` -For more details, refer to the [Issue Documentation](https://developer.apple.com/documentation/testing/issue). +For more details on `Issue`, refer to the [Issue Documentation](https://developer.apple.com/documentation/testing/issue). This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. From 6f26d42f35f02188e2437323c967d706d1951d98 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 17 Apr 2025 15:55:42 -0700 Subject: [PATCH 232/505] Add example for isFailure and severity --- proposals/testing/XXXX-issue-severity-warning.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 823c19e846..2fd9364bd2 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -82,6 +82,16 @@ public var severity: Severity public var isFailure: Bool ``` +Example usage of `severity` and `isFailure: +```swift +// ... +withKnownIssue { + // ... +} matching: { issue in + return issue.isFailure || issue.severity > .warning +} +``` + For more details on `Issue`, refer to the [Issue Documentation](https://developer.apple.com/documentation/testing/issue). This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. From 55dd90e54fa9292565160c74cc982e652cf47bf4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 18 Apr 2025 09:58:58 -0700 Subject: [PATCH 233/505] SE-0470 is implemented in Swift 6.2 --- proposals/0470-isolated-conformances.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index 146dcd95bd..83c4b3a51a 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -3,7 +3,7 @@ * Proposal: [SE-0470](0470-isolated-conformances.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` From 65ba8836d7303e1f5465bd0cbd5602bb6347ce8c Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Fri, 18 Apr 2025 10:12:28 -0700 Subject: [PATCH 234/505] Add Acknowledgments --- proposals/testing/XXXX-issue-severity-warning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 2fd9364bd2..05c122ff61 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -110,4 +110,4 @@ This revision aims to clarify the functionality and usage of the `Severity` enum Thanks to Stuart Montgomery for creating and implementing severity in Swift Testing. -Thanks to Brian Croom and Jonathan Grynspan for feedback on warnings along the way. +Thanks to Joel Middendorf, Dorothy Fu, Brian Croom, and Jonathan Grynspan for feedback on severity along the way. From ddffc2e7074dfb90ca022baa5953932a1f1fb608 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 21 Apr 2025 18:30:51 -0700 Subject: [PATCH 235/505] Add a proposal for specifying default actor isolation per-file using a type alias. (#2777) * Add a draft proposal for specifying default isolation via typealias. * Clarify that it is invalid to use `Never` as the underlying type of `DefaultIsolation`. * Update and rename NNNN-default-isolation-typealias.md to 0478-default-isolation-typealias.md Assigned SE-0478 --------- Co-authored-by: Stephen Canon --- proposals/0478-default-isolation-typealias.md | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 proposals/0478-default-isolation-typealias.md diff --git a/proposals/0478-default-isolation-typealias.md b/proposals/0478-default-isolation-typealias.md new file mode 100644 index 0000000000..35f2adadb2 --- /dev/null +++ b/proposals/0478-default-isolation-typealias.md @@ -0,0 +1,115 @@ +# Default actor isolation typealias + +* Proposal: [SE-0478](0478-default-isolation-typealias.md) +* Authors: [Holly Borla](https://github.com/hborla) +* Review Manager: [Steve Canon](https://github.com/stephentyrone) +* Status: **Active Review (April 21 ... May 5, 2025)** +* Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) +* Implementation: [swiftlang/swift#80572](https://github.com/swiftlang/swift/pull/80572) +* Experimental Feature Flag: `DefaultIsolationTypealias` +* Previous Proposal: [SE-0466: Control default actor isolation inference][SE-0466] +* Review: ([pitch](https://forums.swift.org/t/pitch-a-typealias-for-per-file-default-actor-isolation/79150)) + +## Introduction + +[SE-0466: Control default actor isolation inference][SE-0466] introduced the ability to specify default actor isolation on a per-module basis. This proposal introduces a new typealias for specifying default actor isolation in individual source files within a module. This allows specific files to opt out of main actor isolation within a main-actor-by-default module, and opt into main actor isolation within a nonisolated-by-default module. + +## Motivation + +SE-0466 allows code to opt in to being “single-threaded” by default by isolating everything in the module to the main actor. When the programmer really wants concurrency, they can request it explicitly by marking a function or type as `nonisolated`, or they can define it in a module that does not default to main-actor isolation. However, it's very common to group multiple declarations used in concurrent code into one source file or a small set of source files. Instead of choosing between writing `nonisolated` on each individual declaration or splitting those files into a separate module, it's desirable to state that all declarations in those files default to `nonisolated`. + +## Proposed solution + +This proposal allows writing a private typealias named `DefaultIsolation` to specify the default actor isolation for a file. + +An underlying type of `MainActor` specifies that all declarations in the file default to main actor isolated: + +```swift +// main.swift + +private typealias DefaultIsolation = MainActor + +// Implicitly '@MainActor' +var global = 0 + +// Implicitly '@MainActor' +func main() { ... } + +main() +``` + +An underlying type of `nonisolated` specifies that all declarations in the file default to `nonisolated`: + +```swift +// Point.swift + +private typealias DefaultIsolation = nonisolated + +// Implicitly 'nonisolated' +struct Point { + var x: Int + var y: Int +} +``` + +## Detailed design + + A typealias named `DefaultIsolation` can specify the actor isolation to use for the source file it's written in under the following conditions: + +* The typealias is written at the top-level. +* The typealias is `private` or `fileprivate`; the `DefaultIsolation` typealias cannot be used to set the default isolation for the entire module, so its access level cannot be `internal` or above. +* The underlying type is either `MainActor` or `nonisolated`. + + It is not invalid to write a typealias called `DefaultIsolation` that does not meet the above conditions. Any typealias named `DefaultIsolation` that does not meet the above conditions will be skipped when looking up the default isolation for the source file. The compiler will emit a warning for any `DefaultIsolation` typealias that is not considered for default actor isolation along with the reason why: + +```swift +@globalActor +actor CustomGlobalActor { + static let shared = CustomGlobalActor() +} + +private typealias DefaultIsolation = CustomGlobalActor // warning: not used for default actor isolation +``` + +To allow writing `nonisolated` as the underlying type of a typealias, this proposal adds a typealias named `nonisolated` to the Concurrency library: + +```swift +public typealias nonisolated = Never +``` + +This typealias serves no purpose beyond specifying default actor isolation. To specify `nonisolated` using the `DefaultIsolation` typealias, the underlying type must be `nonisolated` exactly; it is invalid to write `private typealias DefaultIsolation = Never`. + +## Source compatibility + +Technically source breaking if someone happens to have written a private `DefaultIsolation` typealias with an underlying type of `MainActor`, which will start to infer every declaration in that file as `@MainActor`-isolated after this change. This seems extremely unlikely. + +## ABI compatibility + +This proposal has no ABI impact on existing code. + +## Implications on adoption + +This proposal does not change the adoption implications of adding `@MainActor` to a declaration that was previously nonisolated and vice versa. The source and ABI compatibility implications of changing actor isolation are documented in the Swift migration guide's [Library Evolution](https://github.com/apple/swift-migration-guide/blob/29d6e889e3bd43c42fe38a5c3f612141c7cefdf7/Guide.docc/LibraryEvolution.md#main-actor-annotations) article. + +## Alternatives considered + +Adding a typealias named `nonisolated` to `Never` to the Concurrency library to enable writing it as the underlying type of a typealias is pretty strange; this approach leveraging the fact that `nonisolated` is a contextual keyword, so it's valid to use `nonisolated` as an identifier. This proposal uses a typealias instead of an empty struct or enum type to avoid the complications of having a new type be only available with the Swift 6.2 standard library. + +It's extremely valuable to have a consistent way to spell `nonisolated`. Introducing a type that follows standard naming conventions, such as `Nonisolated`, or using an existing type like `Never` is more consistent with recommended style, but overall complicates the concurrency model because it means you need to spell `nonisolated` differently when specifying it per file versus writing it on a declaration. And because the underlying type of this typealias is used to infer actor isolation, it's not used as a type in the same way that other typealiases are. + +Another alternative is to introduce a bespoke syntax such as `using MainActor` or `using nonisolated`. This approach preserves a consistent spelling for `nonisolated`, but at the cost of adding new language syntax that deviates from other defaulting rules such as the default literal types and the default actor system types. + +Having a `nonisolated` typealias may also allow us to improve the package manifest APIs for specifying default isolation, allowing us to move away from using `nil` to specify `nonisolated`: + +```swift +SwiftSetting.defaultIsolation(nonisolated.self) +``` + +We can also pursue allowing bare metatypes without `.self` to allow: + +```swift +SwiftSetting.defaultIsolation(nonisolated) +SwiftSetting.defaultIsolation(MainActor) +``` + +[SE-0466]: /proposals/0466-control-default-actor-isolation.md From 38229b1ca7ef5171ba139a50eadea168558aeeae Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Mon, 21 Apr 2025 21:36:53 -0400 Subject: [PATCH 236/505] Update 0478-default-isolation-typealias.md (#2797) --- proposals/0478-default-isolation-typealias.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0478-default-isolation-typealias.md b/proposals/0478-default-isolation-typealias.md index 35f2adadb2..3d29a4932a 100644 --- a/proposals/0478-default-isolation-typealias.md +++ b/proposals/0478-default-isolation-typealias.md @@ -8,7 +8,7 @@ * Implementation: [swiftlang/swift#80572](https://github.com/swiftlang/swift/pull/80572) * Experimental Feature Flag: `DefaultIsolationTypealias` * Previous Proposal: [SE-0466: Control default actor isolation inference][SE-0466] -* Review: ([pitch](https://forums.swift.org/t/pitch-a-typealias-for-per-file-default-actor-isolation/79150)) +* Review: ([pitch](https://forums.swift.org/t/pitch-a-typealias-for-per-file-default-actor-isolation/79150))([review](https://forums.swift.org/t/se-0478-default-actor-isolation-typealias/79436)) ## Introduction From 966d5cb21cd7f7e9adc277ca9a22daada356e76b Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 21 Apr 2025 22:14:12 -0700 Subject: [PATCH 237/505] Accept SE-0469: Task naming. (#2798) --- proposals/0469-task-names.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0469-task-names.md b/proposals/0469-task-names.md index ebded646f8..a5f1c6af62 100644 --- a/proposals/0469-task-names.md +++ b/proposals/0469-task-names.md @@ -3,9 +3,9 @@ * Proposal: [SE-0469](0469-task-names.md) * Authors: [Konrad Malawski](https://github.com/ktoso), [Harjas Monga](https://github.com/Harjas12) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Active Review (March 13 - March 27, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift#79600](https://github.com/swiftlang/swift/pull/79600) -* Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) ([review](https://forums.swift.org/t/se-0469-task-naming/78509)) +* Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) ([review](https://forums.swift.org/t/se-0469-task-naming/78509)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0469-task-naming/79438)) ## Introduction From 91f492645f11dbdfba68e93c760855ccedf028c3 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 22 Apr 2025 16:42:35 -0700 Subject: [PATCH 238/505] Mark SE-0466 as implemented in Swift 6.2. (#2799) --- proposals/0466-control-default-actor-isolation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 51ffc99c7c..8fb8015003 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -3,9 +3,8 @@ * Proposal: [SE-0466](0466-control-default-actor-isolation.md) * Authors: [Holly Borla](https://github.com/hborla) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) -* Implementation: On `main` behind the `UnspecifiedMeansMainActorIsolated` experimental feature. * Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321))([acceptance](https://forums.swift.org/t/accepted-se-0466-control-default-actor-isolation-inference/78926)) ## Introduction From 53242c83e3c8ab5472ddd78e7b9b4fd1b8086bdb Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 30 Jan 2025 14:01:13 -0800 Subject: [PATCH 239/505] Add proposal text. --- .../NNNN-method-and-initializer-keypaths.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 proposals/NNNN-method-and-initializer-keypaths.md diff --git a/proposals/NNNN-method-and-initializer-keypaths.md b/proposals/NNNN-method-and-initializer-keypaths.md new file mode 100644 index 0000000000..40951ad8ba --- /dev/null +++ b/proposals/NNNN-method-and-initializer-keypaths.md @@ -0,0 +1,165 @@ +# Method and Initializer Key Paths + +* Proposal: [SE-NNNN](NNNN-filename.md) +* Authors: [Amritpan Kaur](https://github.com/amritpan), [Pavel Yaskevich](https://github.com/xedin) +* Review Manager: TBD +* Status: **Awaiting review** +* Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823) [swiftsyntax/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950) +* Upcoming Feature Flag: `KeyPathWithMethodMembers` +* Review: ([pitch](https://forums.swift.org/t/pitch-method-key-paths/76678)) + +## Introduction + +Swift key paths can be written to properties and subscripts. This proposal extends key path usage to include references to method members, such as instance and type methods, and initializers. + +## Motivation + +Key paths to method members and their advantages have been explored in several discussions on the Swift forum, specifically to [unapplied instance methods](https://forums.swift.org/t/allow-key-paths-to-reference-unapplied-instance-methods/35582) and to [partially and applied methods](https://forums.swift.org/t/pitch-allow-keypaths-to-represent-functions/67630). Extending key paths to include reference to methods and initializers and handling them similarly to properties and subscripts will unify instance and type member access for a more consistent API. Key path methods and initializers will also enjoy all of the benefits offered by existing key path component kinds, e.g. simplify code by abstracting away details of how these properties/subscripts/methods are modified/accessed/invoked, reusability via generic functions that accept key paths to methods as parameters, and supporting dynamic invocation while maintaining type safety. + +## Proposed solution + +We propose the following usage: + +```swift +struct Calculator { + func square(of number: Int) -> Int { + return number * number * multiplier + } + + func cube(of number: Int) -> Int { + return number * number * number * multiplier + } + + init(multiplier: Int) { + self.multiplier = multiplier + } + + let multiplier: Int +} + +// Key paths to Calculator methods +let squareKeyPath = \Calculator.square +let cubeKeyPath = \Calculator.cube +``` + +These key paths can then be invoked dynamically with a generic function: + +```swift +func invoke(object: T, keyPath: KeyPath U>, param: U) -> U { + return object[keyPath: keyPath](param) +} + +let calc = Calculator(multiplier: 2) + +let squareResult = invoke(object: calc, keyPath: squareKeyPath, param: 3) +let cubeResult = invoke(object: calc, keyPath: cubeKeyPath, param: 3) +``` + +Or used to dynamically create a new instance of Calculator: + +```swift +let initializerKeyPath = \Calculator.Type.init(multiplier: 5) +``` + +This proposed feature homogenizes the treatment of member declarations by extending the expressive power of key paths to method and initializer members. + +## Detailed design + +Key path expressions can refer to instance methods, type methods and initializers, and imitate the syntax of non-key path member references. + +### Argument Application + +Key paths can reference methods in two forms: + +1. Without argument application: The key path represents the unapplied method signature. +2. With argument application: The key path references the method with arguments already applied. + +Continuing our `Calculator` example, we can write either: + +```swift +let squareWithoutArgs: KeyPath Int> = \Calculator.square +let squareWithArgs: KeyPath = \Calculator.square(of: 3) +``` + +If the member is a metatype (e.g., a static method, class method, initializer, or when referring to the type of an instance), you must explicitly include `.Type` in the key path root type. + +```swift +struct Calculator { + func add(_ a: Int, _ b: Int) -> Int { + return a + b + } +} + +let calc = Calculator.self +let addKeyPath: KeyPath (Int, Int) -> Int> = \Calculator.Type.add +``` + +Here, `addKeyPath` is a key path that references the add method of `Calculator` as a metatype member. The key path’s root type is `Calculator.Type`, and it resolves to an unapplied instance method: `(Calculator) -> (Int, Int) -> Int`. This represents a curried function where the first step binds an instance of `Calculator`, and the second step applies the method arguments. + +```swift +let addFunction = calc[keyPath: addKeyPath] +let fullyApplied = addFunction(Calculator())(20, 30)` +``` + +`addFunction` applies an instance of Calculator to the key path method. `fullyApplied` further applies the arguments (20, 30) to produce the final result. + +### Overloads + +Keypaths to methods with the same base name and distinct argument labels can be disambiguated by explicitly including the argument labels: + +```swift +struct Calculator { + var subtract: (Int, Int) -> Int { return { $0 + $1 } } + func subtract(this: Int) -> Int { this + this} + func subtract(that: Int) -> Int { that + that } +} + +let kp1 = \S.subtract // KeyPath Int +let kp2 = \S.subtract(this:) // WritableKeyPath Int> +let kp3 = \S.subtract(that:) // WritableKeyPath Int> +let kp4 = \S.subtract(that: 1) // WritableKeyPath +``` + +### Dynamic member lookups + +`@dynamicMemberLookup` can resolve method references through key paths, allowing methods to be accessed dynamically without explicit function calls: + +```swift +@dynamicMemberLookup +struct DynamicKeyPathWrapper { + var root: Root + + subscript(dynamicMember keyPath: KeyPath) -> Member { + root[keyPath: keyPath] + } +} + +let dynamicCalculator = DynamicKeyPathWrapper(root: Calculator()) +let subtract = dynamicCalculator.subtract +print(subtract(10)) +``` + +### Effectful value types + +Methods annotated with `nonisolated` and `consuming` are supported by this feature. `mutating`, `throwing` and `async` are not supported for any other component type and will similarly not be supported for methods. Keypaths cannot capture method arguments that are not `Hashable`/`Equatable`, so `escaping` is also not supported. + +### Component chaining + +Component chaining between methods or from method to other key path types is also supported with this feature and will continue to behave as `Hashable`/`Equatable` types. + +```swift +let kp5 = \Calculator.subtract(this: 1).signum() +let kp6 = \Calculator.subtract(this: 2).description +``` + +## Source compatibility + +This feature has no effect on source compatibility. + +## ABI compatibility + +This feature does not affect ABI compatibility. + +## Implications on adoption + +This feature has no implications on adoption. From 7a8f5349ba73bd9e2b783afce0f780e4914dd96f Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Tue, 4 Mar 2025 09:17:00 -0800 Subject: [PATCH 240/505] Make updates. --- .../NNNN-method-and-initializer-keypaths.md | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/proposals/NNNN-method-and-initializer-keypaths.md b/proposals/NNNN-method-and-initializer-keypaths.md index 40951ad8ba..bed57bc292 100644 --- a/proposals/NNNN-method-and-initializer-keypaths.md +++ b/proposals/NNNN-method-and-initializer-keypaths.md @@ -4,7 +4,7 @@ * Authors: [Amritpan Kaur](https://github.com/amritpan), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: TBD * Status: **Awaiting review** -* Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823) [swiftsyntax/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950) +* Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823), [swiftlang/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950), [swiftlang/swiftfoundation#1179](https://github.com/swiftlang/swift-foundation/pull/1179) * Upcoming Feature Flag: `KeyPathWithMethodMembers` * Review: ([pitch](https://forums.swift.org/t/pitch-method-key-paths/76678)) @@ -85,27 +85,19 @@ If the member is a metatype (e.g., a static method, class method, initializer, o ```swift struct Calculator { - func add(_ a: Int, _ b: Int) -> Int { + static func add(_ a: Int, _ b: Int) -> Int { return a + b } } -let calc = Calculator.self -let addKeyPath: KeyPath (Int, Int) -> Int> = \Calculator.Type.add +let addKeyPath: KeyPath = \Calculator.Type.add(4, 5) ``` -Here, `addKeyPath` is a key path that references the add method of `Calculator` as a metatype member. The key path’s root type is `Calculator.Type`, and it resolves to an unapplied instance method: `(Calculator) -> (Int, Int) -> Int`. This represents a curried function where the first step binds an instance of `Calculator`, and the second step applies the method arguments. - -```swift -let addFunction = calc[keyPath: addKeyPath] -let fullyApplied = addFunction(Calculator())(20, 30)` -``` - -`addFunction` applies an instance of Calculator to the key path method. `fullyApplied` further applies the arguments (20, 30) to produce the final result. +Here, `addKeyPath` is a key path that references the add method of `Calculator` as a metatype member. The key path’s root type is `Calculator.Type`, and the value resolves to an applied instance method result type of`Int`. ### Overloads -Keypaths to methods with the same base name and distinct argument labels can be disambiguated by explicitly including the argument labels: +Keypaths to methods with the same base name and distinct argument labels can be disambiguated with explicit argument labels: ```swift struct Calculator { @@ -114,10 +106,25 @@ struct Calculator { func subtract(that: Int) -> Int { that + that } } -let kp1 = \S.subtract // KeyPath Int -let kp2 = \S.subtract(this:) // WritableKeyPath Int> -let kp3 = \S.subtract(that:) // WritableKeyPath Int> -let kp4 = \S.subtract(that: 1) // WritableKeyPath +let kp1 = \Calculator.subtract // KeyPath Int +let kp2 = \Calculator.subtract(this:) // KeyPath Int> +let kp3 = \Calculator.subtract(that:) // KeyPath Int> +let kp4 = \Calculator.subtract(that: 1) // KeyPath +``` + +### Implicit closure conversion + +This feature also supports implicit closure conversion of key path methods, allowing them to used in expressions where closures are expected, such as in higher order functions: + +```swift +struct Calculator { + func power(of base: Int, exponent: Int) -> Int { + return Int(pow(Double(base), Double(exponent))) + } +} + +let calculators = [Calculator(), Calculator()] +let results = calculators.map(\.power(of: 2, exponent: 3)) ``` ### Dynamic member lookups @@ -141,7 +148,7 @@ print(subtract(10)) ### Effectful value types -Methods annotated with `nonisolated` and `consuming` are supported by this feature. `mutating`, `throwing` and `async` are not supported for any other component type and will similarly not be supported for methods. Keypaths cannot capture method arguments that are not `Hashable`/`Equatable`, so `escaping` is also not supported. +Methods annotated with `nonisolated` and `consuming` are supported by this feature. However, noncopying root and value types [are not supported](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md#additional-future-work). `mutating`, `throws` and `async` are not supported for any other component type and will similarly not be supported for methods. Additionally keypaths cannot capture closure arguments that are not `Hashable`/`Equatable`. ### Component chaining From 25675132c2fe48131a9cffa339e6e658534116e9 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 22 Apr 2025 16:49:45 -0700 Subject: [PATCH 241/505] Mark SE-0463 as implemented in Swift 6.2. (#2800) --- proposals/0463-sendable-completion-handlers.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0463-sendable-completion-handlers.md b/proposals/0463-sendable-completion-handlers.md index 498ab8ba80..85729b6ae5 100644 --- a/proposals/0463-sendable-completion-handlers.md +++ b/proposals/0463-sendable-completion-handlers.md @@ -3,9 +3,8 @@ * Proposal: [SE-0463](0463-sendable-completion-handlers.md) * Authors: [Holly Borla](https://github.com/hborla) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) -* Implementation: On `main` behind `-enable-experimental-feature SendableCompletionHandlers` * Review: ([pitch](https://forums.swift.org/t/pitch-import-objective-c-completion-handler-parameters-as-sendable/77904)) ([review](https://forums.swift.org/t/se-0463-import-objective-c-completion-handler-parameters-as-sendable/78169)) ([acceptance](https://forums.swift.org/t/accepted-se-0463-import-objective-c-completion-handler-parameters-as-sendable/78489)) ## Introduction From 8ad47c44227d24f59b5865f0d0a4b090dc6d8f64 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 23 Apr 2025 08:54:51 +0900 Subject: [PATCH 242/505] Update SE-0471 to return Bool? SE review follow up, moving to a simpler model of detecting if we were able to determine the isolation without crashing. --- proposals/0471-SerialExecutor-isIsolated.md | 34 +++++---------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index 539f1adc84..85dbd1b3a2 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -87,7 +87,7 @@ protocol SerialExecutor { extension SerialExecutor { /// Default implementation for backwards compatibility. - func isIsolatingCurrentContext() -> Bool { false } + func isIsolatingCurrentContext() -> Bool? { nil } } ``` @@ -101,8 +101,6 @@ The newly proposed `isIsolatingCurrentContext()` function participates in the pr ![diagram illustrating which method is called when](0471-is-isolated-flow.png) - - There are a lot of conditions here and availability of certain features also impacts this decision flow, so it is best to refer to the diagram for detailed analysis of every situation. However the most typical situation involves executing on a task, which has a potentially different executor than the `expected` one. In such situation the runtime will: - check for the existence of a "current" task, @@ -125,15 +123,17 @@ This proposal specifically adds the "if `isIsolatingCurrentContext` is available If `isIsolatingCurrentContext` is available, effectively it replaces `checkIsolated` because it does offer a sub-par error message experience and is not able to offer a warning if Swift would be asked to check the isolation but not crash upon discovering a violation. -### Detecting the `isIsolatingCurrentContext` checking mode +### The `isIsolatingCurrentContext` checking mode -The `isIsolatingCurrentContext` method effectively replaces the `checkIsolated` method, because it can answer the same question _if it is implemented_. +The `isIsolatingCurrentContext` method effectively replaces the `checkIsolated` method, because it can answer the same question if it is implemented. Some runtimes may not be able to implement a the returning `isIsolatingCurrentContext`, and they are not required to implement the new protocol requirement. -The general guidance about which method to implement is to implement `isIsolatingCurrentContext` whenever possible. This method can be used by the Swift runtime in "warning mode". When running a check in this mode, the `checkIsolated` method cannot and will not be used because it would cause an unexpected crash. A runtime may still want to implement the `checkIsolated` function if it truly is unable to return a true/false response to the isolation question, but can only assert on an illegal state. This function will not be used when the runtime does not expect a potential for a crash. +The default implementation returns `nil` which is to be interpreted by the runtime as "unknown" or "unable to confirm the isolation", and the runtime may proceeed to call futher isolation checking APIs when this function returned `nil`. + +The general guidance about which method to implement is to implement `isIsolatingCurrentContext` whenever possible. This method can be used by the Swift runtime in "warning mode". When running a check in this mode, the `checkIsolated` method cannot and will not be used because it would cause an unexpected crash. An executor may still want to implement the `checkIsolated` function if it truly is unable to return a true/false response to the isolation question, but can only assert on an illegal state. The `checkIsolated` function will not be used when the runtime cannot tollerate the potential of crashing while performing an isolation check (e.g. isolated conformance checks, or when issuing warnings). -The presence of a non-default implementation of the `isIsolatingCurrentContext` protocol witness is detected by the compiler and the runtime can detect this information in order to determine if the new function should be used for these checks. In other words, if there is an implementation of the requirement available _other than_ the default one provided in the concurrency library, the runtime will attempt to use this method _over_ the `checkIsolated` API. This allows for a smooth migration to the new API, and enables the use of this method in if the runtime would like issue a check that cannot cause a crash. +The runtime will always invoke the `isIsolatingCurrentContext` before making attempts to call `checkIsolated`, and if the prior returns either `true` or `false`, the latter (`checkIsolated`) will not be invoked at all. ### Compatibility strategy for custom SerialExecutor authors @@ -169,25 +169,7 @@ This would be ideal, however also problematic since changing a protocol requirem In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. -### Offer a tri-state return value rather than `Bool` - -We briefly considered offering a tri-state `enum DetectedSerialExecutorIsolation` as the return value of `isIsolatingCurrentContext`, however could not find many realistic use-cases for it. - -The return type could be defined as: - -```swift -// not great name -enum DetectedSerialExecutorIsolation { - case isolated // returned when isolated by this executor - case notIsolated // returned when definitely NOT isolated by this executor - case unknown // when the isIsolatingCurrentContext could not determine if the caller is isolated or not -} -``` - -If we used the `.unknown` as default implementation of the new protocol requirement, this would allow for programatic detection if we called the default implementation, or an user provided implementation which could check a proper isolated/not-isolated state of the executing context. - -Technically there may exist new implementations which return the `.unknown` however it would have to be treated defensively as `.notIsolated` in any asserting APIs or other use-cases which rely on this check for runtime correctness. We are uncertain if introducing this tri-state is actually helpful in real situations and therefore the proposal currently proposes the use of a plain `Bool` value. - ## Changelog +- changed return value of `isIsolatingCurrentContext` from `Bool` to `Bool?`, where the `nil` is to be interpreted as "unknown", and the default implementation of `isIsolatingCurrentContext` now returns `nil`. - removed the manual need to signal to the runtime that the specific executor supports the new checking mode. It is now detected by the compiler and runtime, checking for the presence of a non-default implementation of the protocol requirement. From be98eb82098a38cf0e20320544bc428e733deba1 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 22 Apr 2025 16:57:29 -0700 Subject: [PATCH 243/505] Assign SE-0479 and schedule its review --- ...aths.md => 0479-method-and-initializer-keypaths.md} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename proposals/{NNNN-method-and-initializer-keypaths.md => 0479-method-and-initializer-keypaths.md} (93%) diff --git a/proposals/NNNN-method-and-initializer-keypaths.md b/proposals/0479-method-and-initializer-keypaths.md similarity index 93% rename from proposals/NNNN-method-and-initializer-keypaths.md rename to proposals/0479-method-and-initializer-keypaths.md index bed57bc292..2315599438 100644 --- a/proposals/NNNN-method-and-initializer-keypaths.md +++ b/proposals/0479-method-and-initializer-keypaths.md @@ -1,11 +1,11 @@ # Method and Initializer Key Paths -* Proposal: [SE-NNNN](NNNN-filename.md) +* Proposal: [SE-0479](0479-method-and-initializer-keypaths.md) * Authors: [Amritpan Kaur](https://github.com/amritpan), [Pavel Yaskevich](https://github.com/xedin) -* Review Manager: TBD -* Status: **Awaiting review** -* Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823), [swiftlang/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950), [swiftlang/swiftfoundation#1179](https://github.com/swiftlang/swift-foundation/pull/1179) -* Upcoming Feature Flag: `KeyPathWithMethodMembers` +* Review Manager: [Becca Royal-Gordon](https://github.com/beccadax) +* Status: **Active Review (April 22 ... May 5, 2025)** +* Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823), [swiftlang/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950), [swiftlang/swiftfoundation#1179](https://github.com/swiftlang/swift-foundation/pull/1179) +* Experimental Feature Flag: `KeyPathWithMethodMembers` * Review: ([pitch](https://forums.swift.org/t/pitch-method-key-paths/76678)) ## Introduction From 3229a3a89892192507fba100444d8d12a1499ee2 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Wed, 23 Apr 2025 09:36:16 +0900 Subject: [PATCH 244/505] updat diagram as well --- proposals/0471-is-isolated-flow.graffle | Bin 170172 -> 170150 bytes proposals/0471-is-isolated-flow.png | Bin 84498 -> 84869 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/proposals/0471-is-isolated-flow.graffle b/proposals/0471-is-isolated-flow.graffle index 9215bacf9e3508f078ca6b7837a01ee2c143568a..05f3a5aa8d609d77bdf5e16bfaced49f62396f60 100644 GIT binary patch delta 150848 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

    wQmFreQ^G$GVo0DIg?+d4B+-7`$>6 z-0s_amUDzWdOaSFbwA7bXMQap4dC!$aO8>Xjlv=_pX&|jC*)`38S+c=8}eI}h7IYb zh_`QK|W{S#n%SGRBZ zuOh$9=B#KpnGR`%zK(BuhZFzLJ_|p+&8cjw=4-_NwAS(E&dwt8Gx;ldg(4^qst36b zi^wnJrJIUK5Pla$#wtL83ZUtD7E8!)t>k6$4-xsl-=c*4i6!JOJAX!NDI{@si3mkf z6yIn>h`*c^kb&ycO7*3Dgy~U|+j_Nu z^6gSzbRq|yrbvtcDv;`To9`uDPmIBolo~~irb4MODjXAI2sIS*q|+!snQ*kAOPX$N zN|+YITB+gG2yt@3n12?3)vefUshw!|O0XI^el%k{Rq&QHW&vdV!`UM(r_s$90tyqEwWc zioh6*SqMQFwkX+meNp@4ibZ?@$D&EY63O!<|$e#vVS{8`wuRkMGaIm6+^{g zHmf>`I>WM^^~?<=KK2?O#sd$RbURD`?qeF^zk9SfLO7{#)d}hdfK^l?l|-dr0EBk} z0LQf3qZ=|l`5MMg2F7phX8ga(c(X%lY_RI9@bA1?8sHG8U&S9h8Pnz#yA*yKBF0_= z2`Y_Br!pw~V}CedC6b7)e+);ZRCN9so*QE1nqR}A@UP))>Bh*vijgtq@~h8r$6lAT z7k(@!*#(>qiTX~fTqrG-PZdy8CRZ>^6&yphLg+W9IH@roLcExpb1t)#wkFT z05n_=cg3cR3?dysltR(AL{1}Dc76_wJ^l1H_qLEKqJN5Su;PW9+DesBdeM6>6<t8l!^k#Q`I z-!E3nRWwe=;s1Yxn~J~na|7Dk-$t8C%0gA$h&I)&R1M`2=V=#dbBluzuW@49++;Le zQ{>toA%8nYO{bcuyQ%w$kt?VMY6jIv%`B1lf{&^0yd0{(t5O3j?69#-_$Qb^CCQi$ z8?EWO<*+VWa&mdcoE9}}1vQ&$q3)#a5@*|tDb&TF#ItvZFW%o^bYh!1xXrB&Q@muZ zxbEs^<85R2J=DF_yjx%P?}kVGIcf`5o2@`w_mikLynC!QqM5-$-ui4TbL zBuNI4V@M^LMwXFH8mW>bt}D9pAma z`+R@#^YI((7viVzo8Xu1m*H3BXY{M_bNa3HTkW^TZ>`_kerNp7`F-zq$)E5i{oVYf z{=@x8`;YM->p#vv(Lc#Q%|F{e$G^zG*ni*X&-+*Sf9!wG|40Ad0(t~U0)hg<1EK>` z0-1T79)9<(~>*`SReKapmLg8~5P2N5(xlu65kcgL;jkydo(fwPwmIyjup?m~hku<6J0Es2?04B{S+=ZB)+lR|&6CZSEtD;mwaV7Z zHpyO>?U21G+b26JJ0bf*c0Rmc_>l0?;o0GZ;bq}-!ygV`9R5`J^6>TH8^d1=e>r?t z_-wxpXdH<*pi~%2Z8Jm8ncBi>gND zP~D@Nr`oD|O|?_CS2JJp;&{*TKH~$&2aO*wVa|kyCOkahi3v|l*fp`=MCrtl6GJ8{ zCM}$_Y|`>c>nClPw0F{hNq@&8$O!L<{t+W1LL$N=)DfD9h={0&_=wbq+=%9gdm|P` zJQ=Y%Vspgyh|`g($f(Hp$dt&Os7+BjqIO2@je0-oyQp8H2S=-;W1_2~?a__VbE4Nq zZ;IX*eJuJ^^w%)~F#}^p$Arc(G2>$<#6-oU#pJ~}Vy4F|kJ%SYH4h+>|^!`JUu?$*YprCm%~8Q+lL$r39t~rASl8 zri7$~r?4rLQYunvQh%OES(CCcWzS@f$$cmLPaZj0Hd!@!;^g?$RjJ$3s5H+s@3g@5 z?dhj8R2fkj@fj%@IhngN4`v?D{3P>4<}aDQXARFv%1X=1&MMAo$(on-eAa7OJG1s= z9mqPEbt3C*cJJ(x?27EFYxl8l=<&Vf8l^>qZtEVE!Zd zEAyYr-f*JC&{S@+nHHMPnl6|wntrRG%=elXnIAJRGcPy4JuPV3h-qV|$)>3)AFF((a#iK? zl^ZLMS;kpdi^dXRNvv8`^b+NV8 zy4O?_Cxl=_T%<5_U{~h z9sUlvqrfr6QRb+0-0N82*y?!A@vdXPYNj)iu`5ssFP6@^o(c`00_;lN!!8{60fALoq`=Bf9aonSE#a%*>vd zKT|i8pEY#W#97g^EVCY+^~9_-vo_4yG;7CO4g)y)mf4>Yf7KHU6E^Y1P0 zEqz*oTS8kBTQXZ_wA|UUs^!I&ms_^C>}h$sKAf^uIgLd!FZg z&hPjCzvsNa=Q-y*|6_4|_WIn`wS3ogf7i9HYwdOK&3Mni0RqQO%uN6$CIB#le*gv^ zFfb1FJr4kumcSkW05}1rcwc}OuE9+JN#IvuE@J-k6;7at<a1dm4WIg?9&V3@`>xz(2BpEuaNkK?BeM>|q;|@G&rd zm#zQOhW~Lb5Wee&XW@G!{vX%e6#<~p35Fl@AJ-Ip0f6r{0JLRXa=YyI@0MjEvtBu` zrTK4lo+bcb%VIFr;Zbnx1_0V5gF$IxFlc1}z%mW%k{NA)ASVZb6JTMI1DFMwSOl3E zT>t{sWn=nN`S*UASy=#wRA|tQ^0_#l#%)tAQXZ+fEI3A;VJ~Zb8Cwnvt9$N7EnFv~$U8 z*?^+%mq)n86twY*q+dh()5!jRx`9RgUybbF2lgN1nt@5k{HMYK|FW^Lu&}YS!G)cZ z{a4}S=KNFP{$GXnPi5P$!vF8(S0_wx53H=L9PqCI4;PQX-&`28umg!;Oar_uOfZ>P z1OX&KqZTJA16%ShD=dt+TO9Zo7Z%3I76<;tg@rM?#esiuVPTAIao}HnTv!V8C>-nZYnzT+e zU0^zp0U)Yt^mkzT^gt{vsuKJCsJ*uVf)&#dM{C9`eyPHMabp;Wh5#R6FV1fs@<&m3 z*3Z+CsIZZ(R$HyMT5Yx3YV}{;>OP8}YD76n)uL6ksDMs{`R>Din1oG468iAtuZ6p! zeM=fz8ZVnXj=nfFc)y@3MJA^mQPKdKrZIp|a`W8C<>QkK;5*uO;}sxs%6Lou4}$rl zTf5b1NL&$e?R=pq16bZRzq$VqWm~Hr1Bi-X0DZY=dj|0AFlO=nBFh*4c*L5Oo;m|? ztx%^4+?|?~0Eu*e^MzPgPt=P66bm&U0+frB{^4C8bvZ6l&*wo)cnQP@F zF#zgAC%h>w(UAer(~?>@ikOp>x8(mI{C{*Cd5dpbeEXaD_6N7D|Lggtf=A6bwa+0) zUh^Hjllps=I?Bh;Mmxy(4F=FPXW+pAj1Du z0Ny?*;vZ8_WB?NSqEzvb;z{}*sI0S7OsmGsh3s{!EV#!``RDcR%v_ugBl`%?F|nA2 zz~wKbI=e$09dN$moBOSz;l6`HoK(3nYn_4?YkEgy)}C^f%p@un9#tY*m(+8Ma)zo; zE73Cs=avY6s~uJRC!7w`TN5YjIth(+cRe$vJ`6T~D%`;Kxu2kiwZKo_&WHSvAXVEUS8jLq8ah@q$ zJrskt@2Wa%O;T)%(KA$R*>{q>p{C%7UU@nHMzB8R-t4_5!IbY3PmyFX=qC=z9NvxO z3`X34lF^AifhEZ=2{?Z6n^g6DnIY}?X+M{OLXE8_i&A9dTRYvAW(pU5s0mYNn$lu{ zL$di6@RK;A>hr1`ht@5cEKILHODxNhpgt>hQ$0SAquF-bkjU|AkOSvURYySb-m$o` zD(Xr|2T!H{=CzS*HLoZ0QVEkgG8LQ6m{Y5N>z=X!;ZTN%m`B8+T#ys%S3T7q$Tmwg zi6_XU(zn;VI=4UInDgUCi(V@YH}$dWR`>W%`r}rG!ly8>^N4cBbS#R`lWf1{8i1Yq zSLYbOh1Lt_@7&OD+c=JFPWtIhE`)Y60B#OCmpKl@Hs?eubZDK_UU9Nzb)(N>MAlw^ zA}Q8oufx-m0NPDb?@A6u4Q7Z0n3h6UT-*$=k@|Ug=6a8JBq_h{=N^J^^ytxs?|YM< zE*8j-tmqlxDUgoZUb>}(DR1ff`|2Vi)Z@HdUvI$B{2)dE+A zbed?mrKtEWc;LBRfQ`k{J)?mj>6y=eXVdO=6`26MECp9c*ky6H`7R8!%f3sU&A;Ff zipe)?`sw3x%tdGQJhA-p7Q1X+dEYFi2I`k=8F$=kE2Su=O}gPn|A9$* zx$jl%n~SpP-%9MI4RcvDG*aU~!K3zm0f%4UqWI;o+*Dy=A+)P7QeRT3BaI!c*$QnClmqyx<{p=a`kB6LZFUVY z%bXQF^2i&ho?&j>Gy9%(f!=LD9a9LNKunvOH+!GGN}kM8ez>%awukx45a-W0GvfXG zp1A-mj)Yvvq^LoM%|?Ug1<@yeMydjI-Wv}lI#8#SBJ)dxDo?Rz4(zRL?vL#+2-SJ( zk7(duUM+&Q^%BA>NW#bBJ2vxLu4Q+u>829QuoI>NM;$&|5sYmHK5$dN!WIvr_Y~Hx zCSttuSqQpaD2^|5jY+CccA(y7B~LKfXXo>*Y2|>J9Dx5aEXn&k~e7GPa4|{0j_)>NwgWg-ZZQ2d3%RbkIcD$hfyp6?d=QE=Mb>_ zyoKVT>-e7bM{%R=%b|jasi-#>%I!lP>gp{J{1OKa%$3Nequ^8ov@D!jZ$s2)#S>A} z)#NyMGK3Hcg_kz0yJa2=ysVFuJNxmP)AbM&3%xuM&Ga2UPwufslkKCBuCI9T;w$G6 zEBv5`OInA%WJ_It#^f2W>Q%Z}(=M|dt|a3eF@<&3)11^Y?!};pHf4?xtSHu(0ZdVF zHLy8p=&u?9NznTl~x!-7i9RFOun+=Fo5kC?WKJDT-le0Wu9C&|>+d@6yXN zheWcM9)_>_ z%J=-vonyS88rj_e7M25|b)XgfG(TyH-pzxg2^ZUE(c3UQS24E=*)V>H*h8P$suNpG z!+aFn3U{41+4qK{(kAA1*rOu;nZRvOvJvTGbU9Ri(y2S*cjIIgYlvO8^}f)uI9uM- zltXc>g3eiyq!4^|5;~}ossk=0UT8pwK*1qj4_y_Cf8JniYo2a8+aApEVe+#nRXC0K z9@Jf~CULYQMea?1#nycqDiwRc(zI&RkK7-8qM&kDDnV2xq3D|E7z1eE6E3qPMBPt{ zUr{H2dd?CsDL2N4ibnS>EMFRwb@sl?e`#I!fpvV52-BtmvDrsmPmmyWINy{aC-Hsh z`P}yfu_tezX7)o3?F+ort_yk^aCkCC38VMQJL^j$#k8#&;@38QR*?gyda3A@ zwfzfF%NvjT#N5rEp3Q;NwN3BpXA-`x>?NAJXnkeW2ctrT-S>s6wbTLp41vou(bBE%O$Aa)tqwC8T>%Tv8zd(67H~l)?aDQZP3Q? zCHxg7Fuc!2f+QSz+7WvEp!2b*ys?~r+Hl^E%R4(&GfgBFWI>~S?S$4_qrtP{UDJHn z1hnoW!zaGkU}DwNDldnk-2D>vsmBx@tlYUo!SeP%NC~stjK@SdnnqD=aYwYeUY61e zdHimaew4GAx>%MX;UbmtGwbUBE0E=mYCvyt60}Z1l$Gu+ zf5l^XPHYxr>^hvwx^B1s<0ano!EN9^o(Hb%PO>ub@IARk+Jz;crZ8QOX^9OMRdxh* zv3Zj^my_!+dm8tvifG3sSf9P`EupYc{Y1}@ay`6vZu`VTkX}u)HxYmK;#QZ?k#~N? zM_L9MCK_+4A7uD-ex}2{{s3pODM(x%e?p9^5k@>fmznyiFZ-_e<>Yxog==kPp`<}@iqCo}G97-=LS0RPr z_SM+jxjYh2uj6oRrMeCS;0bLFf30u+B5U`&?$%D53Z5UOd4j@J&k#IBI(lL4z8E>0C@bd1fd=d&@Vz3B&>O%Gh|7qKnPDeYCilt zdT!KUFr)Zvo{-5|X8Ri{I07~=Fp>e(S1(Ty0+R~`=!fYOt(+6BilJ$!e|Ki1RfI9u zcl852Y(uZ#=nD75j$bRTkY_!{D*dJhUMv=Rs$(S8S3ZGbJq)1MKIWGfg+jU~t$o53 zM%7ij^J5AF?>SZ081s(pDgK$f+v=_$(eBi`4iL@&&}X1^&>t6D`f8!OaJ%o^cBi&M z){rY~xtH#JaF4yB5P4avf8nI&5&yLiI=45)l8S`xQq)4PbQQwkeV1|rms*R5o9LTd zOJaMl(2=;J_Vc%npGfL9lzPW(pF(&sKP8X%j)ntH1~A=3EbO&P6BC4<%ydlGez~Ea zbEC|{?7_NHsv4*<-J$GeEf{I@?VHK6?$<&+vV}gu8cC2ZjtOMa-<`%kl_s8#vV3;vQEd1` zz_pX;67{*Mf_F@tf2TlGqE#pMmWyD#9Vni-Otn&su_O5jIlM;nzX*-iY<&y3Uk-BC zO+f}ArtI5X6f!$xRG|FgDL?S|TT7sDXy5S`%@ZRWXLGDr4?4pWY|V7Vra+vQiF6$n zTtYC{TOc|73RD_LmrDyz#u)Ti;L_blAE!lP&krKVSHOn_ z`$7F2!eChU4a=t`kLSPIEd?R-ZgRizh%)VqbmtX3Vazr2oZ1CPk|H2BsYQzzz&_lq zzim7q_!Yw1N^@?l-?Ms4g<4_}w0r(d}%IDHL^5S$6up{m@ST(JZ}5&%c^p5z z>li-wfbi9)Ot`x?THWDZn06I);`oo@X;VVuQ;T_je|=?5=hr5lQ&Q)g1yf(0zsNDx z5Uv^OL=0(PO+wV0CeXF$Q`6U85LUG8w5-JPN?z{r@@D2dH%;KM@Y&h_qz9kKlX+_< z0$If$i>T*sw@S6P((ORO2zL1&b5M$#a3d$28WJsyZ0wIHVDe(ov(rX2AePs!5a%J= z5wyW5e@Alo^mGW>!glx3LJ5rL5u_tn z9asM|z$@>>_(L`ZFd^F9xGnR8cGlQ2j?F$E=E12mlV3Kdq6~oSJ9^dUDt3CN-9E_Y z)Zni6~M|_5|e`TS&c;TQw>W)Pxs8}j%lCsaBhnF+B5Mr zXh)O4xx=Qs2@fwnUF<*7UcE3$=UM`*ZD@@c-&Y~T;ojMcNWnfli}%eS|4XL_TbpHj ze|;p`0G_j~4z41*cM7v=otXz6&KCRIT>;SSTO)&feveqhA&umU;GJN;qGryqMZ(k>B;0hb>5gG)s4`T4AD|`eP@*&66eDbEm(Jo++5~nJF=q6RPBYq(hCR z%9BEuzggc7JODIA)(pb#rto1PPc^o(D5Tk>S@C>pv~cX9DK%Mub& zM65^<0^?f|&*3a|Lx4573RV}lqle&ahCUIo@wztnjM<>lewxk8zd=KT|YO8Q)=Sh;L zqsOp?d1S7@4T+rrwM9pgl{p$Phf(0kw5gH~RO4h9HW4X`^m*|VZ7GwZf7nvzl$R4Q zy+%3hd%sWhcCDF^PE5q3e$BR<N$RMS! z^t#Cp;1W^#ng1LH_hetFH#rn6kHmN(qwF|3=v?pg#|cMFhIW73e`5ym{_c6u>hOGIZwHo7Pn;;lpSb_oQMbwJ0%5+ve$jQ~E*^}6xk&Ui zy+=knr!QYJy6FHee~>GnTOM#Q_LS5U^YTvbnGu~wdTL%_uckxm2hHuyr(HiN z$UUOAJtGE)#?9fCR}@7bnLUAQe)A&V&2)S|`gmH^2gV%~SnKCW~p6$udb~y-N^bG zPga705gqE#o{KqPt5n&m_>Rq{#CoXw63c*SYaTkinJGfz4s+Y3Z9xWz3d}R5qy|(h zQb=E!-a%Jsf6n+smvYfB!9Vssn01bwG+}IW1ED^YNUzgO6<{K`>;wbTu(+c6hSjdZ zxK=HaNevza#~WOpVu-0t=R)r=%HS%~wGbmI@r>Q~n&p>`&lvD%P1=)=o(EA>F)e(+ z#QhWIM1HP5Y0#yXzGQPtH;laz_8@KkKMoVhyN*cVf7Lq!h0&HI?)u!2IBiP)Q6FO4 zb+#6-F5d#(gG}~%o=E`JZA@<`0RbsZuDk-9@u<$g?S8rQoq)tm6WU}{hK{8d-*h&){Cm&=z5RD6=CbO7dM1|zJ-v+$w=>-hQx=l z=VciHf48t~f{eq!iC#q&^8N^J<>Ehy{_ngQP#vX*VF0_upi>OM-44qDN(j}j7XQ(Q zgZ?MTA3o6h-|!B>+5nx~16=Q&JJJG)(b>U?a)RQho|EX{m$Ayv%@kFjJLmk`sg`;i zbuhBmk!D#Ofz*Kgsk$WnJ(3CQqb5b<@4U%>e;UdIGrqMs`4vcwWxvUt_+n^sSLndQ zJDwNPo!On^?ca0PKq2J2nFIt?X&$h*M5~zo4hcX9yjT08vA+e zot~dnPE(lvM6*Q4>ca08@fCgnUeW6Z1NLgr5n^GV&dqBLxsuX zf3&>sR|psZ=qUd)ziHL$zE7*PSPe?FYwvDPi?{4z~#{N(nu2}xxZkVs?zEB2Jr z^s#vkJ##P`HgOh%m@9pmEE_g^1Jm!f{$dS2Y+5Q%z; z#NDS0kaVLMfCqnks}N}@`T7Gta&iSve;%L7w1v~Xn3ts=k`&^+?9VOscV1q5DA+Da zriC{3euq9Y0KRG@K3`!>p7dmxDVpMh^zt!EJ9v`mXOef|$*{K^IIC!^H%4fH5SWe4DXV!*5sES2>?yl6(?~q`L*Us@S zSy9 zz2Ul*b6Bgleg_FPq9(!wm4Ya8Beag6k1p5&@q_VX7t*#oqNTi5^l{;H)8-zv-A}ys-Z|?U=;E^9I|1^?xc{;n>Y20^z*B}e+r#3JhpE&whE-tSfcv4u)06G|eot53b&H-o*k z_lJzM#2knUG2DUOz2G59I}6V}PJLd#!g>r<__PZtq$9us@6tpF|pE`e=@&3Ir7xj!(l>+kLR|Rl+z_|*F}CyC+QIKlR8=}nuTITJqzhp zI({kGQ-3HRE5FQ0k@)4>>B_8{s*jKEnOnbje%F)png;%oEvCp%nPqJN&)+$W@P(}y zcnc+{qt54dtyN?kt>z!-T`}OT>ARt&dgy>g=hfG8A?&-Ee{9`NdWfG6AaVCF{CYQW zJjj$UL@b|Q_>O?n-F42>e8-3Ut?Jv1+|QyvqBQt7vgPNnr~U7dYD1q|vHOoeLS}L# z72gdbi?F8w6HwQ@wEnpTZFLX7x+siXT`yadyqNi-YI(dt%`K{>UE1uY*_cY{4@r`r%B^(&5R^wH5x_OWl}iQXSTk>-?u^%AvDSxgqO156o6 zU-(XU^Ldb`p%TJsYzBH4G)Pf~O1fS4WehLdi;eka43y0|$E*$Z?*ByOokxBfZ(R78 zSz?Fie?UP>@m;f5=v>5VsyM0roOsXX-1E8Jqm|zj*;E&jIE#{`q8>zPk35V7PY!FC ze{%5O*bB!qE)a$i7(R~WYDK(<1L$muZfHf9%#pVNaryq&y#fwT`614u)OKB$i?dY% z0(~6Df4ZL8!S4w#cj5FQgcw@z5!HxRg7MjIf1KULpOnphZS38xiEEWB8bW(M%D-L) zl9dLI8JM~EW6SHUIo7K|*k?dAIDp#4(Ulf^39_;s(R0#GK{ou^VJ)xV#-?I|KI{== z?Rj$#UvQ*oA!!2(yZeTw-okCv9pFM6CI(r%k#Kch(pM5KX`TCR)IwT}=b@oQ%kvB~ ze~%tAySBY`!%#Gc(O`jad&dXI;c@-4%_#Ub5;M;ZI(JjcEYhe{EV}gT2-~R6(3oGJxEkpsgWYqNU-FFo}BY z>)-09q@rpogIY%)+35=HsfaN(MI4%}Max4EDDL!k^YzGh^m(*OC0YW~!TZdvs{WAm zcro$$V^8e)I9)G~XVS?vf~bwyDdX@eIQ~z#5g&)~v4WJ~#Z;HXLa^_wj(-{7f3+G@ zD6&_|`eoy&nEBJ?i@GhnmrXLX&r9sOv)gmG!U;|MyOp2A(7qS4YM?M#Ha{V1`UQ$BA;4JZGXt7;3wx9Z|Od&zE&m< zyJGq4e$z^H7(fDoLys+peW{#u9b)4%H1<&{I54=`T zUn=auPIdOY#I8t#^W^)GR*0JiL7hLdG&F9S?yxid^xLwbk9JABF&MGWYa7a}cNF8Z zm?-BXklgx0Xj9ny$>9@)(%J!T-z(;$3wbL&V;k5g98<*^6H4=Pf8C19mZ}@VyVp8R zn3Y&#+h;#x8pUIw{-Vm658dPt~WLB+Q&% z>HnxIc74h@D_l#Ye>p`soZW_?bANeaK}1YD;V0@!9cRDPF6ncPo{!^M^sH-+TzIG6 z|8T^NrCUxo&JK9Yj(yZmEv7XgafSMNw8!Ckq27eaIP|Hq#fd{QnO^1QfuWh&PsvT$ zx~lyiHqTWKuqYj5hZjF+gJQ-2+K+|HQMFrW*?N|slTE|Ke-F+{t9L)nAuU^;-!$Po z%Oxpx%khIkw`tBEt(`VA*P?r0LZ)=CG(sQNHNXll)2zK8B^(^!pm$ota!?9V{>J$Q1zneSu(oZ(X#@B}6~e0LxhRsSUvk9&39 zZrAhr#^=xLo1?gPOb?AZRx~tpaJbqSrsYKN?tc}Ae^{Oc2gtp&CrEz_%=BTRWn2x8 zpUpSqnIDJMbN>pd>#bdn)Gn-4?eYq_l~iG|(@O2xPsMv`7z1tCJ&!X0HcMJzxc*l} zJ)B}6LaTvsrG$J3H7$>eUqMj9 z!-vA9f1!nnP>B|G(&6@vCbCWF&6S0*If}X0t*+apU*^0Vn3PMSUS)x8hp7QOKTC1tk zL~IZ0y@wOLx*9^|6njEoLc+M($9r8n$DS5>e`bsh7R>D{#e_6^b3>Z?qwQx3$8wcf zeiqU0>ub~J=4-NIpP-qeajB09o?$OOk7WcLB6~IE4^268RoRw2Z#pkUx9c%?#c7n% zlId*pcly6J7ZVmy0(9+A@pJVVVYAoP?Isk)%ISj?OLE?|H^zkWsn@<-9^m_ zf7sHmgA*wGG}G41PLh%Sqi4qhD%<#^7GZn!&g?k?0Ym}_-Ae`^0nkS}Pyrf_-qDH;HW6I+Z)N~fA8!*`*L z#&?ak7(a5%@{ut~pH_C;o6w`ZZLnYc%`z}8*7~N1KL^gKn)Ab#$o`;SffDFQJ^apQ zj-d2bZ0_^BvkLa7O@%lwPL-bKU{l2uJzv5DaQYVB7uKjN!@1);t zZ{J~Gcgg@!C~4I`4=J-JmrgB`ky7Y=jS~XBtcERG8A6JjFZ2VISgL$59n~;dV=*Ha zK`dPuL2GQ?__goO0Af*aNW=~Ee{vR&q3%Lb0uW#Y1He5%eRpd4b?g8pML_i{IBAbU z;$fDzAH^;qY4jOW>K+CFDcjS;R(TizUV{P5_^;kjX2GRFwhREYuHICe6K4P& z9t@yygaL44>D=)2F>daFwN7Bj)0DYiw4;k+s3I!#ce-_xkH`p~R z-1!Cy2JK^oI8xZXy6p>$A{uJ82P+Fg;)SgAEmeCYJ>M@iATa$^S=&F|3akEYM?SPD z2Jnvlwvc?b#ffAsmCG2C1=2GD}PW1ioR;m;2r{)Ksd$J{UgYmWBc zF;B^F%-yi@N@NS{7TEtzlT2JNe|{PNpCJ7IWS?gVyZ!g-G^-UZ2H=(4gV>aQb#oQP z8s3iiit(|csJiT90B={8R&V^n1Kxi%`6v6#%PpS#lgdBS=VDe5&d)@X$t3<|UqTw+ z7b|cUZCe864mlKI4?V8!?rzCDAJI!TkAGb)%sxLvb@fpCo`gM!#63o`e`4{0^nS z44{@=;c=zR4=F-LT=Bgw)v0au^vfrORO3DUokJf5%;eyVxKkm#fBw6vo-~|B^YGKP zOsSft%T)~E*p>EqNcI^6AZj!Hocz-xguTl|%3cf7aR%TBe?7*_U$62XbMVb*eN~=) zb6fYlY4gIvara(#_fk~)y2CT!o~^I~?c7P#tPE{l{2>AY1&y=dYu{;jv*WMjSNdFh2@tof%BL1@Px9o+#(R+v4 z!nB2H3)2>+fB#=$3MmkT20={kW}Z(g3u!2pU}-F`rPG-AczW)HoDI{J9hzEftPv;o zX&&((^)-2Z&mlY@kozY14OmujZo& z9PyQbl^=b|qi))b?siY#CLt|p-QOQ78)5ha1->l=7{Fp_s5hLl>_<_rMH~rFTH}X& ztRgVqZCbS86);boei&X|mD-S-yImyU6>Bh?0Z13|ql#Oi>5{@Y1WlxxmjU2D4={jK zcwyw@Ap-g7N%nCV@Cr=LULTgp#cEkNH;REc;AK{&6A2xxg_o0*U@QR)lfhv90Zfy> zVX*;rvvFdw0Rh^xBxF?q0VcD0Wsv~^(vu8lF9JL_lRal20d|vJXDEO0k}rrlaq5rZ ztj@v&R8M)6FM_D$Qj$uyz7XVvUqPH5yV{sF{cX}RN&=73VE-6wa0XXkSUvXj_r4vb zBwSL?7+mP6IrczMJ5S&VJHX7^#@y^j{L62CVG}v^w+Y&oaua<46mKh>T3hXQ(FcR$ z(>$=PjnAHq>X^9~^!rPHVd+oP?0>qyEB!E7ng}qz_@F;teIMhOHdWn$Y4GlFs*WvC zX~{c*@J-t6-(=%gtoq1wSK)mZhfV5Yzgd4x`{^h^pZ}d6A8fNvXqN$h;nk;SsW1V{ z*Q(|B(mPs5+TGHQ(t-8ZHMex#<73~US-IQI&$hRne9JWKNM-<2&14%y-9p!J3RciG z3E70j2P_%cQ`FzL4$umdll!RETEp2x3?S`Qb7Sv@R$3mwvTlVd?+UYe&rjrEF$6vA zRoLUpzpO)@9pLLAk$9hfHMKFypxiL;vCX!*yYJCL5RwqcglXSH-vzZAtP)leU+%3U z9RBGnteTZAC=gNb@JMle3GK0C>jPRn>{|4tXwUQl@PRu92#w&~Z}Arm0otf(E zhj;8-*j{~}mPO~Go&w`n76|H6XcY7UA1D?|UpShfcIEh}n3;MCpY)?B2iMdI&ZCdc zaw%or)yvFXeu}|=Qb!d>igbKOr63e14wRA7ea-u6F8F1=o2LN(sb>9sq3lQ-goahfI}{(-maSO zxdD!89qQoMCV?4DyZ5O12f0F#nIa|1uxnBY$sMTvl7Ur!fXT!UDY`^cjM3-b!I_a$ zZw7?4ojAr97N{8UDs~}CC)O)5D^ybRl*qHgwNtJpK?X9$za})Te1)n-q8LK*AQ2xJ zi*_O|Jy(@IgiX+{2rwZW4D>>J);F$4aK&AsJamuf>qtFI{q+I9+d$owni8rSIGlv_ zgMDP~{s!-Vkc!Gf;nAggdR%j=K856WU7Ps&SqG(>KkD%YAEAW2LbZXJYBB{awbMBy zkzLm-^#bu~N3K%x?JV|(1`CReTJn}@Aai(Ye&&TFBKDL-nE3N_VL&sC1ogz*2~6^Q zy-X7UBjTj(?-ddjphjybZAFF&q<#ipcfYog@Jiu-y_{ku%M$k-RB9_sM1d!)qUMC4 zVIrizV^-{C^N5aALT+g8SDxgD8N20AWtpU&ywq$(xF4NFxl-TK=TgMB_Wa1I}7D0BQOB<(EV zwim~gu~=MAyMy(yJWOB!%N6*vTj7eW$8u*ZGAWnOw+YVrMwYasM^GN5oVP~4?1<2R zR*c<_^;Vx=C1mAO4x{~P4fU^w=A+OgrpG>W(zSJ-b*a_S$>3-`d%0FQw-_myX%Yw;9Fg-^Vw{ zV1rS!o{NGgX{s2-R)CQD@%wu?-)vXx@wEYAmjpGTkSyai-)tn&aG{uRc7 zmVpQ(jr3#L-iASDHM<{!5&gm3eqMTSyHL~E6w@}*6fes9>tFX> z{4?p_c&hu~i3uJGQNg#xS~!UWxdNC7RaG(+kp#jf9-k38WFKf#Ax)1^%9WRYYEkVFGP5aI%668^}g8WVRb z7hD@odOtFjSx}72F_-|ih-j-X3?LK*o|H##Ko--*y})2%rbR5b^I9cJzGhd>U#|Jv zi-OT1z01XCZIij#)nZxJQB54{;}LiU0G>!gb08pp+^!>dZmDzo-f@`?`Dg8dF9t8 zyxyfDgiI3k98?aHe_}E6Wa%isvEM4Lc4}RQl)FeP>qkA1;jcD;z+Gp#>yAx&sIOYr zZDuQ#`#yq6T$*81=~5HBZu6#Qrsg2xBy+ic_CCBJ4s{kv)Qz<(XPI-37sp@Wm-~=> zsbXgPN=(7`J&}=NOGFq`cRE#}9|7* zzMJgGEW`=0pE$LIj)$bv1=ntYahF8+ooKJmd{2rRWmnDjxfB%B-E_7Z+5_c8N`Vma zJrcBQixuS3V*tFW>E#zO664E(I$tk+!BD&l9L^2gyxM&#cqX{FPHC6{xIPH6=9n?>qPq^{$5%#Iru(HrLXc z%-C3eDk}YUf`E!Y5{qGFYchfc+~80rl4ru(p(<>y(j+i~PeXzytCHvTrR!#Y(*rE6 z_LC@aY>-+a?%>>_YiIp?l4=1dU|-_A>h{&hJR$R81DEAC)t@uIb`nv&Ky%Ba^sna zxCEN#*Bw9PDeO7KxqDg%HcttEJ3mW3tM+~4Q@u3bO;ZeDKz+shOo9Qh%YcC--K7=k zsmug7@dc`4|iK>m@PB)=@YbEr!K^7oi|X!L@S= z-86x&)~O7PY@o2tUd`ese%AB7kKRA^)xD?L4tx>L&53kSMU;ucT4D?}D zBp+DQeXgckE$Q^J?DH}%FqKVP`}@kuLlS>d&}Y+^E?WO^{h;#&g7K>v8A)RR#A~4s zWey-ugQ@tH^oD5LT`6vV%jS**i%S`vr_{S`bV?JE2`n}gLc!($iP?&F9W8)0@ zdA8c=4cB#%JJQ|fEgfq9w#Esj7{T5kg2BMWgGAM~AOmr*R5fRR)A@GOe!ouL!*@YQ z62=vKU5T8D=jbyx&_n2__K!tc+Y$pU?wrSxk@b+QaEv)?6l}8zX>BMy^?wxpAW_r^ z1`rzuax6l7{4qQrN7p@EFI;-|*!?QCZt{li%vGVL%fG67i662gLz|1AhA2glJ!owh zDdZ^T53 z^dOi>emV*DMvFv7SP>&q-?CMC?QIA+2Ly^Pyq;O|faOEBJU@zAeOT<9Z6?6yG&^S_ zHndCVL(+%8XhTFIUw`L!y?p;*l9RuB^XHA*n;+sN9kM=u$n+#>tP95&^uNL=(MnMv zumpHLI$3KZ(dhD5>aC>>cVUZYR-?p`)+6tOGf(|&YbvNHT9*AW)10?xz>4a;gb*Ov z6M|6eNV!N|M-aA@+Q{qeUSs0n{QCTHld$ATyUytvQAnDSaMvTqmwlxr)NCU88wjJQ zx~&?BPHohGP%W0EB9*3pI$gQw+?+oB%8ZgyA$#u0wV`_7fWxAh5b$pkV{Ia`jKpCA zhLYMA`;+L01El4=Ep?*94`xhy$_86*9l!YVZ4a<0#sbwm`6C8;rCOzG>uC1mrhK88 zO=WSpxA*xA97p4R2Jk{H#~bo(YR9TP>YFk*d%2W<{aSWx0j@vwj^ z4KgG5e{_^!s)S#@hStgXJ#H~!Z{F-}yUik*d2f;kBAVb9%RoGj8QK)qy`BDl z;rpGq536G_I({`zpaE)gGK(VXMJ21-k)+Kql{-#y{`&?6qB-PcC3gSQ!{u4AhV#Rm z`bRwu$*BH>5^b1VtYS`%QK2N{A={f+bAHWi?%Y7F-A4b@F(of8I1?m1Fs3#+tW{dI)b&=tO6l zSDF(Odvz90xN;IK#zX2(#+NO4jyy|!G$+C4bu;ic)4}hOe!CL~VGnYo#U=_ztRGuU zK$2uL&*^80WaZ#KONwzHe5vq@oMoGGP=qV@n^nvNIL2z1oQK4=HbA7wfMU#Mm==d_ROne4f#5?;SCe?leXe z5%1Y&+9`b#_t(QSAQW zBMAuEw`+wbCw&UFzT8k3!)F|vl`phW6&YUfP;7g|d85MS5oF3qX*<6kMZAuSgK|;B zYCr*kLDn08k$W78>y2F>jE}YE?d$o=zH3ga(}SfJTEtr&nMo=C6buT`xsDLW9cYDN z*jYV-TQUmI3_lagV=5|ts{I8~Z_JuVup>=|<)TABG#+FZ5Bd0ViI#KVzS=LBK#5E! z16hr5a%&`U6KST;tE!x=CgRU&!`2<9NhhE9Plq~M(aQvwJ zvljrzbyz791{Tw~>K8w0=%Ix`7=9~F-<0@k&^G}tSX%77x>^21T~7JuN84uzj8~Sf z$IE5j&^cLh2eGi3A_Gk_kd6#>B!xd9-Ra(+XgHT1-{N-{t$K{Rsc33&dUJ4oH=SrE z_7d_nNg?)!eBrEragNTDut+cI5y5x!V$W(e0^9c^{lIa4XHn4H|ZhKuT{&# zJp1_7$>$lDbGdqLg{B{57n#YiZtN><>n_5nf@OvzSZ_L0c)eQ*2D0Ea0z}YU@*JGp zqbytKm>;Bn*k!i(6fxB$duS%&Fehu?4tCa_yh&7Brz}P5E~;iOrh5`(dZexkz0Wir zJ+>`phL-0^W7S#Vx?FOrEm-2&Nkub``P~&I(w)Uh>gCY5N`i#-(xpa<|5&q3Ln?yx zM{u7Gex(ZGO0=MJsVvGQ%LuJwIH*^M!dPNiUtYz3kG^r2hp$|8IFD?GrCf@b4G&3D z@?>dtho#M-2E9TU!1@)L{bMItcgZPW909s9ghz2vZ;xYrp^1f3UomnZ;pfx#rqMKm zt1nD6RDGXL9Db=+vLQ-Y7D%B)nJaShNH2}W2>%oIi~s*f|JJLK|7T=BSP^Itw**9- znc81}#rncnA{T{GT%Bd9KZ{;$HfK{t+HaOZ1|tT7L*7CbL^)(rXvH-Ns9@OiJaT+L zG!X&Ae?x#!g6@MA-E*pMi<%PV>kgIrF@VUIW+|kPE$U5X*6(9kcHsT6LsU6Ze;4|2 zBxq$P?uf(QqnFGj0< zsIxfyb@OhdYfac8!i}|Oy$vjw8+>D5-W=tZ0PII)8X@ZnWe6u)AytIaGEh2me~8elQIkOZ6zT|V-TC2?iO zn*o@P9m$TqPChi`NUO7Lw95H`mmPY4ClGT>IDE;zANo$FPfY;T32o=3oSF_4=Rv9v zG1Yr}y4UAjdCw98Q&$Z$j2rz^gIg{n#G4r1`5?!-1xvv3P}PWW-EG_bWy4yX1tNtb~mt%0ccv}_y<$pjLBbXjl2=v?f!8l<3%1oO{3)^EGeF* zl#BE)ZrUI_UJVk7?a`G!R)}+dY?%rPcX4EmxH}Naq8mOe>+$e3kooQClAq8o1|W=) zqT~L)=u+jtViNR&8$U6m5?|%S(bO>><{WrGzuaI{Fq8Gq-niJ)({tBMP?1X_ zq?_pI-wwd+d6TM*sa`F?knY33gp0nOws>0K9Ph%~XY1`zR@*80z!^n!{OF#E7l~=~ zGE`GRc=}~oW)=voSI@+M7JjHZW$^2~(yFBd8BQV>P@>mxjhFWJJtJW@#C`v3PH*d_ zE?upiEAmO}I?nklKTBOd;~bs|aAJ`|bOTx?Mj$fc1DbDZ=hHa`U`ArcR4V@>&_%?VNw9d$Gy_ON@nB@A zjzo}H(^GX|yeH4_xhi|rx`#vibSD=Dc2g8jnMy=;^U^;;cg(2g891+rjE)}KUL?3WmZrWozN+=1lDW{Rdu#(W)^PL{c-F2sIVmH@cCe5B7uJ|tDHw~&#BE`!93I4@7_+uBnVj(e6yH2 zyKOo;;i@vPpIby-hc4?D@X8$py$HZ-q!-G+YDe4n*Q%q%>|Dn^sOtF|GBX8miC&; z!Za6Q@OycrL=Wx=69MaWookM5)M_7Vv`}%Hom{>m=5-`0SNC^p+mb!k!HAQx@1cPR zBrTP$iq06JSkXTswd#rRjIfjJO|{-{WTo`3rQ6!n2c?8Q@A2;t*Wf<+NaKv$A9^}} zMS?ylBV%w1g!QAErqUbk<9NUm8)4iKzMt37ih)lRKU}$@4#a0g2>Ux!FT<79wOINQ ztaY^{G*zf($*pn8p=ZB2e&?lDWSL%j(nQckPc7>nEPJJly6gG%2WFr47AZv^ayv&1 z$+|@}Ynumuq?nLilK$Tlo@SrTSQ2$8aMCrkHTtdby}bf8Jwk4yz19y~ zjJ76Ek*X6FV)YenH)s76KVYEdYZSL4Ab7#3X3(WQ?Qq?zK9@$ocuDN&V>&l~FR{zZ=p9Lh3R8tB7RXNvC+mnSJt+1$iNkqG?!k8gTkWjGJf9rw`Q7)E^fXI`J=bq! z7$*sJ&z!3yza=K3Nkas+gmJrnu{?#*yUsEOxXUT#5+VZMF6Y$9UOxWEldD<-_PO}x z4ZdzV*8^sxrxJ5%ND##U%;nxNt+!&osj&>%EEFoi%^`U!r`) zpHpPx=2_vk^a)fQrkQeyJ`|2-)7o&GyF7JwV%(>><(b~Bc5lj|8JCKGtwXzSt298%oPx5G# zEGE5#R2%R_!n=?V(3lw)xWN;LUVTw+$Un2eW*8Kirr5~Ihq5@Ai*(pRGBFhL>=b2!ox z$%{D6^oD_39J9r9{;e5Bl9ecTKLZ1U)Rs*%~xF??twhDVO>Upf5%t4q1>xD zR)jgp@vX<>o_n904bbE!EANcHF;Ovh6In%ZN2wRA34iYF86!vRdu851*KtdkGro9h zsyg@}x-3Av^4C-Z-6vOhZ0?VB$>rj^#1E8&?yP#Lv)bei0IB4>IvbIW!q?yHz-BBt zKck*noL2ZE`(o>YhQr)Pf1ZG=8tJ!g9Vd0CcmEKpd56N66p9hcl9;d#mXr-vh~`s{ zPb#gQa^d~5(5s<*Li4L;&hO9XDzm;!X;R$iz0$|Pk);|w1OgNzG!PYf(OinXq4$rY z>%MiBHog6RWX6%Tb#vzET~CQ37ok6EeegQS#v0{Xfm$c3QMadxf5RL^dES2PIvaUg zmtwhXyysHs-1iW@s7kRaSh#kS3n0Q~W$Y$*v7l^o*V@)$&5r5!V~gz5^`a`vEeZ3> z+w@Wa=?O{)ahrY#!o!4T8bb`=k~{)M@k9c@{^9E`8DEDY?{8lGa znyN>dY*t8NYO04)3CZMbTh?oe%k`e?$Cqo5{24o)h4GE>IqIcIttDc~4ovs;gvw5w zX8>$S0qSMqE0F(Ghy?6ws7F?fGNE7wHyB@4GQB?Re>LrN$zB2S39zT-s@`a&HDZI3 zgXhgEB|nYMptm5@iF6*Ftc8>GubrLwHlW;Zm9yHczr7%P z@rdr=e|oo9_9KW~A?!W!0|Tf>Wk9{r4`9T80z0{&JfNo175694rQRa+`_(MP^zm-i zO$k1e;k(OUIJ)joHHp}s5m31rE0Y@J@%1hBY>`vIYUsJ-c5BH;G~=dt-JP(Ut`7=J{h22e+Q^F!@g?Eh6Sbae$=>Bdiuy!7esY8 zRDEO)DNf6!Mi(P-NM%}uY9p_D`>ARWd0vs*Cdae6+(B{BOP)ik0 zf20bD5X!n?{D^a;sZR6(DGs;Vyvfz{->h63FRrBRKevrEzA8R0v!ff6|rkGC44I!pD2@gI`3f?TgquKN&!S8dZQ| zM}n=76Whp9pj7!P*$QDWdF-n^+A+rgIri!-ee^^yK7X(7lX`U9#Tc{s(<}fbkx-VP z4=tgOAWsvK`DNXquN)&it?Cj+Z4O&8k_h~HVs(5v#aY_E?ml{2Yxxj6dfc2Sa*gD>#n?m>(K zjfvMiw}h#Bv=sdd6cy^liMM=jYUTpN)9=65Y8EC|msi(*)c=VOSKnlNW5uUlxWm%H zG=^~o@c1a`$^hJ^7{LCmmYPbtpnLJ^-Zg*WdjUh_ zpEU|?<`c_ND#uQouQIss^rQ021Ay#~M-22R)_v;_RBd*I-etuARxNv>1Z*FQ(@&UzZOl&|X zK>sQ&Pb*~rUZH}1kIa`GF5P?myqbec>>=`oYpq#z8cF#|F>qI0HSYkFG`eht8xf zA+U{yY30meV8VVlV!@n)X<)@qr?g~@*;1O(BZ=D^Ich47@WEM|a|1a`14wmbC$wp= zcMiu(^(B?{Y(SjB{Ke?2v(b8%m$K(By=#bnI1?ZL-uKyX`DbzYfBA|F;l~Wgp((gp z?1nZ+?>AX;ISow>F8&D@(&iN(?C!P8^kwm zw{d(z1(YKV0^mgJfAbdIsQSSEz$Fz_xA5$}g~4!@_>wP>2G^(;e|)qg&)B)6v##U^ zuKF`Iu4ayv{1|+U#|qGAq*aMjHvytC0XO$^K_+=-^90Y^AzA&)LSEAq!>%7)J8dmO zYD!-Hbs{nwd%7D|VZ5io>u^Z=NvA*cD8D~+r`KC*1HYTRf5Nuw>7M|^9j1QfOd`ba zRrUnk51HbAoJ9!#(XEwS>y{Rey?ak93?>hl$`LsE9IZCO!k&c4KSR#i|3GgzQ-l$h zNVtAAcKSHB-lV=1gcH;fzZ-vbwuxG7z{bkYiQNh286NgjVN0=xaI?G*0_cyXwYR6| zFlCZA7qt9*f6ZJ5_y-La%Gb*sFMQ;&HJ5xUb@ITse+SnI{6{32e^Rme|8T6dI*-lvtsUFB|N1Cz3{ry_^xy8_6rwe8o-LDaWV)%5@6hlT&M(LbwT z{D1U64*x3R_;*RH{{d@)FlT7R3?Kv^i>>QV(Hh~Tf7-;^TNJpBY&4C{%p~I@d(tIT zw~teQ+5d34DF(Yok;a~c;%m@s*hNp|r!NTeaTV$}=fz%pn;cKecnw$g-D2A0Z*PUV zzOO9Xrt8fNfc+#bA9KW%_i|JA$L|u9UM2rC} zT1GQ7{VyB~JNC>K*+f0S?wpPsVE|l#TXfaTe{uOQF8}RZx@@Jks}x5rb>)r3QcZ!D zvBovMRPOhgq|Q4M#>eT3eHg`m;5En?keQw%KN|iIe#zDI- zJJ+_2AUS>)nDo8=n{>Nz25{vQa&YRy5}orCQRQABT~lm@ZsN?GNAADG@-Hs`^KyxF zh*VqT%cPvAf5Wg6;SaPo?yZ=RL>}(uR}Mv6+qPiSzsEY{Xb9UK^=y_3-2HFtf7h$@ z8@6QMoexXLHv4qoLxtC7zrRi`j#RMhXlfqUwn!CpTyB3VmXsWGmZR|O(pak+=ni{` z-BAabi367fj;`AN*6o%_8tui_oz8xev<&aHvGRf`ZwA0dyZj2Pf?A9>;Ac*?e+fc8 zrH1-D)&IvEKNx_+J31_e>9E=`&yy&dx|b< zy{JaxL7rv`EPL<22<#u;p?P%wq2Y)|{~Gc?*pTHRPqV_38`HgDmN*ZY>Iub=naiy!tAf1A(IyLK_H z5MXVLZgeBE?`(4&Rg8|e}8zE6aH6)SCq%&Xo zJ^Hg3aeeu%|D$4-3qC#`LbextJOmGz34yyz-R%sf^UtiM`!C`WfA4)RE0wLIRR=y( z@%H9m$pPd=WnXBeMEkLlCsV+(ZfG;A6D3Lij66vzMhK8QEMUaD20mpa?=z$>&t6rR zCkxC2?-z9z2XI`?R{D`#FmEI|_oQc7 zJz0I^tRTy7n9v^ve}Gp5PwK`XqA4~w`klue4#z2v9;Cl+39pE z#o4;2JoE25*KBr2K;?)|hiZML*OAb!dxdRp0*8V^W&K|@rNRPpxsLnaQpi_4AQr1S z`lxL$go}m3VT=r-kN+*K#Xi8*qf$eVQghP_k>kBOGAiF2(LE?fiq?!tC*C zlQSFFFW<2o!#{fA=0hLDgBM$mg)R;da+k`ee}a!cpzG0nMa27r%vkNJ^HLiN=UsXD zoh-a>eu%Et=KY~@Y@WGzVq!PVmRWZaQm8AmS15cblmmGHabXN8HtnxV*Pm>(2n;M} zl{Hc{CC^JZbgFF+XlS%n#Qm<5j^Kj&Wr8PhOwZs0lLYNQK=~0emB!_fsV23PzNZJ+ ze^Sdz=f}E87L5ZD@kPN4Zg^Cp7R$c6F;Xc&hUlyoOU5YWUacbvH{W0Ux$Nb7!MoXf z**1v7!v3gx;!&-Ng_q*AYef5gNc;j6ghBck0PortbNqmce8>Gi=E+AB=5^649G&T} z6gxY`*u;U|6eUt(AC~BZj=iUlTsqb+e}?by?3uM}FO|5a(d$)rbZIz2gzvjKw;KBZOJyvfZgUPe+~!98Uh0j;V_F(tL! zhB76O1MY=2bj=ceoqQeSE^TagcD3{DkLoGX8pV!2fe{CHDb`@b5+?a2&ff`{mUq3Q zU?y{e?=B_bdD9blc_&uz5C7twEFf#gE$_C}j8Y(ErU ziQ=Q5L8yUc#8#QKLcXaREyVn}p*t$`iG#ueA*E%`@j;?_NBM}~)C)~Gf0-g7aYFr} z57ZG?We&=dstXHsHB&>^A0HDjxMTX`VV`<-qHG>@l$1ynF2iS}5@znAxIi@rl5lFM zQs3;OY$dq1&C+lzr^ayA*Qj&}Po~tU`$R}DgbU%vwBBkkf{^*(dycC>kJD~xZ%d)3 zV8y}0@}EENX`HKj!Otmnf8Cxf24!ROZ-}M;Z;dJ7Y>^CreqDuFOz){eF#ywE`28>c zmrkC)O__q7UF#~;p_NiSDXMNi?Pnp$R0Y;=%FV$?V)xnAg(7uoLkmx3TOIm5hHCX= zUAw3BJ#)60Tt&=WuUg#V`?YX%Obx*_nX>DyI^9>thf)4d2ZenPe_VW7QIK@&^NQQK zrF2>`HUyP`tH*SdAPjO%CiJ~Y98Sq6;<{VqE)q75bSiq^xSZZ=W^1@<_^mlaJjP(= z6;}VhvfjS1nEaI1*3L~a0CAR}MKS2<049<+Y~n*?NAH>;2KW^QjAVgNEnV4fBtzy* zesFPRv+SK0`ZM}pe_N>dv*Z6m0xsC}-M|ix&U^HhvZo?W;pnhCN8DQwA3c0sGM0{d zS#ex5Mjk@&Glf3ozfD75roE&JPFCNns_^5*=X!1{__uuoQYm;!!x;G9D6CjJ6bHi!=|Vuf4+TiGOVG7rk0JVt$F;9 zpp_3r|4lbtraICoYQ}%q1+TfC+Ws#)3Gj1ZKDmjO-!4&u1MPcd4&VKxYd7}YPc^tS z>tWXA4%-;(k2S9s{x|(xJ7Ru=p&)Xh5e<4TE zHa3>;E_S5jf0{bltM*@DsXDlIGy^c!Gh+bQs=poHJl!dlRMxLlkvCN1cci`oXu^&^ zp{X6?2zkmjepuF2?@o@gdN0zN-X(LufDds2?5AAxE7Tz-6jV7xhB_ti>PS4hlY{c#Vi#gsyuoo!4A!PE@9ze+`T-_qT>gJ-H~KZQPn{bXv+x z(*BJ-`vp52>xkg+HP88)oJG&13~^Qakn>el*x~&^xI4TzYX^$kE-kkhp`S;pK&>X*L-|UQl4|r20t4>nVl8uW{Iynd#z--q^6^)h{Ah^ z6uQ`m?s0}c%r!XLnAxZMB|qtISN{h8r6bF#e+SjmlRizo)c)D{M})w13Kli7&~+AF zdVXl-?%4ZUhcH<7x9h(7nO!E?Wxgb1C}ySLr;IRC0%U4_e>WBq8OvOR9*hio&AP0I zZ!=45_AgVP8_*+ep#hZrtSKYbloM&*x;h)8eNImMbJUSh2pEi=fzngLvlsx%`EPH)QmttC z71F^h&lpj>-(Nk);t;ce+^cAitWDmpB1|3IN6RVTGt{J{`l0FeUrzp ze~Me?#1}iu7oy89NHsPbNq-}Fy4-Bk)Y}$d`KdHgvmVs(lpe01W@57{D#;Q-_K@6lqPDl1_b7RNRBYKS%%e#Bwu$wS-azP^MQwe`&=W zVH&#+Y9NEE#sI3tbLlTOD>r}9Txje6tFJlw@46!C|9@?KSV`Sd*zZOAesk|sGHw5&j!B-KW$Y>6o}wkI1|dPngg z-YoHU%E~+3Y7xtoJzLW|2L%;iR6*z>14syi$I0;0mHgutHyeD-JzOvTnmmyZnsY(! z#H?xJC-`nMw?>nh$IMw^a~Gb7tqqMqd820e)MlW4cOtX*t`V0lE9Ub1e_Ai4a58{9 z#}3NPUWfpeiIx#4;-xpQLLW$w;bc4bO&bw)b*hI11^*5#f7G9O{5R z>^gfUM@%2KbiTUmSWE)wC5>N-bMq(mFN!?G=%PAp^_#~Fmap*6R>r_;~*dRtw(&ibS?@WasUCPJ#N=_$3uBnF%nJrefN-H!`zvmrRcnn zS0cB&lK8%uiAmZQe=#$AEtC%`ZXdN?w1`a+PmH^ZJq%)d2*39&IxbEsJ-6w;qpU;h z+E$7(6P8!-(O9k>5#7UrC+*j>bwSQ|)K7l*f&RpBkCxMksC)Y}& z@&eBW_UO&w`# z?D-_i=F2n8`VOyNg91NMpv*}bV&oBFqnLAG*6P4An}W$)Va zzYWni``uw`4n=fS13*m++Ou|X_?9)%LYx z-^rnB89>Hvs##d#ySCm>Qno3f>^3h>OQj=nDWZQ*;ESyH zlQK;)U#Zch*lvgFYSl1HwX0u4!`0?_fESm?$JxlvRe00H?}?FhQ;M9M%TPoZ5#9a! zf0JH)TVpo=aK9Y-wjb+uC|yuwovA{m1q2zYs@4`=8*YyLisHihWD0{@=3fmI=%cOJ z?&!->;$w%j)?flNt687?GLL2a?AFlKyllaG^h|L3-J0V6v+0KP-=-VYbN%RgnRN=u z$gX(`a|~oPBONRb43>Ifz2K}|C*L5Se|GD@J;j_e(m!ILiVR@!0+N~e>_jabV*p)C zR~f*P?amW8lZjgtWy?iT2H^M21w7V%Q5D{cB|e^^mAm~hj85F3=vU?6q}zR)S<&9{ zrJlyE$1#9QncX;$?dcq3CX*Zu2b#Nji3cC)AD_a`Dp*i7XipY`XI7%3bvHyue@X!) zGY)pe(h?cK&+T?2CbaA;U;urUt0Oa-i@xhq_^p)N0Stf(>X+_J$Y{E|mXz`MKEc`2 zN&Z2h#x|{x&3^vjN!}N{{gW6bwn~toJwpA=`g>;>klj|3h^{yNAoFnc56Qk8#^P@v zF)=IBtZQdCB=}nFkaB*ahYkPve{$AYHM#dGpQD0h1+He*n>@tpJ$ULu9$3<*KA`vP z<2E#-NK-v-df*X!fdWCHhrRKATkE-P6SrxXc{OyH2s$D#InU(KXR&7-?jJni(<(@L zYT#dxLv<(i_q8#AOqtry43%~n)SIF6!?V#nbu+X=i?~*Yjpc+>*UjWSe_)Rl70Uqr z(}Ju7TpF(a?=BKI!M@*BVyPwtDe8xTkiwqiSXcU=tIqXMC>#vc(93n)J>~eCQsE+b zI7R)DISs-bt}ha`$c|ell|?4@-Qk9dPvc75B>bK_Ma^Ev2F75EP zk0802hNDeC8`-uL{**LDe;y;O1`&Q0qzbNS$uInejxQrmWbZ z>xS%;+H9=b#dJ=E66(=OY`_^GFxP+q9GRZcS`dxB$=lvMnpu#ne?Yry75hb1z5DdB zQO%z?qT@;B5NzNUo71n`w8GD!oU6(Dap3V_Yb(C_eV#mu8u=}A!mg2ty*NRtHp!WM z`D;Tc0AIc3tW4hHpLgtK|6EWTtQySQ*wG28HGFiq_@s>T@Gen-Ds;KKUp#Z;2(ir^ zd^LHB@SG}CGWRRne;+2-6nt|w=Vi7zOWqlDU^M=1TuAux(k*~iOlvmaM;uQiOOk35 z52m}jzXB~T1y%_fi!08$%$DoCKFIprUsTyEE|>3u!mSbfR(Gao<*2W=Ab>*hRk@{_)hG6L!R}X2s@A} z)U*Gv&B3(~d)g$vICFp_d{jI^If9=B+@c5vpqq0O=|CxZeTxY1LMjsBNhjJx&LtF+ zJ;Ta%pN(2be~k^inX6ay9J29y5(MBk=NIyssE15LLj#~Ql%<+fsx2XuYwl;OE&V}- zsmjx)%Cc`q+mdqv{o>n2?hNagl?pz(9BZVjaIO_b6&Rs&@e+>)Eb!6_kZO*dc$(AV z3-*rp@1A(EZx;%%Rq~V?@_aFKzM=CN^QScOkAiqFqIkmaFH?8}n2@l3^~wmc4JK6Gw`@&djx*^Pl6SxD z2G;jJ)2I%=VX-~M6EGNFJ})SA1Cq@E@FnYSe;5F}I8nBRs}hnhpb!Ie+#_#+syg-6 zy=7Ec;!e=&tNEd~u4b%K*{+67Z^XP;pN-ki!hC}wYQq2boS^d@{TO{5CD4$W#zd*6 zW&Za%UZZ)_KUJ4(&%MzZ8<4Z^);}_AM6fKqTrP2eH`_R@o6HAhlFGpmom;2Y+e`1)?s;=MT87?HUown-IM3ksDki5Xx&C;XS57n zA+7`ruK0Pgw1hO|EBTt!9U`>f_Ui-p<1F300kq~1_pkP1_>lx?gXubjDYqS3F;#bI zh^1r(2YYGZ)wEymlsFR+nKPT*`(!%^f5+96ArtalL5!txyq_w-#L!&Uf%pkfD3BCr z$qWqlM)OhfVa|;)PEcM>>wpu#2OmGXpuUvxbl;N#MRwtMkvzyx`z!0Tw`Pcog_EF=Y2-)givzW|awYc5qY5V7Q zazu`H-i$ZQF}T>Y^d2RA@E+GL42&r2mf1fEJrXGFD0I1SkJX(nK|4AA}k5zC6i3X7!(9+ zQG!o6zdvzQ*n;9ASI7ARe=%~iwhxdEC$w~Gv5;0$UL}&tnaf{@2DoE^MEwx#En=mqok1883A1&TeYJBmJPpbGNh3%L8-PSs9?-2H=tzn>=G z3;3pQhx0k{Ynov8GEGO<-PUvv0u5vS<_QDdg-CAl?Z6J@7K2nj8O8Z#pM7NVkz ztXaoSk+D-MI~ipbB(lsze3v`_){an}mT=(_5`{Vu3yxw!(=X2iY zeU|q*?{l*xwbVg>Z?lg5AMCwnSd(A(CK|dFY0_Khpfu?yB`P8yB8bvUKm-JYh*E-v z1VMTe5D-uz0-_>>-X-+jK}zUBKoKNC4Ux1H-n(%3IS%}kKrrntsQIC zg_68(!SWh8^^hTn&ESXNw?#H&zJd8J(9tq_^MVx0e{%_P3O?k5>bD^(f#XAw-0lja z^XAurxH)b1WxQYfkUdmO<^kP3dCDgxh;MUyn5=?-BT+fUKMvr8`yay0XZG(9E4^d~ zUYC7p8}JTqlDnJb!?k2GXsVqyvdx&>Z1@8H0VYF4kz}DN>qm)Uh!~gcjKFmsrjJdJ zl4hJ!h0>(88ZUlne_?p*PMs%177IcVEfSW3N(J+ENW&iE5V7J{aZd}nmu7G9aU0Gt8s>Eb5{vBX!nKsU;3gnz{+4KrMRyj7Z}XI-G9 zkVC-4!zgWG#0qce70oO`FYhdnevOe|(mBWYtsg zL`(Hx4fmiD|LUukOCp$0N0n9l@Fmt1!#}To;jTkO184v?)ft;l5RNtfy1R`jxwWnJ z4V0~?At*x^%|;2H0)5ly>uh~=f{#u{o-{JtKqtZ(@T`@7rO@;rgeBWV_p8rzKfmeq zmeqTpAF0mnHOtQM?Iqw54X{TS^DF|yip`94e)uT3{zoipK6XBLcMfy73ao8i#i$H_ zDKsoAzl|bZDf zk`h6M(rR)J7D4&gZjbXDNVo>!@fX5>)K^F4PWBiCsx)t;Xho(WbJC$-W)SOd5KZO- z8jBg532_}jvR2Spf0vFF2m-Ve#B~@sz3O&h$?5z?_~mx*s=y840#m<-DAA9;T0T6? z+1 z<SWeL*{8BEPdkIjLvlAI>7 zt^ox?wbKZ{C0F;W-YNhG#US-BBW$^*0Lh5-#ha#e4j%{e|NgEp^BZ`IX!)Bnk(WHo=P+xISjHad}Q(N*bT@-MDSVoRE0E5W@ZEjy+e4!q(H% z<7cfS^ZGT2%6{n}Kk#D0MpesZ+W7%j;t2kf6?Mi+_exV;ZR5*-eAyzb;B6Y_ENN%tSa%xSV=N_?@1mCE z=*IzZ7fn=HONOgMjXgNk{6jOeFb)p6b67Rs>2t52p+wDZ#`bUZ02l=E;C`OPl4~GJHk9Lk8zi{p`F;tNU&WjI*Sle=uNLrwkaFS-q!!($cs;xZA+P2sP|P;w*qk z&xlNY^HO>^DhlNScG(pcyVZJ5j$~uql%*5n?Bi>nB}Ca?=j3nxV<`>Pfp>%JmG3o78}K%X8oJ>v_07nOb)Q`fwILiQdYgb+Ph?vb40enyQM1U!HA327lpuQ& zdp2kQMzRcl(fRE+xJGkiaQ*kUxJIO}S8l&j%TIo27j(rz%RZia{p>~5IEtur4_y72 zddgcssr~b zA=T%l^S4@OBjjEGgNu!P120nt>$bKE z^SWc4bo7PK8|~Rzi6@=-xj(_LXySYAepRLA>%ZMW?;`~K~xRnj%~Jw^n+v8aJCuZWOd?uFOn{G3=T}_r2+WV$6DRS zRD&Mm{#;I*a_I|>ix{=7sMEe@=Jo9QK2q0z9lnZg%GfL3gz#XfiyoYfZMgYF(X~)M zm$Ioi3;w8r$EORHhq$*CPhY{Fm}PsJ=LPNyD=)d$*O>@%gbqp*S(Ky$6Pz+p_8)ef!Sl-jv;bjr* z4bAlq-D5qF)q#$%{CUx;tkPUdbzGs+$=|Jg!;M)`{i~yR)!W37GXn;`GnIWcPnOSE z-2U0ID)XR|T}$9SmpHT7PYvQ};hwaAn_Wl-8o*a?=C}B(h@SJ1gdeJE2XAX1^Lv;z z70Ib`k59H&Z}Qa%QDz=Vzz0$LAtVDLm|!?#a%MT;d@yR`dl2h1%M^cLc#(haX&yqv z;xckog`8eyVb79?(Y^pYOGHsQEU_5^@a`i}yjnnU6$GTu3cdD~0PloAphO0HM)O-4`%3tUPIP@9`P5SX>Up9&?hBODY`Wd1%w<$a1sXT|?p7Uk<(6boXkd1c zD^pq2DY_gUrM&LoCh`#E5}`eReFfp!px7V39nnqAt;s5Jj`=^lPoFv)@l&wV`t=Xb zTRu+&7&g(h$o(ynCw1!hp!a~~Yi@yh3D%gW$I&G|4kG!%RW%Rqv2-EEu^`O4$PM*u zw8UT=t#2Y4u-4!PY>F?gfXbQGG!wC5Q6c3sUml0}YItyF!i$T-5(2J&_^2e+JUiwp+dq_IsHBT`*2#q<|-09*GC7;1HC6To^9%u0HuJX-jH1y5t zG(%P;uev5}wj_&QPJN?)aOcmZI<7DA=fp=CI|)yCSCirarU z-mY_LGBH0ZKLAQmS8hV{2n_S+KwvE2MQ@aUns<;|&R3G1(`rX?U{DD2i^C)A>827` zi^COZVD3lw8n_;R*hyMjXzJH?hE`b3v!&J(E9(>0s%{rqy)Vxc)3=z-?Y$70Y9Su} z^QR|p82l72HD8Y+%FzG=Cn0vuvNOL?{NHMwD&BL-_8`hk?Yo?{``z#Q58l$j zvJla9)C<9w_KWRw(EzE0ITZHf`M%%chNQdjQQve?x#YWkPhl};S}Lb)OBkMr0*X?o zCuSgApjwX-)d0bA{FT?^=6JrKyRVU*3}E`5P8mG;@BD~7Gf{f$3?BoiB<8C~0=<*qt@Ntzcphk8`LeqDs z>~!>IVV*^7fNHWdcosc87MDeMTcX76MqJ&x4VDFeL`u(S!5yvzOTfRwJn5z;z(-A( ziB=WR@7-wL&7dC%x`1bq%HVJ0@3$f?KlW*JAe1yyGk?2Snee0jekV9I@zy zBCwbTG-F_{fCflt_zqRf6>NBH-&imb`E#Vbsuv=xGS2b5L+F;LzyT6{t_V?-?PdOHM+4O)b-mMWa9&R0+?j8!khjp=ATo?S5+r}(*Wsk(V1USa_(wsjd{Ayfj&jb z$@$)v>$#RCnfCFf!_E)bZ?4VIqy8;_Lcqj`Y)e6s&uv1Ozs^UkG{_+8+YneS&;9m6c8!dbc_$c z-T0ou!-M#C)t1$U%%9x{s-H_*uRQnL+R(b5g1pCC7Zz4wrO>+E7s6lHfr#3FVRmM< z)btLH>@$5#LQpXXy0~?J+yktp0b)IEc)mI*{=lk4G(%Hr2ULH8EhRrHdX|rh{YR`kFnD8&aR>;d6_Z&yRSA@Y-Hc18yN4C%*{+7~V`^Y*f_Jt+WCz?5|K zdNEMI$Om6_KyatL|8>I1cr#PJkr3g4k9r~gLQYHf)9AGyg)0~DmZt8(1x_!2gbnl} zakg|MA^1{0dJ|1aH%#BUL#5pSVVs<7O@G0x?muMINzXaE*da`7zD_-{U)&>dQC2j3nk*$Ze^(^NH zM%NAq%m4w^j^pVZ3DUoRM)WFQ{&OVUl&hiJd;S_1Us>j8GV}c9+sgREJir&Z2DmSx z%UlX+yqP1`C#^oi)&Z!im6EZRkk#&P#Y- zVci-00~NO}Pto`>^qS`b!XKFiY(PFidx9iD`=GarP)L7=#@q&O`(^9H&cV=;W(VgH zasTpbLlTafFRKlV&!77JqYe-3Lf~vN7Badc3O;3E-cE*&NSe&snDZG^Yr;fx?RjE^ zLyJPE^|%Ez0WX<<4iR)m_L&G0^GS+CaNin_?spCTZ$eUPbw9Ufs=Qm{U`w2z+A#FM z3%(I^@z21!N)4jwbtD1{T3p-MNelHabLSWUHx+EVhONq^|CqbTGQfPleCy^jP6N>) z0S4opG{kyUE%7WYxM{jw2~z$MNYCF-%{+Z)ts9NTKBnb=X>1*O3ts|nEC9Dq{-6f^ zzBSA#!g(4X{t4yzeq|8M>y4%K=TMceCK&g9UOIQGh)OS!3{+<7_!>W4 ziRgzFJW7Ip@dbXc3PZf#E%5fI?@c5APmH|3ynjlzE)P zN){|UZ>nzUXm5HFw4E_JGAbADcTU{7aeZ%y>=(0t)`xNIO+>7h<MCH76vKroy%07Y3NR(plu(mRtFPZ#NsdPO} zd^fzE@3ZrD``N>f9M4Y3MjN?qAp32IXMp?K>&AvyRQCuEJJGP`tw>+}qpX_d&tINg zemGozm}Ofta`r*=A8BqTJ^iK`aE< zl+QVEm&NZ1*`cPMpvHl5bsB%|;u**|MLyGi##6dPyuN9bccZE2!V%iHt`1<)Vh1C> zct0^Jt4i1K);5?tLMNpX7KVMLL{O}qtmgp`uWs!Ddyjv76QXW$KLoHVbBx5>^R}F@ ze>K_q`WJFBmQX`nKue%#fIDc+_sezDRO!k(@ZICwB1TL=`g`Gb zLMA0=8oM3WBp!q!~FgYk~!=i9^7?*u#jRk^|4-q$zraxJn8q#5l%O@yImO!Q#bM@ zuDm(za-ocBkNpVKr+lOV0ub@wdIjWO1mzIql9X;1#D zCpQ#l7p@*MILL;b%K+}L&;UG~^ZdhL4jQ2Q3;lqHnM{w$Q-`P%hp+p`^&<p;mk(6 zdC$kcm(sHE7j82^Sg)`?M#|3O|2RH@V>+1T8~%2=dg9qiOhDio=lfc@958-~dq;Av zqbU#h8ZCvK?)yA@3PEO^dvLZp+88ka1R~boAZxY1p#?zxoIq~k_l<_WQQLr$e+$-m zVgch_Hv>i1Wtt>ThsfVsxDw{)fO-Q8L@nia@Iq}m&--<*oY4>?9$<$rDkZ2DJ~Smf zMrsT-XX%`o*sf2mQT)Oc!M|{cXOJES$UO*_C!Pj4p_{=6p9D6{ryLjwxtvfBQZFvT zs~1^14krZ_P}=9XnfALn?I;47e_K+gYj6Xd8JLFzZTwtYg_{TYTuOK2qo~}9_pVV- z84p6e3+^tyFx{%$uWR=GBXFn40B{6OUZvw?%xkg)(GLZ?NJN(tUHeVATdSK>9A-k> z%eM1_Ld35eCRof+9M+v<-2hq^7*5r->a`wM5S>!vtdIg^{r0EV!|G7xe*jQVm^gdT z%g3c(Q;qxJIq+EzLtI2O+7Fy4rG(F!)%>Pbymmq8iksU|STNp<@eX-R`>YvLRg^YZ z{O`X6AZqmo3%N74pFDF3twku+)D=d#_}fv@0t~B&E)5gaHJBsi8BCi}Y3R0V!c&Cc zv6c%veTQ#9fy_GR3`Xh7RF#h`(CnTanA(N;Q-s8sN(xP#_2uO#}RzPy<9A{9DbA|Ng`F zzo@<4|J;fOW5A^&f&%_vAA!w?JCYKduct6w#g*oLe?RfyXH@0we@~C?q^1q9p_!AH z1_Fn8$EVt|%)f;RFc7z}Jc~zEj$-Tq`!ZR0-b97yNp#s}@(HO_&Iz+Blw}kMcLi&Y z-q{#mAIlPR7*g6pC(r;jj@=Mu_=qE-wz7NZ!`<_r+BfY!`B?l2h6JB@2xS$uvskh1 zd9}nG665Nxw0B0Ce+l2zg{(aw3uF^ulV!vkI2CL{e3%WBYF1UgNu5B<&+Exo)Sks- z?zg|(<2l1BA18`>kEWBXg;DtE6f~oM)d0_c&+A2t5A6h=uVY=%+E+2-v?TTO$U!of zSg&w|S52z?7*=LFOxZZtdrWd7^HAQBo$;LObPdpM4D5j2+S7vWq0J2dR&^2=vbg5#GYwCl<{r!{3Qy>=gB#AomnIoHP zN_bVKSy{BZL`eBk^Pd%G5fD(FI6`os2TT%mIy{`t572kllHd~4aH&XK$JFOp*lYRRV|XKB$G7_91xMpKPSG z4>9Xa_SLv7eu?uiOZ}jta;8o-@#FbMI1TV78e{}N3m*jWg8Wg7OWh_y#2J*6KTyO- zfKIn-fAB)d(_;`qGu3uyG<$mu=~PUB;m_~CG-wCcGXSbZCLnyH zq>immlO^DAx6)N%CAA%8ukdpf>(mo9liBk(Q!fqRjacL%)Ki|fLxf`o z(#eJuWT9-^j*hlkr!ujR6T0u?h206wf2n_xn9iqUH9PcMN>e}5gYjA3S`FL2F3AXH zi`U4Y0ld)S{$hR!?arrLKH*kd)746zwVk!lGm{lat>Jsw`!&JKPoijkJz~!kkFX>D z2_)IV7dmum@p-8_x7bVkF}L*zQMr>#;zya6*q*!R^T`1$VBLG4kJHQmFu4uXen(+D*()CXQNC0xRT2lgGi zkb)*W#J3SpiEtlGD#66Z63>ZPr8*6Y?`|2pwa1OGblg`HA-I8@KR>9v_3 zzj$~rei+A;)|rW4lsI)|IR1p6!cXbWGpyP_!$F=<8sI`Z-Z7eNxe;}4e>45N(+os) z!{3tcV;*mPfZMy<0z#slN|Fp!t;qm#bmQOquf%y*%2QPuz=sA9h9+EVz=x+)SywH1 zEY|=0Mtv+QDEEAb%WnVf+pybmf1KhOqPtqWNG9|Ie3dE>_27957BNwVKI~a#hYH)w z9)vm-1o<8hDh`;1HzhG-f5NXsO}*s5T0PwK{T2QEjL-nge<%eeCe-0$jby4g+2V7k zyH(f3qu^iO<@Kmg-#kv8tb^pU?*=nBv@C*Fs%?^?161}BtPLL(L#GdI`?_g*z_^0+ z7C)@D)fN9LmSs%Z$9p>ziAzCWoYkFQ)LlJcc?S>)C_N5QLu}a72txp>(0!^UQWoG>Zd(3*JxPemUv@u(qm@begQ!hFiw85wm+&W!j^x zTtB;CEi5b-;dqjwf1ev$?5jFDz9Zh4@xGx_{3>23BWi;ZK4-YEe>29_wIcG$*X@`) zr{#kUD^5#in7Z7uWm^v~q5El=QegrhU;Nx|PZEV)Ynlm7yA=sHTN%yGOX1Y?;wl*` zSPe@d-nm`*_4OCzYs76dQHdwn}ch(!Ypf89pz<VCT<3cNfLWt`Jn=bWhi z7TEFFay{Lxbn8XCmh_F5cCiO7Pl+vIN8 z1fHT!e|Q*5vErLzU)SB0&-{|i+4gul$2Zwo*7*d}upQIo-GO%^Tp&vmxrK>*K8geS1>WU4XNJff2KY~s$UkpGODbIHb?uS7Y5b` z_R6DB0YHwMw$3nf$#zF@a4YG;(mnTV&xPh~e^aE(aep*O1{83xz_tk-u)*x~Ab>^+ zAHV7q0jKD`B7fDWQZH$T?2%$s+xS(Sz0ZN$@>y-%!m4Nh!Z-SUMItefUNOHuWE|#~ z2R|{bbU?r)boEa7d=k@-xK$^?viQ4}e-!K=T(Fl8vO||Yr^hfWosu%|Q$A5ayR9|} ze`tSnibInL-?XCR9}UG%&-TS(gF)m(Z~v=8jFvCX4vjy!cw9*6qa=5nhdC3$>xjiQ z!lTbH&;~MI>QsH4U+m5Hw&Wj#?X}aq&s`Ts)5I9I`CYZHZslJzQ~K>okE#d6_w@N* z;?i44>O{v4L{CZzCoqvJjA$@v3YAh0e^W`ReDhn~L;1@yv(B@yRNE^RKU*l{&S?p^JJ-HE^(!w6}lLoXDhGHfkQK-Pg?5BL0r5pjsZUOGK9;y69lJe_jGU zQJ-=U4`hXFIQ6Wjd@ECyoeln&teTLgSr{p{f~-iC_q_hV#)TU5H~&KxG6R+z_29SlZ7~@0e^u$0i(L5e%#HixT)FT*T?)h01>m5@z(LHa5mA!l z1(oZe0R-AzR(0|4hLAS_$8Xp)vk7MJ&$u)@F1vK#)Y2>nuFy%A2S{9G zF5(V8(26*-Svp(T`{SKhN-7IxR?(K}r*q+R6fup1`0u zDL5Z>0wHO_4b5}Gt&AP?u9(cNSrtt0;y2=<4q=G;eAP{#OY+wQe;kdZ&O7ca(DNWW z2?Xy1iBJWogKHuk48#=Y$zVG4aE_9g2~EN_enQ_v6C-~R-pi7Q;a?yFTOI@S;3iWt zU{NGBm3}+!U{Qp1>OC1;UE5~E(#C3F%ph_AE};Ya&-rx(Q316d zhttNU{4MZ9Rq_uPf78h>wR7u>dR)G;?2om7DA}v&I{5UN$=A%h2cB(=R5znZH5ITpxo6I@C0A{dDcb*MiM8F^mlI_kW*Lxc@pele7g!dZ^K(!J9fP zWk}5X2(!b(GvDn#D*A-bD~V(Z;2#K-|JjmBb!s%Q>%~cge_W8#q?-aG%C7Ms`~ugK z&sU;zK9J4YwfmjC;tOxPh=;@uuE-Qzc%)T}GzGs|lW5o2ToZ%I;=yrn;Xsv*1EGL$ zEz`HVCv_UX2R&F=lF1c}JSFv^l;rs4>#<4B#=hdn#mP$9nO`ep~w+8?We*g|?0N4gSW1A4ia6Rj*$PJAQ_-PvvVmD{ud!<>sT`b zG7B$6&H%n@seC>DKP$`{A!vZpLVrt|-gZFKH8U3V>HGgxIqm;gEBdgB$}xsLh&x3c z#-N|-j*tS^1g$?fsi*mH4IYK84M?kROIv-Yth@U0e<}?i;ubRk{$PJ-ytAiI(%nUh zZ&QlHkX(9Yo1#@E9Y5*kIcqT(Yk%v7tI*+*`s4-achbBJfJs)=o;U6?d;(bqiJ?j? zcglRm)(f|yfSR)!h^X^52V1#^PpG>be|9!`$fvL*7h=nMGL-TXuDA<20RvYZMBNCI z(btQZe{SI#pGvxY#y$QUQ)J@UPnMHeh^ur+8b{G{=?UbXqOFu_sG4 zSdn3{G{H|X79T6Ot{jezcDZ-MhLa@|Gr~nY|JL4(ff19BHWlmeJA^=D+blWqv5OJB=7#CKZ|Y_Z9_hs;J5VDf3bbkWwQWu!_D_cfe242#U{!DKtZzq zo8GB!a2U|1zIItO;!I?1@Y1JY(xlR;pWlacU%P_4`+$f=nGO^bGbqdtL)YIva&dl)^U$NI=s<9I{u1;R%YMh ze>D2Z^(sbmDVQ+2d>0EFNF}>s*F?V-7(My;E9&Nr)WtIy>mgj49cyh*B&cu{Dexd_%o`)FS zW!K3pGaCgwV$hO4DV;RcANM}q{;cr^f2#AVIqtP{&<5}RsY{iuvR#=@Dv=0f6bwyC z=s2|ts_o0$OERgfM8$rT|LNW4ydVG8X32xJ{d`FzWc!@NB@;L9_W4CRJ(76?Rk=C| zWAVc6jyo4x&(sgrzxxt?^IVL`WscFVOL-VA3tR0a3CCRO7@`jGgsu#b32L~We~sTi zO5XVgJvRQ6cPm#k*l6*yVEk8^CwkGbOuml}1HXzXGi^>_YzUG>8IsLzxRet9xg!Rc z9NNIwRe86rvhpbR>GSj}p_!8Q>9=ZwJ(4^5d0vwLCXyf+H}M>vV+lK6@gdLygb#{k zSJN=M_#lrn=uC`|)279YmO9)ae-r87Bkcf~|7tD3@G~x954|pFNXVT<2PA6z*2DY0 zf2*FOR$;|H^OPe~+9&mr0#9OIwx&eUc~43?h%Rja)X%FN(`0r$KMinm=A%y9bu|a2 z>9Tmy0%&orprdxr`R7a8{EV^BOzzzQmVAB9!$K(m`2pi;fCk~7Dclk^e>4KTIORSN z1u=g9M!fLxi=0hoIbX+XdzrKGSC}<74di<3(F;r)>iHynVm1K`;fLlPbyJmQ-^~6{ z|AA5~o4uVY)aa8g3LlnrstZ7#PRbZ1A8H;M3ozh!5<#~iaUOD%7dq(0^CbJZ?C$fH zNpD)yAA7ymj1O;ipBDFhe@foF*ejP|I_8e^+q;P~?FQGiuhpHTG^{0&g^lXQ5e+_R zKjxgj{Dk%9t|~Jc1r2MxlWQ^B`5vImgl{~co+u|7TYbus98)+Yb>f2|j(dn8Uet@wg1 zW34^?e&>oNcpV+N;u<xK@lI}}P?^L}|cJc6t0IxZJ9$Su9WT6FDv*$^823=qQ zsIz}>Qa@R1Fi+kje?Gx-R+{&~l@Gm}ijJ;9V^++0mw-rtnr2_K?gYEadKUTU*U*6O=>X`Mywfa8_&rWy2hgE#_zQrL_)-IZpmAZUF`sfVuh;qb;SbZVxN=DXVp8at5`>OjD8JdQ^%0i z!d(-Kfmo9|f4u1ip#}xsZCyz{hD`-T2-Plqyg4D*BjBXwdB1DJmi>Wd5qlRfgpMOf zF-1#sslxeebMT!b|qnOfO?4z;U?d3CJtqe#9vcT7~q9I{6i zd0rD$e;9fHqs_49FHn!o0(#xAn+Aw37}(n>{WcTeA&lp3rq1M2HnRwaR_R8I3h4&3 zmb|z41kDy}EX1F9|Bj-cHS@hD5(inAlKFeZ+nMNxMe?t9RV|eYhl`bcemVC*C#dyY zqp2SgyZ6YMMsiR%vy>(l{MX(rbe%?DhM)&@f5aSl3ui_smdVAQRJ4G1A8L-YcIjOA z_MNa;u?@f8aGYcYfITE>zAV zPxgf;g-j3iSkJ;a>4cEYgaroq++j>Kcb=~zU;G$_9*;T3&ROYFC-cVgZkq)P#B!Oq ze+}M0zf&1CWCnoyz$byYt80s-&52$s8X#%xeZZ=~=im7-ikZ$%TxFH7cfR7`cG9qw zlEaxL%Ri05sy4>&5M5GeAMrM0j=5=4Z^6BSGlG%(C^e&{Z(Q*rxPXdUI8h_ktB;I3pQfK7HQ9KRB|>H=}#}x4oko z=^DHf&4LJUMRJa9TJ3vZOz0MZczHpJNBjdBU0dt~O6Tg1L7G+OkzKLvnd&kP(}_yVXt*J|J3}dL=ch6g zQKe~DhTKMijPBiTtwXY0Zahr4f3J>Y7WC>-;Z|9q6T*Q{K~=AO&WON6MVItj`DFs%4`Mw#i5jVke;q)G!!&TN9n+%xDuf9~!!PY~>8>+*e5Eh@@O1XQEXa+Rh(4MTl)QD*x2 zePe)p>ft*5cj@e;OCI0hviOXYtlcP6cw3l%2t&uqtl+B`{TZ}mJP3ot-XwhWRQCzX-3;7GTc?Yr$0i zR!M=6uJOR^1FNRelF21Af}j zg)SRa5*Ccp-Ra3lD$sEmkBzK<;i^1kk-sRf{#56I;`KSZ6JJ8*fuqXw6P&zOcRTRS zAF?AhNvF?q&0Al{E1mmle%w1lo9hC4pcJF|Ju|wv=Oh`BMN`&O(RG#R_~O`3Z5MI9 znar0yqV3(=?yFvTf1{M07fu~CK;b#mLdpRK? z>Wul7_IBosAoogE7eu-+m^?a0` z18ljcuV{S~e-&qXP|f&h?(ZAqNzi%arT6;IXN7pz4871a5!M(H z;k$gPC-c7#?SBEXpglEWk&GSsyEMSxw_JhqMbdNdwVjJmA%O~XN8G)t@L#d?Y|FFt zu%Yda%{S2|K9o|>9dHb&K`({75N~b)+2_=3oN=i2iM`Qa_rPB9%*L}X+vfyllnf(0 zGopWie~7YqdnBI^DW4+xJ>+KhZp5n98kec57r z2m9Ozw_D7$@X_kce3v6{f8U<*%Y)K8z&CU#9Y-%NQQ1pyHiWxGR3QFgCsi8HLMZV$ z*~`1MdkSL-aDA@XcyMM;NuH@+v(+o3k<713@9gZ+e+Ac1m!DMjsdWuD>L7>@?YovxP*nWE5}OZptVh~s zv1S=NtjOpMS8~~Y=${BqUS!_)+hG%&hW8gK;E?-fBuRf7;3V~of5>ixhg3AtrWa$4 zefBNnZBUxg=Z()8-Si8aEO*AIMGYt{RW=uJ!ZAjtE53V3<2s&rl?K4&e{+I$tqQH~ zt`{8NS!uLNFk^KTU)sKHGa6+LfZzFhcUBtCWGOSFN)FjnvEj7TczJv#;HWg14d}L*ZoE@!Cu~!A#<6kFD)?}TQVso z57-~J)LzOVnb6TciONSlf8RoMT4Rx)lBNNkYSypqA@|lbdF%N8cromrkVqI`U(<_t z2!6iSfZFTY&{(`lWuM1`I^oQCp_avQqeE~FM>Ps^rm0Dv?#h?QPob+Um{mJ_gWEe zC~7KWaf#qfG$*MOFF{VgPR~fKXt?`)`qUDlyT6z8EX}C+7VncpGy7X^FO^k$N$J^T z{sr85e#KvNGoAb~f1#R7uC5ni47}n6*(E~WL<{m=;CSuH@Wka`->U1V>}@y=EDewm zOy6U%^adO~+FPIawYKB-r(G&Xs~#MVi1*U~hQA+*D{lVObCo}$liWRBoE5=kR+on# zstakD5D0j8yLm1wDHr>5*q3W+phnK(^9#ma_3h5(0mhEOe}6TA`~A0S6j2mEGGK$Z z6JPP}T-AQz8)VgUWEn8e4-l}_G79F5KI@{Dy4GtWI87Z}tIp^GFP8U4tQt)!%#v+3 zCC$W6>sCJ42oBCVr@5_qkzdD}DE^|t;))}D+AOM!&J#6BW{55mIt!gH0yPnl*h*7( z+)E|qklJ?2d9?aam3I7e-bo+ANVN^Q12Lx*l;6TPt6@% zOH8QGVw7pF&2bDE3X%r4c^dR{WcHkvaBQa2qnu+6GQTMS(by6X5`xzCt*TC|GNnjr z+s@wB%iVbPPUiL#_B%=s_Ro~2YE=(vkwb9@F=$Vl1;1V(2V4XkaK4O=LO#t?^#-US zl@wA6e+8mBC`U3n`~L8a`uD`+cXpPtXuI#(c%Eo7A9m%Y*&O-iYo~zYj07e9^FDnm z^$$mU&MoB!t<1haZh`YHjCd|ykOGn<$h?TfO+pCHuZQz9lS5sD{`q`n;4f0Y_Okj$ z&xu8HgYjpUsB{0dFOcJZ)63;w??L}#N4!b4f7M_A-BxG+{vc@6|M_l1{cq6D@t^jN z|7qGg&ioVL|49NIexEu;XVZ`#8epk>-6jbZS+xLtXpwLMf5~{e?4e*;ZF>^OoBBGf z*Q!uJkf%P@AvJMSE1ziAMoC2F5dR(Z(^iiG2;&k!MilhMszS02k ze+`rzy5%)QeHwt{B#54(C)p-L9Vd{uIdmv{8xhK^&{XPtpM0 zu{Jco<}Zd{l7c^X$hxS#zuz}9y3j;hI*}v8Gl+rUMKCo57>mHYo}n{P3LuKj4EBdk z@&ZXJG{BTM4nh?WL(p|m$v^h~WA8uqfBs|dKlc7(??3kbWAA_0UNAF!0&xgKHX!Fa z5yyVHpJx8uRImEaG~3le zs)(=|-CJ9DKl)yMLlDQJ_RRpWQ#1e<=NozqJow8$<3iD7-wdLsyD&8+uMbI9p-cQt z-J=Hj6gK3u>M8VX8o^Fb1*hpde_8zDFn&e|SO`9&B#gZGuBs^jh9Q~UHNJF05tR_Z&bXxc}#+F>g?-;*3dA&dUe~#x^Gwzo1 zK=AM1Z2va$45c8{I?#$zhVXA&xzdfDo3NYLu?$koRkElO@b7Ye6AmzNSkF;niv@>F z{wHwCKNkLD;r|;85jZ446Q|#eOv+so%19-9ZGw267ADGoU5x~bz3HVQc;|B5PX zOx+aioVe(wLDo9jo1y_OXLo~$GJk17-{Ud?h7AO6WUbDe!f$he23Sw{ODqHsJsR*a z;4e!fIT|2Fl1@uf9b0c)kP@al`V&b9F(r@7pq>b&GX_ob|1Smwe+yBUK+GoWM2#LK zM-@x~chKWv)QapyaQPou2bMVX`qee(lNaPwPOJzNUI;ZhyB=eJnhhYzQ8^fB0NJK4 zH0cbSpB@m?wrrFC`z`OELH`-_e`HWWJY)}zGhIg}nVf}Bo!3w7kR%4$)lC|?p6o!L z>`(KS56|8A;X5pLe|VZWBNzU;bJ@yUKKnS0&h&@C8Ur){CK+TS?5t1u?fIPH7x3Tb z1^)Y#Kc3sN#nEx?zg^9Ze_x2lH!}bf{LiTWjQY>0|BU*dd(;Rj7cmg`eWO?3VU5Q~ zr3~sJKIhnMt=`Y6kpGPL?L|iE+pnLok88VE{+G|@|AP+$f9>=ClD8fIe|$Pl{Qdli z7_7uWsQ(9h?;a23*Y*vcqHIgZJ|-cRZDm(vP)L%vuozbv@T}zwhWsD`b(ag)$CRqAQY05_4PJj*$Ix zi(!#^yjl*`AKzc_u;7WRp4Q&j)$vkCF&@}$khz$@mr=z6JkfEo>WM7~L27p4iZihz z-&TA1gq6X$A-S|M_srBA(kITAZTzB?Q^7Cb!EEh&1J|Q^5*D9Ok=CS+Q@2i-$e;ID zUF~Ole-5wOKjjI_l;+xB^wL64mZowRZ0H2bGZG~Q0K}7{-(n- zD#frxVNcH!yEl0}9UN|d%*2N)9Rk(l%aO$*@T$U_9r?#b%WIOAE+_Q{1_vKE;yRI1 zu8?9}`s+yZebNB2nx+J6@9@Q|3&L%N)Pl@Ce;seeSLkQvIOy6Ym>YM?pP1uv&uCf1 zXoI23GXa!zMiJOsaMJ49XmJ&(JASLzO6UhK$5DT0>l1gZEPF-YmPvN^42!kSIgBG~ zAas#=iaQz9VzuALO^~FPjfZ-lA5l}&Y`WOSv3K~IbH@M(rO`eupE;%Uyzhd-Hw^&* ze{6abJ)lliT<=5*(VZA+TheIJnX{Bad~QSD{%P|Jg?Cskm`)|F^KhC-a9HEFZxi34 ze>y|__iwhfdo3;xtGdzbJ|^@`YDhWFxEngoc|Hw42|GBr8>^f;fsli7w=IssayveH zrBR5laK!A#Q`=L`>)DHE)&_2SYmJ}Nf7IDu+}ZH9@?t^SXpFtRB$rSt*L_V6MbXbc zm}g1q(P}rU$yRY&GqQwl5eI_Vmp4Az;;TBDrG)(mQ#?5Jp z101SzCmME{tTbcRk}N3-HG6qpLK3u;_OKo!q>dbNG^F*!`&m z$IpBhO;1Rrb6hWo<03Q{{YSnrZp`2aU1vyrarh@%bXi-xZb{haZWxzMe}TNNN3g)Y zeIcS#6ARp{OSCg^0ctNrq{fFBg{llX*Ixr<1Ck@d5>B;GOrlt-h{L_A)Kk@v)2qf2@2|V;(&13;w%Tz0J+1y$ld4!Ui zVM88BHjqEZc(XZBI^9X}@jrQ8?&W=71s_VaB>&M*cGuLL117ns)s%~jdVMRJaBs!* zk7i)}{;#n{fBpJ&|Mam(NMDXUyIy;2reBG$n-nwT`1BS$S;*v5#6u|{%i4ULx z**nmumM1*6=hJtVv!rjA9{L!6P!BM*c1at5hk>R>l+lct{fLv)P(J|W=;B`LtM3_8 z;7R*xe-|e3UL%7sxfgNbE8VSu@qsQ*Q$u{diC=1{`xrv^;LsbMFy6~`iO5(k7c}K{1*=nXQjzB_j5!u7ko*($Eh_Yqn!bxgmp9FgxHT?Vc)7C=-9-j9R2iLEZ zPAd6S%+I4%UFHKg;EH7NgyvI-38qGN>m3)-(Ze4s65}dvK6$i%TNQEsm9g=o)|uy5 zf4JGEU5g?v==?rO1+q^+h;+`XZv1CzV*majkd2;d`OEvsd26DsW=~^mQ*Wf%x!k>J zENUQ179?c<4!=DIi3TcgORL}K*4G5@KT`P0SK~7!*JtT^xaXmW)@kF|t0&9$J2~Bo zDZzujb~7b8=d4y~WK@T9=WIM-d##v+e~PnA^sN`_KRd6Hb?Mp52<_S9Oxit7*yD(B zhfL~c8kji&eur*{o+IE|Q&WF6A0nkjKT=nVuXyz{Wpd$yy{>(5KKDYGofv1*>h?Px zZX)K9zPazbI{Wn|0Lb zKS`Jv5OaIeBy9aZ#uc~-jUBgreE-p z+_R(qo01||8%9>u`z*ttqOB28T^=T3DQ8Z8I|#b#@Sj)*^Vdzkno!?`i-vI4_=O<} z-SMh$tsAiQ1H!IijMcapvX9nH3I7rMr-hJk9`AA~47}GPC^7S`i;pC!VBO96GmzlWCK$~EBxZ8#>rS z2~5#vH?wyKA3e*<6}56^;>HUY(wJ0{?2R7~@EzZ|oLSN(S65RLe?3xS;-#4s@P_-v z0geTfEZ7?tjj2hE_(l@!e}pR2Oxuxp0h-VSSLe$d)>@5)iU)TYeLCJAV}H=0Eys*5 ztTQLz+#lVYNOvXR#C;xGMEMroa!&FZyMpZ1K5a@P!?~_x1mPobunyIsfn3H2v?|lnH`UzvczIFyWA05W+-jP-PBO zY-c9u!g_fQ-X!_+e+l0G$^`-$n%93yJ7x@rpJ2++Q6y_{;tv*Z7A}KdVgb#bPaI}{ z(!+gmBpW2w;v)4!1>CO+Dx+^k*sDEp@ne6yMp*vPw)$xx*Z`rv zBXx4A4I+d%b@l@plyC@Y=J^)nouFs_we|&nM*86DU9U*?%OZXnY%_QEgM?o8Ov;a=fN)58`nAy?&Mk2`97Qn((8)Mf#m15+cE z%hX^3Dn%+a3I0Hnh7_l=;nHz%b2&~f1lQxO|8JThkBptRM_JZ`bbcEJMj30f+vxjM|ICCzx=0ruRqnAeW-!t z!j61(MzMhgTw?Ss@$j$#$OZN=l$YSNyRX}!F5UOh>X%Q(RY0!wom0>A{gxk6<>yLz zX`#$vKL$g+HF?{q@92MS;o(2Cf&bB~dX<+@Dd1Z5e^%t=_~!YM=Hs`1iRt7Yc8RTw z!FH|enA=Qv=X|Y8u`Gah(!PFyec1;X#Jv1HMHrif_>9|<8V8e5W5{i(RBDL#Y90$P zDtBiAybK2xkXFi;vhv*j>>q!)I^5vbzXtu+p#Q%ev_hF+7NH4FkOj!%?I__R4E2sW zajCGbe?1qAJ3RT-9-dsfm*2q&k!1nxyME z+r&SOa?m^JdW`3db_6sw;}YZ9PoEqa2d40zVXa-^i$}{918V!4-#qTxIJO3y{XugZ zxj!WXx?DS~`Cbg$)1?r}^Z15*f+AmB;X5{=f1zI-MCc*9q?Cvy1Q51L)%$7}`h}6V z42CX`t@t)3*_fO7*q}cm*YTy5jhk_p-zw(+NcsMA2kl}3b7(LZ2JeCBPotZTsM2R3 z_|C75pCkiIW-?=lX72)y+n>!k1^E)NIz@`voFC}6+D%ug*}L##=aKcynXvDxFZ=56 ze+k}?kcoZ23sVvxhHN!Lx#txZ1OBOBW|@uc`PG3_xQBFg16dA_$eT_SOXP zJMX7UcO`)-Q0j;IfH;&`z)yhkPCFaFeRC*?mpQ~$m7z5|8j)m@uG<#Veq(ySUO4hf zmYCQ>*W~7BCB}7>th6GHjws%Pcf;Sjf6)T~!0sbeo+;}@Q$h~$BlHsDH) zEv6eb*O5W-FKc718_$QE2g;;BiEs=FHB5Gl2tTt4nGEOvbACsO=yMZ5vH1$AeZzF~ z8-XR$0v>T|?kBRYZFzpNr5uuCf1YOnUXaO97jh~QU4$55s@KfsOOBT?r)^4lwR6r# zFL5*CDLkXUHVwu@6{I(g%Yq#0_+didz0`L(taREHD*U$o(HFVv1-2nP zKg58QqRrKwnneEH?~Tv{5KuJh^x3os>;)mgyq2P}Y| zX7^_jw1so;5M7vI=#K4rru4`)7Et(rn#}?t8<5Nkg@5Ql7nK$=yvpdM z;E7wfO(H_6A48hWSz<`ncVOtEQ!HS^1oYP(VTvZ8A6k$FBW8m=e+xkQkqw|MAZBX< z{C%cbk?qeba4aDG=pVb3myff1o!+p3i8}ely_DzMa`lzr*$wWW^X}2}`%i zMdF*Z26l7;;*nJ4dNu$jY!9@7CAQGq%ps;O-bI6W~%)<|tq59{iJ<_YrPDjNZzqxWzB*ETckg@k=g7U0E=|4OF_wRCn|JX(0 z|H9tC=bgW-e@}5TFI!RESirmPIOG;qdCT;V@LF*@faLw11;{6!VgV1znBv=@OG752 z+Y!|8KU+ZW&=09pqGwuRuQI!JF)+_u}5Dv4>A<~*(&|-)cYT}3P5>-je0nee;saenAZJpsU00(=>`+A8LCxo z(sjLdtYPGp_K2n&{kub7Dq=cK!N@`X!w*AHsVK>;3%m^;n4Ds^G_$dP*vF3u=7V*& zx#6ODXf4CPl_Xf!u4@odMek;pnMLS=-GHb^L=45YfFPHwtCEThBcnB5UP+yIpxl+9; z7*fm!!n(i!Q$Vc0cbyzAXVHzXpGCi=efrWb+#`7j?!GrkYG);!?^wl@&~p~RqqKqk zqCTm^FwE5;yW-{TOrYZpy<1lHl+1m@BEfVJv`BF$(tNx8l1cmeY(XUBTWRb@Oqa zM46lCO?co&;Hv0ZQ^bo@)1U_i0vVV6AE=pGE0|^qL`I;%ek|kiX;-~kd zZsg_TgA(K4i(Z+zE$U8kTYifKxK|cLsd!Q#lm7(Cq1#RF_r{|gEP#KO4tD8s9HtSK zOD9cN@8~Z%;?qPJmC_tz?@pSn+KRLWaRu8~sSNfN3=RISl@=(vV{|a`=q~3!B$mTh-`!i|I#=H0if=42R?}3x{qD90PHE-R>=0j3`!JrC zr_2&N#2oSulg;8iPWYaY%_&%`NT_;!^Rn@gMZSIfrw$&jlLkO8Ly#;35jHQ$d4H8R zPvmc50X4{07O)>Ko!YU%Q$svwt48VT>v`jK$^~2F!w;+$(5p=8YL1AKzkN0`giD8B zybny1Ph|nG`F?M`cn;ZfWu668>9U>h~Kt z;XkpI>>u4Y{_Gl{&EZ~(G`S=?2qJV1euDawkjmrhCO5WTn>|u~y*gc@LVtbXPbQZf$<2sIgjY_kJ^ zrxaNA8`zmK92VgUj)+J8Ot4C8GSvT5$@Ar^2f8mR;lep`E&Y}VuMXDhcputpWbMCbbrl7@5P*jP)pEH?(#5Bh!S%Kvf+&rV*#ri!SrYVE=QAPPVG!% zs@PDKiV@P>dst-7ufq|l>7qFz{~_dN{0(z$f9ZT*(crnqg6EPP!r_{Xx8S)_WKDOh zz6sf3?yc1RK{)sx$+867>Y*^3#+!7v8@6%HKq!J6HhWJ*L4Q;NMY78C#%o8@c;WXO zs7u~Kp>s~Pp?*+Hl|o-NuHX|!0{#&f4i!}-NrR6`60hmBb+(8Wz?`f$krMi1_yqv7Rex;6=-qi^AX$;46uGwtgsBFG{T`++i zg(q7ru(h=&*8)m<_3}=k0%36^{Hzb>@-bw<`jisoC4ZG%0as?EL2IDG?G`Q{%J*WY zYWw?(3*UN$C^ouFdVB45Ptbo;uNPT8(TL~))s+y>DG>#5)#^ldyh5zavxWLZyV}}~ z^WxTR-shj;)u9Sk5AD)P^_R@ni`Yge4YL3*^+_`dhT1^jM@=db++NQKigtO7fvdD~ zh0{Wk<$pGJKY6Vg*j3uCcvsF4whfblR6~foG<)U%vMwf-rb1-_-Rfk)i@6TG z-DB5HKAI?N)%M|FWicVfn+W%fEE0 zI{ar{zS(%y*TvpD%zuw3$I1MP-G->`hmGHhcYg~&bxW(|WDyh61hH`LliGdP8^O;G zC(KHtl+DPHNbUcoIU?=K5&Mk>1933OX$|FV#ZCQWo;mD(`?HPF6#9DdF{I2Z|@R5b4| zE`RH)eDmqk<&jg@qgT#{$V+_UU|&!^p@|Zqo||)s*W@p19?|j`_b2+xpEiGyuWE4N z+tu$qEvfDh3%CcPT1$OWoN|gPt@KFKrxqg)L$^y^dcb>MrW{JB9U&%-^rdA6cRx)i zmAq%J`0hOzg(6v_1pS&t7*D_+$bGP99)F3p?*`T8^N-mUJ+7bBod5PQ|J->VWAG$8 zm{AVCy`G4yu3ufEou!|qo_+99h6ThmiWK48Zp9qP@rcpWJ$&JXaG7aQUgwnWb#3BQ z`UUP21PnHm$%iKWz^ld*mF9Ww=OQ_A{O045P!)4W^^1(WZ!ss;tQFN>!0}zCbAL^K z-vvR;QDjXl@dS;xq*E}`O=4u&@2OV5PWOIu1vk6$%%(!##abPa^DICUx_BJ@^hX}% zgd`Y*m|y|bm`*ERMBg3yHR?9aY?g|%9Ya~&vhkd7q!{1 zuHH%YHhi)Lc7EjiLSx|_34HAO}geS{q znlleNKeOPe$kFzDF_l=E6q20!ROE-77W>ZD5+_qkX7V8R^Re%7}yrN*%#(VL87#x=j#*WC^wT}4evcVNWn z)}+K%gxHAwjq({QWQmV<7A0A_^X~4J&W`SWj$u96!ZiQk$aB@ZZT6<}AzMvY!0mwu zOwEyO(g3AySk)w&G4?iiJb&4jO9YFZ)wTOjn?Lw;!Esynh~bozj`F=mLAuD1SxL-X zL9=eUt-zo&EPfD$cMlc*hHP<6?Lx5?_33#C7Tt2Mw7ot?B|^SpPjP5!uO`Qi4*Ops zjOL%3;v`7A0P_el40;L!mZcz>_MxCv-+#3cJG zTx9{_;C(Crf0{Znm#8(=XjqzqC=BxUPxZX3%quU_?yKhBvj?I^(7bnHyMC8o9$Wej zP%ZUXTpcEYdCbq=2I6D$)z{%pRH_n%8;WR z65H+TcOu4W`i)mtYd1X;bp2HqACtv}%)+}=* zm$ca_b}B6}1b=#yOD8Mo(SaO^OGZTwSetX7Tzl^EOfBJR96AJ(F(fO&uTl7}G<-SI zimVi`nRjb1$NJjs>GmV}B#0HCisdo6!V52xWM&SK`|m;OSpfY&g9$YZ&k%1zR-scg z87`gmIyXa!W>zlH%U`gaLfx5*XL>m;RFaBrPup47Lw~0~kZ@C>cGUiP2=xfKZ9s~C z=VR!)*h=%U+R=($7ZabGb?<9Oqu)F&xG;viHzbnDtr}$rD#KMnx=@mId&c7$P;&k; znhsszVM+!vL_JL?1=nAfb^ns7Q=CNdJ)L`j!)(NhLi*!UFg2E`on@(U$*;soUQvv~ z8x)IkJb#;%K4i!<>3j636y+jD8arS^Ma{AaT%;e?vVw}fT-{6>PcCOIHT=BTINI@ks1)e8ipqu72V1GK@*C_t{-uz*Q_pIs9X;JLTRI>F=`hE)qwl2n@- zPY-oA&wsZNCEz}c&|>0nbrUV1SS0_|uDYy; z$RxO#_nYaJ!4<4cr-t^pU<>Zp^wP+hWe|6}Nm(jVGV$5HT!Ax)(1~ z273&r(_F3OdtOikZd_vQwq?J_EISgQ`mw2q3x;v*gY0Sbw&&oz-3SwlIt1*|tLH3S-bKV}37UXG_ zDR27dncVcmTCXFnFmJG{H~eH^Cqj_fihtp*#U;6klaJ)#Q?WOH&2_G2KTygxjr1+B zD0Nc=L8aA+qH)LF;qnLga&rY6EN9+vOTmN4G{=V^?$nwT?OonDkdigUmn;+8L-vlDL!EB!v&B$O%&<#l?@do! z-;qHHnh_0e3k-74h<_4kI8*gTR6=HT??QGiPJ?IDC$GqotCa} z?^5bTxuRvJaqhX&euZ?cysGt+t3oXr{a@tcpB_7OY}=i}0@!Aj?Sm0)1iz$OQS8WF zs4`gH;;L0x>GBWg>&Yp{m%1B`-A>niJ=2~f=O(<-CN^Y)&myMz$$!5H+;ov_yix}) zss7ZhGj#0SsFpS5LODD!^!u89>$eoHA}z$ao*bc!sS&6#zf%dz; z4~x)`I(%gqTdIDyJMO$S&bDR&mr~AL*}WcxBwbyfiY2U-BY#OhS`fm+jjr>1?M2V{ z)YoVf=X6Y!z4)X8Q|YsoUc# z>cbc0eOl9JU7lRheU=yh={&6{bMJN~+mcIfh!Yj(oPQu|=;%2GhWgrP^h@yEyPWY< z^0_&1JDX~Q_SW`V2~)im z7%zqr!Gbv@J}XS>aCS`jWg1d({vjk&(&@GUr(LQZpe)6c-RD{?BCtEmk_`^U)KF4z zivvcO?n@dVJYs4Miw*b4m|8UPLHErLc6nt&zJKHs?BIv)wYXnzb&ovC`Ne<@jo0W9 zJc{b*Cc}7B11qPSy>RKn+KSnuZ*APt?zT)DzhX0Wd?`xuat$aOfW`62DHkeC$cDfC(9UxsV!r*4>%*kd0 z*zd`@)rkVCS-ZCVj%+Q7IV+=XGjbho1Uy|E6gGExd#YL%j?)mn`ym{>3*%+!LU~)s zD2Jabr3($+4gw`q>~v49uDQ)XGjjsAW`ABe%_lBoM0dna9mc$zvYI@z-uXKP8qNaz z!0~4WkwVmf_PU+W?>EO}vC{Jb&9`6cX2yP2?T9us=4jnJI6=Uyo}0JgrHU~5tme;J zb>(!viuSx4LJ0MI-<+@K17G^^!1m-tJ0oZjV5Jn%kF?@_y*#|!`_?Q-<7C^Y#gZJ>IfK7Zwe>Tk|# zDbMjYG`N7N$GL3WE`GHqv*>gL&*^2#6otLU?hl-c^27vL4__)4m3>c za5gDvyBj9jSk=GZIb}~5h90D&H_H)N4D31J*%CDLfs7%ykN=M9qs< znaJlud*5@Gy}ZKxl?8}5E5VR+-R&S@x-I$g;)wn!chzsNWx3LyfE3K%M>IPePfXvl zD5)ec}KOP zX~K0XshRW2&w}(^eTUB;pSr|*SNp|=($iPMPVO5Nc$abO9n+JYb{O4eeKzRq)}>C7 zay!6#n-%CFl2&uXn^qbvt<*H#`RUUO8C@GIm*U7(F@N^g4cB-+l^Mu0QW1yYHyKII zJTN5}a!fWJorv03^Z_bU(wwk3zNowAtb53uh&8;}E>r1XlHqF^9ijj{)Q6Dl^aKTN zow&FjuxRj@M zd;PF^L4Ve%4+<$J0x3m70z8Ly9Pr34t5k5EV0&up1~q^}qzV?%O{vhuDb=;tudEjK z96P=p*fYLyF-_-Lz5n;}c43j^F`5ubuM@#Z#=S4Y3KAkw+4SetwULfoB!MH&%8D4AF}`E+JQCw-Y@X? z%zxEiCK|+0?X+`rchE1LO6G%6WIMM84O0W@I>7=0Z=#lbeE#j;H>3-GfqigEoIeOp zz%*Yox<*~8!4eTfz7qyFmt+A`&i{rL5&>?YK+0q4JA>v!aV&sX4kC5PDzUrLsjmz^ zPAjnh=wGVCH%lmPwdAF6%&mY#%RQ7Rv%GUw){>w4w^>DJlaDESd`W z7Iw%qMtsXq3@jN%9HqM`I(46`G1#m zO6JC^R9YBwJck8zKppV1sU+hsKRR~~9wGd?>@qIgzJG)1r5Ne{YiP^;S8NlabK;wK z3ugNwrVB|E$89g$tSb-skY?KA`qCXfX=m{?3*YR5X?Bn;Pr6ZbPprQ-_Uy?^FF6dxIomDN0cFa6jYd8FJoHZt#+ZM4D+5r6ui{&ln1 zlUswCx9%S(?#s;9PMEEq{@J9&RJ$;3OR4)ogrs_ zyx^ROTR+XetqxabwOa3ARMlDL^g`v{1y|Fr9{G!PJ9!4MK;!<`t`AiuF_a)B8`N0? zC#@s%!9zYYG?n|u82m;M&Dt-E1=K~CtbSm`-o|>4=LBGC;1eQc{D0o>rxxaYC9ego z=g=TK78MyR;QAi6-rXNtxbABTr}z5Q!9rYlY$=T^ltjNV*(h=uWr#X~7sQ&` zGV+^+;5xPBOh#sT(`aag+p!{Z)!~qRytW)V?&UUYGkyAhotQWDo~@1%Y{=m$w4 zw5bpZ;`a>q51bJFhJQP<)OUR6Y;A+dtImTHyGus!c5)u+iY;dm0d39MY#&^S7{F{D z`&}`%n}Ve0y1jjuY`iZ|RJmxqf(3-E^#WsO{Ig`tbzjXkFqUR9+;sDKj5u6(sL_P1 z)85{ef27gLa`CCcrb&asmpGkoOZRV~C#aQfnb+zg8eL0ZY=2+k%$>3o=T%=x7LBeb z43O!0b2-hmqx$ftH+=TPop2Og12+F>FC+Z-OA7zo z#&G|W+BX9>zJGpZBEH}#yU9pq#<{N}7!OwPn6=xfcNzLb;P+@RPr@Kj2U*XWy(|1Ki1rGFy**i3@D)Bz!xU?vA_#ub}M zEFb}H_R_I$QrlOn=6fRJ)9eNQxd*e?XgQ47zZ_kjgYiH`p{md^0dO#>xy$`-*-0&C zVd&xhu>0;@heAZHjgOeyn%Hq=B&GX(!gvKxl_0I)$*TmJ?hZ_B&O}_0%;hDkTuYyy z7P;mx_J0p3+&i^9a(K_Iz(o!UgkR;@~z=> z6p006Nd=nz3A3i`gS;{$&C>*oRp|@CG~}&;ukH9?Vgz>#l&QFq^W|x?s9#+z^Hct; z@PFdgd4)~HP{7^iAZH^O&}QJ#Y=O->v;1z|pA0SE{zAQmsIy zaew!|NymDluNlWqS<6T&~aud?q@^UCwQs<-chl| zzV*F}hVgrbsk^Om7mx6^?P&%1F~6XyVt?CHCrj`tm88@*9c+FBe&*g9VU2Ls%TWnF zV>`4$vP&~Y zeQo-X{f=jjWxVKHn_ZHI*FN1j^KH|NcW&$1pI!*q_1#s@)UQ}QxZkjYQGl7tMpYxb z2ZX0#ScOK?Wem(>#-dQdy?_4W81$?fhu63MiJk}qBG)sP`5-GJ>+BXtmc%zp!9TQ|80t-R0< z%7ZFixsi3xI*SM0Mt2tslaF$9123Q7h&pzNv6rUDc1Z?I0cO7#^JE=KtrCqxr)aW( z)!vcU*RVbAvHMO5X87%!VBi<(_dO39m|@esE;dN5o+hCvMx**Bui;u_wM`cxA|_DL zPh(4U&#a-&rsqJD#DDTn3ZDYs*WbSRnmNh>-XYsS*dLHVx*1vCVM22%Zx`0$g1Gtn z+GwfMkiH{Ecm3{IaE@>ZJV4ief5GP*mUQMp9`u#5MW>&zaWTo<_DZ2H;LVw@yzzrD zK^F#5Zc@_-ei%{M!zFu?{={%d`sDIG!`qx9*(X{xFAuGO+kaAokkJ4EW6K7L$4Jlh zuZeTW)m#}OuD#bK@0{Cc;r{8Bo#*jd^TyJ_Pojl26Hc}WmxfpJH`a}HYmt;GyQrsW z25^rtrY=m~aRRM1b4&T_t4Jnc+``0VIm=gD!M^eWk0(cpe7o-zSjC7-SLq9MQh!NTg7f)yFmW#%RvH<(OaoZf zeAkfTQe+UV&27b1qFttG^wGD^S~Y1OLt@J`J^5u_?tVrO?HuLY7@1>>7)5F3(1($=S-FhPgt z^0jg`@qha^T{CgSNDi+3w&6xxoUW<|IH)Y30@*4K_6oCbgPL6=E5+C3opJE?lc<1t z+H!qUu<5=1Si*q%0*viNKL!66#b@W};T zm9O6c+iQ>C6ej#Sev}hGFd6ul52rwFw@sHdkS83f&Z zuW`tI_03UE^1L0}ij|rD**TNVBaL>1F!1FED&u}r)mw(Q#9qL`0zIM)l1?V1iGH|=X(EW6DL1En7+^= z8$uFf@{W)KD1OvZoG4R_n%zOkwkhs7xjZuKY*Atfy*rS0I4s%AXCC_YSvJhW#(!}W zg*o~{u+J(9MKZ@tqUXgsWZVhocVe3GO=ge}=^GRo?M2*b)wN5V3z;^ASugvv&t4pq zZ_ke|Lkgsj5jA;wY{+T9P@K2b>#C|5o%RgAxyw+sU5rm0F_ivb{%mFEgZo#wdvR40 ztJ$O_iW#Z7nhotcDP^yn{jw9o^nX@Hj5Ny*cU1y0Jcq8lcZ)V3K#cv|`)8_0|KAm^ zUYTwU2ntZGo%T}^kynVDJ6WaCzK1)KXD;fhLm#Gw4Xq>YG)t<31*x0`B>qJ4n7o=f z+ip?VcR2J>x^_Gv`;Oe>GTAfUrDxfu=+5L#C5g1x<7&a3g7Hk5j~R9(^?!CfqM0eF zaYJ~hdUoK@rkq0BhI6DulK*CA19|5v&6D}boMyQ!D?{dfR7)WtJ0P6br2F|D4ez9T zLVBK*d=YsluUv8I_DRtQPXj!OdrqAlFiqCui(}hxF_aCnS56K6DiZ>-iz|!QLNdOr zypfy&?!4H|_W}UWJ}=k=QhyTB4<=o;O2G9N@=ir0>kp>WLyW4qwcE#D2OaDY!K`q)~=|jPeAvJ3nfvT7#%Q|1wmukhTzW z8a{e8mTOh+JwuvJh@|O3G&X^-V(P=rAfs?%`ayI3>TNlXQ&cZg+J7Xa)>aO9B7~rW z_j-8kHjKVsurXqoQcsgGMpR`|Lpzuceo7(3cUH10<;!W$mUNrvjTHwtKANczBa-r! zhfDwC-OC~kgy=ZZ6;LXX(a+iDx7~gM-SlHFH43Ri+@_i6{L&2IMlV6xo!|d~YhxV# zD)F(iK3qkj{y6J11+b2Ob~_&I-Q0Gc^+k9l9Ir)OLJSOjv^tfxz`cOoOd zPwlYARjW6Z->=`jTP*bka!VWXPo5P4Xhc%dv6Tj6o zMD@WMzj{i$26y!QNSkpK`Z{ja9uU*aM>U!22jkb<`}Jr_?K_a?(DKG*?+yC4n=d#- z@3UNAO8@4Gt~(kU$GU|xxy=JYnY+(P6-M8;Tkl6^=75i|fVm>fKDrDE=|Ht3|G=+h z_~G;1Ehp0XpMTX*ZN6Goi=WU>l(^EDe>M5*XZuzKfZLKCu&XE9kaRjg5s;d*wNL7? z;HcX0fSf}T>e+V#f_Ck29`8QNHRr+cJPlHW6i4vVHK^=RM#4F{jtH zE*EpmxyBsh9y4R!qkTbU#lYVB?xZHSPY%CLOxCA#!B>RA>bUOF3C_@DE){XE=v#~X zI848OuYWNoh6Flas1z4JGry#3)AwxfNNk(!E$g?dO4Dd`N;?=xjQ|yhI6gCyu|$V~ zQI=5(&*^@b7Kz7iKZv|eD3unRpWJmPj@|)E60J1xnoQn{L{tKF`$QN)Xs5TePbT4H zoE=TC^0X-4-a7|6B?_%xV{Fhxb*Ux|gSaZu=6_7PzEsCj;@~ouI(nnXlXKL;erST9 zDN5G|^$D$Hbc_17v6d|-*&Z2QtB+v&ru(h_Qy}SfLQm3>xCbr|^twi!Yf4M2%mdo4 zdNm_ko_suoFMORt(+x&COn?O~P$9NMD)%)Qjt{zPEPBS8SKBxHN9B-x;{CzA!pVhq7-ngp{4wugQ-gtQ#X6l4w$V^S5fW@yKl z6StZpwdF2L2)7@4$<2FYaP=}b-4I39WC8hMEFj&_o&}_-yc}v7w4J$Stytp>b+>ON zsG7_5eb8%D7nxgye*BCu%>_#=qg=@CMSp&;<}xoeWWUl+CGs3SY(A>!o?cUtu4lB% z!q#cM6`==V^%0-yB4NZoP%=?vp%sFkoqAIe0)EBf@Q{X9BGQ*96kN>=BC0V zyoVNw99U#@X>w`Klzd`8{Jn^)^?%ex_HIaHWa1VM6CsSFaSY+V;cv2~>5^NpPGUC; z`1X-dVdihv>77+6k*#ciX&$bp#E`L9nkshO3 zKEbYHwhmHIlbD~3CZ_<}r#SEkQ!aoefa(Ofz<)v2FQ`qC2xvu#^Qfo8`?-@VX6@X=LDu-(2gZ7S4yAxZEb{>H2Eh4k0~# zZUFM~&mgWw2$O}T8Fe_HV&-=_E_koi)1Rj^77MiA#V(qoZZ27h>3?*hV{3SP?e}yN zGa-xjSb&leO%pZZ+6vq96W>z!Tla*I>ViksP$_LsSU^2{0r}|3#ccRaZ={?2VLbUe zGL~@FzY#d-d4d&d44cYH45@cu-D1{H%ogs2O#RnYO8b37{XyQ>-?c)O(iQ+&Rdtrr z=sE5!Oy##eTny+{(SKYL`k4G{k2V92e2k|>trYy)m-LzNujDf)>Cb=dU#$K0a<~`= zS(7d*sMouoL;jr3MRHhV0k(HP(k6a=8xzR_CVzpixWWaXSsl!0%c|_q!82WAgL}&2 z*WM;SLUPKC(X?s%Ykz(=cSo2l>L&8SZ~c}sN6rQKS4g_tuYWx>?*GRxpL+Rf!vu0F z=+C)M&$daFRpc11`e{xDD2ZBrCi&xMs7JlEiSrY}x7%F8?a*Yb7F7SOvH{2d z_k2YEM)*U#QdH2gq&ITcm!Ky>dl1GYAD(|Zk!g2qPjb54AwJKHy*I-?aWG`_^NV!! z-oAhG%;!|0%zyq$JD4VnP+rV-D*_Zx7Qk~51ujC!BLk?u9bhF3xc?YO55}FH#Yi(; zTEZAJpHMILpuNj~?4^QV-ytxcPtsrw^ad6X-JZ>i)onx56^mE^sS4HNYRv*pNE3UR zBIj5D1luMSo7sWC2NiEI=Spm$Az~9tK)k zv49TWb-_5;mjzw)IAlIasFK#()eBzt#?3|{9NE6+6r5>jK|iWJv1W=@V*!Nynm^B( z1`U*1fc=|sROnxm`O_vd>`L2yDfHFZA?#6*1+>Zu578m+Z1*K*akpgb2UWy-IGGo3 z{vbgsFn{8!o5(woJ~t%)g1w87TG6pH7q)Vuol`zHfB2NXwDy(l7uReq|Eo`W{%iY# zjF10o2Xd3i-~kExFT*W1#pNuZgl*)4okqnK&N z8=TLkaS((D!&oiM`Z)u}6R1CafciRZ*q;261%FH!T>N{bQvNS)kUvOc_rLZ*(#baW z=n7;~%WfAw@_{t}JTIq^C)B%!7ld0RvK3CzF5LdQ)E)kz?B%~+*1xAzA=8W(IG-oR zLEkvoe)N$2uYe!3iX4Dc8|7dX`ZAfD1OKU|(S`mXcif-UHoK_ULCrPvs3)<#r08;& zdw-ZO;n}&9o)7T)u0gf8UMCf5y)lXuGy}q=&5%6E59kVuR{t>}DvG?(s+kOzK%Do^ ztqOFUHLyzymABnqxY9nX>!;OyAj7g{#U9xPANNyv@dNTEvkfJSkfjJM3X^q-9S_Us z@I1P>$oy{mT8;k8e1<5a?z}>eea;FN4u4&{5*#?AOdu6i_LH>>46+SzgDw``b%~J+ zg(6N3H|P-fy5<(Ojk!(V?WUM#EN(Qqhen!rbbalUbaVIc*mHRU&0}OqK~oPfDjJMw z8X&Dbgb4$EDe@v)vO^{NGUh*pd@V1V@o-mFL|%w}t#IXs%F7zN2$-)|K2CxO1%Eq8 zHj5!Nj|pT4ijRIZY!bp5D)&JXVe#DilWW~Ozw)XG11)`yGKB~7UnPP!W%MoroYcrT zx-=t?1$g?$r!SfR@qg@|3B~ zxXT77cOJ;5-JzqvqL(0v>H^-Q!GGZ2M&@0N2Aq~pzgf-xnDOHRO=V1xqPla+3xDO% zWEr7TVQ&O-)fT=J*$J-@N??!rEzlXfN6{pDKpOrjAF1s!6M2;Iy1uaUa;n8=7*GY5MRrV( z&-xisFTSDFyddIY#tlAu3@$9LdpFFfJL#1vn(t{=iyOMN&+US}g>>e=lfV{^8q6rb z?nj(rlwtMhk`$vF451fjuqt|ecIWij6+ft31f6~-j~q3~kjy)0ztT}WHr6`xF_o|{ytMpYt6zpk7aNNiHFE#(6Q^&1N=*~8D6i!)R}y=n z-)jc4&0JzTMa*k4$QtAlodD zK_*LLuyS;hVI#9i|9JbwqVc)9FP(3puGRwe^$QN9{Z8}x3PFjN#ohNmeq;g*nZctcCEGVWq#des#VOU zgw8aoN@*dUa-OP07QX;ke%3_3R&`rX3N z(*0(q76+}=3@MK6N6R*t?Wm=xGQYV%2K}p&dBBH@*Nx0dEP|9Pk~Lf|c(sJx7?WB& zuJt|kQO+;BaetGgIAQ317qF#qVkc8%ei-jJou2OtRr_N7V6di#s_ON@KKS9|#S=Ae z_sa1o6amPoKKLV4^~R!csSlcb2D1a~ZI)PVB4Xl&XX|c@ICg%xm3fOpXEyOsH1}B(?6`SS_Ffxs zr#Dt-QGcl!FIYqjM^0T|>ygL%cDy{_bOg-B_dZwll8~d zHmQ<|u}f7!Fx97rd%5=pR;MELRgjgx+t(=`(75{7aDW+?H3)sWX+y;b?Gxt zsG+armr~eflEd5v;P`Cc!0f{cR#9T;BDyA`x!!B=?cn+IwYRj+Svjclr7T_3I)4x@ z6#=`fjCqQ4gUL=HtQfx_B}0cV1gftyV?1iLMAP=S)rEeC&EVQklz;2DgW0rIL^$Jl;W{Nei~aN{5B%=uf0)$q-?(xALHfi$rD2}1 zfa}Yf+PHWYKvngb*gCzw*5=`Bpns7}G(NCuLJ_zxRs7_6EBP}1+ljO$BP{`pOv+o8 z*~Ui~?{VEU0}z+kyLy-fq{)NMEWo99V(aER%tIzus5({=Im7~LCR*CkulkF54;wh7 zR8|YjcLAl0m-l(-~Yd(u|{u-*?E(>43ogNy^dVl#B&9?ti z-YBV5atPwsViBirCE-%fMzVk=H9w$AB384<54gFisTbSVk=FE%p$ZS2hFCm(LP*LUMth2o$J+Hj?)DI)bB%F(G+|M0D=Oi#- zEq9#C1AL3|ZQeUp0QITnm-VrnN|JiHf-iCW4d+RQs1aW#uQd_vA4;~PgW9>5zh26P)?&O;$ zf!2_{H&i&S6k4AP2Y*&uRi-xzd_n|(flAH2$rEovT4YZYZn*48>Tf4}&PZJHE36bT z5RHmbR>O{9hL-`vHgF&L<@!1-dVJewx=#3Bci(IQ=uQn@oLcb(6PnFNh%3JCTOeU0 z0%3#kmODt%jIQdr)@oBEmVSj9|#zl8vN1WXM!nal!KY@q5aU}Pqc1>`Ff5HWxBVvETM#=}hbmVy&z zaDtm|OcrVxyIT(fLVZt@yQS{8Pfr_beUetp2?iwH9E3UF0o!`gmdz$wCV&a>V=qx> zBf6?9dAIlHY+vVVR(f#T$Q^?Gw$5T&`N9g3FB=hy9o@G$z!b78^)6^lS!MD{(oQ+i z?fXPss{8P^eq4XAPgw3>UXpVzcpdv>WrWdgI6TAKlFvvs3LwHqVyKUYP*;=VYcZPl z>1Mb5jbvZ+t`rz|K@M^lseHRqpiH>&_&ImCI=li8Ygq=skX9#5f)R{RdgSzQ^;g;B zKliS5eNTzPqG&$P{-(M2iDxOOX3PWjw!%~~&UcIp^)-K3-7OTkUNX2wyZgb<@=9y- zszOzm`?=thPVP6kLft|mo=lrcYBdXZ^BT5wG0=i824kKfQIE2K@-iESX8)^o-DBY0 zNeJH$JT4A#ggvz7Q1yn0kNr@_&9QGTZ}&%Cww6-;XnO6|_Z7=!i&(52$lbPuO(Y8K zX0Pzjx{ZIJ6*W;~Y3q}8c05nK!e&PQsf5qi+0RSIN>obpIRQu_3xLqgbQkdz&jem;rOQ-ZZ{yTTFRP_4FdCrT;Mn8= z3^{P}##^JiB%xUE-PwM=MJ?Lx%Ec*&cGM&H(OZ8HMW(tA={4$XEfZncADV+K@{iur6818DD0TEyRhJ@T#?Tr%E%T? z^bmhi1Cj)nRA*qIl3Ojhy0;A#i;`gO8`B=TV}Gv-we8-)Z`0E87n7)FMhTstPtJU{ zNp@loQ?=8j4qh$Uqk8`{! zakp@1Tu&88>XCbK0MnlZxXD7=A>t@6q5FRm6`ApiqieX);Y*YQrQtcYS>tnZhd$m_ zpMQCUQgeJ*4}*pICvO_VN4c3TD=c8nJrP;ph2m#QgRZT0C5deJVy$FJ*-`s;V%{#} zkZD-R``TKxkynLP21gQA-)Q}n6btyNni!`(x+M`U;GNZuAPj5d5_x~^ zf_D_o*{v3L>%Po$;|Bnuhy9_s*}m>DSjqyfpcxohZ)OvF=X#=fPz#)X4BxrlU0`6# zxO(3Wx-Rj(#;{Yr|3KH<%J=s){EAOU)toHkPtxLO;yPa?%V|n3OZFyA@O#(b&C^TT z57o+;Eo!Z9G<}~Sduqdr8Hao_aHmqRTfc#^+kUO<1ez> zUGFcQ)|G-*7F|Al!|(gUGKEk@uc9uo4~Lh`8r}2&nkMxYdsXg&S6RTd8n)jmJTy#_ zSV&<32f}FHEZ{xSpK-Joj;*_qUE;MBRF+cc)aL5yDq`yIzfJ9I3;!u`g+#IK7cK%S z5di15w>=O7thranYil^BN@#z_EdEA1(MFeM*FScqCYtTbd(WjZUMeOijt!>!A38dD zQlD-4AB3;~Wev8$WdSez!mTJ{t-;tmY$RYlHyol_H6F^{vioq-!p5V~W?+k3k;Vxx zP-2fUFlkGE3+kFf`5~)Z%uhAUZWiE7O$OIi=;-x{1{xYQP5U}L)4P9|NUm*zK$!CM z1B^#>X+n0X0wE_|(O@RFdXL)p*r_O+H#_+J48|{*#dIHhXQv1|Fq?g2&@UHq8rk9^ z)muHd%b#&(zn~&)rY_*;6a7UGg0=UfW*E zC#XD^0f5GBCI7mk!bpFZn`Sl%wFpzfBwmHnrrQmEJ$_Gy`X|7u7ILtLsw@C8+V&rd z!2iMPd97uxrcNM9sy+?1y*1umFFoU+%y04^#h4`-ijS z|0fzIiK)&UM^`L2_R7K$x?mph#hU*v?;m_!+*Fr5t%V$&jH8ZMYeT<^U;S9#)M*sS zJ(3PeupLqvxPKZSszirsdg)*I{}_-|ZJi^ntY=)IJtK zJ`Ib6li$I7Sb*R+pIu>i&3j)OOv6&rHN8HniyCX)a5{>=^RgBT!~CCF#r{Dw%@WFeuoi$~Ll5%nU$ZZN zD<&F+W+rKpAWZT2-*PJdlI}0*{@>Cy@KN(YeSgZvq);MKtTS%dX$Y+};`nA8yz#_P zlFgL^C%!R1S==GR|Hz*s<3L4;#%y#n8d!%vG+=*ZJN-Z!<8JM~cu+A|%GbEz7a~>6Y}3*r)B%}6_Kg3pTg<s{GkMc|>FV0;!MEhKaqg_RP(=pK?G zA;)C$h!E2RB?DV{9a_%<%v*lFO8N#uk6`MdMja?2%*5z_)AeIVMw7*Cop(nXumH?6 zJ{DlJJ80wmPgcn7x-1|~l`_mg%)+-qEB}9Fy!dm`bTb(F*~27AJj&DuR`j!&DYEHu z6U`L2!8`;uumBR3_;0#w|Ge7$^I4mJsog)gXwuJANe$@L0pd)2HrqV^cJcd-1XLFM zqC{T~uvCoTcA`%X<0eZX<;4#%*cie37d|QGi_+txbN%n1tK2;4sl0?uh;2+V zRS@IYI{w_p0GZ~lQSkDcnY%aeO>w}WLyDiI)@{NGEk?WF^?Z&$jwdzV_WOi-SB3`$ zIns8#&-*$*EVaF+z)z#ZD{s2mGNt6T_Fn)U|Cm-;fV1 zDGl{>8Pb4iTn!!>6)%n*MTlo=+kIPEa=6H__6 zk*PC$Lq|v$|3LSslyjxCmH+$W%IP0YrpNAG(0t1;0w@^UFU-)cBYP*R#iy1M$vCHM zny*d#qNsN*S*P@K)XnoMobMFRw(d|~tW~%v9c==AS~!yDf=bV&ka}We?NVt(rnK{kK_IRITBjZzJ{oKM|yejqBBNeLy?!O46JS!LB zl>5OTxR_CvnYxiVi?`M8N9x|-66B;t zFxUvl12Px{R?`}vhEt>Glc zvb%ryo@e1#zPTNK;F0*&O|N~;<1+b7C}#Fp1g|Q2mC5^p=HkVa@l%+@wBW?&x40AO zI%Ol{^Tej5>w_cKZYvK~iS8ntGv=q$OVwm+*t!*{~GATfAM8@sDSHS6X(_j-l} zp+p@OwJsf(ZGAoMmn+|)QXbeilOq7!T^E1fEXSal9B{72e67~GO0hu#XY{^%eaBV~ z6sPu`k`a-tsV}>u?e){x@4(K1o)ilL3uuRNkA`j#a^Cr4X6+|8Lv}BOUQO)lOyKO0 z|9->bqWjWzAY_oOl&Iaf$>)#?`(~J^OX#tU%kL?2B_$_6f76Kfrv8$bE-1<0Z)AUa zgtKYoTZBH>cVQDq-edbtcxA_87tMeF%H^#^qJNDa;9!y72yt8P7* zZ`Qq5kO2fbqN*eoX*3;XPmVlPfU@+?cqW!~BGpgVs#f=WW2!)>$Mr(nO8#951oCk| zyy;$uS07xE&c(KHG0bjwmBm8>85Vz4UH|Mzt9=+vC%W{ypW8dUu2$=O|FKU1EyrW^ z1FwnB0P`~osD&&n(hkqx3=JXL)vNy45LWw9>`m7B(%(E0^qup1KveSMlk*O@a+AC` zf7Gc?q9WnsbIGG{5++`a&PQ1ESw1lwq$KP(=DQo`E}>O>l9VoWG9)MN^}K(>BQcQx zxGmxuI6?s!J_TU`pN8=rs8xyl0U1a}NPx+4W_$;Z*>DZO;@Bh+JL_4Y(x==<>3 zR<9lLaN!b1?dE>zkyI~izvCm-`!`*5zRrfabH~xc>KJu>EWp2<;-e`C#xTXXsSP1J zx-Yx%p(^-nr8P%%7dx`kYCW;aoLlK{-$wTHXp|K?Tzz0w|BmzPBL?Ef(a_g~;}e zZ>!VDnMC8&Z=uN!Rn-}X#UCG0RIcUTW5)R@JQeZ!hor(3M(yW*zUn`UnUq-Q38Q!t zf`CN~x;iUX??%)N# zCV@x+AXv&v_Iim&p#VW2zA+j zsw^N;rSz_Jik-C$99^)_u{-e*v5&Yuz~EB-8?qJVSM0L?Mkrtq94nIKrUuvN&SnIM)G*xw!_K$u zvA2Jw9BCgh{t|1P2q4cQ+wSyqH1C1ks3sf1JZi||)Plf5r`Fupn(mC!DV2kydt6ue zZ=Y3dL0y?h#EC$K5gK*F4brqjzG%^P8!?w}z2U^p{V7=+Gs;(ms0TlFc3$b4-gUWN z?hNQ5aU!WwwNf%V?|SbmD!y_Xu5uG%8+W8c+Oq%Q6kpxzB79l3vO zx{Ft0x&8|MyL}C+X&+P;^lgRlH#pLcgZbm?z8%;D6!Gup=R=e$zM99DpKfx9v@Oc8 zPd)bb+se#R92GViGl^NWAucD@4KJ$GE;*a!*#wn5(>+DbK;P~ky<|>uwNeY{QG*8t ze|9nVNO=A>S+FKR1+msqO0XutyC-il6r+ zBrLq<6ARj&;*dD@kS>8HCNIiPvVb^L^>QQ&@bnW|B9dGv2VS8{eRrEYS$lu4X@wm; z-F|dZ;iHn?O+=$`L-p4XrFql>jSZLjVWKR+N0|j&*TfT>J6d$Nwx^ARhO`U??(Y~) z89E`PV7|KdqGQq3Cwx_94zXXvZSK;<5Zk~~awaKe@i1{B7Qb^q8y@R&Kw?X=eHuUM z;uKza?lHF0J%zNXpxc8RTa>bBllbmqWGi#*}Ae z*^6tY?`%9IJE7H+D6ZSf_zosd1NI=<`~~?C;sV*_6=DNE<|OAk#d%C(hKn^+!M7$|Kbz#w-tjpvfkk9dZU>GSMa?SPFCB=qgc2W7U~Fo$s2o=bS!TWVCJ9 zN~@(}_b*&x<6`-d?-=%&F1CH7dV+H$%sx3N1B3Eem<*c_ILKVO^MN8rO(>fkRgQ3#bug+4^s>DBX<$(o>6pL zkoyL+Ryyqbj`4Y1ljyQY&v6Udq2t`wnX9^l|1R@H8+Q*?yAjP+Rum`m3-kyX`-CK5 zaXEgWuBaFt!oNF9{PjGw{i~!q|M&@k>FDF~l}pauXQqFFb@a#>^PB?hJPR0hfUN}~ ze93|BcQztm*OJFXTXQ6{tinw~(-wTyE*n@pzue)edT@SclE?R329Y~^kdK)?Fb=31 z0?MdFLh1ID;25e9FE~o@lV4pt+RrFd%T8X(PcKU5WZsb=HJB~}224UmVNC`Z ziG_IU7olBN@#nr^eEffsa7Jag`I$76*PbQ|-m-~Aih|*V z^vi7frTs9^2X!OvTV9f#mf!7E;=vPFe|eUayKleUx$J-?ba}}FniA83lQ6QUIUomz zYla~rbVuQu+Ba1JicWsz_}6>|+U_;xDecd@MGoCs_!Jz0_(szMD+Z{C8To9(g1evf z$U%SGSl9X;1)Io+C}-s0k3PGWTs-Yn=9+Nt!=Xn8Qk#`j19D9*&4}*D$cE~GkwmyE zX|b%fWZvwl5fDap&6}K%yWH&qXG36{^vKUt0(auH?NGKW8iXNS@WcCj(-F{Wd z?R>GJx`G89pTLT=PdnU?Yj(UCITdk{RBV5oNgZZ9Mg)=|qsfHjNSG(>NDv9~K%(vh zUNh5Zcj{*FA;yz9tDBVeqMNBJEe8%KpyE~DAZ(q zbY391uDT~yN~UD!CSboCx*fad6rqO#Rcx9jI70o28;#5Haxw#@YwrUuQ}~ZcJ*-W< zM!VLcEn=n?m%Af$<>Td*ovUYwKxCLg4Du8SN+n9i>$=X=-S z>M7kVjA%FY4qT~pRlKQppdJRQ2IE4=t5j&3Ir+9#(OBp!c=>?;gM5FrQ$vel8yeDA zWDGCK*FN90;fh;Z1`jGN%u$X|lfeD?vuGZ50+s@a(HRSORQG(cS3=l=i(FCg(e4nT z$WD6Hl;ho}BXZ^Bc#{9(6PhYmK)@|tBKQhLGY_H9PW-G<&?~!eI6ONbd$O_`!NYF?jRJpVX;AupFo3Li9CR)Sy=zn7r=dNvn{MSV*7d?t?f9pxnOj7= z$Ejx)5_SQ+0OTp0Y~yDP6-JJ-fGYb13gMs|ly9Jr`MIiA9jofC@J#ruXy;WKrlYaL z30=46udv({U3M%viMv;dh%P39iaMhn*z`ByG{#$E5|I*DEEP8i|j#H3pLq{NjNi#8jg@DNaaxE zs@>Z!i^oTvUHjZ|>ovbba0+rA`U$dg%4ECkmkPaQBp0%k1=Qf~v49(zLWm&n1z|*I z%>2vLpiY0dN3ZRh6~}7nFs@IJjLL0dU9J`F7T!3SAda_rj=0Lmg55}tn5bf6Xr{=n zRfw$DoiE?M%}|}cO}a(Ej~G!aoxa-a2Gc)X^Mc%zMlR_Co4SPI4)h2MAeJmD5YXa? ztDx(1I)su~oOk8TcxdpF-tD*R(%w-mI$zQ*Stx%hV*3=f(E$gcC$IW(H!!0pY9_g4 zF&ss+0VNtI$Q2E+pdi=hO*^ZYUlN@@jVn9hSK45AY!PLW_BWaf^=_Jce#=Nk`3bS@ zUqT;J4LKkuI)H@C2Fv$LS8_j&wonbnIZgG&~k)Kf& zo^7}UgQG8KClQK+NRiN(GogF4ZOKK=j!j~euIc@4Lpjtg`HI6`dSQxq06%6@mdWJB zkevP7Q8lO-I?vs!Aw+e)7HZaoU?;Oz71e*6gOVOk{IYaX?$;V-?3zy)HEVv#;gU>Z z0i)-s6h;H~keA#6kTJPk@mlNE$^uCWU{x z(f9+yZ4gO1M=@yCh$CwE=!_e`Apa{Im3dQs@bQw_SjS#AezZgSsFa&&N$bC8Br zpO_GpVDhYzg-(E#h4WHJ>vMe#inHGMWK`gt`K;Vjee3koFZncI6eDfF5bis>EFK!j z>b4rG@Dq!{YT&E=0gZbNWjq-;o;9s1zJ}wpE#XXIq~(NN`Lvzdn5UNE>YSX)iiEY zlQGVNHW4Am4VF+;oBKj*+n|cI@%G;Sh3Sg~OGtO^1NHP)wYYmBn{iVgt{{Jp?Ls15 z=tksiY%G2`lYj?3Ps@q32aHojRcwC@8)e$Qu|G(4&awM8ar7w3XdN>Pr@D|mA0lOu zpKyW*9+E0-fe~o>`StZ>KYHiXN=fwIvTUMf;u~|V*QN`;lzM6%;~~zM1{vdJ0n`je z_S)O^ypRy@myR~#J*hVCLHvKht#fJ;7^$~v_Y?C53xE-QF%H^PZYauxT$b!hSmv9n z!9&xp)vGV65v=Zpo>yEj|Gzf{5Jsf_0E%^pMxO&&y1EBcsfi1Rp*1rQbuEy&{~fzz|KyKj06TZb{z4htE2 zfA3zLdZYh#v!VlxKg&I_`>5R=_jK&D5|fOYjPk;>Z6f!R^geIDaB&aE1ptuYuzUXZ zl9Eg!w zUr+rGZ?wa=^e1GPc5u2+GU&RTfLja1>eFB2z%Sv;X27lSon(Jz0l{YH98~(t`YW{X z_}tJOe_i_0MAf%Ceo6O{ZA&-6J(v#@pt?ZbAe4&^dt*0p1L4eNT1N_h_Hkw%Gg3z< zu;-MH-~!7j>?K6sTNAo}2STOh6@WPtXY1k@j}Bp-Utao@c;LsAYj!OLi7%}J8{54& z$C>-+{NQ;4eDr@(8=B{~zrg5mLbi|~+(NcC^=ZTIvU9(vc+({+2a1!L=fc_4Xhhb0iAhv~M7#JzvP#W%16BrfnR;|WxUZP%NX zh+#T>T{Mf;+y)+f53N9)ptW-q2!@o*5>E_s2{4V0`*z12M)^lUkyt6`S{8$S|^xdRc6}(f(&G!+%Ka-l3$KU1(_|)yem$w%rp|y@}J=76VHd5#8NaolA+{ z+n$;|6?vDyXGC3r%1B5sCjtJ|;uOSfDh1I8mdoCt>?yU_v&cM{*m7oE~eW;HoW z^Co|sJ*t`-V~C z`EG~BfaxF$Sj#xI_HtD-(E_rA9vZGKaQ?Tg17Sp)!`y`Kqo|sWs9BwLKg27VAU}Vy z6V7%)3(n>29ilq_@(=A0Rmv+S-x2b8rpR*S9q#sU4S@|N*L#{VNqL55curN)L!qqe zL9FtEqAR?jx)EUqh857AKwly%`VQNvnoy2D3%sh}dH@F1dL^H{Y~E_HwMzg%DWJ(V zHjxnWdluk>-Z?A5_VZqS+B|~qUT%NWDjs9w26NdV$8Ot0Yk}}lapW;nlOhZ7Nc5bX zxrgv4;ba^bX{}k~n1BNLH`9jByFF_&z4i3&<|#w-6?L{Y{^i_+|1*4t|NM>1zc$dX z8|V=DHGu5e(J|1ng<+;zx}aSyQCdlpC9RxughhMy22#uwI>?A=hq=Mn8%Te{0X16= zzhK`5FW=R%@Q@tOY7E0Y8$#?+N1EMgFJb=@_Ag=o*M-G~ffF1~AXrfUrw zS&CDuDXOM@OGB%d8tS7jsiqiqNn0qS@1s|98=G4khhx&o7K>k4z&_2<4(7+@Xxy6f zm;Xb_)qjdO;-A0b|2KbO%*-a^KBfvS43;>7C`x_%xIhKPqcXhg>)e)KPsOGE(|Jly z4x3z6l5CVzTm(c;eyC;v{H_!wW|AvWlexo*{Q=_u8a@tGV(#f6+Aw4~TH$nl_J1OY zp<4FP+3{Y%FChC{-OIqyuSGzq`B)xyn0y#aV~5FyDeMo+sg8dF+aTn2m`WNB|Dzl{uGvR437( zE94<;Ef6A%B5Mt^fCSsW#QaOl|4A`BZTJv!;47jg-l7AxO_7ny+}q+ukcFHYB)yk< zP@d{J$e-O;Ks$fLE2iAUwb5Jq8TWtnbpI0bFERgFF>U@vit46HAom-(Hb}XRZ z()Ww%N2rkuLJ*7%H`0H_0_J3@IHpnM${h=dKSR<|Ll%EDR= zxUGG@^Sr<3UQud>tfXqj!l*V?D27HVmWqi)>|+53<-sTx;6}4x4>+f~?DH?r+x^{H z)MWD5E9NnHWilguLI5>e|MFMPtvcNI{WLumFzQSmX2#e350=9HQ%GC>)LWv_sFg<( zi7={4sPBJf*RQ8JY)zZmhm%4rTp$mxX8doS<}_rJ2px^M*p7jgJ2+-amrJFK1%*zU zgtbP^5lUTIz{#mxA!9~dJIpQlr+#{)+4?y*znMnW*uzN0?m~@VicoU~_5-(npTlnR zyMqxp7kHd`&Wys%{6I}+0Y&|6O#FBDl>NK<>PjKg|A)Qz3~Tz^+Ju9MNDaM1P?}Pu zOASSuh}Zxr5*3jqmc9WYe~D-2dERTD^Ir4L%=yomnfE#$_LpQQyRCJvb?>s4!l(BK zG_hQ7&e?5dEk9EI_pd$g<7<=9Jcw(nYAF16tg&T4Igr&mU|n%dP|)P1SLB!Dtm3B6 zYOR<9C4t$Hlc)p8qX70NekjT~pzMc?;+vlz$b7bENVI2UhjcSafAa0H+F)i~l^$br z%6a5?mkY*ObuQgb(R)1pE{sBy4JHOWMOkT>kf#ve*gTI)eVF;&_G;W)rc!4!Fsp(+<+|G zSp25Umx(0nhQZgHf8z4srz#cu{AMz7fAhXCI5?io{JdauU(n-#O^*D9-_q8f)>D72 zc4^T{=m)7LqycmvOcFllI6-wpeLk$JF0Z14_76`wn)eSCi=pRMiOw(aKw7KLh$&K_g^e|W4miOQrdY+zclu~(JN zOJ9so<8FJ7xj;m{Wc%Ty77#}bK2bd))N8rxL#%JjQM=8h8;MrjsU=$V8R_Oyd^VP5 z0)M}tR>nm4Q&XSb)meACzH^d(tCR@JNvsVF^$Qoz8N2a|nUW)d%foU4w&q9VV4ZU59Gs7uSxy#$&5F7-h#0C6lzf7eS|<}z zM7=OIx#fD$j{GiY>CvthQfA|P@nbd6?Ar`fN+u{{I9q4$r z`Ki0d6)U09WVv^*hfGc?8P8xr$7-J;rI7OsPy=iL6Mqq*0)(wzzK;^LB3HRrSARM` zN>*HiX57&^evtBz{@wahVcVLy?(WQg&My7;)b4NL3zlFz0<`C-jT(Sy`K*@Cu`lob zpO(__f1d}LgIyq^QnJp<;ypr3KNn3AZfsBm+%s=#=<=q0__-)(hD1;Sl%mQG>n-5&SpkLQ56g^vGjuo9g_Y4U~Ej$_@ySW zfE_gUxnn0_aOKI>M;q}eQBH~Yv>8}4vbx3>RgW4-aqNqkq-*f{vv}$$lZyKvb*|hXQB4+Jl>duaHYlcD&j>kgd zg{yJhlMDR9cLqSnV(MX9JrY8ngmCF@%TSL`1?%#J_nkNBBz|~x?7q$mr)Nh!>XH+h zGX%Fd`vU{3#8ere`ti*);vBi0xP^HQe>_-T?`uQH)NmUXJgazOpMOI(`&o0HjCkfw+CMUAdX45^H(eg z-NT$5&Z=(KAXf4sIh$ z{9>!ROXwV`t~r9&os6)wPY?s&*iUW$6dci!~V(g63Fy@A5k@F zg@}9ih`E>5fln>txi9vUg@Mw1teuDmF87q=g8ZrL7_BH)ek^?of8CtcyRs1b z!g~XKQDXJM9{>*E=LH%t8IaP`EM%Nc0zzHqdz| zI=ohSc;CxL@jQ&kxcsflf1$))w>e0S++KOi$d2H$`bGXx#4lnrozn)lEkQl^1~4Lp zcDrr&f(3qrTR+XC-aHocV)53UoQxwOVPO6>PHjZ{o-ofAs!4P+gP2dgFxA+z8r<}q zE<5Kg@gU`uwL)hrOVqOyAIdXgWxexN;a1lVL$Vp5rrbvuT+yHFf2EH@9E=EMeXv7t z4|w=_`yV`Ro?@g!=!%-R z@+YS>s3W2%MXYCott{tj}=|1>b*Y9ujIJ z?jHX+;mMo3tvs>p=>b3c=$wOXoXAlKdsc5lQnfI`p)^T6f5-W`oxctxO`*TawS@br z(R+oq%zI{#5UMV%)>w`(9_1+yY?CDW_G^1L*?adg-IiaJymsiiZ&RRdW z5j$spQkg|}hi8Q{^K%==q7Cg zOT&de+BGo=fAzzn6N*L6-g%|k$u&Re5sFjR(^MUj2VIgWdSn=}@>-mm@kw8^EFwTvw6Yz}HNktqHfx)I#VyHblEM)6v%51x4;0osR;FikIcc>m$9h37xe+WlBI0~sVhhV$9)#66gD}J9M zr*sc**$)CeH~wmaxR*AHPC)Z^ouvM`H}>EM0|chtRlE9T8Yw&9)>ro3dH?bGMLTbu zOzY8L)t8q%%(-qo7~9SlH>mvv#e-w1$MM0B>HNf@=pzZnQ16n3ftz(KYaKGDH<2f= z@0&k!y~sGO+P?B+SIVW5 zdX3pY6IGQ6=~uJIxAXI2xOKDfeoM38Rl<3e1)WS~K1*m$W%}tH4^2Rn z&M`TRCSHKa7^S~1?*E+C4f5oS8X{k!RsRW3kn)fL8gQJSgH0ljxDoJY+OBM7Z?2Fd zf2NBZkCMkiKV5DN$l||yI@Xz87KE%s4nv6-AdjI>S}tvgqVDDD!xCc)XPq&>fHD)nIDFp8S;rmJ1X(&H=LB%mcdInjSIr_tA$F5KpCCWs@4}J z01a?_Je!*f20zl(;05m5i-d{0P&CfJ&G?K~Jv)1>Ut18Je&abOEs7~;e~+mr{v>AM zwpn%1`)OS_RfSL}>(fhFvy`$JB#3+2imZUb!r$}rwSKB`=>%P;ub3JW)A|`8Kna%G z5rH!~YvN@#yRrLrQ@!Y&E8q8=LSna8{Tt=sZml=U-F#MXeX0O#uuBxUN8tyChCFqr zTWI{P z+0kbSoHyQ1e$G)~FN!@vgeJV-_H3X?1MRr=KRKy$SNL^dsr$yua>OSEYI(Z*NU!u&yyb!YtuaaptwiY zODg`u;W4L3h*r&|mi63?P0~ej1<9p%G}ww3kMXHy?SX*rSLPR+zAT5?!;NQ?Emfl; zEWT@;EGoYkUt%SjfAZ{I4VZrT$tVNFwK|kk0FJGGWf9NWQ9f%`+6 zt}I7K+%NX@-~UpmGyef~>(Y$u+XTMM2SJu6)W%Nms_fdVt_(uv_Xyxk1!Cse?BO#!EiYoKo3Ip?NByU zA$R(Pi#Ql12fF*_Bl~yM&^B;vuNS>AwOU%%qap44Fx6W`%fr7;EN>ReH5IM$3Ng#C z?iy7g4}KyzfWYWeMdolj@LGx?I1W2qAR} zQ(a>?TmYgt8DLaIlr=jrc;@_z;^gu|@Dz*>`4Pi`&?Gvbe6PSfY^gkIk0p{_BE=f( zuCVQ#mmB=4(x7~>`|1$8*hy;7BnsCIW!pA(l6mnOe-3t^qC({p(bz+m74mewqPG3Z zw#q-pWao=_D@Bu(HrZbXFqh|GA*~>A(waWjI;WBOIm%4qAU3|mGW9U06mIWaxXTX! zMnJj0r42hACNdO5bR6e(^%rpq=@OaQ4X^01k$;yjgA-@_@#(Gj62CJ`{u8Gwtt`H* zMYJaL>vzFG>N|L@qs8GB#siWe2>A| zY|io}y~?lW_tQJDyk$XJt2*@7_ChE*J=~GyJ>E!z3$EdG(dheuz45%CXFK}+iYLfBV(e1AgqwP(S3idvGT8Bbm&!O8&fFnJ$0({DZ8RYrSDdr5mid)Wo458g4REry2W-x)gdrAvy5C{m;R#Pxw6 zx4YlvKGYW85-x5B(d8k-UEz)GEuGBo$8~1wIrtGy@~5IRx>N)u)5^VNDTyGOCTWN& ztbc;b?Q={;9syKVUkF~BvWYEiPh5ABxs0IVSOIu<=bR`hb zYgp4%?LRT1HuikV@|LQI!RHufKL!ZSovF;>bYASB_or?W%#1#TAznZ;ty{y{N`Lmp z8iB#a7YTE*$JeJqb`qQIb*|eEeAwZ8JyvztiFaQ1%{dpS0jlR1>Lx7Ouxw)qJP<4j zw?9KtibvR&dsehgZyxQ?BhS`LhQta#bM-n{tS!v)v{@|uHT#-lceOh?b{2Ju$%KG* zyi!zSEpygd+GjN!a@r;uokz*lnSZ0AFYfsp&xhVRW1w7;-r;Qq4Mg1>2b9r0;IuBC zH^80hZ!TSIB#|nD#U#yPa>F{l1qy#S-#FkMKGioVG$dza0Z@C>yeO zjPf-6_)BV7^+xN=bxqysM$xiEE@ysM9rb8n+9Aj>r9^5X?UgBr$zjdu#(xNlN#rqv z1>o`$Zqwg+V-@k9gs>t3AFaaO1xCNXuW!-bEZZI!(H+AZH%4PtBjX! z^@aSW&Q7TI4_4iYR?SZv)`Y!UA=)gdP*7wYQq5z96VjIb*y@(2W!wc1@~`K|wT=b+ z9H(=btX@&U?QKTB27lxT{8uCxAlQ^f$l-ypqnh7uf9gBdau>jke>T4MurXigu2~_t ziEheVEvYUMEaKSoeek2u{Sjc!rX_5%dVA|yfr&%0WHL`Yo_`p3UGGA%>;~i zMuVF^1?8cO{y=jVwJuR;9f!0!(gKYe#GnMgy6Y;Xflfo${q1wDEKLu@Qom4A|3w;FE zsNRH!9vH>5;!)Z^LY#n+KA2f$9-3md53yxv4g!j^>;_)8j2& zjdcQTm7~GeCv+YikvrC4*ZzPxlR4UZ0qbBa+Ipf(41d+*L{(Dib%$>R2Q`gzFOB>8 z#HYhNM+8P?rn_N{a);8rzWlt5?lgnEhKT)n3%W^U8cC5wyZ6@2XAIIorOP*(!Pw&1-)7**M-z zI)C`jEiTpI?lczos~>$bAR_(c>U3S!NDh7Z@}}zZioV~x_+>N9^3II=>pBn3{UP#2 zS}UCwIZJMfDT_=Q%OW@^Lk-t$rY#i4v(mc|4w8oNdB1R8mL9hKRQWa(DS+xR)eT2*?+5o%2Al5Jz^Qfyg8BUiYjynpS;tyc~f6OT_uP>*nbxH}{U3#8@zNr;MF z?SZzaCy?R>W!R<=;(q1d_3!$V-ELOAQfoW`Ggr#XSSa0?3JZUF(oFK;fkMy;mVIel zFmN2*2jion(#ZEoLyzyH4!{$(OC~?GiX@8)f zP*2XHe7Av{D{-a*GacTQ43ICg{UnNLi^xq|259w**%&_A8Hm_U=1X>wJ4k=P)Fgi$ z$YZzAv<^{%n#k%qAh+DTh5Uq%rP)DGBL_>kdsyYz?TNwL_C@Ko{Dn+bN#%!H114%M zsZBGvW57!;c}J;kR^DWaZFtb#UVpnD!Ir=}Zjkv^@K`Ojg+>k`!LeG4u>eG zr*>~lW^ZhLK>6M)`=m44_)_I3Ys~u}vzV*Qj*c&W85vx8qlh5|;K|P-@YR+B`}x4> zL8IpL_auj7Y7{N`p*vghhr8Ec>`e#IN4 zv`5XMmUM+Icmqw&M9Vn6BZN}5%QB3dhBbV~)NgNu6N3r4ee-hlBy@MclHvaMHBrA- z!zb}=QMT6NneHuTV&xByC|SblmJg6pvq|7?x(taNYd6(lSBCwr_uIhK>65)OYbx#p z`*PQxWSo(G0niN}(iL^mT7Qac>$~x>ENkX+q(z=b^_XmFsH42VFJy=tSoS*q zm%U2(#{)$FUt4OWXho?|pY4R9sowoLdWOB{5R*_^KSz$kgurDnO@A2Lk-SF+koiwu zGNpR4D8=$^*#T!@2GKUVQ2 zeiS*Q(Kzb7>~3EfcIbkylBHC}o2{yn=#79KNFS_TbaR2CVOI&aC!YZ_UVevxYqw;= zjllfHl9eL)+rs?*k7(a+kgS(@F_}Nj%oF zg$IkA!qlbp!$hfGQ&7K^h3G*&`XK=AeZb9=Yg)1ILVu*F|FcA!<4X;THsb$_N|c+$Imj7^s09KsXVr{0_PZ7IPW33f^{lGMFjsZ4+XUYL%(I zR=>##DSz5M$G(~y&unabF_c_7(+CFB=jf&%15IUoL;XVUyn^4qA^2UuYG*AiOQ0e| z_2md!Z(M`IV2FbDaA;SD2nj zXSv_00(kmCmZJ3X+h<+Y^Bp50M5h%n+!^xtq3A#wmpvZ1Mv*uC6b0KnS=Bu+)b85w zJJR&Wfw2>s$K-S=f>s~|8_p3>8t-LNTI73)+>P4mW&4VO+IE<~VZC+T7`9^m!gpb# zsDHy9C6_LoJ%77@>lSqZ#{ey~(>bGw=-xW2I1om1@0~LRH>6ZIZl3+Epig#=UbFqE zTUAx+vZemb`NV^%)67tfGo-}gfkFHSP=yZ`UWI?64kE8V!tb)H+MeN zKl9G{V&H`>eVVm1dcXb}tsJrzj zcK$3p#DPma)@)Acu-;%d&lrsuVd{-Jau`N*WPp;Ptf+usK|~lSwzkj{2z8Tqm$*Dk z_-@~=E8btXZ5MbwEe20I((^52G>mP9Di}wuroAv#4S?`50V+6N0-68HfB8C>gMZoM z0+lealP#GBf$PmL&e4XhR-HJ(^1gOy_!uiG`j5ql3PA+GuzFx@61jntof~g#=Y6+@ zGNZTZ#K6 z7kKa9gSNP=QY$~Hk+ss|fzFinTYoY^hgC8=R>?@Fd?eHAp|}@+5=tLO1T@h~86Y1G zkww63=zP9w(9w=C*_4`F8P{V89Qag=+O?v};+M`t@(0X`5Wzq35`s|J+(A!B7p(>< z@8|f^m#x^b?pDB)SZB)JrRSC)a((_-%&`qs}!*r?e&lQ0G7AD5#!O^y6Q# z!M*4tl&H=(Dp$$-!%kV}+B+^v!IbO!$iB-DQjoY8bJ9=m*M2o+4sDOrvSH#=itIC7 z*~lQeeaCXq?9|W{%S%2n>VLH&WUl9^yGwyE|L(Wm5ctWJtXIy5&K%e)iF>8T{oF^3)~@8&gO)sK;rs z7+gsK57A?VMU}4dby)}qyf6R$ZXjgyVwLDATJc5+R-t$Mlbxd>pMRZ_Y^Gx~({p8j zu0m2^_4x^u4t87JY-4f&AIGB9n9_)?K zId;6pCOeb+_S0TAL9sR-00TrZ0Dd@3_{=tOG}#sqzHd8X>f74b$NAp}bN6HABprw6yi4XKO7vNsm|l z))OCZRV2}k*2BceBTzr|Jo~EXVDO?wAF9zY=GTiubA5RxgK?^}d%2=^4@X{|sXxsx z*OaMs8Jwk+T+sRhcAB}`W=vNXCWD+=IoP-zyTZG@yJU2+VSi4oNk7Xe$M@=qzTi88 z$9#{xXvukIE2;S?Op0|+mnkV~tK-otTwNekk3k3|k^yR38X14}ZK|`XEiKL~X9ElK zSoT=LezNdR)Mv3gc%AgfUPw0fJ@pHqL6M>!A)y}K2aDTK&X>0Is)Tt)c%9{Y|H^Y% zEq~o^qqNO;(tpND=3;jK0~h}~0;Uuu4HxW%2pTI?0HQ-}mn4>>t4>{OYi#u>i4T)X z7WS6as!t#8)=D?i{hd{g>XE?Qs2sia%P7!tKt%7uTFeu}n71wGpKtQ0m1KFfXbEoT zfq*RfVRYfL2jT{hO{kRgJCx>EY<2U-we)(ACDn{0L4Wy)7VE^?Hw;i922dD7llBI3 z(V}#o06w_SU|UjEF1e+B&apE?=-4w)`Oqk@$krI|dq4TA-{$Wo;l{hSV;GhDQ%%r5rQ^Nc+LzX+$>KiG>URuS#joE!Q5gdQyB31K^rLz-P{ED~qu20hNihD+ z#lD9juYbKHQd=Tk%d33sY^tz!=oWnBrn>t{8`cD2h2B6h|NTH0t0$FhLcpG8RxVeC@^PwT_# ze(h>+eOs{Mzjtr+meq$?xuA))nk&Owt@5w9G;hsqMKHyJqXgLv6>DTt%40g{CPdp< z)G~j>_4RWim3QvbO4l5GiORok&b|L69w|3AXfOt^t%e3+7S;z*jeFgam>A@N&Z%9R zTYrSb*rxaN=Ny%YoDKT}9|yFzWJx<-(}@(BM9^<-vK#;=FfCI9IrL+f0Q}3&Am#Gp zmPTpL6+JueW|ez)f66-N9rH-9Vj1Rr$W%yP{?oPPQr}*V*RV-GBVu+}uM^W5R|I0H$-4Qmm;kpsAR8hSq{W zu_x%zgjc<%aBnkr+#jbD_zeEv~!YOvLz|CtY4bk-L&5G{(oUomEQkl*8WEFJE_6TIa0?yZysnzF9y>&?v+s^ zNZ#uMObK`Emk}q`6#Y=3Rd4;8+P-1Mspyg*jeCjQ6!c=4y#A^fqxg)aqU#$ zkDJ!DW#8>i&Z?`g!n7}CelvcXJbZHAi-s*ba*ieQ?$EcqW2{8zMdrNSpwB=-blLCA zDzxM-Me|pF5=Bp`N$t-9HAFWFedi0=m6C(PfQ&QKIkJvxXhIB+tII00*1 zPg0}$tlEdibu>jSeQAsLJb&5U*4o-?yKE;nzV%V|($y+491DeqDH0Y4YuY2ECLBZO z1kw&jcrIdtY#ff!aVvY3UN&qH9r>F@d+ZchSr2{brmN8J@W*f~AA*HT@DCFq z7NCr{O6RC0zS>zJKKA-sZ7rR_S*jGUn4j zl=2DX5B^Oa;!MK#ASLHb5Q$*sFDoWJaRim!pLZuR6WPlg2Ce9!-4 zFg%;QiPKIzATfO>bI8*b2EoJFdu{`nB4?p=#gTmI> zUF=>l%G;(e)1tS`Hp?uP0M}ILU+z3X(%20=pGVTZkz#g|9 z>s(dSB{q3$mmKmOI1DywPO})Yc5V{QC6=r;&=C>d%u3 z*JF?M8K;^laq@yxZx?0&Llk?&MPPtpgMX0e0$eMQ0|iGW%Pv3hlZXmS-uED-pT|2* zrN^uWSXaG#k}dC}J4roDdj|Cj#)^_<08zNk0~nLFa~A|R0w}iw3)^a&rFtJZ1Xd4E z{?;QlD|qv!GC+E^2U)+P4xxH3L%lF!@YI#Q%z%ffkAgn)TZLB4H|oVa#fREU+JCK8 zKnG-{F6s&R-c~e=O*=3_YMt_4vLL@K&U~XWgM-Ors6}-JL=SfsAXfS&d zAaMqsD*jS7w_dydC11Jn51}c6$B|iyv=+c76t}n%Q^1eLe<{HZ#X{?=vK%@>wT#Ib zy%mD(d?jzs>3?QzHvoM;$NqBSpMQ{J%q59F$qs4249I=MUkPS_Y;V^3)(X)|d7(az ziE&fCdF%A_Q8THP4Y($g!2j8(v$tY^CQnv=-TysKhKkXibb(Rx#YL!ZLQcEhe|PU4 zA&3Y6wiE4#P?WGxdafNT+@;5qNwJ?~Aj}z{`UobRehbOoYx>_FnCU;3|9=yn4E*Ei z8vc?}wd7?xg)lFH`5KP4Eq&X6BCzPuyLwzz`?wu{T=8+)*=)oJlYg(WKArWuoQx;)-D#ZrI<(nGQK4D@m~ud4HMra1th5}V ztj`r20o~-OSNY1tVLJ9Eu&2kUIJf`4PUcZ7d`yjuS35vBNn81fZz9L7-$2oo>%tZ)eIQLH+&uSqwy z964PzCE)4eB%ke^@w8kiGSc(?KS@Cdu*SDT8+g*?eYoQlCM0lFE(Y{5Kz=Fx>r3^=H}Yw|Df z_$$HVACEKlR~FXM#OZ8)l%*8&~m>XsJpZDg7xPpbRlKp}D2xGZg)VG5(TTXab6aUc0IO*0t z+!DqBO(CXP(0>$pZshO^J9OjhN9gVfPXrgtl>XieQjh5wrwAgT4A3h;<*V}Fon`%o z5Vkk`i0iBD{SSc3aDt-{9M-RW+49w>eq2-N)Tvpbks-$cIl-v)u9H$ec{mh)rGSG0 zDyk#tGeDf}Y4oFAUrZVF@pF}UFE{MuPm}Y6|8yRLLl?*_>}}56Qh1N*g$Q< zrq644%lj^UI-Wf;ttRFb>YHi^ z%T6xU=znJqbl2HbkpaTH++l$F&oe;0RH7qII4uDKIDJBqg#Ru6&c7=DtK$D3D!P0? zOJQ!RKw?pXbZ$W35CS%nj0yp?e=@ch!0YRtM~?xG8K_C>}p^_Qj>F zkI_-)xOC*#|8<5K`WFQH{Oh)Y;uxS{6qbv?0BsBrAIuSkdaLD5&t7YszScD3HFKo( ziGOAAUCse5F{L=M{9A#~Kew%l8Bn4+FsraW9+g#_UYH0~WwyDxC86=#Mt`#Q=iwhu zZ?euFw|HkVeU5#H@)Ff^zRM7fTD3_;p2WiM^`%t<4UTnFL02=EiP#|#bo+?!lPhuD zi>ZXMzK@*rET}gu9wpGFMr9+S`?nMKBY#q}Yk-3Jm82_%2G^sE?4IUdOeoDBvEyCf zSW3$mTSb3X!nJe<3m_b5#T`%zbY=0qU&WOG8;9w1R8@20#Qci>tXOe6%^A~7(?44` zvHRnSl6_=g)kcx6Y{DUdlf~!C6OGu;f&O_>nT7F?rsG2!L!^*>IP`B`*RQQ#IDbr& z-Oxr439%11>WAzH7d$#b%VKi8v}hDr5gyI}Iec{aD2#*F#}93^5JMiq_4`)#gQ7b3 z|6y@7eL$=3P#|c?AU`lb0v(cgNzv(F)n2FCn;V;wB)>eH;!J9d%#3h&=+j%ReQv^3 z6o6XK6b1zR;DI={6etdUT}xczpMPGJQ|^wwviTQo-}FG5HAYCGWUt(*p+wBy%=4nI zz1s9Y&k0-?>)#Hw#{jP=Lx zKg+%TckTWQ;@|xon?fx>5-1BiRbHVSt!Za)tqtaQwR{dLRG96r6@NY0xB^nIA>dw5h%f zP;3#c0`+yKX@v^;hF<;m@Q3G-)0ka<>^2>|J5DO5OC*s?8K7e4ITR7~3YGG2p$~bi zC>I!@iOK*B0G)ykrUCvM*neDliaV1z_t2lwb^nX)`upBN@#PqQ*uHLHD3dtt`v7zQ zCFJ41y7#Z{{daT^DFJ8iMadvID4y^|az!KUX;Xza$suzfxD0jcTcYaL`e6?JO?@N1^`1h$jASc7OhjCjHk#viX0R z9SZi(<z7fX$zha4XfXP)SX}QP~XvaeU z({Xf|n(K0Tgq&H2)PK(nYBN9=eBx2NOC}&YiZVBHWQBdGEV|>*hS67*Vh+_V9cZDr{^dEDjE{VEmx?)Ge4Ek@&+4gh4c&!EBcUd2+WPsSLX=yrWwgvbM z)$#uAyyS*~U@xBJY9s^XgO$e0HCjJz7B2DTwPYKc?PmWPD1ZD@X=9z@iQuJG-1^0V z6bcYOlGSqi=pIuw9;SVA>de~oYIw8s6pch z;5JDrW>uZ2q<_}O42`a72TC=w9HjaEZ%;(GeBZYs&%?owY1z%RJ?jRDAUDfF=a*lUZcy#azn7%m$V4KAbopdfgRt7Lp zsK&CsB-`C!aR{GU^`h(1{{1LxulrickEENo6B5=k%~H}qkd_%>=_PUu)|9(>heYXx zh<`x?mSl#yyEp)p^3pe?WYb&wXX;9y>Uq8#_ht>r7`*8xCh%JB@}NC<;qRZE{EwEO zj>#zgxL!!ivI0=BZ!*>ij=iJds!1_4Qj&4aNrvrhPA{i zCXqsWh$8{ls>0p{)^I-CTx-cL$~4du(0}6me08Tp=GTTkS?^(K%HXr|-WI*wJ004m zR`1$LJ*re;o#wMWis55`ycnQ(XG|S51?mS~7$4HsCp$j!Y9qzQE8Nl@NbG;>q*OT~ z=yuHoYDzEDVc9>9TfuJkAPs0m#-SAGSFF=K0~8Z_bIz^itz2*0tus+-BmsB0w|}4b zSu^pJar3<2!TnI;B?gGg)4#1AApo2wU=k$`MITSybDIj3w-@5nx^me@g>6?WzTV(l z6w-v~7=`f0tpEz!gDY6B3(L#8!02sVm4%+;Dt-;$j|VMmCkO;Qdx$G3YX6h?Z~#g? zzrs!*FW{Io<)F$Doz|n>del|b%YWKA?u4`)d^a_As2H++XZ6xO%ZIiI_IR}7q_j={YakvY;e zqfY0f3X;~9zs=A`9xAT**NbW$Xu^;l*I>#=9pN7zk{&}$e7X&!`ms$Ip zSt~#VM5isdtU_oB`+M|s2biVH7z5O_FtkxYN}><&g#NjuQ^>+=cxT~z~XG~upxcK`W^8%g5x7M+Qt0mro_j?T3RYWNV zFb|pnP3}i1@0||wWb2Hz<<5|c#-w!u z`RvGzH}S%kR%0)*2Jo7LQmv5g@QdU>4`Sl!qj^{6`d|y~Of+dq13fDZ)YSd@)YI>W zw&-=C#o_2L^6542KG?@k*9lXOFj;#jauofh5e@FpBx#%neiER-Swt8qaXH+PAJ(gP zDyQYxH+hkP34cdLi-BQTg6`#MC8#OFl=hU#u!_+QA{o#=@FP!SVr@KvUFxUZtC|+6 zgnKs|+Ks4DB8xc+i3#!!{cp})p4%uDVj;3`cvEEILpa9-<6u(Ks(u2FG(orCZa^r&pZHT|RCXNJJe3q_%Iu@#`%!P{*Z$3hqAuAw_=reol1SU-!CkFv05eXsV zVC)D%Lv`mB-tEi!7tiNBhNhh=1t(*b6VWMp@tD*D5#C_ndRX9&mfBMip$l`A4 zf|eZ1QT+V1NU`fic|aLCpO%GtL+k7k16YtpfPYLUAWh-d@2>DSLAw||*OlQq1aeDv z5VTteUUrO{g^4t-#JVY@4LMl!Igvi7Xnl8abIWeX?)Yu|Dqf5rw`Zh}Nc!oM_)7w3 zDgx&~ic*a~A|bD8!)n#zZZ-EZKgP%h~B%NFP{OeD@*7OC_V7n`KWyn7WLdMl~=%y^w`q zeA7@rDhAcq+!RJ~w`*v z0)pPeEXJA5)Lx$sdAjS@VdWQKoQ_?l)qk9T{ zz*;c&ha0VIS0gUZVSNK#>>hwr4)hf2j9TBIh&r4&d*crI*)@-ZQz-L!-P*$AV{t~h~rAGtbB`PU5OyaL~5Wfa``1}kj(&Bio; zOj?okhL+6aW5HPr&{+wqhmM=k#A0$DuuaP9D>yJ|Y!yoUfirm#?GeznnSVlS>X=%F zXeK*C3bM37bw{@x)m)z~B85QUsngVbV3T5lI1QjEepC@a9KR5Fv6pTT<)^EV3HsS^ zAI*LG3Um85j0U{-??KDO7=)MSq2? zYJo?&hk&%CO2*a-@dC|=V1L~}@kek>nDTvBD+Vx^-UOJK{<@Rz^7d_}Qog+2!8;9_ zSM`sH!=7@2XsfkZs347GQ*D5Qasoa?XzBYVo8&pc`&~9tY-9z}3rUjxWA>Xye3@^=2C#o4u8tM(Ni0zy0k=<`L{C|Y^@O?yBUZYSai`PNh zlK6ror-_iKP|x-da`>ehcxMB;GXUn&SQlZwqnwATGLb+0p|bDr{M z45he{(e0M;qPrQNKy#x!Ettq6>i*N$8r6}Fm zH3n`t#=6AZ4d4ltcm)XGZLa!r9vfVx5;c~+NbRtn<6i>33XNXPWPLSB_f<;~HS9Iz zF5msmFi6b!T z?s#9wCA^qp`vNec7chN>C-LYwCU74ODlvhMF%3bm_}Wlouphze-qoMgM}6kAa+;{T z5qGPT$1CK;*=)^JN0FKU7)a5kCmSgKb7r2K zPJex0L8?D8^v(Fi`R3t$H%{tzE050}cz^!6z=BaMO%jBVwOP>*g&S*wvKz>fV+G>= zByCgD#ErRLi@IJvpv@)Tz30W=#PYOPc`1A3qi2>UWZ)mktA*rn3Yq?q=1zqM-Rs&- z3Pp+_j_sGex>>}lt6S?ac{%p$GjG?IW`FMwRk$k+|V*s4x@oXuw24sx8|! zMr$3^^k z{E9x%xtin8rQYtim^o9AQv7xqk(}^}U79OLU|}wnc888>RsaX_{z+|+5g$TfN3el* zFwq+Pc%;+G^ke)@8)#$by&7_p; z%_q^cXD26aO$DX2k^TKmWITP_g@2#EN$!7f_?6lIZ*L_5M$7`Hs~>ldvP51jV)18L zGDoW~J$-sA@rtT!3cyzRdcXaXtr|_i^Yo%2;@I}9z0_gHXLTo5?{dN7up|?B!rir2h?qC+JbJ~p@lsM?-8poXmV9rj6`;S- zA}(D_5$bf58*GFSLhg0qT3tT=P+iq1!wMVkbi1gz}4HIS!z}tJ8<-{?K>A!4b^z@XY%O!>do}!J`xk4 ztkYjWS*jFi_f~H>2`S__+3pe;Qe&T>?X{X3Fxfh%uien{)!;k-@iI=I)KHEB8VCJT zv;Lor&0*o-3(5nsbXPWmZ%`W}bgL~HxA)V5MT>`O8_J$3d(A&hXMe*fNNh6wWIIgM z0L}`r3Sbl-9ag_alao;*bHp_|IM<^OkK!&Gjy9y;;_D%f8x4H&8o~99IAN$~gXAcY ztiSlu0!c%aZ)ukr$ilmCRf@VF%LJut^gMq{*-l$GSAG!mZSIcsQ*oyjj;$BQNO@GN z6%+76$HgQ8e1lacOT613Hy-1C@~VtY zn2qlE0~YJ3$dd5|SjGxtW$EOG%VxP?dhu^B!u`~{*Y`@sn|}?O2OaS&+COUDhX2re zB#e8H0BbyWP)-nBF(nmb;Y&V^4>Vh>rQq)$x2N28{eKQ$zwMAG%4xUoEpO!OZ$$MC z7u=1M96W$BfeLDmvC7i)$(Auyd3oDr0~pLj|tUECEt| zGoQ>qM(pd1Uw7mMF7_XqsVu$?=Iu>q|%>k%Y-Z=b(#UaXjA$w zd)|Ur$^x#eTq-0l=xue@{o1tq@;&!tB_t|lPVVVAHch5dbm--#%L#aN?C@ieq%oQk z@$;hw2XV8ynx{FsCiWTF#v_7?BTOJ6nuA+BRA5;W%YV0q^+Dmdrx@IV*h)m8T_8<1 zs`J636kiHGf4S_&!MW9MtB;BGELYF5JWGakejH)^V%Z!bxOk~zsbqUsJ(XUhRny&f z*J1)EpKW{BZ?-j|=vUYBF$C8KCeU-|1*3ZjMdwmx-+i5jebo;tn|4DFfenAgH z-ff3@YJViY5U3ZDA19KLqT;?nd~N?ljo_@SZfA1r3b80O2Oqi2;HN>rFQm0;op7SS zh|hFLQYV^MId=Z)pu*6d$_yg^g`r_R&yAFp&K`@|qH7%qC3S}(1N%fkeU?(I(~Fu< z{)QgX5*XRQ8x{HHI(V40@$4+muB&^m`P*Fe@_$sa%vMgdmFP*;XpG#kL9>H&sswV7 z36zVqgD5x5KALOuuhmDrnfHoIi$2xptl!q_NV$LUo%yHulJbwKV)~I*VP^n(BE7l! z6u3qSq`%SjiNW&A*T&gbHI;|y)IYNnH;)N3vU<+dZFvbcA~l_q$OPPyMzI&cEV7Jw zuz!C;!`Om6{MLnoFKb`rIk6o+#2*6RKvNRwxfql?7F5unsb+Z#hdU(Q9Nb*7G651W zUh3A47p`t!_;Aw#+h*^E-}9IWjI5)QF0z13tGVT9p{4yA1or!NM0IA>5Gf?>w1xos zf#l+V=A!tW3?=^acS4N;-+Ux#>J1H8fm>n-(qQ*Aic5C@*QFyc#osiekn=7 z5n(sbRqhwe z==JV<>2{*g2_kF9veDL~jeo9wqmtEHfC-p6VLblv`K&i6Pg(S+ z=`<%3C^EOFtIn3CQ@l^pvzkTGFzyBP?s+~xY&EHW`5ieL^)tT=nWlfql5lyzk9rz$ z%&1xTJ4@U!Nr3WC+p)KfibILhj*{+Kl2!|eBW3TRI&iCK0u@$ak|NUh^VM6m!-1Dg zxU;@$n!0E&iTv3PAvR0WZ7V{}r+4&o>oP8%`VYKn?tgg&-9LUv{NFVzh?Qmn?)t7I z2u;L>5(FkcZoZjGG*o{N5rI@rBtP-AVFF4ykOX9hO&f}21r2qS1qVrY1r8!kCnR-f zL~fUZQD@xJAFW%!Bhw}goYRtTXevXr%Da@==hi@F3@s~a*_8?0L!fsb3@HD(+hvvo ze=2q9!Q)I|!A5(R53kJPG8-+EY+xl>fIt(Sl&g%;@G9M!P(y!JX*rzH+#w27ch8^c z)jC`fSM}+FZ`Yt>@&}p`iNApuac^jDs)RJk5Bt*xZtF?Nark~V zk+v)a{I@_f%NfGR4x6w8M%*kYG*|gP=m~y1+Q-@F;P@>unTOp5Do4JQ->OaJ5jAdq z*jaPJN`=x^2bF&e;%S8(+|(rvcku0L?|6MVUb@s@%561wvPsJML(B1g-uypU-ts;_f3;t&FM8<%npvd{YM;5K zAo=J$jk5P@)3W3ez5)Q@z`^QClaeEV$Ya> zD>{_1cVJ6Rs+9={Xz?BCwXJ<(zOb@6_DC#XJp}aT|Jo}RXsQrWTtX6P_hFej_ofgb zDRNT!Bk5a;i+f)g+B@xs);GXi!iw+Px%a9M9{}Hg9D#XV%B`VBC+ZEF1;|D{3HDpQ zHq^zldpv(m{G>QzPLX=9b|m>>P;`mT$SDH4G{pDc-Rky7OnvWn-9X=ZI?6ZImVn*pYuMmpgM7n-$2D7~Uh3tF7ME5>?b7 zg+zE}k#`wyHf%Nd<%-v+_Zh1Zs7JpfE1055=8(|Bw%vHUB#KOJp1Vz(=Ed6P>L05e z-%lAz1nvomHeA|%(uS(+Z$a&Gf1H+pX97{L_b0oQj5WR64A}Lm=V=HwqUmzncS&f- zPicSt*$W#T#)}k&=Ydbe+LQRPk%t@g!rW6911fMl1Ch|G9Zi!j^Pc(!U%kiH=MPzN z%tL9yHjFFnl#?uA*KA2YgngT(kRz|R=8{R_CIh8~KT7R_SE{Hn zvo#6ZJtX{x#uYuSmdLMgi3j=Y+cq62fkuD!X+9g1;YNEx=}G&aw9~pct%l;IQ{Jv0 z-&8;|;PUVLcvcgn9*Uf{KK)rFf-HvbZiB^rv>&5ckpfbQsa5^Y{iRNo$w*HiYW-C+ z)~e#Sa|Gr#C}U*HWsAagJcgI?Wm2a6gxlj^O>=b^cgmpF2}SYq9^P~NW;LB=TJC>h z8}Q{EJ_E2?7GlX_Z$(#QmsePn%%VF+i-%9u!-Il?;vQ}IDP{iyY_%>hWwhI z=`*^7KTWzk#g|T)dkTptbFrNn6tbu>H_h5FdR;K*y0Wx9b#kj*tTic|H11~O3qsC| z$%xfb6<=sjyvko#*0#!67r)v*_w0YfKC94&K{MYu+F(+DGAP3;hO$Wd4#NfJEobRg*_w?POe0%?qId0 z&~HiPCrU-J{Ksy;4~yh;@;6&=y5*XV{qzR#Gd9bUNmO-YUo(UZp()^$+SY&gY~ehI zGt~12yl$G!UjJm^Y)Y-|*MGrbxHM#NodD$q=g-xVunCXg8VB5l8w{w@=O*0rEi&f7jP{?biN z`&muV^=_*fKUl+VKtle)t|2C>DpOpws#sZYXmWrvO+UzM+A2oaSDCZ?1MndS09wQ` zf>D%f^bEDFO)?ACqj@?%n6w#ZJ&HSX)A%&MuxZsPgH`r`C*L{dS)6|s^9Z_+)qm

    +6uTuI}t>L9OWf50;kMmW{sUgRb_(;|sc^;fqjEF+IY^K#nRz z)2aL^x4x=@Z~SStmAJbeOn}C#M}C5hQQNSBMuxY8*eRAI(d75W`9bYgaaLsY`m_O- zPaJW-$$R_4#>#s9x21n3IkkpIZYQGlW6#r|Ig3W3-yco!y6N<~7PyOkAH}tx1C-Ui zn@Va_d?q(N3V4ATR{30E?w1tb?lWgx?{RdH1FOW9rytJ8lCH}+V^$fY*Us&koM zjz8Go{u%OpUyynORh7}_s5G3}DI*Ko6SB@*C*y3@6$iW=W|I?bXTPEv?*{j>6n7r7 z97it1*S4ZYdx?Q7#_pv0DS}UU8RpuUd8|}J(dri2b*{AH>7&)$_!nAty4NE&%%#gy zjLtHFNGE!Mkv@OzP5>Z;t!sUs*nyF=NLrtyowb&oVnwqklm%?)H2B}nwStdx~qH03Y8z?>#S{vBX&&KGtvuVY|+tH8$zZ#Ei z-yeXF%!qCe+2{(6MDdyS~|c9=D;3ZyK_4Rux`Nzi^bLivKy=BG70{Jw!YHz1aw%Rnav3 zD9B&mew`3i1>9_GYrL$TdJ*_n)&cpZ_D~{e~9&##rg$17WX_B@(eIj)R9cZUP z<97yvzbnp>js2DF(W(U`PEE^)I&xn3gfD}KVt0Sy@Vad*(o4k$cJ@bO0jM{W*Vy&L z$ZwMncDv@3T@~}J(-rS?OD9CEU#dngA2-)KsdD%_T{g(H)rc2F3L4XVU;uGl%M0O(N9Ah-FZwDBcprOLv;WiU zqnsShv2{}XWa??WKm>}HA-p)S2<4@z6a;_S4G_Y6Wis7G-lvAPxEs8?w#*^n`MP!* z6$KG!R&#&cQU=$`Zx(4c>!c@Z!XP?8mPbe@0c znpDOFDjH7~x(^>AZsi9HLbD0{7d*ZOWLytmYdO6LD~9qjxDkgzlggw>8J+-RSVFI=t8>92Ued-`W?Ojm8z-U}2fAPJ2o4%F2qSjf5 zj>;A7356cS;&WfywEGAnu7e6x7Y~1&KH@B>_Qd10N!3u;BZ!O8S5i;FtE`9K@^0(B zb<><3-V*I#CkE9jOA{gu&38=kH6ASp8td3Tp+UKy;&|vM6{`I75SkTCSuTAbd%%_63@n zMw=962!qh|*cM~Ah`RnMmfqNviDLtM+f3lVa-%h+ z)C{+i>~=)Lq+nR#p<0H{%jnxNUt`8wzLXoe|A)>35uV}SOF}Y$|EnvMri7t zi7uhu;OlS&c=0SSYE6ILiyU}uvn)V1C+fDLaVi&^f8_m=!5y86W!Fkef9-dv_*It# zAwyBY*iPHT;rl9KWzd7jeKZNM{)agk+A0Z+nSW~Vso3%+UM?K%nE50Llx2`=y3zeyPGvq!iuW5JjZgC9%4<_J@ z9gS+=-3`jW09q4@)vhTCnrhiORP0>Q(}Guedg_Y+-#Ml^y0D{3*5oLfQ21GLRJ&!w z3SKIX?=gQ&#F8+A@$pv)FB~7EC$F9iuya^WZr4paE_%RTDvtX%^u8r{EUHZ-0#Xr> zj)#ignu16N>0U``Ya3EQX%5jk8 zRzV_#Vh*PiCwrZ!^S^V^IePEyY4`hw59PD%SWr0`-AEaFDNUD*?D@S8hYAMym{)l1 z>v*a*w7WQW$5mV*wfUQz0pX^JrzlU-l7*Huzo8K0;QP%bmjQ!tI7OD5$EPxNb(IM%OoFW$X3*YIlEwPf7WN zq)s?z6*eYYcz|{t&ZZ{laWmN=`10ddUt=!`{eCMs+bqNQ24yo6_JEE-`Hdh8EG>R; z!vS}zEnU_=EYGX?4u?VLh!z{D#zKE9!X#7&WORe_g#=xJ1r{&?kHy-D3y+^wc8J?I zzsoB*(eJquf5FAf`i0?*lse^+H74MV0gt-2CM8Z)rp~u%JPW8#9l{WIR3qlc)Eb|< z@HKS=Dx9oq{9;SI!KSM|&>iqVU~M?sK%c+_MBTQHWXLx&;3bPT#T8G?N3MSnC#}Cd zAe%{uJG<_cTo>SC^r9DJXmlZOXpPKeNzf*M#+l+1`z zilhazFxCsR)a1$jYt^yqquD24-V^RwxRiZXE_|S}3LS~!+Z5n3$Mf;Dy}pu32<`~8 zIEL%u^gMLg?=al??7_)kPmJLL`;H%IUW97ZrKwTX9pH{eADhUQU0;8eG5JZB8UFhc z_2)GeilW=@Rj%ImrH<;YlwJ**M{o!k7RDQex`12b$l2 zD+jzrS%oUPZ)T|vb=iO39hbV-cragc6~Mo7Wvb=B1mi<9WFgvg4RDwe0v>-P%h?zmW@+_WJ45c5 z__6BA+;_O~an1K_k!fbV&p800rw-m&(i%&7Vrd#;VTh}Q(v!DH%RG{%1(UYzhObps zYL0(2D>#1O!6(?uN1Xsl6C&LBgbD2Z6=(IGrcXUhs7=BZw{<5l7 zOPrs4Mb9_i&`^KhR!{Qs6zK+JwDL9y)9Mq(Fd}V7nk2jhEzKkqiwkjm+MAEf`)Y!$ z#xL2K#<;lO-MF2UdFMCYW)&5Rx<3^P;qmvw&&8Se@fab0NNx4$Xnuv?QRKP>kyRCKC(AOF12QmlW%&v`gZnVrV5%R+cBl>GR3N2H)WYXNGfI$&5!Jzszg20j!QZabdL}fx!Gqj>uma( z@7Sog{QG}<$wCJSB0pj)%Gmdu-7C35;~}95u5IMUMv_6gCZy*-8?n_WXZN8Yh}(K# zFw$pq+JdTEGcnpVomdcRB*}`ySAx=p9q6$JDh2ktyRb5&$|5d{y4zW$OAFw+Da$xU7rj!D*S)uxxu4YS_Ui;yEK1}2@G~-{mDj# zYPEl00y8}{e)YI|Eel#yfVZ-3~6MpO{#@7I4OqVckq19&(T&gZw5L_-vDN(?YLD3f?fAxIAuL zu$b2Bcn$gEqZvU&cx7zv)bt^nwWfc6IO__62~cf$8NCn*4*JFHe>qg?O0hdl&oDX& zfpNM)c74Jc1t=JLA=cH2q(3dtUH~TK3JBFk8JvB`vcAlP=3&aTtHF_}o{5IO4I_(B z-&U3BseiU8k21Ju5HJ9Huu6w~mbCix&*yO?eN$r*Z;of8l%*$KGuFMj0)2naK!X37 z_ITAN9iJ5W7sJyg^`d6hW2tSwf8)A_;A3Az#npbiO&%dwA8>h<-NN<)_5xO$zG6t# z51PUkWWEj3C7Ohn{yq?dKGSgA_Vny!DlLBXjmhnidi<=^mew}1Q~&cDM-{|V_I|9@!d%_lP% z+#*!*vnN}XIvrH2Ja4SnN8Jt&kGvHvH!djPk;IUZrHV3vAJ&7=wF%asOXLVtDP!W8 z0D%Z8_o0h8oMh0)nE?4U^siq4)N`>Q_HWAP|L>_$Wrsyz!iEt-RHJ`FJQ~MyDV!@P zA;-fzpZ#l+e`n?!f7RxPDNl|FT%w<0f!b(fCw9~NQ9pItj|p_a=lXFQlstMI)D1Q| z+=b>TWhlE}^GK)M4>?|OTU}e~oKlSx?y#^y^ubJO$tW?@K%c=`Ofscvv>{K>bF|?h zwUXoc7X~FFIjd__)CPZxRx2*wvn)}>`m1c{QbPW0m2>KUirR;eCS_WH#qUH&b6LVd zdZrIW?F(dFzUFU3*9QUuY48#3|5<(d57k(T;bTlpRp`bwo-F`v+Oa}fV|_Na>S6~5 zfXdvo;1PM>F!HgmuV*CWUYvp0|9j4%(<)G{FeE1vXse^=G*R_Jx6Z78z$I+wPQ_V5ge_k*@XIXL|Th&ARv%|I@!GZ2zaFbBoPyyTO zuH2m434*i>@3K}jGX0AW`9-g4#&X=u4n3^_9*Js&Rl0v8byXre*dfGGDW)TSrWfC)5vG68S}LK;Df zVHZYd!At-#$}$(+e@zS{B}Ck&OF@#LYnf1nz9~&dsdH^t2P%V_(m~Mz{(GL84zP(8 zm%69>sdFr&O8k@aC5HTjk&x7l-tI#)0qOsi8>WBUNCWkw9Nb{+R5F3-D%Ahs0#<(s zGNrKo7MSFuUHUa>pe}5Y7jJR?Zf~3SW}DavNj<)~Jr@^~3=dX#W3B=lpX8gdWCvpkrZw zHd{iT?oPF$1sLBLCw^eIs0qir10SmyH=Y|}@T6&qynN2xVe)v-!ywEs?tj4jeHx%5 zHiCBYJ+gz{nSuf#({fn7|n+0opzmii^P{ zpzs-}^?R%`(D7f`&80wCkPV@(YIf^GJ-rC&xpk-MryrCQ5v0oq)q#LKVl2LAN|SZu zV*)vRQH(vEOrT@f!uY|Hi-GFhCz$}JO*m?S-H8c=mZQj8s5TM&)GjcB!mGk)7LR{^ zUR_ZbSN%JxlNoSm`_J0`joM%bkmK3XBt~j3;!xedX0QF}q)q{Dbh?R#b-m&V*98~htFY?qTYocuFjL#Qfb!J9 zDQZZ9gXZ+y`y{W(Ok$IdY4zY;QdfWa<7E4h+rmjgW(WIw&g@hKeYtxDzEyxVz~WhE zv~IzWMU9>#TQX9)cP5p(t=kDr@5EgF=^j4kxO%>(GbES*n0n>>|1RqDC!7IBVt*?Y^sg&wUdT(@DugfrD0Cm=?4S1OY*QZ6%e7VX z6Ikq>^8VAO>iUGdG$qpg#Ls`^Pse&%YB&!+H$G`W&%}C4L#|X0Xkl^L#G#%p`7q8G zt@WqOh%x8#lqXuO0dDHh|D|21F`vb^gWwPk2Bya#S?`|fgl!sm!c)1Nmx{jyIm zfn?L$OaLQ=rVIaM+mR;mLA_uJtd<#QlkI$Pm!?fn2V1uH|1eN{d->x^>NHONSZ4Do zasdNlu~kc|8;f!eOrU=Va&NCQfjj*>T9%RMErJH)WiQOZrj_XT=Ca47V|I$W8tYJ% zZeJNqkwVU&KXiWtZW^8YtMXS_oEA-Ch06SQ^{h@bHN#-sN>H^YVEv%R`f1bRR7t27gbOTiauI=owO8PGjfi@z~EhJb(3> zt>k=55^k!aK6n6emU`Lzy=}&wH|@INRe|Rfs)`I$Z;&pT#ZHfNQ?JEB|7)8Cw$Rf5 zqOYc(VI&su_kw@y>e*vx@{eMngzF3(bn{Uy3^ZF5*;)}sdEdpNS@J@bjPw~uBo8g= zIre}2M)-f~G?gWsGGn|G1!YMJ{lC0p9YcssaLOl8ip)+B8ID2fTTF*Ybs6al80d!- zS`a2QJMD1PubR49+?C-q27C=yuK0BcO#LF)uJ|wkIi-K)6(-;UYe((!^#!<$)*N{k z)b{Ylj>fv7DjM4PtD`OJ;)L!fDtR~DSlDI^Qt%(MX7rCI>i#z$Oc)fOJx%PL$fZ?yBTx>+PwRaSl^#~qS(SD3ea_3>+aQM-R>;RF zT}TxRfqZ{xC+6-by!*?&O|9c!s3wrz5~K*F4j}Pt7ysHbVIY~4vCg69I z2@IA_gb-jHOrTYh3CwgeBvEz6sKuexW)h}t!)N;gmY6=*ZwKLKImgEJu)k-%yIF|d z$g1i#c$%dxrfsNQqf69^f92)Yy1+KhvA`cGij04}YAix^pN;tI0Y?U-TA{3BnKYK| zR74Qb^kX8sQm||o$&v}|C^CTq*yY@yLMCu20)b|Ql{(t+??(ir+$v5v538i#_V-TD zKZD}m!PZ@~HCVoVf`Rv%z;5?u{qqGSfYo~# z0+zmiuK5cl0Sia%NI+eEsK*#A((&CJ{-b{fHR<&Gi3A6AR^$5CepYb&(LeehvJUc3 zNH+UFKgk)^<|kSXr95W4p*3NDX~?U2EPwKRh)+thv!H6xCx5Az$;oFVg>OFmy=(4a zk*~JQVRd7J?_)9okDfd+A8>jp-rA3-ArStUztDp}vu}9q1s%dtQTzTc-|5R%`}==H zdO>&>gNOXuLL+>O4s|fUKc;fa!T6D!_p5tCI)klCcJ*Dg`9Y7{ENo!d+CkOauAS9) zW_NFsboHO-8_k7kEtHwJ%Ros=35`?Wc>~jer773e7gVElsnQI*_j*=2IMi2Amp3&z z?w+O>(bPFxhFG|lDq}`^5SSy6F?fHd%ziEQ+b`_|xeK-SO&+^EoDyMN>I%1>*X@nq zo#B1X)m?qkW>^a*u(QF0%VPN8U)|#+(?dWaLTpsF}tX-npbTi_nuEh`PAAOX*H230*g9< z@Xj=LYf@RMd&#JvO@BqUesq5=e?Gz`9h!jjW_*Q8HKK@?V-U)7l20P-s#&oUQKf7i@kPc|KPZYGqb^TUJJ;%>^Pv|&@ zQ8ml-d}w#T4AML$iJsP|giks!zOZW=PrF2U+*zf7Xc+T-QeZmU`}}{3j>X|=ND!;i zcOv_K{VGjpOb@J7Xgs*5Uq1ezi0QRkc($!FpLV1HNjKj4Q&gMLk-_ROYNs+hy$N+E z{F2^W=&Q{>ox@-D&sjsfGu1>jhQQ*HYK)uJ+f8>Dnx#lmk%g$Q5C0Fj>s1Wns zvpU1CGJ_cnXK>4s8YsD7?gyF%X)@tSzN0O!KiJ)Hy6YN6S^kDsELO95NT6z?N_X4h zVLO}MrHAp4A{l?iex(B6FRAn!snIT!gBMBNoe-gFm5UlHh!ch59)e?S=e`^p%Y7JY zAA04)i`$sxMRM&$dLDy+0V-Z)s1tIe*HQPZnzyavEyfprwPJ7Qohx(EAG`0WXcYI4 zQthAAR@1uupU8|Ei|k~QH5lC234Izw(Lz!KUaURKZ(4u7DX*dXF;4GemFfBFFmquW z%~Ln`+0t?{AS%b_s@m`$hP|#OtkAtTh2N&lFQ$s@6q24WxGf19;bZ zBIP}(#fLe@k#&Hy*pdwjV+%-86*(1NgswVnZWPON7SCNpVY<4|%yY~(ratG_FW-sSdKg_$PZ#?!EzN`7hSo!of z9rHfat79<>Ngv$uVmIRcB}Q3NHdryr4?j;&g>Zi{frTBF)t-Ol6h1U!d)- z1WV6W3e*1PhMt{SCa{+YFo6^wG7qCiEEcu--e$q;Ujq^A2v^4Z2CQf>0!(UP2}66c z_IK~{I>3TZsi-g6L0AU%kp^Ag&SoJ58H8%Rgq`U(U=cl7y%-~_RAti$djpT&zKDup znBjjr5r2$h(x6WEk`O;vwv*7>s>KI2T!!Y&tsEDmtC4r6+h2?R$K zEjvTjUN%|&lw=_-Q>gQQ%%wd4cn;tHY4K311GTQ*VR;mSApG%I%bKSK2`z+CD2(-y>xm^923Ypf=OeDBKzuLE4tLj z$R9=r$diRn#6qh|y)8^{464q(k{`ALIDs?1@(C)I- z?X4r?8d*0=y-~%BXvt&g_jY6osFi=aWR@3+vlSMqE;yKRVsNf!HlTbPHR8&!tfW*k zfsZB7U2DHHGAd*k9{MNs;8+yJe+cW^>Q7kFAgUMOjPeUIi^`nb;weJ|w84f3)wlpD zc;&uFH*X&}v4W~mYC&;;On~zIBYA2ikPJ2XZp6K)7nq*Ez*l_H_5HY`7fgTWy!TzJ z^Je{Zgygr!k}>SE*BRUpCZOa?l|qdSD>2d+t=DTiF@lKWpec))%9HyOuwF?#<6wB( zy7!^x0Dce_>?( z%5b(zy~4FC&g9z;_HA+(HIjc`GamV9eieDG+29-gni@rPz|b^@X(Ae}Siu~KGpVo} ze*T?f@_IKthjE+NkYjCV;O0FhU?|h9PcMPGTkb`ek)vACu}~f(>8T(%eySZKWdB96 zlAb9YZ?m1GDkf;`BOG*1E^;(_UOt8MwmQljiqD(msG{dU@7bf`W!Qf-wOO2Au7aGH zeCqlkCUDQ~*$e-j7ozLI9sU!7yH*?-$Z<+3)f71bVMjT`eKr%MEK?gTiOStaDb5qm zP^-1cyzfs=`frK2Qrba2{F)5o2M(2pf}>+_8d1&M?vidvCg1r>6|!@EgAO8wbr{#e zN@lkWG_^9XY2%&MV4#1Z2l!%oxWh6QT{G3eV;p{ie7R z_OflrZTBJC$?y&|uhBsk*Sl!oH|;ZauWj4tFey9VIlNtSd^D48qCdX+pKmYKq&;5mRHJ{|8rX>4Bt;LHPtReq zq`p?}yB}XRerFDQ77I_>xv0C`$^>qgK{uVNNwq6Z)Js8fMALX9UfNaAmb6N3hwW!b z2fd!WsEuA8S-y*H48HRzMI|V|E%}hnSJTt-&(9J3D3&W?L@$-DsoJUKglUU?I13Hf zVDpsQ>N|;?dI5h`mzV2ri+RI8=kSN)(X;}{^e{bE6t$~#0i#G>TV?`OBYVVS@F`iJ z!L3F%J^!n0OTTY-|5KMzhu}0lr(oWzmOi`>#>+-%)n_3+W&sKrm5$}48xRno+glv9VWKNm2i#~E0X?zN*ySE)%n$S?I-8#E2FVv^sXkGHj3BIasqPtIxAb$l)V zjBap`B-gd*TWT9fP>H)?+fVo_MPQdLx|2}6eFN45#mhD0&;l4a5!q4~}mzKVs%*$%;Psq>zoeNd=- zo+2iD_2q0j?^jay3Z#hf6+*H?C7}*zL-~J8Za?+*KkDhf^9XDl)gsI1u6Rci9!N+Z z|C$qdO1~zIZIKDoL@lQh&?Dg{-=Q9BqndLYZIXXck^WL}uX7!fmVQ3IUJu94D!K-9 zS4Je>%IMLnIdiRXS7`-9?1jnD0_e{S{O)F3*G5;5g_y{HTPX_k&-&ozRe9RsSRR`qM#KQ(?9_Xl-DZ4;$?gy?hz!Dv&s- zTSu~K#qJwz4K7i5^(lGF@LbTf->2T#cORuzToA4}5Ng&E<3jbU4iZTu@|elj*C#tgim0#79Q*M8i>f8S_VYEd z3K|RJZL}=P5^6`P|Jd@n;Hoo}PT7Cx>sH$KZP1klbNE+ddtcoC;q-I*hvHAQ!K)d8 z3YC|_TyG1d#%FchkvX&MF)=Y)fc8>Yp)Gp(aE`BEYCULLeDV(4Rt}GrHRqOtx|crH zQR=hv#}Q}hxz7dCaldNAYu&n)PL)}n2j7u;J9aaE80ZpLAUA)S_<6abd<=iaAEE-K zDt)J7fz<^}GSmaZj|d>|>u(?_LZhpr7ZD;1b8)1Idk9VjC!H*s+(hW=kXS1 zKmDE2al~a()XEeUiqIhqM|(eF0=z+ar@s|CNx&2ria&F_;#3OdIH%0MIS~7GNV`d@ zeMr!wo=$JhaN*bO_dj-CaQ=U3-FSq=wsssL2?7drP5RJev*iZ;*DCQ}=;&a+p|2#} z;433EH}=vztR_+xaTiQ|%ks-s3`xYH3bIHiHcZ=xd)#r-{m%Q^G=l8U5i^?W;dY57 z+7awIt)yrf_TjCIRTdl_uf5;BA0w+(SI?ZZgiwFvr$M4~`0Hb7J1l=|dX2aWJ|%@y zVD;qmcEg9$?YIFC9D>K+^UQN&6{D@4r{bq1h|NPJ(R{!6Abb1k=0e>}U;hHzeghV1 zoD^}rHtEhjuygx1Q)_2iU688`DX8#xV-aD$Pty>=s0%8NCNhc~O9h7FF z#6}Yl0R^N*sR9B5A}u6H?+6MA2$8OWgpME(IsyXHB`6_usR>93r2RJMy?1=~c+PLU z=YH>dzkA>D-9PqVWDoY*YtA*-oX@k?+HWY7cLq7wx&C9FMBV|Ns zKR26rm*SrrhA)+n_@mAcPT#TSM%HlE1m5LQ0U@JTqS)`64~zZp@!!2nkzg#yDbE>u ztQU8}o1}c$PpKxM*P<$!wKjn~ed)>ScAxarUS4wa7)=sBh!%izlNz_LRpJ+(qE6Nf zoDSMCwk+xubA*2-D2nBUK|d6A0Reh3jwf?JD(@S%Ki|T-S$6f!elt!@CtDUixuCUM zo)@F#w*tlWd_{-X?^U=IZs53d%F=*1f5=VLW8w9DkkW(V9dB1D)+@p%T|U`1)*201 zR7RglG!;v};&b$j=cN@Ffw4}JLk+37gZtYAU>l3}`(J-2es5cKu#-7z2^x>_Fkyr% zhQx;lT}+pLHcC5AI^3#~QWp`WrdQx(Qq!zoU*q$vS*W@3M_k?`LG{v`E`^mJE74Wa z#16aKn#`-6Vh@FdEuM9^9uN5%4Jy<0%n~DDpHc*DMC1v_GP5&+nQV5~1YKwGDm%rs z6zSZmk5zx@>b-|Q{QJXvb_%7Rj>m`IVvd$hA;`z8@l3VFL-~9|48A1UhPseHxL!^2 z*hstU)t?XdrVStj8;?H#*RZUtPq{OZa?D^SW)92;kS!dws~fD=cwXXajxYqXg5X*I z;lw<{4i=zgJpfq&lbmSt0G}wds3W&Dvj6!?bl879cKr^bUA{M~QiB_yb$)ZdElGqS zD#zNeOfX^KsS=nPDS-esqJ6@zCE!}zO6t=JHz;JQ>j&r{pMAQbZb_QZ(aim^#x>st*Vz7jAK|IqjkjY17W2J2P zyH9_+gq>?icKGFHQ2Zs-usg{CIo?ByG7W>^weRm8LS8D{XnFToz3w?I#v#@8yW#=s zweS6@h^c(25K9XkG!DI8hNsLfLpcsT@b^v7xF5c%XZZozKnIE7o^gC~;%$HjQanhK zK4cbvz*X?Bvf!4DQsGBAoJ1ryv=w`v*nNNeV5AK_>rfx6_}Gwd5mbUA=6b}e~hsNvCK|5#H zBcSUp;N2%5QE@Z|ii>+R0NT!2k8jP*KP}rx1U0SN65bvFKy}!4|RX&Y2@aC4mcTAj_uxfuYj(_Ak z->694D_#p`gnxq`Ea`7k=hDn*yJ$aLy5!GYCOd4{X0Uep=(mVd!fb~<&xH$@S&qAE zAL8-D_3C4YPn?z=ZjWFphBuK>QDh-Rv-bP?v$-UTX*-j~Q~0?FYqN&e7FHHc(8+71 zP_1$Ww*#{|&kixZGL1$wTW@~}s`K6=u@pIb?mS5mn48_yxn2Er+C}9_OYlvQILPsf zDKEgNF78#>aD;?FSe5!?!AFYk;aTEyM&2iN2+J8er~0a9=2jaWQwiC3S?q+$tNneZ z+>oj4bC`u_nh@<%dTPSGyUKC*-{+56!*7-Hr0P}&}Jc(!bJzsbkS|{ zWC?3YI%qH(nqBp$3rt-EBpKNYFTBY+t+5L9Wy7ofx6Tl3X@`HFWStXjma~H);ClHecJb|_*2RCH6{nN(=vXWb|}Mfy7wwEo|++}#vFJo zb=oCUGiR`5;TC=Z+dxg4&^!6!8Mp5BihZ#MSmxB(KeoD1OEi*z?%hpx4<$lK-cQo# zAkCgm2uYxdm;isUuW$fRBk?Y`2e%TAEm@x!e0(*a=)1FdeXvF3lv!KSzE%>4tr+`z zm=zGzyl962SFMR{fs*8E=%6`uF9_ZU8bdor(k2U#TyT)MtvAY$NVr-&)?mb478HG9 zrs7)at*leGBbky6QwI08Kle%IXLHysH$G0GZ3sLjZI9K!O z?|97@EAfT2v@#}+T>+YJ<5~C+vJ4fCxF5hi{=6j>6XOCGC@oLbPuEwTiQBR;ZgkS) z+MvF!pL&1gG5;J|2rljKSSJAzmIa1qBRm$C;k>1_U#f&&)uwa^T@@9{>v9`V=V_{GCwJJ)cK%GZ>W)_gKY zn8RY2Sx?yTioJT=rBStuh9-jXTI@S220V1oS1fVZB`ucm?4zIDhOU?=x6GUD z%K!q~TVi030+*eRu_yEsRSAVr@_l3fpI#ut-+KSNlk2&12g+p-1?BBw>=~WAF`MI_SFv^=pvECC3#}*>bx{p zW{|)}|1kdQ@{ik-K6c7-FWny z#Z=E$!5$Y67EEzr@)YdhBg1%pix0CV+QEpav?p*0yhF&e3o5ShT(~RLpsN0{-awVW z^r>g>7GCZ9%3mx`l4NOjXM;Tgx(O#irqQ9J*MK=z;xw1ROac>sU~M6j&LG;}!pEHw z7&~qP$wqOEhXiiZi?>F z&uV?*IbyjxL3F0Zt^z!gZ%ISGh7>mq;S<(sF4iw8dvq#TeXvtL{T(FMFW~Y|Td4C` z7q)^W1mS`_crJ>6eN}&^SG=QT@$OzF0Q(7TccN>S4+hpR*Ei&oRwrAFjVoMRKo+~q zZ611_Y_gy%{@ry))c2Gtz`IIL2LJ2sP^-~F(}h8{q+C4N0?$^qXs6UjJ(r#T~8uiM#9R=$!P||(fId8|NDP|di?@ZG`)L>euB>8xe&r&WE z*ux9z>j~ine`7Awy6&a+E-z|)LbYxueVI0u`s|ac;8>bdsF*EzCn@FKXmxs+n@`xQ zqCUk@m8#6DrNP1FtM$N?G;h2V`YF-RjeA0^H^7 z*dVyNBpZ>xS00s9nN?xlLiLSO%RukpO3xFU#>w`_e?xvMZ*)>P&yJuSGW{+yp`uZq z>X0wRML$pzX(JFjR8-g}LuzV#;El2%2$$u{WZHN4bL;v_X5tu(=?RaPll*>CICQH7ofx!B* zHsyf4e;4;dtJFglvhk|vU+*W7MAsod4}y37O1y{<_jW^=Sx0Ehq;p23I|SQSjCg2? zOo-E{smZM_wWI6q$>WtjbT4$xYweC@`)TnAoz7hc;6E;HSzKc9-H+bOWL;;f$~e-7 z!cC1>X*>ec9@02@nV{H4JL#(I2rXSYcT(>ze~e@;pQ&y2aa;Za&-NXdD_PwaOdQ0I z#km81-~l=^{ag%8iO8wVT#)I)&2{QW%E_b@J!zZUT4F}$vdmzGZ^)Zlu`Q z(t^__ap3NZ_**SeY0@3czyAluE%V(K*)3_al4+(hx`}p{@exN3^jhTvNqrl?J86-j z`q6hGXy$BPxWS8ASRO|+D7q5F$QZP@e^r$qSnvarcM@w<6}@)+DpT4q%}N!EJjDU5(a~W)id)yKkM~k^6YY(n0CC?f6f>X8?F*dheA1{$Cmz(R zc5HW?v6o1G_0#8T&Rei5vIT8;e^Qv5NE7~n;DG7pShSasLh zt9-tltdOG+JN0x1QO&!0e+q9gqrE~vQ7%%S!FfN|vArBkojgAJUdgO-Lh!Jv--}MZ zjS;htJr$}!42(zl+$0!Q!8JGFC-4PfWMw#3z)maBy)`PgvqZ_3RgKqB7PJ4SmaPYu zBQ1cTJ)o1qb9g#*cWh;AYCROoy1=_z(IHZ6DZPMf0Jx?8Pkj2qq!IPX2j~t`yau8SfJ$at!O`EtX)DG9W+(AZwMfc zRi@1ekzm2c((6Yl>_f6@A14C5osRQ%_{BDld6wMOui!a#f8$MT?)l@s*wrwyF6vfmzcbWK|Oczu`U}MBG>do~{I;|6lF9A~e*j zQ1DMkHiQfIX?o4dsUqtu3s#jCV=0pEn6Bv$bv2<{Nl>sdWpUE}rL>a$lNlD}W%RLn zU3@DJOyPdssi8uxR+IOdWtOir$=ZP0Q`0XE(ntt^bUwS2-C#r+^esz@_c?etK8Ys`dwm&U5#l1YqHJP zdzVi(e|Qnofmvq@V+ZE6fdwg*3@ORSfrWhcbz3=Oi0WGNrnMLS`Da<@RsB4d#w`^Grdj7CIWdTA}z`?jdL}oNF=FTKXDZJ-k9Vl;a#mt}+9)%3IsQ>|k;%N!9M{ zS1q0Ch6LhM;7wVu^Q2yUh#3GKFZv>^2`mX}e}Rs22|T%9S6ps48Xsv3^*h|n5qX(U z)Z>VmEfZru!pS|(e++O9B(csg+DTGoTir_f`{b0|{kd6x_aR1_H@l zn&BxV2f*Aze45bX0c{%c8BJMC1d)hB=SG>~)oUn4r?mp^5Ic#rZde-Js$Pq;n1IRp_pA;)GChKh>*r0nWoZ~yxQvVUb&FD^j=Co|nvk3*Z10_Sm zFC_hGSGLV5`BlVgk^&^s9P+f%LXe$fanM5cOQ4eWyiE9M(<4FpXJiaR^~*jurOmJ8<>|)_;>Fsn!MXhtl^YG9YV?6Xx6^uftP_;0wRC=quG59 z*NzOnuzXgwpXq5*?&-!2LVu^M4^f<&P%k}$j?6k*)-ZNYC8aJrG3UVJBI$sSn_`19 zdYrnPkrPrAw<8`_`@LpI7j3%J4t3E%rwyl3yL8YX;%E6qvd`3Z+j+PwMGBwVen7_J zMnb#4RY5`Z`{T*4c@1TlN6KD(=K|RmuFc5AAeQ#M~a-Rf2EmU zIx;w+Utt8xk1MtnNjbDllqab8%= zM-Ah*_LwVYu0$L^NPm{_4Vh}C4Nl5XW8s3n)tjAI5M0K|$JNF49L6=Tyg|>)OG>&& zNMWC7_%)em#t?p+yQ~(}M6@k5X!0zzOyfKWY&9rnKM3btO6kqks(GG!$+q^n+qTJm zgDscsE>sc1c0JM){smd-kWb*kfm^Hu0q@UTuWCmaUwZ!F*nboM{I%?pe38NP92+6E zJ(1(VIbohhUZM_>+zB(S;BrR_H`h!xlHhZF#I>_6&SXR>%Ju!V#IA*#{ai_FY1&*z z6xN!VL^MGGh`o;xByFfUkQD~Nm%sk;0?}*&nN(>QdS_HG7X#!0W18+m)jgUeV zD^g7!G=YI)Fn{2>x>BWTcBDH=%p`!y$TwH*?K_-$Xpz(mBDt?7kc~CT#uROm{Cmm; zJTcz|k8RD8tg249JA8tCaY-Qm^A}a^L&wDO&T4lpr|tyLodfx!DcrWLlj?+s)lIxh zGy2F@lp183ox>OQ!^4?_Q)Kk;k9F6ze9NPr)q~gJMt_3jJQdaemX7tW6FA3}DDokg z>mJ{F1D*7Ju0KczRhCp8OwmePDH-dLh>R?Y?LX1fHM{SoqA39M^S=YSyid*SPy~pQ zVD64wfyq<+QD(W?F{eAHVy*t(n`Kz*!^h;=Z`ao zwF0k9Pk+kF-;7er;FC>ax%A}9JA_|@52wn^g*k)`I2wap`Hs&Zmf>I247&K6HZ@#d zt$eU9l~Sh(RH6F=L*~mPW&J;DRy2P*j}}8~Z-CH2nujPu)Fik-J0YeW zSyR(8?r32=9p}H)a^a<$nM3-r8HdiLB@SY>`hOe7IrpG3G~S>;O5<2PDVyv;(P|)Q zx6AVwsMS2`Qx3JdsQg67NTobfwCs`)>#BgH*~tDOq$3rO#R+-{c7T*dNWihTB6ux* z0V>57f}2)Z zdO~m#j05i&rmWY4Wm>9%VlJvz&Gw!xRp2+8|E@bDIAW=ya23@4@|gPiN+H?2aD^p% z30vN|YL8nr)(qT7n_ti#elHu>Ue#OG%6spFl$C&fzfjZ%;W^6_H(_f4o`@L+lz)gN zNh~yBBU3bl(O=ZKSo^=iGJKj*t^8Mz5q?v9uIQ>N$`LF0AgR9{*R}R`~K|s zFCIbRlBeB3;0np~%?LA%6<@At+7s48NXhtyiK#Y}gDa2oj10(@lgx9>(m;QWoGGLLMRi_}bHhqT^Ded}g9SAWgC!#>h_ zjRP7zwIV0i%G{lJ?tJA@i8sAoDxB_Fr3(^jb-~)*Mq|`!+F+L(%&G_w-|3e=R?fq{9T$GCrzf3Z#~6gOUKvqDQ6s3YBpG;ky#7{fsIOKiFRgj9y2CaJ zRuIdndpt=W9&Kn$EsG*%jbT(V*yBWxs$#ec zfs(hj5>}eY$6;#J7p847Q?l-squSA|X&-2q+TfWUGH+%@*M{rV#K%6@@$awX&W0e1 z-n?sbIflhL{+ z!>GQjJZpZk`_yo8p1g;QP8VmWmW}1pF!9&QyFHpu?s>$A89Ye->9THe+M}-2bXKJZ z-#N{`$^-awnTU4li}?6Ldwf4mJxX6?#;`P9kX36*B%C*y$$#^?_t|IMG6Lth7x++P z>5@}~k_5%*k%9&}&bU5P+EFMI;!8szVoD4`(T88AeMTSAkc9UlsvjM&NPl7?H4%vQShf;6$iYC+H+xIn!S%Lfei-%jW!Z*$5$o3bavrm8-#-Md z*v29o8wF_J&_eZIGjtF;N!5y)T7MrG2)Wx3J{oAUq1xcDPPqBT@mZ!{*yfnrub~6$lZE#=gTZBG!9ag(22!har1BS@>7mYP!6a5=}(QFf$v<- zzLZ^k-@~qaRY69|qG0>QJ;wtUeAMb3Byrd>+5E-x^y(V_35PEM8c~Y?uo}gdugAl| zzdd{{@4GJ3vJsGGay~I{Bjs-7k=u_<&-Y2^;SsAd zp@9wxQ}e=$wjmC$Jb(Q8L*90{Dzw(ZFJCt&)Ai4%SbeG~8|RveP1&{LS*hTgEFinFiAs}7sXDLNF>SBh!;z2Qb-c4s zqJPb_14M~c+V~6br$5|ZuEtRX`NquGMJIS3Gp!Q+z#+Qtl<#a@lb!dytCFDLGcMEe zU>Jn3xGoh?>-a8BCoF`o?EU2P-jtz*%c z6xj}=(IA&Ch3IIr2)^sbNbgA;SC8Rt=1V(C!`T+5&$Ui~ zG2#H2n?Z4t9B+~W-%zfTjHeG*_&9nMi0Y{^YmFq<=RNB@-TPLm`(4Q`z6sF$dVdEU z6o;;au9o3KNnm^c?pOsbj@=^t^zfFegGw;h5l)$4Md_360ugtfwARP-I-_nOTqH`c zt4g!)t{?1gLWB1B97^mINb#}pWw<1U zyk29iPuRRN3NysZPoE2ioiEv~evj+59_+Q{_wrDGRo2GMmiO^Uz!#P|Y&hB(JrO|c zB0wSm^l1BC`U*axwV(Z4Ri1zOXk+ol_s>WbjoA;5S5R}sEImgUyON~$mMOp!;xpp%p34enBt z@8dPnJOq40T6Qycm!9NJd!JL}&rW`}S(X^Qze6GRVu-aq`PTA9$F_e2k`zmmJd5vs z`-aha!SX-{J@?7LEV1OZEPfr_^_EyOk*o*8HzgP}qyXYwSr~zEc8{ckDxfXsgXX@i zmRy)|U+eGpq>euczOd#dhwZgmiZqLTp-Jv*z8y}Lp{AJhh2ZbdK^R_>EaiY0VG*U!XKekdWQd1I#NpWZ zw)ibF_!3x@Hjb`xh#{ZaLoA_~0EYK2nDuttB%uKaMt@n!}e4x9a4d8%k&gaZLt<0TzmiS{^0@viwnals+A_2_k5b$;ibMA)7l|w()jgTq_=OE zQdV(s5Q9K{lx?yIzibNRtogaVvB|R)Ec0Rv!?#%GwmS?+5KD~zS_cM{W3k4H{Q z$Jo1;AJc!7$qzRidG0p%=#aEze<-|f7qa@4?CpEVAWlP?wB?0gZZ(ga>ut!2!v*Nz zQY2Qfw(GT~y0)rMF~a#aXC{Jdl5fnk_zKP&C(r0BuQ@DMT2nQ0 zIeo+7+TAOkCiT1I%dhpghABL%Z57x}AnH={8Wkv3LmH=Ha@1^?RF()~taS=+;Nim6 z=@=+jT$Yk>>PwxHpM$o<($Xi;CsdM#Agu$<0>6M+LWm&lxyLphC*7;5Now_QVo5(9 zJq>?(*<^F~Ue@`(sqS*MT-J>^w8T&7I2SR5nrk|f&<_3zFwMx3_iDCpNawU_8$!%0 z?|fr|U)q@U9Xzx2!!wW9@Z`l8Ho7~PG=K>a>_b8mM+ovQtOhv9%KQ7-i~bI&MFxns zzR#^>2vKX(VYXFaOrDhPGTw)p;!Ji0rig#V?UgvPA?=F*a+Pr!JFZA99Qp|`(;M{= zTWY@3+aK>l!Bs0d`Imegm1N8OVSBp7wcC7|*imfp@t?sv+z6W^_(Ms)kp+)xrAp zLvv_p)`phPU1BId@$sCDF4x|Ky5g^@4;a6}#o=SvN>qnDMz9T1fmkujbGk%QgqdR_ zw_siFtSv|5-(0xO(Nia9n>_1n^NvFg+z%y5AQR}IhgQ_@=_j2IM-}*T5fcFOWA|;buOQ^lH;z5a zBk8)kuCB>ZI%9>7fvzVJUgc#(@GEQ64nt=U2RiW;O;9$0X-PE$uM*ZfCrtL672m7Q zV(~HTE>61sRF}^tE}`xb1KEG;FGN<(ioV~~`;#OniYva4&j z0GBr@5AyizypI&CA5asBpX}%!9C#?}Iukx_`XK74%zcAUj8xDo*7??^y1!fNuXZyu^*F{H}UC)MCk`%&P6cz2_%C)e5umaij!UD%xmKpd|Dg+$D_%Qa=MMnfCubfC2?Diu4AO%=(5Qr%r<5O_YF)$D7-RL7*nklYN(u;!LZ{tVE^PTOJl`HP zkJxKI+b?|J2-|_Jq9A65+xOT&+?BVO^?D8qYn|Ai?JoS;xw)nL>9E2E8=r`_t;ymq zo5rei&>z$5HUHU1@A&$E3F;Dxl)qCk8qpFQErC*d{a0`pDwGa#hwSibup!0`@km-i zQsc@W?=`?esKnH_nb0s~_6tKzIL7b(ucrK`sZQYGV}G`)A>M&lLn!ZNo`*(~tAVa| z_2K{Ohp{+zlB6jmZSPS0^7dXyj;efk#Mqyv)7rXukPdpBNT{+Xcs-ks4$jt17BTKLOD-hd-HkQ)7NuV_I2j0>)^+0gj$p5MSc&X4L;va z(j~Hw7ZSxuV6sf_8)q7*>f>;|W|3t4^4*aFi;V54$R|-&oJ!Xm8D5^;*U21n-(#zt zn_)BJDZ+srMA0Da02-9nLJ!Xq#1mX+svB!Qq#P@Y65S|&y>~54%$S_qw*y62Ya{?u zb`uqiKBUG#sA$@aXhlV(-|+7Xd&@9?WwuEAZMUxA+apOQ=I-i<{z!zrss^T>4)p0k zF#)UXc$i}#PS4N8Zs64LYx0Rlo|nhnJ{S+p9U?96%%e>gU$ZA`DAGD1ER9MO&H;$y z#8v~oKZK%x?%}Hb;-XCARWYbtyw1QmOU+08I*Boy`Qwc??!I=gV@yDL*~U?qN9)GH=Ijw)YBnYopvm}Kmq zbMo|mv{~5Y+ETMJMzHz7C9oRpGeCGupCas`5ndEUQb6EaX93IYO=sEDZ)FrM4;Jdo z*t0U7k!w21C#d*p!?*nb!k!KSwUYG=$hT!_1+cpw1+0?qZa(ml5ojaiuw|SqWidQJs&y< zDGD8VKuS49+yU7qK+x9Lf=1s{zPIN{NHf%Wu3E3z)j z>XHQGv^)kvWFiTYb$xT#BQH)kYaAma*GVBBKJdz~`aEeK7Sqoz6g{sjcqhnoA`Dx9 zDIvlRj2%-bHGM0P)5U<36w#huUF+q|I*j?Y8_EuE5lcJ*>Uu~x@als@H@`wm6o?5t zV*byWgMX__0TxU^wIg`Jlo+1ha&$F8HsoMV8fYGvIbuWU&h}rgg#!2avt(RdkiA6q ztNP@Nl#A3v7~@pGFzo6;rMlNmD;>*!@$XhLUf1l0OY-%*{R9(7BFcD(+7uP+3V_`- z9b2&^fn-vN)6-(Y9rF+pQu}*Wo>*~}MqW;%1rY5fsEKsYVlgRz4q`M)Ai1K)!L;c9 z2sB<9@+9$w^n!wcQpr>!Oho$MD{+jK7GYeMz zZzWJEbP%q3@4)k}w1x;B)HIw+6LcqP(?K~ExOEEab&YH&Ef8HBad9nBR})qPOoJM- zC>=C#7r#y0pAW`QAj%_EO>xGQ2URgOKiP z_xnB~jSQi(bkHyT{Jj)`SI`uHGQx|^``d0(^p5-QI|=zkgnv`WORtiJ;TNVoh~M?{ zR}pTZ=pYU3x7JLbzprbF-7v%skv1>%pVsuBY>epq`l`ko)MCT~;8F0g6C`yUBE0e9 zV7+dUcpLh#rJ#j$a*E+0ONEM6p;hJ=Tx-%JpYV5bWAf(qCzBN~mRq8KjJGBMJTcC$ z^oOJ&n?1CHd)p{t*lAws3wdrj=*KP87Yt%>r}odI zjSCMGz)uD=d3G*L{^c@2C+Hw%DLUx68UaCtFG6>pRHDA@Qt*Ga*8R2_vX->Bx}4Y? zP1=KOr5FAbFx2+*(LtYoa!U|nas9Mt=f&k$gak_T#RaPGH$ZO%ui5+Azbex7xp0M4 zUp+b~Utw(Q&W8LS*SaaK{1m5M^k>RdV9xr!rHSu^aT{889{o!Nf&RGoNYwx1Dy4P2 zF>RCG`0FPKR?;8&MhU=*@$gUoH8mRk@j^X+A04No?bzcqPEfOdf%sx@fMP?qlU$Pd z&Nmdw|GJz_c4%d+V&ZhOsOm=IKF`i1k4~PSvAyNIh_$znXQ)ub)XU`xq5$b0V!y)X^5wywn*v&ya*lkQHVk2PSJQLEC(MkbJjJbl23QPx=T#tEMz@nRPv@RZ ze$gv4TRq9E#uyu<7)_PPDMLjRny6KsOy3-K)_({GoNG%Y6(IVHvp@SOqI-GnsbG8# z#ElNxy`a9Ax_kmcgFs(%n}UfdT(m&#HBIte9|#19$=BfDfk@)%??~gQMo{1hBtviw zf-01iMhAs|x+3WyFzU-830g-BqW=x`lX~$-ByjH!Eo)OG5+=~Jc!L{2M^yUhpoFnS zW^RP-eaONvd{$)Csvo%bhn90`+}f*HI!If*0D%+S%h|vDb6+&1tQ5Jq1o32dky`-B z;U8Kapo0#H64!yq_IwC}kK0TBzqQMt3I6)kU}p<|T+33G>a_`w;a{8H8%qu{0Hy}I zejrI&dx`&dsi2&Mm51V#-Gpx;n4a35z1a0@+dmP1&@4R2Q2XE1czMul@BwGo;3a0uaWK{4C)A+d=#69*HgMU$rG9v{b+#BqaHY z*%DlTpfPLI;-fE2+|^wyc+_|8s7&HFX-Rg0tj5l0>V=%>uQxbNgH1xPH!KQ z$f^0$;AaAVe=ofx)i3|kymEcGjvm|fDDJnSKhnSC1VLmq!0>ixRccHB{vSwo3J3YB znfU{A8CRY>1Dv$qUBgTy^Ca%&t1`9cR!E9}qUkE2Lv7&#Krg~hzZsED^lZw$5T8d- z&-15}@8^BXzkUv`LjjB_+?iT~Se&WEQbgZF_O#s#tzM@JJ;?y{=3Tg_w}EI$gyR=L z+b(O@0I2sjUBJBn(5MWbK>zf>xYIaBk$Wn4Ku!42;#Ktl5O?mCy|NiJ@YU1C2 zMl5k>uXf@H8PNPdrxTi_ZI0M8jdZjtcK7`1IbbA~4S+Gu1;!Y8l@^GqWg%+)W?0$_ zkUvVc_y-B#v4ANCvhNTZXTjrqzfAz}tG#cke~~Mf#$QAPY$i8;2!W5U{B6#h)dY|K zge+jl&k+AB=RYE6AN1=OF^XUsM`1>PQLIT=r)gKgrpXg!1nws)G=bpux!O|MGT7om zcleQRPrf4yOi!WtN_Va@Yssgd(cR@WkZEnXeyiZQwGIHHmsJ1Kde(nB)9ycBZ0qkb z-;FWi8vug8Ttrr|x4RnS*rPRsodrV6%$vPj16gMc+r5}S`*EIBuw#Bi$bxTwh>Q@# zR{(7@%ixI>AMf#~tn!YJ`rJ0$kWx z17LryzAPvovmhbLp@ zUjO&&pP9S9#Av+}&Qe-`o6=2gyXf7}CS#;C`!P(I&-+OJQzn0brDeRu6nJGFZ#*4I zdOn>HDZ*JXrffWe;=JM}cP@2fa3$HA@6ka>rmb~(p@@Tjn${gPdv{y?ywyO12?WUu z%Z^xlFbMct6?U3j!Y{wkXA!tqv^{oL+}v>vuwPzn%GuNvz@uM(TfRZbql2cGpObG2 zr)`0k_KVZt+5|dC^yf0|*tu5hu7DDn!Wu#c#pM3-8}%7VvXvkAp+$|R?dZ}$?EvaK zVo#O>-0sC8h$Mtm2dTu3N9;b00^D*U1@Vb`5x`(^_-$HvoID-Gcn^5(;veoTZ}QUk zdWcqZP>y#2+z3H`c#LS}hxed=-mL8JHUK1BJ^$oB?X?YJVHN@2fZRmmZ1+}JvU35( z-}H6wrN7>wv;(0^ftrd~%ydG&KvJy0_zr0KI+g3a;>Pnmxd6#uBHr*JcXq&?l!PJF zKdQ?`+E9eUf6(M=e?lFi1sf0EuV#zSH6myvakZsC9vx7Booq6Ze&t@B3V_)j$z(8% z5h{;pR;Dmat&eXK9fxFKhQ&YX5YhF<9&)I6nzG;anVH|vc0X*tp>iqmI>LGYf8^7Fu+W?XGcPjs7n5l(q zpCQ9X3@DU;gc+Llk1>jjdj$HYk`sa?$nu*ye*YW#68($9e;r__)(ZA5MlL!CB1)oz z5_i1;2P=qMr?Lt_Y5SZ1W?8?#F*Yy%tI~fRWXz+LR_diTI;j5>4KfSQM6`75t*l+u zN~MFImhQdwmmA(YG5`I_{0TX##^ND$nI%f8>r`TY@H^SrQ)y96AeJt%pFCrxo7-e4 zycfJrLm0*|M!7$gu>bCZ-I1`q)LE-bLb~9LHx?aa&o<9k?HTBoQ{G=n-pSd)`n+Bk zFyAqHGvo?2K<+Se8(N6y{Jj#eea`SR_>`E(5542uI$CBy9nvu`b6_G7E~V#{um0)= zy4^{ChUkNECHOZ)Wf9B>-;0Xui=SjWhH##QC2GVTdHST3+|CQRPIM>T?;n?^MWrO~ z= zKiNBf+2r}S)s?YQ8yz{@v!5asXs2wXrxCw24a}1Z#APT8=7D#HnCRKR&&YZt`5TovADJlSPz( zF3a{at-!Op5&t4u`@~xCn@U9eVe)x#^tzUMF^Yw0EF5+Wr5(*kV0)2D}2e z(naurdXEyI+iaCR7F5-%!)vbdmrpOwhmUG&^TXdYaoiNr)~&1sRAYZN_RaO{Y6(z- zO^EsZbm_<>Utzmw%_GHmJoci;gU=t256?qoAZ(K?hz2ALvsplWlDXc*%J{~ABvg(@ z(|99TI!TV> zkIs>|sda#XFH1?})N>J!|5esHvp&&J)AwqJZf)k$K|lIN(RMC`k9!3No?8-3sW8C4 zcD<@l;{w|XSRC4TLr#MZf+diDOy^soB~X`0L4U9PO?g}d1jls&WaP!xQWjo!#69Y8)LjJG7T^^XuC^k;S}!X2QnFf^<-SS0M~c2bCFX z(?Nqe%ReqsZ&1JfcN^5d()G`*Q1HLT|G&onFLnJh(=`2~#=lQ6BO^f7&uwka?D*5W zvx#4&PD=DBo}B_+5c`P=hTW%wm`_tP)Fj{c=G@hPM|!@pX1J#G(QLM+`_);~tOq`C zIwvpPj=y}e7EF?$gJSD{b;Tpp4&$X;hGGH|qS9YiXKq|Rds$2(@s(HEeA;3E(9SC^ ztMZ``=0-4u3!j`CN@34$bxt9Kr7zqg>kq#aoJ%*T|J?b?5p@4HGsyJDeZKbV{@?IL zHf20zoY@i1QYs&vcN>hZFBh!LHXfu6L-#jAc1E%6RY|*<<@~3Aht_6Pww?Hn^B(XN zzAP#e+hoTW>;jpAuG-=eQ~S}jI8pB7L%!wZv;pwF-`PE;%3p2jSKh$Oy)yDB9U~w?sX(a zPzTnmf|Ym2xM>i7*UoMgg-Lm)WSGshJMeWYK`&mn>=GX+*sfY%3J`+gjS%CWx;%o$ z!?{dT6;2yd0k7<6R~oBGjsz%fy#vf9AKfUpd~4bK2^}PhQST<`fKHu?YpHh)X5+uy z%=GAT@pmVU0~SA0IenvGsv@tB?sP1gA9!M$IY+a!Epgd@Or;&%b}8s0Y|c0o;Yav2 zgsM7|?QWlWnt-u$xi7NvsLcI1$Ft(v4!@hPPVtJRm*sR!JK0DM7D;s7B%e+%Z`k$+ z=Rs#?vigB7BX)n1II*b~5f7T-9nIEaCti_AYopa+=P=L7mrH{{i3%u_} zG2HTASsz0@%kqMh1gOe8!Yu%2I0m5fC3qrftb@jXMe@QG_4D~+jU#jher~ZUx3#TW zbshqNDik^Qy$jZz+UJ6ENgzostYFz*k0zQgZy#%prk2Ur92N3u?JM`Z06y)3sbwcg zsiaK{A|phOj7(LgY`2=5lngEnw0~suXL_0${zUR~)Q8yp-oiR8iwWV7%G8xa0%MCx z78ibh^kdGC^oOM~jMs*fq=lok)IylZw$FtRTv-a>8jUoH4$jcW;*Uw6Et0uiihs-J zneS3m3#~4?7JzMqMr$yU&^TY1J$~IJ!E7+!mOqhER9h;@{DSBsVWE8oO+Zs2UqUR= zE$azTc8xQ>A?;cGc*|`rsISzVt1^cYD`#zUinULUs$s#P=ngea45Gl-xukow72z{0*6 zH}DG+RbOfS)cgQuWagaJk{|_r;s3OE?cq?ZZGUx;RGK8|Ad?jBB$bq$rlVwfO%ci+$Nd7ky$58bchP3g)S!wZoPHR^;~yCc+L9qx_!bfYb% zM)vup?{JzE6#M2=LA&n_8YnfrQBS>p>8;gNZP+KXCzLg(xI$a5LWC7ocT!>;mLS08 z?uza2cHR_3s27>Zgo^5(+4bsm_bJeCiw+ARuIkT1M>ez&a|K>qTwGi~G5>y~`tf%? z@%SQNOG_KV$>XPio+KVlsDc;W(MEu0A1C1uxqS~tc56QB+f`k8d6kckr|1cPDYX8e z+(piBb+ZJ$6zgg8&bmhz_V%|MaN8xF2eQiSf8~Y;bar ztnmtc*MZRa_d7c;41!z>YO6JWp~)*h>mA-ww)Hi)ZeEJg>h9y&A*qH3NukzcA^Alr z#v3!(xMo2`aY0H^aN_2ECxw1*+kvXrNnn}Dv@R)XsM09XyX_zq?_Ez`239ptooUlj z?ku5tg2Y%=g_s`|YjGuin=5EqU9OHaKs8$=EpM2Cg%n zxrPfz<3rJbPm6 z^Tiu7J+9=-MXhbO@!V6h`@IL>rE)oQRui@JQIcgpXP_|quFa>Sr5=2@y zAkyMx)Zmr|E%?x149fZcGOze~bf?SPa@yZhH-{b~3#dU3c1tmPuKK(m^}0 z4(z6h!-o-IT(^Wz6{@hJNm4>S%8K-3hfC zkA}qA*H2h|Do`ZW_5^Ca&fMoqk>9Y`Zv6zkhn9T|)qEd+el;muJNH6jR*B&P%?v_R z!bK+aKvsXWCi^@m<%zphl3_HPHkait--wqeFE5AhY;H7BlZer-SIE=dHtXP6ZpU{@y@9{!7h}4n+kC=^<-laAU%%W;5&UAdiJfiDgPhKtZ#Xi z`rl=vbNE&80-Q&tzwt|O9<0q^5PV!Z#m?eK33*bUBX^0O%maUwtvQW31t$s5ztqvV zdQJ@^>wjiMSFC9fx<$P|B4mAB-S%{u>6qG(ch16p$qENq;hir1{T1-8#zu?!f&)@| zix0hTSZQN(=){R*D~~MM3q*>zji94P6s&bs}id1+HYO6s7|HLu2WUSY&Zj0x?T*cffwMjD! zI8tZ*Q+Ya0W5Hw1)FL*KLqmXtvVx0Tjas6AkbuiWfUX76$}kPW-Vvn4zfuW8fZcj! zQ@0SnszZ}?HT2Lvhfx>G?N?V{9M9QtV%Vwd{*+gKr2Awrlf%0@vv`c-(0yIB%I`Iw z>ho1nG5*lII)}l#p*_CtSK`bLe3X_MP|fr1yczA)wF;~p`n29SZq>`VhsJ8pj2xbS z{RRp>ZKocltPNnAl0*?qGQ5)-LZ^}&L_4e zr9(wUI_`ug$+>nRvgzhqni0TyY4u8fp8^NKWHsUY2w;tMOz0A4o#2VN)ZOtK8j9z9~S0F%W38qSYUH5R#0B>tzPi^n&h+e;V z8zZma(v*mW#f4E@OgCx7u;%AeV#o`%XkoSmv=$4i1N^6#Nj` zZHWM3+Fa@t1aL`_?^LapK4~U@LtZQo)0&SJ+3A)#mPa|trTT;#^6S=TtyP#kOHm^O zu4NVALOIrzu#EWLs3TY8?i6vd;2Ld_y_~X&i(3BaoppEpX6FHw3TpLTjTD}68EfLa zG%UL_U4vyDd~jlfxrLD(G@bTWae{R+U zZ{K9GLy3a_(Rj*;vXxY|k>|rka}!lHQgu<@1=qSsWJ1iyW4D@)LquIt|!vyk8vaKeL)3gubu}CGz_1+IYI& zOu2U*9GpDtAuud|TO{;ue-d4drLvS^xv6LOBh@|_to>K36{0snM+8u=uRh3{_=JP6Y84&!)x{03 z**R*)>J>l!X*PPAMSK19BR z031i`G(kT&98w~^1-Y-uiwn#Eu#$kf94|=B+L9q4=ZLSm+@8B6fJ96&@aY-(d!?l$ za-k##O@`9;ohkA!Slk2zs8konWs0dZNWQI%)?Q|}Gl1&}O}+1KTrukKy1H?Cw2)eQ zcA(i2519=qFncHIe??6Hcm#N%Mm@1x2|K`eou^@*nS2Rvev9WI4QUA7A%Us5WC8(N z?--VO;wu%^8l%N`+H2(*c?ya_2YW4lF`ApSZl26@_=7(-&$U#>;^_y;UgBE+F@a?n zk2q}Ji2w}n01p&s(Zkf0bMKgVVDhuu*S^nX`}klJ9n`}1e?mo!Jzf{A&YhJan94mk z*T}NJu%at3;JwyQ?33+B?I};oG1m;FSqy(&ctH-2cz~{A93Ud3>)3dm3TPm#31#2! zf5cBaTRUk&DkTza-28T}N=(zSv$ZuGGua#^ryR4@Cgm1aZqNFJ57sqkX2NhRJ4YG2 z4mSpQJ7#wXe>G}tH*NMys*W7lU|v+C61C%0&31wzLFT6Zp$bZ>7P-YvaGwV!GZza} zAUtu~`_h8m598V!S*(Lr$RwJl9nfA-Egeeg}CqL%r z$Gc@T8fPhEV5$9m?uED&WiGR2GKO?S2KyCz=QcbOe=T70xgV2FdHa3L2m6MA#u*3QPw#-#*J z$yB!6Vh6WmiABQ|?*Tvp*a(o$`8&Z<**s!}^{TWW9dVi#aiQJdr1V)m9lzV^C8hCx zH~AAAe-<59n0?T9bCBw$Y_pq5%@@YUb(NDW9_j73+`YT_)WoNOV3#gh3tnKxjlFV? zDknT&VQw>6qTVE5m~eGya@$cm?ReD%lZ!GuGPRHG9hpyg>MkNg1pJ* zx1203x$eMvxjyy$_Ct_z@nQS7gv!i0&z@{srk@_*6}Vf`b7B+RcJq$0tw6kzI9v#h zF>w&bT+oJ_8pVnQYP#^6dk~6?dW|Afe}C8m6cLBPs(c(u>!&ve(24)nChF9tU%^}i zC<~4i9l%ZdpkV?E9>%tvLV*4i*)x3P&nNuqBJ8!+86=iGZ7%%l~je2 z6XRh7;5t46`IgvLkckmq0mr*hGBR@{A6wXp05pFD7|p@|Q|*&cp@DUQB$8+V}IA1N9|%@ zpP`&-DFljExD!P;@Ly;={08QNe=qkVKn8Yd7XrAuiVJCQU@Za!M;iRD*5%I*kNra1 z#W%$$NxOo!-W138hMVdkPqJt-7KWAu|5NMxFS+}V&4x6f7YHDOfs?@=miSTHKfti@ z9}4ACzUb#awOBx$41w2S#oDOnsE`HzzYDKe4s}%W`@j}?BZ(<*)j)c~f82Da*U;%~ zTIamE2vBF*Og-t*)n+DCp>vF#&PxwdDG1=&+M;rX{FJ#Hno=(S~10ToYK%`=Jt|T{$+6sry#A=`8Y2P2KjxQ(;K1c>MJYJ z;d0vqB^&N=LI50^CsVgZbtyAeUr3ivzTq>zHlugVAdSN2J=q$tFvv0XV zzOf<^I)Vhp@+k6OfxxH42_l?I!g5V96Kg;ks|uDH#(L!-0Qt&He?P%Hf=g;)k}?__ zwLwCtyDtMI#vfxw%?ww4q;-S{|cL8Jkgr9n?WzriP1T|2;pZiLKGpLJk+9_%x@B z#3Ed0YQ10xJ0(Pee;C{SnYsSduMD3-s#p(I6Fwb7?H}zzfVqO$q9bSky+or10akr( zu17Tjd`%KW082D{`e&5kntajML5xr}|FbUs%wz|Rugg5s6a+BCVT4L>8f6L+f-m$x z>)`)nF%SIOQ2z){2cVk%*C0vRC>#qs$(lo2w~4k=wJPaXe_$*6x!u7-Uzao=D`=i1 z=c9df)9li9=Lf@nGjV!>`h^+(!b*7MhakDGaTCUsCA84UbiGpg@NzU6teAM#zwoNxL2_7C|kWzM(!i}{Cqmon#D-?{oj zzB`%ot*;~aDk0yU{7+P={UP6%%t2cJ22e`@0ssRP000080DViBTESg!n_4gc03C^! zPM88JAAL)gT0(~J*>YzB0Al+C01N;C00000000000HlF}mzS6V9|j(n0ssI2)un|# delta 150826 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�t{WX^xZ7 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 d00000000000001_fmD})m;xULG?)Sa002*fY%~A> diff --git a/proposals/0471-is-isolated-flow.png b/proposals/0471-is-isolated-flow.png index 97db91af276480fdef60f67090f87904e26389c5..bdf5bb0ba8fcef956c2260bd085be3e9517bb7c2 100644 GIT binary patch delta 57613 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 z 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 z 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�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 e{oxaQ Date: Tue, 22 Apr 2025 17:37:14 -0700 Subject: [PATCH 245/505] Start SE-0479 --- proposals/0479-method-and-initializer-keypaths.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0479-method-and-initializer-keypaths.md b/proposals/0479-method-and-initializer-keypaths.md index 2315599438..a4f352978e 100644 --- a/proposals/0479-method-and-initializer-keypaths.md +++ b/proposals/0479-method-and-initializer-keypaths.md @@ -6,7 +6,7 @@ * Status: **Active Review (April 22 ... May 5, 2025)** * Implementation: [swiftlang/swift#78823](https://github.com/swiftlang/swift/pull/78823), [swiftlang/swiftsyntax#2950](https://github.com/swiftlang/swift-syntax/pull/2950), [swiftlang/swiftfoundation#1179](https://github.com/swiftlang/swift-foundation/pull/1179) * Experimental Feature Flag: `KeyPathWithMethodMembers` -* Review: ([pitch](https://forums.swift.org/t/pitch-method-key-paths/76678)) +* Review: ([pitch](https://forums.swift.org/t/pitch-method-key-paths/76678)) ([review](https://forums.swift.org/t/se-0479-method-and-initializer-key-paths/79457)) ## Introduction From 882598a72217fa8aadc091b617d544b3983e97f3 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 26 Mar 2025 11:13:26 -0700 Subject: [PATCH 246/505] OutputSpan and OutputRawSpan --- proposals/nnnn-outputspan.md | 622 +++++++++++++++++++++++++++++++++++ 1 file changed, 622 insertions(+) create mode 100644 proposals/nnnn-outputspan.md diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md new file mode 100644 index 0000000000..b1488126d7 --- /dev/null +++ b/proposals/nnnn-outputspan.md @@ -0,0 +1,622 @@ +# OutputSpan: delegate initialization of contiguous memory + +* Proposal: TBD +* Author: [Guillaume Lessard](https://github.com/glessard) +* Review Manager: TBD +* Status: **Pitch** +* Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) +* Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) +* Review: [Pitch](https://forums.swift.org/) + +[SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md +[SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md +[SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md +[SE-0467]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0467-MutableSpan.md +[PR-LifetimeAnnotations]: https://github.com/swiftlang/swift-evolution/pull/2750 +[SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md + +## Introduction + +Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. + +## Motivation + +Some standard library container types can delegate initialization of some or all of their storage to user code. Up to now, it has only been possible to do so with explicitly unsafe ways, which have also proven error-prone. The standard library provides this unsafe functionality with the closure-taking initializers `Array.init(unsafeUninitializedCapacity:initializingWith:)` and `String.init(unsafeUninitializedCapacity:initializingUTF8With:)`. + +These functions have a few different drawbacks, most prominently their reliance on unsafe types, which makes them unpalatable in security-conscious environments. We continue addressing these issues with `OutputSpan` and `OutputRawSpan`, new non-copyable and non-escapable types that manage initialization of typed and untyped memory. + +In addition to the new types, we will propose adding new API for some standard library types to take advantage of `OutputSpan` and `OutputRawSpan`, and improve upon the `Array` and `String` initializers mentioned above. + +## Proposed solution + +#### OutputSpan + +`OutputSpan` allows delegating the initialization of a type's memory, by providing access to an exclusively-borrowed view of a range of contiguous memory. `OutputSpan`'s contiguous memory consists of a prefix of initialized memory, followed by a suffix of uninitialized memory. Like `MutableSpan`, `OutputSpan` relies on two guarantees: (a) that it has exclusive access to the range of memory it represents, and (b) that the memory locations it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. `OutputSpan` performs bounds-checking on every access to preserve spatial safety. + +An `OutputSpan` provided by a container represents a mutation of that container, and is therefore an exclusive access. + +#### OutputRawSpan + +`OutputRawSpan` allows delegating the initialization of heterogeneously-typed memory, such as memory being prepared by an encoder. It makes the same safety guarantees as `OutputSpan`. + +#### Extensions to standard library types + +The standard library will provide new container initializers that delegate to an `OutputSpan`. Delegated initialization generally requires a container to perform some operations after the initialization has happened. In the case of `Array` this is simply noting the number of initialized elements; in the case of `String` this consists of validating the input. This post-processing implies the need for a scope, and we believe that scope is best represented by a closure. The `Array` initializer will be as follows: + +```swift +extension Array { + public init( + capacity: Int, + initializingWith: (_ span: inout OutputSpan) throws(E) -> Void + ) throws(E) +} +``` + +We will also extend `String` and `InlineArray` in a similar manner. + +#### `@lifetime` attribute + +Some of the API presented here must establish a lifetime relationship between a non-escapable returned value and a callee binding. This relationship will be illustrated using the `@lifetime` attribute pitched in [PR-LifetimeAnnotations]. For the purposes of this proposal, the lifetime attribute ties the lifetime of a function's return value to one of its input parameters. + +Note: The `@lifetime` attribute is not final. The eventual lifetime annotations proposal may or may not adopt this syntax. We expect that, as soon as Swift adopts a syntax do describe lifetime dependencies, the Standard Library will be modified to adopt that new syntax. + +## Detailed Design + +#### OutputSpan + +`OutputSpan` is a simple representation of a partially-initialized region of memory. It is non-copyable in order to enforce exclusive access for mutations of its memory, as required by the law of exclusivity: + +````swift +@frozen +public struct OutputSpan: ~Copyable, ~Escapable { + internal let _start: UnsafeMutableRawPointer? + public let capacity: Int + internal var _count: Int +} +```` + +The memory represented by an `OutputSpan` instance consists of `count` initialized instances of `Element`, followed by uninitialized memory with storage space for `capacity - count` additional elements of `Element`. + +```swift +extension OutputSpan where Element: ~Copyable { + /// The number of initialized elements in this `OutputSpan`. + public var count: Int { get } + + /// A Boolean value indicating whether the span is empty. + public var isEmpty: Bool { get } + + /// A Boolean value indicating whether the span is full. + public var isFull: Bool { get } + + /// The number of additional elements that can be added to this `OutputSpan` + public var freeCapacity: Int { get } // capacity - count +} +``` + +##### Single-element operations + +The basic operation supported by `OutputSpan` is appending an element. When an element is appended, the correct amount of memory needed to represent it is initialized, and the `count` property is incremented by 1. If the `OutputSpan` has no available space (`capacity == count`), this operation traps. +```swift +extension OutputSpan where Element: ~Copyable { + /// Append a single element to this `OutputSpan`. + @lifetime(self: copy self) + public mutating func append(_ value: consuming Element) +} +``` +The converse operation `removeLast()` is also supported, and returns the removed element if `count` was greater than zero. +```swift +extension OutputSpan where Element: ~Copyable { + /// Remove the last initialized element from this `OutputSpan`. + @discardableResult + @lifetime(self: copy self) + public mutating func removeLast() -> Element? +} +``` + +##### Bulk initialization of an `OutputSpan`'s memory: + +We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from known-sized sources (such as `Collection` or `Span`) uses every element of the source. It is an error to do so when the available storage of the `OutputSpan` is too little to contain every element from the source. Initializing an `OutputSpan` from `Sequence` or `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. + +```swift +extension OutputSpan { + /// Initialize this span's suffix to the repetitions of the given value. + @lifetime(self: copy self) + public mutating func append(repeating repeatedValue: Element, count: Int) + + /// Initialize this span's suffix with the elements from the source. + /// + /// Returns true if the iterator has filled all the free capacity in the span. + @discardableResult + @lifetime(self: copy self) + public mutating func append( + from source: inout some IteratorProtocol + ) -> Bool + + /// Initialize this span's suffix with every element of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: some Sequence + ) + + /// Initialize this span's suffix with every element of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: Span + ) + + /// Initialize this span's suffix with every element of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: UnsafeBufferPointer + ) +} + +extension OutputSpan where Element: ~Copyable { + /// Initialize this span's suffix by moving every element from the source. + @lifetime(self: copy self) + public mutating func moveAppend( + fromContentsOf source: inout OutputSpan + ) + + /// Initialize this span's suffix by moving every element from the source. + @lifetime(self: copy self) + public mutating func moveAppend( + fromContentsOf source: UnsafeMutableBufferPointer + ) +} + +extension OutputSpan { + /// Initialize this span's suffix by moving every element from the source. + @lifetime(self: copy self) + public mutating func moveAppend( + fromContentsOf source: Slice> + ) +} +``` + +A bulk operation to deinitialize all of an `OutputSpan`'s memory is also available: +```swift +extension OutputSpan where Element: ~Copyable { + /// Remove all this span's elements and return its memory to the uninitialized state. + @lifetime(self: copy self) + public mutating func removeAll() +} +``` + +##### Accessing an `OutputSpan`'s initialized memory: + +The initialized elements are accessible for read-only or mutating access via the `span` and `mutableSpan` properties: + +```swift +extension OutputSpan where Element: ~Copyable { + /// Borrow the underlying initialized memory for read-only access. + public var span: Span { + @lifetime(borrow self) borrowing get + } + + /// Exclusively borrow the underlying initialized memory for mutation. + public mutating var mutableSpan: MutableSpan { + @lifetime(&self) mutating get + } +} +``` + + + +##### Interoperability with unsafe code + +We provide a method to process or populate an `OutputSpan` using unsafe operations, which can also be used for out-of-order initialization. + +```swift +extension OutputSpan where Element: ~Copyable { + /// Call the given closure with the unsafe buffer pointer addressed by this + /// OutputSpan and a mutable reference to its count of initialized elements. + /// + /// This method provides a way to process or populate an `OutputSpan` using + /// unsafe operations, such as dispatching to code written in legacy + /// (memory-unsafe) languages. + /// + /// The supplied closure may process the buffer in any way it wants; however, + /// when it finishes (whether by returning or throwing), it must leave the + /// buffer in a state that satisfies the invariants of the output span: + /// + /// 1. The inout integer passed in as the second argument must be the exact + /// number of initialized items in the buffer passed in as the first + /// argument. + /// 2. These initialized elements must be located in a single contiguous + /// region starting at the beginning of the buffer. The rest of the buffer + /// must hold uninitialized memory. + /// + /// This function cannot verify these two invariants, and therefore + /// this is an unsafe operation. Violating the invariants of `OutputSpan` + /// may result in undefined behavior. + @lifetime(self: copy self) + public mutating func withUnsafeMutableBufferPointer( + _ body: ( + UnsafeMutableBufferPointer, + _ initializedCount: inout Int + ) throws(E) -> R + ) throws(E) -> R +} +``` + + + +##### Creating an `OutputSpan` instance: + +Creating an `OutputSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized instances of `Element`, and the second region is uninitialized. The number of initialized instances is passed to the `OutputSpan` initializer through its `initializedCount` argument. + +```swift +extension OutputSpan where Element: ~Copyable { + /// Unsafely create an OutputSpan over partly-initialized memory. + /// + /// The memory in `buffer` must remain valid throughout the lifetime + /// of the newly-created `OutputSpan`. Its prefix must contain + /// `initializedCount` initialized instances, followed by uninitialized + /// memory. + /// + /// - Parameters: + /// - buffer: an `UnsafeMutableBufferPointer` to be initialized + /// - initializedCount: the number of initialized elements + /// at the beginning of `buffer`. + @unsafe + @lifetime(borrow buffer) + public init( + buffer: UnsafeMutableBufferPointer, + initializedCount: Int + ) + + /// Create an OutputSpan with zero capacity + @lifetime(immortal) + public init() +} + +extension OutputSpan { + /// Unsafely create an OutputSpan over partly-initialized memory. + /// + /// The memory in `buffer` must remain valid throughout the lifetime + /// of the newly-created `OutputSpan`. Its prefix must contain + /// `initializedCount` initialized instances, followed by uninitialized + /// memory. + /// + /// - Parameters: + /// - buffer: an `UnsafeMutableBufferPointer` to be initialized + /// - initializedCount: the number of initialized elements + /// at the beginning of `buffer`. + @unsafe + @lifetime(borrow buffer) + public init( + buffer: borrowing Slice>, + initializedCount: Int + ) +} +``` + + + +##### Retrieving initialized memory from an `OutputSpan` + +Once memory has been initialized using `OutputSpan`, the owner of the memory must consume the `OutputSpan` in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps. `finalize()` consumes the `OutputSpan` instance and returns the number of initialized elements. + +```swift +extension OutputSpan where Element: ~Copyable { + /// Consume the OutputSpan and return the number of initialized elements. + /// + /// Parameters: + /// - buffer: The buffer being finalized. This must be the same buffer as used to + /// initialize the `OutputSpan` instance. + /// Returns: The number of elements that were initialized. + @unsafe + public consuming func finalize( + for buffer: UnsafeMutableBufferPointer + ) -> Int +} + +extension OutputSpan { + /// Consume the OutputSpan and return the number of initialized elements. + /// + /// Parameters: + /// - buffer: The buffer being finalized. This must be the same buffer as used to + /// initialize the `OutputSpan` instance. + /// Returns: The number of bytes that were initialized. + @unsafe + public consuming func finalize( + for buffer: Slice> + ) -> Int +} +``` + + + + +#### `OutputRawSpan` +`OutputRawSpan` is similar to `OutputSpan`, but represents an untyped partially-initialized region of memory. Its API supports appending the bytes of instances of `BitwiseCopyable` types, as well as a variety of bulk initialization operations. +```swift +@frozen +public struct OutputRawSpan: ~Copyable, ~Escapable { + internal var _start: UnsafeMutableRawPointer? + public let capacity: Int + internal var _count: Int +} +``` + +The memory represented by an `OutputRawSpan` contains `byteCount` initialized bytes, followed by uninitialized memory. + +```swift +extension OutputRawSpan { + /// The number of initialized bytes in this `OutputRawSpan` + public var byteCount: Int { get } + + /// A Boolean value indicating whither the span is empty. + public var isEmpty: Bool { get } + + /// A Boolean value indicating whither the span is full. + public var isFull: Bool { get } + + /// The nmuber of uninitialized bytes remaining in this `OutputRawSpan` + public var available: Int { get } // capacity - byteCount +} +``` + + + +##### Appending to `OutputRawSpan` + +The basic operation is to append the bytes of some value to an `OutputRawSpan`: +```swift +extension OutputRawSpan { + /// Appends the given value's bytes to this span's initialized bytes + @lifetime(self: copy self) + public mutating func appendBytes( + of value: T, as type: T.Type + ) +} +``` + +This is also supported with bulk operations. Initializing an `OutputRawSpan` from known-sized sources (such as `Collection` or `Span`) uses every element of the source. It is an error to do so when the available storage of the `OutputRawSpan` is too little to contain every element from the source. Initializing an `OutputRawSpan` from `Sequence` or `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputRawSpan` has too few bytes available to store another element. +```swift +extension OutputRawSpan + /// Initialize this span's suffix to the repetitions of the given value's bytes. + @lifetime(self: copy self) + public mutating func append(repeating repeatedValue: T, count: Int) + + /// Initialize the span's bytes with the bytes of the elements of the source. + /// + /// Returns true if the iterator has filled all the free capacity in the span. + @lifetime(self: copy self) + public mutating func append( + from source: inout some IteratorProtocol + ) -> Bool + + /// Initialize the span's bytes with every byte of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: some Sequence + ) + + /// Initialize the span's bytes with every byte of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: Span + ) + + /// Initialize the span's bytes with every byte of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: RawSpan + ) + + /// Initialize the span's bytes with every byte of the source. + @lifetime(self: copy self) + public mutating func append( + fromContentsOf source: UnsafeRawBufferPointer + ) +} +``` + +An `OutputRawSpan`'s initialized memory is accessible for read-only or mutating access via the `bytes` and `mutableBytes` properties: + +```swift +extension OutputRawSpan { + /// Borrow the underlying initialized memory for read-only access. + public var bytes: RawSpan { + @lifetime(borrow self) borrowing get + } + + /// Exclusively borrow the underlying initialized memory for mutation. + public var mutableBytes: MutableRawSpan { + @lifetime(&self) mutating get + } +} +``` + + + +##### Interoperability with unsafe code + +We provide a method to process or populate an `OutputRawSpan` using unsafe operations, which can also be used for out-of-order initialization. + +```swift +extension OutputRawSpan { + /// Call the given closure with the unsafe buffer pointer addressed by this + /// OutputRawSpan and a mutable reference to its count of initialized bytes. + /// + /// This method provides a way to process or populate an `OutputRawSpan` using + /// unsafe operations, such as dispatching to code written in legacy + /// (memory-unsafe) languages. + /// + /// The supplied closure may process the buffer in any way it wants; however, + /// when it finishes (whether by returning or throwing), it must leave the + /// buffer in a state that satisfies the invariants of the output span: + /// + /// 1. The inout integer passed in as the second argument must be the exact + /// number of initialized bytes in the buffer passed in as the first + /// argument. + /// 2. These initialized elements must be located in a single contiguous + /// region starting at the beginning of the buffer. The rest of the buffer + /// must hold uninitialized memory. + /// + /// This function cannot verify these two invariants, and therefore + /// this is an unsafe operation. Violating the invariants of `OutputRawSpan` + /// may result in undefined behavior. + @lifetime(self: copy self) + public mutating func withUnsafeMutableBytes( + _ body: ( + UnsafeMutableRawBufferPointer, + _ initializedCount: inout Int + ) throws(E) -> R + ) throws(E) -> R +} +``` + + + +##### Creating `OutputRawSpan` instances + +Creating an `OutputRawSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized bytes, and the second region is uninitialized. The number of initialized bytes is passed to the `OutputRawSpan` initializer through its `initializedCount` argument. + +```swift +extension OutputRawSpan { + + /// Unsafely create an OutputRawSpan over partly-initialized memory. + /// + /// The memory in `buffer` must remain valid throughout the lifetime + /// of the newly-created `OutputRawSpan`. Its prefix must contain + /// `initializedCount` initialized bytes, followed by uninitialized + /// memory. + /// + /// - Parameters: + /// - buffer: an `UnsafeMutableBufferPointer` to be initialized + /// - initializedCount: the number of initialized elements + /// at the beginning of `buffer`. + @unsafe + @lifetime(borrow buffer) + public init( + buffer: UnsafeMutableRawBufferPointer, + initializedCount: Int + ) + + /// Create an OutputRawSpan with zero capacity + @lifetime(immortal) + public init() + + /// Unsafely create an OutputRawSpan over partly-initialized memory. + /// + /// The memory in `buffer` must remain valid throughout the lifetime + /// of the newly-created `OutputRawSpan`. Its prefix must contain + /// `initializedCount` initialized bytes, followed by uninitialized + /// memory. + /// + /// - Parameters: + /// - buffer: an `UnsafeMutableBufferPointer` to be initialized + /// - initializedCount: the number of initialized elements + /// at the beginning of `buffer`. + @unsafe + @lifetime(borrow buffer) + public init( + buffer: Slice, + initializedCount: Int + ) +} +``` + +##### Retrieving initialized memory from an `OutputRawSpan` + +Once memory has been initialized using `OutputRawSpan`, the owner of the memory must consume the instance in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputRawSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps. `finalize()` consumes the `OutputRawSpan` instance and returns the number of initialized bytes. + +```swift +extension OutputRawSpan { + /// Consume the OutputRawSpan and return the number of initialized bytes. + /// + /// Parameters: + /// - buffer: The buffer being finalized. This must be the same buffer as used to + /// create the `OutputRawSpan` instance. + /// Returns: The number of initialized bytes. + @unsafe + public consuming func finalize( + for buffer: UnsafeMutableRawBufferPointer + ) -> Int + + /// Consume the OutputRawSpan and return the number of initialized bytes. + /// + /// Parameters: + /// - buffer: The buffer being finalized. This must be the same buffer as used to + /// create the `OutputRawSpan` instance. + /// Returns: The number of initialized bytes. + @unsafe + public consuming func finalize( + for buffer: Slice + ) -> Int +} +``` + + + +#### Extensions to Standard Library types + +The standard library and Foundation will add a few initializers that enable initialization in place, intermediated by an `OutputSpan` instance, passed as a parameter to a closure: + +```swift +extension Array { + public init( + capacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) +} + +extension String { + public init( + capacity: Int, + initializingUTF8With initializer: (inout OutputSpan) throws(E) -> Void + ) + + public init?( + capacity: Int, + initializingValidUTF8With initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) +} + +extension InlineArray { + public init( + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) +} +``` + +#### Extensions to `Foundation.Data` + +While the `swift-foundation` package and the `Foundation` framework are not governed by the Swift evolution process, `Data` is similar in use to standard library types, and the project acknowledges that it is desirable for it to have similar API when appropriate. Accordingly, we plan to propose the following additions to `Foundation.Data`: +```swift +extension Data { + public init( + capacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) + + public init( + rawCapacity: Int, + initializingWith initializer: (inout OutputRawSpan) throws(E) -> Void + ) throws(E) +} +``` + +## Source compatibility + +This proposal is additive and source-compatible with existing code. + +## ABI compatibility + +This proposal is additive and ABI-compatible with existing code. + +## Implications on adoption + +The additions described in this proposal require a new version of the Swift standard library and runtime. + +## Future directions + +#### Helpers to initialize memory in an arbitrary order + +Some applications may benefit from the ability to initialize a range of memory in a different order than implemented by `OutputSpan`. This may be from back-to-front or even arbitrary order. There are many possible forms such an initialization helper can take, depending on how much memory safety the application is willing to give up in the process of initializing the memory. At the unsafe end, this can be delegating to an `UnsafeMutableBufferPointer` along with a set of requirements; this option is proposed here. At the safe end, this could be delegating to a data structure which keeps track of initialized memory using a bitmap. It is unclear how much need there is for this more heavy-handed approach, so we leave it as a future enhancement if it is deemed useful. + +## Acknowledgements + From 7c44259ae0fba3808bd5a7443ba078ede37a785f Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 11:25:38 -0700 Subject: [PATCH 247/505] Proposal edits --- proposals/nnnn-outputspan.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index b1488126d7..1423d3b02a 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -13,6 +13,7 @@ [SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md [SE-0467]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0467-MutableSpan.md [PR-LifetimeAnnotations]: https://github.com/swiftlang/swift-evolution/pull/2750 +[Forum-LifetimeAnnotations]: https://forums.swift.org/t/78638 [SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md ## Introduction @@ -56,9 +57,9 @@ We will also extend `String` and `InlineArray` in a similar manner. #### `@lifetime` attribute -Some of the API presented here must establish a lifetime relationship between a non-escapable returned value and a callee binding. This relationship will be illustrated using the `@lifetime` attribute pitched in [PR-LifetimeAnnotations]. For the purposes of this proposal, the lifetime attribute ties the lifetime of a function's return value to one of its input parameters. +Some of the API presented here must establish a lifetime relationship between a non-escapable returned value and a callee binding. This relationship will be illustrated using the `@lifetime` attribute recently [pitched][PR-LifetimeAnnotations] and [formalized][Forum-LifetimeAnnotations]. For the purposes of this proposal, the lifetime attribute ties the lifetime of a function's return value to one of its input parameters. -Note: The `@lifetime` attribute is not final. The eventual lifetime annotations proposal may or may not adopt this syntax. We expect that, as soon as Swift adopts a syntax do describe lifetime dependencies, the Standard Library will be modified to adopt that new syntax. +Note: The eventual lifetime annotations proposal may adopt a syntax different than the syntax used here. We expect that the Standard Library will be modified to adopt an updated lifetime dependency syntax as soon as it is finalized. ## Detailed Design @@ -434,7 +435,7 @@ extension OutputRawSpan { ##### Interoperability with unsafe code -We provide a method to process or populate an `OutputRawSpan` using unsafe operations, which can also be used for out-of-order initialization. +We provide a method to process or populate an `OutputRawSpan` using unsafe operations, which can also be used for out-of-order initialization. ```swift extension OutputRawSpan { From d0426fbf5050f094dfcde9c4052cf9d02313e9d1 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 13:09:11 -0700 Subject: [PATCH 248/505] Proposal edits, append-in-place additions --- proposals/nnnn-outputspan.md | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 1423d3b02a..cc7a18beac 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -53,7 +53,7 @@ extension Array { } ``` -We will also extend `String` and `InlineArray` in a similar manner. +We will also extend `String`, `UnicodeScalarView` and `InlineArray` with similar initializers, and add append-in-place operations where appropriate. #### `@lifetime` attribute @@ -61,7 +61,7 @@ Some of the API presented here must establish a lifetime relationship between a Note: The eventual lifetime annotations proposal may adopt a syntax different than the syntax used here. We expect that the Standard Library will be modified to adopt an updated lifetime dependency syntax as soon as it is finalized. -## Detailed Design +## Detailed Design #### OutputSpan @@ -563,18 +563,45 @@ extension Array { capacity: Int, initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) + + public mutating func append( + addingCapacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) } extension String { public init( - capacity: Int, + utf8Capacity: Int, initializingUTF8With initializer: (inout OutputSpan) throws(E) -> Void ) public init?( - capacity: Int, + utf8Capacity: Int, initializingValidUTF8With initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) + + public mutating func append( + addingUTF8Capacity: Int, + initializingUTF8With initializer: (inout OUtputSpan) throws(E) -> Void + ) throws(E) +} + +extension UnicodeScalarView { + public init( + utf8Capacity: Int, + initializingUTF8With initializer: (inout OutputSpan) throws(E) -> Void + ) + + public init?( + utf8Capacity: Int, + initializingValidUTF8With initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) + + public mutating func append( + addingUTF8Capacity: Int, + initializingUTF8With initializer: (inout OUtputSpan) throws(E) -> Void + ) throws(E) } extension InlineArray { From fc5b957b3adf651e2f75da244913faf0c45bc06b Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 13:52:51 -0700 Subject: [PATCH 249/505] Additions --- proposals/nnnn-outputspan.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index cc7a18beac..f7f6bca341 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -18,7 +18,7 @@ ## Introduction -Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. +Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. The memory represented by `OutputSpan` consists of a number of initialized elements, followed by uninitialized memory. The operations of `OutputSpan` can change the number of initialized elements in memory, unlike `MutableSpan` which always represents memory that is initialized. ## Motivation @@ -640,6 +640,14 @@ This proposal is additive and ABI-compatible with existing code. The additions described in this proposal require a new version of the Swift standard library and runtime. + +## Alternatives Considered + +#### Vending `OutputSpan` as a property + +`OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and it fits the needs of `OutputSpan` well. + + ## Future directions #### Helpers to initialize memory in an arbitrary order @@ -648,3 +656,4 @@ Some applications may benefit from the ability to initialize a range of memory i ## Acknowledgements +Thanks to Karoy Lorentey, Nate Cook and Tony Parker for their feedback. From e1340f0b4f22e8cf91555195c66b53ec6214237c Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 23 Apr 2025 17:02:08 -0400 Subject: [PATCH 250/505] Assign SE-0480 to the warning control settings proposal --- ...warning-control.md => 0480-swiftpm-warning-control.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{NNNN-swiftpm-warning-control.md => 0480-swiftpm-warning-control.md} (97%) diff --git a/proposals/NNNN-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md similarity index 97% rename from proposals/NNNN-swiftpm-warning-control.md rename to proposals/0480-swiftpm-warning-control.md index 622b8c9971..84e6d929c2 100644 --- a/proposals/NNNN-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -1,11 +1,11 @@ # Warning Control Settings for SwiftPM -* Proposal: [SE-NNNN](NNNN-swiftpm-warning-control.md) +* Proposal: [SE-0480](0480-swiftpm-warning-control.md) * Authors: [Dmitrii Galimzianov](https://github.com/DmT021) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch]([https:](https://github.com/FranzBusch) +* Status: **Active review (April 23...May 5th, 2025)** * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) -* Review: ([Pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) +* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) ## Introduction From d9828bcf036b2a360cc89411c7a8c3e7f6400e26 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 23 Apr 2025 17:11:07 -0400 Subject: [PATCH 251/505] Fix a link in the SE-0480 proposal and add the review link --- proposals/0480-swiftpm-warning-control.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 84e6d929c2..47598f0973 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -2,10 +2,10 @@ * Proposal: [SE-0480](0480-swiftpm-warning-control.md) * Authors: [Dmitrii Galimzianov](https://github.com/DmT021) -* Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch]([https:](https://github.com/FranzBusch) +* Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch](https://github.com/FranzBusch) * Status: **Active review (April 23...May 5th, 2025)** * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) -* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) +* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) ## Introduction From 9b4e4308afd7eecf08a08ecd9e80f1c14653d0fc Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 15:32:31 -0700 Subject: [PATCH 252/505] Clarify bulk-initialization contract --- proposals/nnnn-outputspan.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index f7f6bca341..462a304f41 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -116,7 +116,7 @@ extension OutputSpan where Element: ~Copyable { ##### Bulk initialization of an `OutputSpan`'s memory: -We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from known-sized sources (such as `Collection` or `Span`) uses every element of the source. It is an error to do so when the available storage of the `OutputSpan` is too little to contain every element from the source. Initializing an `OutputSpan` from `Sequence` or `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. +We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from a `Sequence` or a fixed-size source must use every element of the source. Initializing an `OutputSpan` from `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. ```swift extension OutputSpan { @@ -134,18 +134,24 @@ extension OutputSpan { ) -> Bool /// Initialize this span's suffix with every element of the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: some Sequence ) /// Initialize this span's suffix with every element of the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: Span ) /// Initialize this span's suffix with every element of the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: UnsafeBufferPointer @@ -154,12 +160,16 @@ extension OutputSpan { extension OutputSpan where Element: ~Copyable { /// Initialize this span's suffix by moving every element from the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: inout OutputSpan ) /// Initialize this span's suffix by moving every element from the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: UnsafeMutableBufferPointer @@ -168,6 +178,8 @@ extension OutputSpan where Element: ~Copyable { extension OutputSpan { /// Initialize this span's suffix by moving every element from the source. + /// + /// It is a precondition that the `OutputSpan` can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: Slice> From 61fae31fd98afc171813d85782352ee49c7c3eac Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 15:32:52 -0700 Subject: [PATCH 253/505] Add `removeLast(_: Int)` --- proposals/nnnn-outputspan.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 462a304f41..92e6012024 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -187,9 +187,14 @@ extension OutputSpan { } ``` -A bulk operation to deinitialize all of an `OutputSpan`'s memory is also available: +Bulk operations to deinitialize some or all of an `OutputSpan`'s memory is also available: ```swift extension OutputSpan where Element: ~Copyable { + /// Remove the last N elements, returning the memory they occupy + /// to the uninitialized state. + @lifetime(self: copy self) + public mutating func removeLast(_ n: Int) + /// Remove all this span's elements and return its memory to the uninitialized state. @lifetime(self: copy self) public mutating func removeAll() From cdd1c14af87e250c45c4d0992a9aa6a65df69677 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 23 Apr 2025 18:46:25 -0400 Subject: [PATCH 254/505] Wording suggestions for the weak let proposal --- proposals/NNNN-weak-let.md | 97 ++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/proposals/NNNN-weak-let.md b/proposals/NNNN-weak-let.md index e91230bd47..9acd0bce47 100644 --- a/proposals/NNNN-weak-let.md +++ b/proposals/NNNN-weak-let.md @@ -2,71 +2,87 @@ * Proposal: [SE-NNNN](NNNN-weak-let.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) -* Review Manager: TBD -* Status: **Awaiting implementation** +* Review Manager: [John McCall](https://github.com/rjmccall) +* Status: **Awaiting review** * Implementation: [swiftlang/swift#80440](https://github.com/swiftlang/swift/pull/80440) * Upcoming Feature Flag: `WeakLet` -* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) +* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) + +[SE-0302]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md ## Introduction -Currently Swift requires weak stored variables to be mutable. -This restriction is rather artificial, and causes friction with sendability checking. +Swift provides weak object references using the `weak` modifier on variables and stored properties. Weak references become `nil` when the object is destroyed, causing the value of the variable to seem to change. Swift has therefore always required `weak` references to be declared with the `var` keyword rather than `let`. However, that causes unnecessary friction with [sendability checking][SE-0302]: because weak references must be mutable, classes and closures with such references are unsafe to share between concurrent contexts. This proposal lifts that restriction and allows `weak` to be combined with `let`. ## Motivation -Currently swift classes with weak stored properties cannot be `Sendable`, -because weak properties have to be mutable, and mutable properties are -not allowed in `Sendable` classes. +Currently, Swift classes with weak stored properties cannot be `Sendable`, because weak properties have to be mutable, and mutable properties are not allowed in `Sendable` classes: -Similarly, closures with `weak` captures cannot be `@Sendable`, -because such captures are implicitly made mutable. +```swift +final class C: Sendable {} -Usually developers are not aware of this implicit mutability and have no intention to modify the captured variable. -Implicit mutability of weak captures is inconsistent with `unowned` or default captures. +final class VarUser: Sendable { + weak var ref1: C? // error: stored property 'ref1' of 'Sendable'-conforming class 'VarUser' is mutable +} +``` -Wrapping weak reference into a single-field struct, allows stored properties and captures to be immutable. +Similarly, closures with explicit `weak` captures cannot be `@Sendable`, because such captures are implicitly *made* mutable, and `@Sendable` closures cannot capture mutable variables. This is surprising to most programmers, because every other kind of explicit capture is immutable. It is extremely rare for Swift code to directly mutate a `weak` capture. ```swift -final class C: Sendable {} +func makeClosure() -> @Sendable () -> Void { + let c = C() + return { [weak c] in + c?.foo() // error: reference to captured var 'c' in concurrently-executing code + + c = nil // allowed, but surprising and very rare + } +} +``` +In both cases, allowing the weak reference to be immutable would solve the problem, but this is not currently allowed: + +```swift +final class LetUser: Sendable { + weak let ref1: C? // error: 'weak' must be a mutable variable, because it may change at runtime +} +``` + +The restriction that weak references have to be mutable is based on the idea that the reference is mutated when the referenced object is destroyed. Since it's mutated, it must be kept in mutable storage, and hence the storage must be declared with `var`. This way of thinking about weak references is problematic, however; it does not work very well to explain the behavior of weak references that are components of other values, such as `struct`s. For example, a return value is normally an immutable value, but a `struct` return value can contain a weak reference that may become `nil` at any point. + +In fact, wrapping weak references in a single-property `struct` is a viable workaround to the `var` restriction in both properties and captures: + +```swift struct WeakRef { weak var ref: C? } -final class User: Sendable { - weak let ref1: C? // error: 'weak' must be a mutable variable, because it may change at runtime - let ref2: WeakRef // ok +final class WeakStructUser: Sendable { + let ref: WeakRef // ok } func makeClosure() -> @Sendable () -> Void { let c = C() - return { [weak c] in - c?.foo() // error: reference to captured var 'c' in concurrently-executing code - c = nil // nobody does this - } return { [c = WeakRef(ref: c)] in c.ref?.foo() // ok } } ``` -Existence of this workaround shows that ban on `weak let` variables is artificial, and can be lifted. +The existence of this simple workaround is itself an argument that the prohibition of `weak let` is not enforcing some fundamentally important rule. + +It is true that the value of a `weak` variable can be observed to change when the referenced object is destroyed. However, this does not have to be thought of as a mutation of the variable. A different way of thinking about it is that the variable continues to hold the same weak reference to the object, but that the program is simply not allowed to observe the object through that weak reference after the object is destroyed. This better explains the behavior of weak references in `struct`s: it's not that the destruction of the object changes the `struct` value, it's that the weak reference that's part of the `struct` value will now return `nil` if you try to observe it. -Note that resetting weak references on object destruction is different from regular variable modification. -Resetting on destruction is implemented in a thread-safe manner, and can safely coexist with concurrent reads or writes. -But regular writing to a variable requires exclusive access to that memory location. +Note that all of this relies on the fact that the thread-safety of observing a weak reference is fundamentally different from the thread-safety of assigning `nil` into a `weak var`. Swift's weak references are thread-safe against concurrent destruction: well-ordered reads and writes to a `weak var` or `weak let` will always behave correctly even if the referenced object is concurrently destroyed. But they are not *atomic* in the sense that writing to a `weak var` will behave correctly if another context is concurrently reading or writing to that same `var`. In this sense, a `weak var` is like any other `var`: mutations need to be well-ordered with all other accesses. ## Proposed solution -Allow `weak let` declarations for local variables and stored properties. +`weak` can now be freely combined with `let` in any position that `weak var` would be allowed. -Proposal maintains status quo regarding use of `weak` on function arguments and computed properties: -* there is no valid syntax to indicate that function argument is a weak reference; -* `weak` on computed properties is allowed, but has not effect. +This proposal maintains the status quo regarding `weak` on function arguments and computed properties: +* There is no valid syntax to indicate that function argument is a weak reference. +* `weak` on computed properties is allowed, but has no effect. -Weak captures are immutable under this proposal. If mutable capture is desired, -mutable variable need to be explicit declared and captured. +An explicit `weak` capture is now immutable under this proposal, like any other explicit capture. If the programmer really needs a mutable capture, they must capture a separate `weak var`: ```swift func makeClosure() -> @Sendable () -> Void { @@ -76,31 +92,32 @@ func makeClosure() -> @Sendable () -> Void { c?.foo() c = nil // error: cannot assign to value: 'c' is an immutable capture } +} +func makeNonSendableClosure() -> () -> Void { + let c = C() weak var explicitlyMutable: C? = c // Closure cannot be @Sendable anymore return { explicitlyMutable?.foo() - explicitlyMutable = nil // but assigned is ok + explicitlyMutable = nil // ok } } ``` ## Source compatibility -Allowing `weak let` bindings is a source-compatible change -that makes previously invalid code valid. +Allowing `weak let` bindings is an additive change that makes previously invalid code valid. It is therefore perfectly source-compatible. -Treating weak captures as immutable is a source-breaking change. -Any code that attempts to write to the capture will stop compiling. +Treating weak captures as immutable is a source-breaking change. Any code that attempts to write to the capture will stop compiling. The overall amount of such code is expected to be small. +Since the captures of a closure are opaque and cannot be observed outside of the closure, changing the mutability of weak captures has no impact on clients of the closure. + ## ABI compatibility -This is an ABI-compatible change. +There is no ABI impact of this change. ## Implications on adoption -This feature can be freely adopted and un-adopted in source -code with no deployment constraints and without affecting source or ABI -compatibility. +This feature can be freely adopted and un-adopted in source code with no deployment constraints and without affecting source or ABI compatibility. From 35d81b6dc690510c24ff26a73633601fd6d69b34 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 23 Apr 2025 18:30:44 -0700 Subject: [PATCH 255/505] Clarify some requirements --- proposals/nnnn-outputspan.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 92e6012024..c642798fe3 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -108,9 +108,11 @@ The converse operation `removeLast()` is also supported, and returns the removed ```swift extension OutputSpan where Element: ~Copyable { /// Remove the last initialized element from this `OutputSpan`. + /// + /// Returns the last element. The `OutputSpan` must not be empty @discardableResult @lifetime(self: copy self) - public mutating func removeLast() -> Element? + public mutating func removeLast() -> Element } ``` @@ -135,7 +137,8 @@ extension OutputSpan { /// Initialize this span's suffix with every element of the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: some Sequence @@ -143,7 +146,8 @@ extension OutputSpan { /// Initialize this span's suffix with every element of the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: Span @@ -151,7 +155,8 @@ extension OutputSpan { /// Initialize this span's suffix with every element of the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( fromContentsOf source: UnsafeBufferPointer @@ -161,7 +166,8 @@ extension OutputSpan { extension OutputSpan where Element: ~Copyable { /// Initialize this span's suffix by moving every element from the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: inout OutputSpan @@ -169,7 +175,8 @@ extension OutputSpan where Element: ~Copyable { /// Initialize this span's suffix by moving every element from the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: UnsafeMutableBufferPointer @@ -179,7 +186,8 @@ extension OutputSpan where Element: ~Copyable { extension OutputSpan { /// Initialize this span's suffix by moving every element from the source. /// - /// It is a precondition that the `OutputSpan` can contain every element of the source. + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. @lifetime(self: copy self) public mutating func moveAppend( fromContentsOf source: Slice> @@ -192,6 +200,8 @@ Bulk operations to deinitialize some or all of an `OutputSpan`'s memory is also extension OutputSpan where Element: ~Copyable { /// Remove the last N elements, returning the memory they occupy /// to the uninitialized state. + /// + /// `n` must not be greater than `count` @lifetime(self: copy self) public mutating func removeLast(_ n: Int) From 9a796710273e66e4d6617c6e298ade368cdfc4e2 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 24 Apr 2025 12:10:27 +0900 Subject: [PATCH 256/505] add withSerialExecutor to Actor --- proposals/0471-SerialExecutor-isIsolated.md | 51 +++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index 85dbd1b3a2..d937e27773 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -135,6 +135,52 @@ The general guidance about which method to implement is to implement `isIsolatin The runtime will always invoke the `isIsolatingCurrentContext` before making attempts to call `checkIsolated`, and if the prior returns either `true` or `false`, the latter (`checkIsolated`) will not be invoked at all. +### Checking if currently isolated to some `Actor` + +We also introduce a way to obtain `SerialExecutor` from an `Actor`, which was previously not possible. + +This API needs to be scoped because the lifetime of the serial executor must be tied to the Actor's lifetime: + +```swift +extension Actor { + /// Perform an operation with the actor's ``SerialExecutor``. + /// + /// This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while + /// retaining the actor for the duration of the operation. This is to ensure the lifetime + /// of the executor while performing the operation. + @_alwaysEmitIntoClient + @available(SwiftStdlib 5.1, *) + public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) throws -> T) rethrows -> T + + /// Perform an operation with the actor's ``SerialExecutor``. + /// + /// This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while + /// retaining the actor for the duration of the operation. This is to ensure the lifetime + /// of the executor while performing the operation. + @_alwaysEmitIntoClient + @available(SwiftStdlib 5.1, *) + public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) async throws -> T) async rethrows -> T + +} +``` + +This allows developers to write "warn if wrong isolation" code, before moving on to enable preconditions in a future release of a library. This gives library developers, and their adopters, time to adjust their code usage before enabling more strict validation mode in the future, for example like this: + +```swift +func something(operation: @escaping @isolated(any) () -> ()) { + operation.isolation.withSerialExecutor { se in + if !se.isIsolatingCurrentContext() { + warn("'something' must be called from the same isolation as the operation closure is isolated to!" + + "This will become a runtime crash in future releases of this library.") + } + } +} +``` + + + +This API will be backdeployed and will be available independently of runtime version of the concurrency runtime. + ### Compatibility strategy for custom SerialExecutor authors New executor implementations should prioritize implementing `isIsolatingCurrentContext` when available, using an appropriate `#if swift(>=...)` check to ensure compatibility. Otherwise, they should fall back to implementing the crashing version of this API: `checkIsolated()`. @@ -169,7 +215,12 @@ This would be ideal, however also problematic since changing a protocol requirem In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so. +### Model the SerialExecutor lifetime dependency on Actor using `~Escapable` + +It is currently not possible to express this lifetime dependency using `~Escapable` types, because combining `any SerialExecutor` which is an `AnyObject` constrained type, cannot be combined with `~Escapable`. Perhaps in a future revision it would be possible to offer a non-escapable serial executor in order to model this using non-escapable types, rather than a `with`-style API. + ## Changelog +- added way to obtain `SerialExecutor` from `Actor` in a safe, scoped, way. This enables using the `isIsolatingCurrentContext()` API when we have an `any Actor`, e.g. from an `@isolated(any)` closure. - changed return value of `isIsolatingCurrentContext` from `Bool` to `Bool?`, where the `nil` is to be interpreted as "unknown", and the default implementation of `isIsolatingCurrentContext` now returns `nil`. - removed the manual need to signal to the runtime that the specific executor supports the new checking mode. It is now detected by the compiler and runtime, checking for the presence of a non-default implementation of the protocol requirement. From 9e6bb4ec84bfb6971fe7833e4db555a1dcf4e2f0 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Apr 2025 13:13:24 +0900 Subject: [PATCH 257/505] Mark as implemented: SE-0469-task-names Implemented, only pending a slight availability change to be done in: https://github.com/swiftlang/swift/pull/80984 --- proposals/0469-task-names.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0469-task-names.md b/proposals/0469-task-names.md index a5f1c6af62..0d1faf7de7 100644 --- a/proposals/0469-task-names.md +++ b/proposals/0469-task-names.md @@ -3,7 +3,7 @@ * Proposal: [SE-0469](0469-task-names.md) * Authors: [Konrad Malawski](https://github.com/ktoso), [Harjas Monga](https://github.com/Harjas12) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#79600](https://github.com/swiftlang/swift/pull/79600) * Review: ([pitch](https://forums.swift.org/t/pitch-task-naming-api/76115)) ([review](https://forums.swift.org/t/se-0469-task-naming/78509)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0469-task-naming/79438)) From 2d33986f412e6642fa51ba707017000cae5cc03f Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Apr 2025 13:22:21 +0900 Subject: [PATCH 258/505] Mark as implemented: 0462-task-priority-escalation-apis This was implemented and is part of 6.2 --- proposals/0462-task-priority-escalation-apis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0462-task-priority-escalation-apis.md b/proposals/0462-task-priority-escalation-apis.md index 5174719ca9..f12b6dd375 100644 --- a/proposals/0462-task-priority-escalation-apis.md +++ b/proposals/0462-task-priority-escalation-apis.md @@ -3,7 +3,7 @@ * Proposal: [SE-0462](0462-task-priority-escalation-apis.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Freddy Kellison-Linn](https://github.com/jumhyn) -* Status: **Accepted with modifications** +* Status: **Implemented (Swift 6.2)** * Implementation: https://github.com/swiftlang/swift/pull/78625 * Review: ([pitch](https://forums.swift.org/t/pitch-task-priority-escalation-apis/77702)) ([review](https://forums.swift.org/t/se-0462-task-priority-escalation-apis/77997))([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0462-task-priority-escalation-apis/78488)) From 4b882a887ed0e1c5ceb3f452404e834f1d7501fd Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Apr 2025 23:14:17 +0900 Subject: [PATCH 259/505] Use typed throws in withSerialExecutor --- proposals/0471-SerialExecutor-isIsolated.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index d937e27773..6de9754b93 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -150,7 +150,7 @@ extension Actor { /// of the executor while performing the operation. @_alwaysEmitIntoClient @available(SwiftStdlib 5.1, *) - public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) throws -> T) rethrows -> T + public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) throws(E) -> T) throws(E) -> T /// Perform an operation with the actor's ``SerialExecutor``. /// @@ -159,7 +159,7 @@ extension Actor { /// of the executor while performing the operation. @_alwaysEmitIntoClient @available(SwiftStdlib 5.1, *) - public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) async throws -> T) async rethrows -> T + public nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) async throws(E) -> T) async throws(E) -> T } ``` From 8c7b57b284689553ad25713e3b07b662c37ce90d Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 24 Apr 2025 09:01:20 -0700 Subject: [PATCH 260/505] Add future directions. --- proposals/0479-method-and-initializer-keypaths.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/0479-method-and-initializer-keypaths.md b/proposals/0479-method-and-initializer-keypaths.md index a4f352978e..0bdbef0fc6 100644 --- a/proposals/0479-method-and-initializer-keypaths.md +++ b/proposals/0479-method-and-initializer-keypaths.md @@ -170,3 +170,7 @@ This feature does not affect ABI compatibility. ## Implications on adoption This feature has no implications on adoption. + +## Future directions + +The effectful value types that are unsupported by this feature will all require new `KeyPath` types and so have been left out of this proposal. Additionally, this lack of support impacts existing key path component kinds and could be addressed in a unified proposal that resolves this gap across all key path component kinds. From aa2dfe3974078b1a4d48856802627363ba654b52 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 24 Apr 2025 09:04:30 -0700 Subject: [PATCH 261/505] Revise motivation to account for limitations. --- proposals/0479-method-and-initializer-keypaths.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0479-method-and-initializer-keypaths.md b/proposals/0479-method-and-initializer-keypaths.md index 0bdbef0fc6..22850e43ed 100644 --- a/proposals/0479-method-and-initializer-keypaths.md +++ b/proposals/0479-method-and-initializer-keypaths.md @@ -14,7 +14,7 @@ Swift key paths can be written to properties and subscripts. This proposal exten ## Motivation -Key paths to method members and their advantages have been explored in several discussions on the Swift forum, specifically to [unapplied instance methods](https://forums.swift.org/t/allow-key-paths-to-reference-unapplied-instance-methods/35582) and to [partially and applied methods](https://forums.swift.org/t/pitch-allow-keypaths-to-represent-functions/67630). Extending key paths to include reference to methods and initializers and handling them similarly to properties and subscripts will unify instance and type member access for a more consistent API. Key path methods and initializers will also enjoy all of the benefits offered by existing key path component kinds, e.g. simplify code by abstracting away details of how these properties/subscripts/methods are modified/accessed/invoked, reusability via generic functions that accept key paths to methods as parameters, and supporting dynamic invocation while maintaining type safety. +Key paths to method members and their advantages have been explored in several discussions on the Swift forum, specifically to [unapplied instance methods](https://forums.swift.org/t/allow-key-paths-to-reference-unapplied-instance-methods/35582) and to [partially and applied methods](https://forums.swift.org/t/pitch-allow-keypaths-to-represent-functions/67630). Extending key paths to include reference to methods and initializers and handling them similarly to properties and subscripts will unify instance and type member access for a more consistent API. While this does not yet encompass all method kinds, particularly those with effectful or non-hashable arguments, it lays the groundwork for more expressive, type-safe APIs. In doing so, it brings many of the benefits of existing key path components to supported methods and initializers, such as abstraction, reusability via generic functions and dynamic invocation with state type safety. ## Proposed solution From 0bac2947de068b83f51b2ef83b1783942e5655e3 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 24 Apr 2025 11:05:50 -0700 Subject: [PATCH 262/505] Extend SE-0471 review through April 29 --- proposals/0471-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index 6de9754b93..e20eecdae0 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -3,7 +3,7 @@ * Proposal: [SE-0471](0471-SerialExecutor-isIsolated.md) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Active Review (March 25...April 8, 2025)** +* Status: **Active Review (March 25...April 29, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 * Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834) From d62a69b70edd64a2b1b1f1ddefc5d7dd8f1488bc Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 24 Apr 2025 16:04:15 -0700 Subject: [PATCH 263/505] Update example. --- proposals/0479-method-and-initializer-keypaths.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0479-method-and-initializer-keypaths.md b/proposals/0479-method-and-initializer-keypaths.md index 22850e43ed..bd1db9fe2e 100644 --- a/proposals/0479-method-and-initializer-keypaths.md +++ b/proposals/0479-method-and-initializer-keypaths.md @@ -142,8 +142,8 @@ struct DynamicKeyPathWrapper { } let dynamicCalculator = DynamicKeyPathWrapper(root: Calculator()) -let subtract = dynamicCalculator.subtract -print(subtract(10)) +let power = dynamicCalculator.power +print(power(10, 2)) ``` ### Effectful value types From 7248f7b0128dd6d786e8adeb320084f1a22379b8 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Mon, 28 Apr 2025 15:57:18 +0200 Subject: [PATCH 264/505] Update 0008-exit-tests.md Updated after acceptance of proposal (with modifications) --- proposals/testing/0008-exit-tests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index 1950c173f4..6a7849b0a6 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -3,11 +3,11 @@ * Proposal: [ST-0008](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0008-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Maarten Engels](https://github.com/maartene) -* Status: **Active Review (April 10...April 21, 2025)** +* Status: **Accepted with Modifications** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/fdfc7867df4e35e29b2a24edee34ea4412ec15b0/proposals/testing/0008-exit-tests.md) -* Review: ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)), ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) +* Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0008-exit-tests/79553)) ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)), ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ## Introduction From 315b2ac314833493c1331a34aebdf87e232ef9ec Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Mon, 28 Apr 2025 19:08:10 +0200 Subject: [PATCH 265/505] [SE-0343] Fix typo (#2812) --- proposals/0343-top-level-concurrency.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0343-top-level-concurrency.md b/proposals/0343-top-level-concurrency.md index 8549c3f78b..e11e040563 100644 --- a/proposals/0343-top-level-concurrency.md +++ b/proposals/0343-top-level-concurrency.md @@ -40,7 +40,7 @@ semantic changes, potentially breaking scripts that already exist. The solutions will only apply when the top-level code is an asynchronous context. As a synchronous context, the behavior of top-level code does not -change. In order trigger making the top-level context an asynchronous context, I +change. In order to trigger making the top-level context an asynchronous context, I propose using the presence of an `await` in one of the top-level expressions. An await nested within a function declaration or a closure will not trigger the From e3864541f352cecc896fb0b24efe667fa75a4ae5 Mon Sep 17 00:00:00 2001 From: Philipp Gabriel Date: Mon, 28 Apr 2025 20:32:45 +0200 Subject: [PATCH 266/505] Update 0457-duration-attosecond-represenation.md (#2775) --- proposals/0457-duration-attosecond-represenation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0457-duration-attosecond-represenation.md b/proposals/0457-duration-attosecond-represenation.md index 6e8da7e7be..b88984362b 100644 --- a/proposals/0457-duration-attosecond-represenation.md +++ b/proposals/0457-duration-attosecond-represenation.md @@ -3,7 +3,7 @@ * Proposal: [SE-0457](0457-duration-attosecond-represenation.md) * Authors: [Philipp Gabriel](https://github.com/ph1ps) * Review Manager: [Stephen Canon](https://github.com/stephentyrone) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#78202](https://github.com/swiftlang/swift/pull/78202) * Review: ([pitch](https://forums.swift.org/t/pitch-adding-int128-support-to-duration))([review](https://forums.swift.org/t/se-0457-expose-attosecond-representation-of-duration/77249)) From 1df2060fb6da07f823c6eca0a1584263d344961c Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 28 Apr 2025 15:28:43 -0700 Subject: [PATCH 267/505] Specify the correct warning group for -Werror in SE-0458 proposal. The warning group is `StrictMemorySafety`, rather than `Unsafe`. --- proposals/0458-strict-memory-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0458-strict-memory-safety.md b/proposals/0458-strict-memory-safety.md index b9ce0f6221..dce70053c2 100644 --- a/proposals/0458-strict-memory-safety.md +++ b/proposals/0458-strict-memory-safety.md @@ -510,7 +510,7 @@ The strict memory safety mode can be enabled with the new compiler flag `-strict All of the memory-safety diagnostics produced by the strict memory safety mode will be warnings. These warnings be in the group `StrictMemorySafety` (possibly organized into subgroups) so that one can choose to escalate them to errors or keep them as warnings using the compiler flags introduced in [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md). For example, one can choose to enable the mode and make memory-safety issues errors using: ``` -swiftc -strict-memory-safety -Werror Unsafe +swiftc -strict-memory-safety -Werror StrictMemorySafety ``` ### SwiftPM integration From c336eab95dde9eb0432e52d323b6c96896c69e52 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 29 Apr 2025 11:50:53 -0500 Subject: [PATCH 268/505] Update state of ST-0010 and link to acceptance (#2816) --- proposals/testing/0010-evaluate-condition.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0010-evaluate-condition.md b/proposals/testing/0010-evaluate-condition.md index 577b991d3b..b0ac6ecbaa 100644 --- a/proposals/testing/0010-evaluate-condition.md +++ b/proposals/testing/0010-evaluate-condition.md @@ -3,10 +3,10 @@ * Proposal: [ST-0010](0010-evaluate-condition.md) * Authors: [David Catmull](https://github.com/Uncommon) * Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) -* Status: **Active review (April 11...April 22, 2025)** +* Status: **Accepted** * Bug: [swiftlang/swift-testing#903](https://github.com/swiftlang/swift-testing/issues/903) * Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909) -* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)) ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)) +* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)), ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)), ([acceptance](https://forums.swift.org/t/accepted-st-0010-public-api-to-evaluate-conditiontrait/79577)) ## Introduction From 9c5318ce7e2d860122265d6709444d1e1b7c87f1 Mon Sep 17 00:00:00 2001 From: Mykola Pokhylets Date: Wed, 30 Apr 2025 14:11:25 +0200 Subject: [PATCH 269/505] Added a note about optional type --- proposals/NNNN-weak-let.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/NNNN-weak-let.md b/proposals/NNNN-weak-let.md index 9acd0bce47..feacf3f02f 100644 --- a/proposals/NNNN-weak-let.md +++ b/proposals/NNNN-weak-let.md @@ -77,6 +77,7 @@ Note that all of this relies on the fact that the thread-safety of observing a w ## Proposed solution `weak` can now be freely combined with `let` in any position that `weak var` would be allowed. +Similar to `weak var`, `weak let` declarations also must be of `Optional` type. This proposal maintains the status quo regarding `weak` on function arguments and computed properties: * There is no valid syntax to indicate that function argument is a weak reference. From c173228edff342a0841b349c10f598b533c1ccdd Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 30 Apr 2025 17:11:29 -0400 Subject: [PATCH 270/505] Assign SE-0481 to the `weak let` proposal and put it in review --- proposals/{NNNN-weak-let.md => 0481-weak-let.md} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename proposals/{NNNN-weak-let.md => 0481-weak-let.md} (98%) diff --git a/proposals/NNNN-weak-let.md b/proposals/0481-weak-let.md similarity index 98% rename from proposals/NNNN-weak-let.md rename to proposals/0481-weak-let.md index feacf3f02f..69c59ae8cf 100644 --- a/proposals/NNNN-weak-let.md +++ b/proposals/0481-weak-let.md @@ -1,11 +1,10 @@ # Feature name -* Proposal: [SE-NNNN](NNNN-weak-let.md) +* Proposal: [SE-0481](0481-weak-let.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Awaiting review** +* Status: **Active review (April 30th...May 13th, 2025)** * Implementation: [swiftlang/swift#80440](https://github.com/swiftlang/swift/pull/80440) -* Upcoming Feature Flag: `WeakLet` * Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) [SE-0302]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md From 196c7b321d210efd6cd87029eb0ac0e151a93148 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 30 Apr 2025 17:12:39 -0400 Subject: [PATCH 271/505] Name SE-0481 --- proposals/0481-weak-let.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0481-weak-let.md b/proposals/0481-weak-let.md index 69c59ae8cf..60a15f1884 100644 --- a/proposals/0481-weak-let.md +++ b/proposals/0481-weak-let.md @@ -1,4 +1,4 @@ -# Feature name +# `weak let` * Proposal: [SE-0481](0481-weak-let.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) From a87b818da018a2cd4644abe744c8f1381344f3ae Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 30 Apr 2025 15:01:52 -0700 Subject: [PATCH 272/505] Move `swift migrate` from Future Directions to Detailed Design section --- ...NNN-adoption-tooling-for-swift-features.md | 63 +++++++++++++++++-- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index 2d750e459a..3a118f1190 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -160,6 +160,63 @@ belong to a diagnostic group named after the feature. The names of diagnostic groups can be displayed alongside diagnostic messages using `-print-diagnostic-groups` and used to associate messages with features. +### `swift migrate` command + +To enable seemless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - `swift migrate` to complement the Swift compiler-side changes. + +The command would accept one or more features that have migration mode enabled and optionally a set of targets to migrate, if no targets are specified the whole package is going to be migrated to use new features. + +#### Interface + +``` +USAGE: swift migrate [] --to-feature ... + +OPTIONS: + --targets The targets to migrate to specified set of features or a new language mode. + --to-feature + The Swift language upcoming/experimental feature to migrate to. + -h, --help Show help information. +``` + +#### Use case + +``` +swift migrate --targets MyTarget,MyTest --to-feature ExistentialAny +``` + +This command would attempt to build `MyTarget` and `MyTest` targets with `ExistentialAny:migrate` feature flag, apply any fix-its associated with +the feature produced by the compiler, and update the `Package.swift` to +enable the feature(s) if both of the previous actions are successful: + +``` +.target( + name: "MyTarget", + ... + swiftSettings: [ + // ... existing settings, + .enableUpcomingFeature("ExistentialAny") + ] +) +... +.testTarget( + name: "MyTest", + ... + swiftSettings: [ + // ... existing settings, + .enableUpcomingFeature("ExistentialAny") + ] +) +``` + +In the "whole package" mode, every target is going to be updated to include +new feature flag(s). This is supported by the same functionality as `swift package add-setting` command. + +If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. `...; please add '.enableUpcomingFeature("ExistentialAny")' to `MyTarget` target manually`. + +#### Impact on Interface + +This proposal introduces a new command but does that does not interfere with existing commands. It follows the same pattern as `swift build` and `swift test` in a consistent manner. + ## Source compatibility This proposal does not affect language rules. @@ -217,12 +274,6 @@ is essential for future tools built around migration mode: Furthermore, tools can take advantage of this information by favoring and auto-applying source-compatible fix-its. -### `swift migrate` - -The Swift package manager could implement a `migrate` subcommand for interactive -review and application of migration mode output for a given set of features, -with a command-line interface similar to `git add --patch`. - ## Alternatives considered ### A distinct `-migrate` option From 777d3a385b56a7795cc7e07ca842834ac8700d7f Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 30 Apr 2025 21:25:39 -0400 Subject: [PATCH 273/505] Accept SE-0477 (#2818) --- proposals/0477-default-interpolation-values.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0477-default-interpolation-values.md b/proposals/0477-default-interpolation-values.md index 60248240ab..c880eba3b3 100644 --- a/proposals/0477-default-interpolation-values.md +++ b/proposals/0477-default-interpolation-values.md @@ -3,9 +3,9 @@ * Proposal: [SE-0477](0477-default-interpolation-values.md) * Authors: [Nate Cook](https://github.com/natecook1000) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (April 16...29, 2025)** +* Status: **Accepted with modifications** * Implementation: [swiftlang/swift#80547](https://github.com/swiftlang/swift/pull/80547) -* Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) ([review](https://forums.swift.org/t/se-0477-default-value-in-string-interpolations/79302)) +* Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) ([review](https://forums.swift.org/t/se-0477-default-value-in-string-interpolations/79302)) ([acceptance](https://forums.swift.org/t/accepted-with-modification-se-0477-default-value-in-string-interpolations/79609)) ## Introduction From 3fe4b4cccb74f1a04d1bd8bc4c583e1d7fa472c7 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 1 May 2025 19:33:38 +0900 Subject: [PATCH 274/505] Update Task.immediate proposal to new semantics --- ...k-start-synchronously-on-caller-context.md | 340 +++++++++++------- 1 file changed, 219 insertions(+), 121 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 836920fce3..93cfb85323 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -19,20 +19,16 @@ This initial delay may also be problematic for some situations where it is known Today, the only way to enter an asynchronous execution context is to create a new task which then will be scheduled on the global concurrent executor or some specific actor the task is isolated to, and only once that task is scheduled execution of it may begin. -This initial scheduling delay can be problematic in some situations where tight control over execution is required. While for most tasks the general semantics are a good choice–not risking overhang on the calling thread–we have found through experience that some UI or performance sensitive use-cases require a new kind of semantic: starting on the calling context, until a suspension occurs, and only then hopping off to another executor once the task is resumed from the suspension. +This initial scheduling delay can be problematic in some situations where tight control over execution is required. While for most tasks the general semantics are a good choice–not risking overhang on the calling thread–we have found through experience that some UI or performance sensitive use-cases require a new kind of semantic: immediately starting a task on the calling context. After a suspension happens the task will resume on the the executor as implied by the task operation's isolation, as would be the case normally. -This can be especially beneficial for tasks, which *may run to completion very quickly and without ever suspending.* +This new behavior can especially beneficial for tasks, which *may run to completion very quickly and without ever suspending.* A typical situation where this new API may be beneficial often shows up with @MainActor code, such as: ```swift -@MainActor var thingsHappened: Int +@MainActor var thingsHappened: Int = 0 -@MainActor func onThingHappened(context: Context) { - synchronousFunction() -} - -func asyncUpdateThingsHappenedCounter() async { +@MainActor func asyncUpdateThingsHappenedCounter() async { // for some reason this function MUST be async thingsHappened += 1 } @@ -40,33 +36,39 @@ func asyncUpdateThingsHappenedCounter() async { func synchronousFunction() { // we know this executes on the MainActor, and can assume so: MainActor.assumeIsolated { - // we cannot call the asynchronous function asyncUpdateThingsHappenedCounter though! + // The following would error: + // await asyncUpdateThingsHappenedCounter() + // because is it is an async call; cannot call from synchronous context } - // Proposed API: - Task.startSynchronously { - // Now we CAN call the asynchronous function below: + // Using the newly proposed Immediate Task: + let task = Task.immediate { + // Now we CAN call the asynchronous function below: await asyncUpdateThingsHappenedCounter() } + + // cannot await on the `task` since still in synchronous context } ``` -The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation, it still would not allow us to call arbitrary async functions, as we are still in a synchronous context. +The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation, but it would not allow us to call the async functions, as we are still in a synchronous context. + +The proposed `Task.immediate` API forms an async context on the calling thread/task/executor, and therefore allows us to call into async code, at the risk of overhanging on the calling executor. -The proposed `Task.startSynchronously` API forms an async context on the calling thread/task/executor, and therefore allows us to call into async code, at the risk of overhanging on the calling executor. So while this should be used sparingly, it allows entering an asynchronous context *synchronously*. +While this should be used sparingly, it allows entering an asynchronous context *synchronously*. ## Proposed solution -We propose the introduction of a new family of Task creation APIs, collectively called "start synchronously", which create a Task and use the calling thread to execute the task's "first synchronous section" right until the task suspends for the first time. +We propose the introduction of a new family of Task creation APIs collectively called "**immediate tasks**", which create a task and use the calling execution context to run the task's immediately, before yielding control back to the calling context upon encountering the first suspension point inside the immediate task. -After the suspension happens, execution yields back to an appropriate executor, and does not continue to use the caller's thread anymore. +Upon first suspension inside the immediate task, the calling executor is freed up and able to continue executing other work, including the code surrounding the creation of the immediate task. This happens specifically when when a real suspension happens, and not for "potential suspension point" (which are marked using the `await` keyword). -The canonical example for using this new API is using an unstructured task like this: +The canonical example for using this new API is using an *unstructured immediate task* like this: ```swift func synchronous() { // synchronous function // executor / thread: "T1" - let task: Task = Task.startSynchronously { + let task: Task = Task.immediate { // executor / thread: "T1" guard keepRunning() else { return } // synchronous call (1) @@ -83,17 +85,17 @@ func synchronous() { // synchronous function } ``` -The task created by the `startSynchronously` function begins running immediately _on the calling executor (and thread)_ without any scheduling delay. This new task behaves generally the same as any other unstructured task, it gets a copy of the outer context's task locals, and uses the surrounding context's base priority as its base priority as well. +The task created by the `immediate` function begins running immediately _on the calling executor (and thread)_ without any scheduling delay. This new task behaves generally the same as any other unstructured task, it gets a copy of the outer context's task locals, and uses the surrounding context's base priority as its base priority as well. -Since the task started running immediately, we're able to perform some calls immediately inside it, and potentially return early. +Since the task started running immediately, we're able to perform some calls immediately inside it, and potentially return early, without any additional scheduling delays. -If a potential suspension point does not actually suspend, we still continue running on the calling context. For example, if potential suspension point `#1` did not suspend, we still continue running synchronously until we reach potential suspension point `#2` which for the sake of discussion let's say does suspend. At this point the calling thread continues executing the scope that created the unstructured task. +If a potential suspension point does not actually suspend, we still continue running on the calling context. For example, if potential suspension point `#1` did not suspend, we still continue running synchronously until we reach potential suspension point `#2` which for the sake of discussion let's say does suspend. At this point the calling thread continues executing the code that created the unstructured task. > You can refer to the `(N)` numbers in the above snippet to follow the execution order of this example execution. Specifically, once the execution reaches (3) the calling thread stops executing the unstructured task, and continues executing at (4). Eventually, when the unstructured task is resumed, it gets woken up at (5) and continues running on some other executor and/or thread. ## Detailed design -We propose the introduction of a family of "start synchronously" task creation APIs. +We propose the introduction of a family of APIs that allow for the creation of *immediate tasks*. The most frequent use of this API is likely going to be the unstructured task one. This is because we are able to enter an asynchronous context from a synchronous function using it: @@ -101,39 +103,38 @@ The most frequent use of this API is likely going to be the unstructured task on extension Task { @discardableResult - public static func startSynchronously( - // SE-0469's proposed 'name: String? = nil' would be here if accepted + public static func immediate( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - operation: sending @escaping async throws(Failure) -> Success + @_inheritActorContext(always) operation: sending @escaping async throws(Failure) -> Success ) -> Task @discardableResult - public static func startSynchronouslyDetached( - // SE-0469's proposed 'name: String? = nil' would be here if accepted + public static func immediateDetached( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - operation: sending @escaping async throws(Failure) -> Success + @_inheritActorContext(always) operation: sending @escaping async throws(Failure) -> Success ) -> Task } ``` -We also offer the same API for all kinds of task groups. These create child tasks, which participate in structured concurrency as one would expect of tasks created by task groups. +We also introduce the same API for all kinds of task groups. These create child tasks, which participate in structured concurrency as one would expect of tasks created by task groups. ```swift extension (Throwing)TaskGroup { - - // Same add semantics as 'addTask'. - func startTaskSynchronously( - // SE-0469's proposed 'name: String? = nil' would be here + // Similar semantics as the usual 'addTask'. + func addImmediateTask( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, operation: sending @escaping () async throws -> ChildTaskResult ) - // Same add semantics as 'addTaskUnlessCancelled'. - func startTaskSynchronouslyUnlessCancelled( - // SE-0469's proposed 'name: String? = nil' would be here + // Similar semantics as the usual 'addTaskUnlessCancelled'. + func addImmediateTaskUnlessCancelled( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, operation: sending @escaping () async throws -> ChildTaskResult @@ -141,17 +142,17 @@ extension (Throwing)TaskGroup { } extension (Throwing)DiscardingTaskGroup { - // Same add semantics as 'addTask'. - func startTaskSynchronously( - // SE-0469's proposed 'name: String? = nil' would be here + // Similar semantics as the usual 'addTask'. + func addImmediateTask( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, operation: sending @escaping () async throws -> ChildTaskResult ) - // Same add semantics as 'addTaskUnlessCancelled'. - func startTaskSynchronouslyUnlessCancelled( - // SE-0469's proposed 'name: String? = nil' would be here + // Similar semantics as the usual 'addTaskUnlessCancelled'. + func addImmediateTaskUnlessCancelled( + name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: (any TaskExecutor)? = nil, operation: sending @escaping () async throws -> ChildTaskResult @@ -159,59 +160,162 @@ extension (Throwing)DiscardingTaskGroup { } ``` -The `startTaskSynchronously` function mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled. +The `addImmediateTask` function mirrors the functionality of `addTask`, unconditionally adding the task to the task group, while the `addImmediateTaskUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled. ### Isolation rules -Due to the semantics of "starting on the caller context", the isolation rules of the closure passed to `startSynchronously` need to be carefully considered. +Due to the semantics of "starting on the caller context", the isolation rules of the closure passed to `Task.immediate` need to be carefully considered. + +The isolation rules for the `immediate` family of APIs need to account for this synchronous "first part" of the execution. We propose the following set of rules to make this API concurrency-safe: -For example, the following example would not be safe, as unlike `Task.init` the task does not actually immediately become isolated to the isolation of its closure: +- The operation closure is `sending`. +- The operation closure may only specify an isolation (e.g. `{ @AnyGlobalActor in }`) + +Another significant way in which `Task.immediate` differs from the `Task.init` initializer is that the inheritance of the surrounding actor context is performed more eagerly. This is because immediate tasks always attempt to execute on the "current" executor, unlike `Task.init` which only execute on the "surrounding" actor context when the task's operation closure closes over an isolated parameter, or was formed in a global actor isolated context: ```swift -@MainActor var counter: Int = 0 +@MainActor +func alreadyDefinitelyOnMainActor() { + Task { + // @MainActor isolated, enqueue + } + Task.immediate { + // @MainActor isolated, run immediately + } +} +``` -func sayHello() { - Task { @MainActor in // ✅ ok - counter += 1 // we're isolated to the main actor immediately and may modify its state +```swift +actor Caplin { + var anything: Int = 0 + + func act() { + Task { + // nonisolated, enqueue on global concurrent executor + } + Task { + // self isolated, enqueue + self.anything // any capture of 'self' + } + + Task.immediate { // regardless of captures + // self isolated, run immediately + } } +} + +func go(with caplin: isolated Caplin) async { + Task { + // nonisolated, enqueue on global concurrent executor + } + Task { + // 'caplin' isolated, enqueue + caplin.anything // any capture of 'caplin' + } - Task.startSynchronously { @MainActor in // ❌ unsafe, must be compile time error - counter += 1 // Not actually running on the main actor at this point (!) + Task.immediate { // regardless of captures + // 'caplin' isolated, run immediately + } + } +} + +func notSpecificallyIsolatedAnywhere() { + Task { + // nonisolated, enqueue on global concurrent executor + } + + Task.immediate { + // nonisolated. + // attempt to run on current executor, + // or enqueue to global as fallback + } } } ``` -The isolation rules for the `startSynchronously` family of APIs need to account for this synchronous "first part" of the execution. We propose the following set of rules to make this API concurrency-safe: +The `Task.immediateDetached` does not inherit isolation automatically, same as it's non-immediate `Task.detached` equivalent. -- The operation closure is `sending`. -- The operation closure may only specify an isolation (e.g. `{ @MainActor in }`), if and only if already statically contained within the same isolation context. +Task group methods which create immediate child tasks do not inherit isolation automatically, although they are allowed to specify an isolation explicitly. This is the same as existing TaskGroup APIs (`addTask`). -This allows for the following pattern, where we can enter an asynchronous task context, from a synchronous function, that is _known_ to be isolated to the main actor already: +### Scheduling immediate tasks given matching current and requested isolation -```swift -@MainActor var counter: Int = 0 +The Swift concurrency runtime maintains a notion of the "current executor" in order to be able to perform executor switching and isolation checking dynamically. This information is managed runtime, and is closely related to compile time isolation rules, but it is also maintained throughout nonisolated and synchronous functions. + +Immediate tasks make use of this executor tracking to determine on which executor we're asking the task to "immediately" execute. It is possible to start an immediate task in a synchronous context, and even require it to have some specific isolation. -func asyncUpdateCounter() async { counter += 1 } +The following example invokes the synchronous `sayHello()` function from a `@MainActor` isolated function. The static information about this isolation is _lost_ by the synchronous function. And the compiler will assume, that the `sayHello()` function is not isolated to any specific context -- after all, the actual isolated context would depending on where we call it from, and we're not passing an `isolated` parameter to this synchronous function. + +By using an immediate task the runtime is able to notice that the requested, and current, executor are actually the same (`MainActor`) and therefore execute the task _immediately_ on the caller's executor _and_ with the expected `@MainActor` isolation, which is guaranteed to be correct: + +```swift +@MainActor var counterUsual = 0 +@MainActor var counterImmediate = 0 @MainActor func sayHelloOnMain() { - Task.startSynchronously { @MainActor in // ✅ ok, caller isolation is also @MainActor - await asyncUpdateCounter() - } + sayHello() // call synchronous function from @MainActor +} + +// synchronous function +func sayHello() { + // We are "already on" the main actor + MainActor.assertIsolated() - Task.startSynchronously { @OtherGlobalActor in // ❌ error: MainActor != OtherGlobalActor - await asyncUpdateCounter() + // Performs an enqueue and will execute task "later" + Task { @MainActor in + counterUsual += 1 + } + // At this point (in this specific example), `counterUsual` is still 0. + // We did not "give up" the main actor executor, so the new Task could not execute yet. + + // Execute the task immediately on the calling context (!) + Task.immediate { @MainActor in + counterImmediate += 1 } + // At this point (in this specific cexample), + // `counterImmediate` is guaranteed to == 1! } ``` -Task executors do not influence the static isolation properties of code, and thus have no impact on the isolation semantics of these APIs. In general, task executors are orthogonal to actor isolation, and while they can influence which actual executor a default actor or global async function would use to execute some piece of code they have no impact on isolation properties and therefore safety properties of a piece of code. +The difference between the use of `Task.init` and `Task.immediate` is _only_ in the specific execution ordering semantics those two tasks exhibit. + +Because we are dynamically already on the expected executor, the immediate task will not need to enqueue and "run later" the new task, but instead will take over the calling executor, and run the task body immediately (up until the first suspension point). + +This can have importand implications about the observed order of effects and task execution, so it is important for developers to internalize this difference in scheduling semantics. + +If the same `sayHello()` function were to be invoked from some execution context _other than_ the main actor, both tasks–which specify the requested isolation to be `@MainActor`–will perform the usual enqueue and "run later": + +```swift +@MainActor var counterUsual = 0 +@MainActor var counterImmediate = 0 + +actor Caplin { + func sayHelloFromCaplin() { + sayHello() // call synchronous function from Caplin + } +} + +func sayHello() { + Task { @MainActor in // enqueue, "run later" + counterUsual += 1 + } + Task.immediate { @MainActor in // enqueue, "run later" + counterImmediate += 1 + } + + // at this point, no guarantees can be made ablue the values of the `counter` variables +} +``` + +This means that a `Task.immediate` can be used to opportunistically attempt to "run immediately, if the caller matches my required isolation, otherwise, enqueue and run the task later". Which is a semantic that many developers have requested in the past, most often in relation to the `MainActor`. + +The same technique of specifying a required target isolation may be used with the new TaskGroup APIs, such as `TaskGroup/addImmediateTask`. ### Interaction with `Actor/assumeIsolated` -In [SE-0392: Custom Actor Executor](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md) we introduced the ability to dynamically recover isolation information using the `assumeIsolated` API. It can be used to dynamically recover the runtime information about whether we are executing on some specific actor. +In [SE-0392: Custom Actor Executors](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md) we introduced the ability to dynamically recover isolation information using the `Actor/assumeIsolated` API. It can be used to dynamically recover the runtime information about whether we are executing on some specific actor. -The `assumeIsolated` shares some ideas with `startSynchronously` however it is distinctly different. For example, while both APIs can effectively be used to "notice we are running on the expected actor, and therefore perform some work on its context". However, `assumeIsolated` does _not_ create a new asynchronous context, while `Task.startSynchronously` does: +The `assumeIsolated` shares some ideas with `Task/immediate` however it is distinctly different. For example, while both APIs can effectively be used to "notice we are running on the expected actor, and therefore perform some work on its context". However, `assumeIsolated` does _not_ create a new asynchronous context, while `Task.startSynchronously` does: ```swift @MainActor @@ -232,13 +336,13 @@ func synchronous() { } ``` -We can compose assumeIsolated with `startSynchronously` to ensure we synchronously start a task on the MainActor if we know we are already running on it, like this: +We can compose `assumeIsolated` with `Task.immediate` to both assert that the current execution context must the the expected actor, and form a new asynchronous task that will immediately start on that actor: ```swift func alwaysCalledFromMainActor() { // we know this because e.g. documentation, but the API wasn't annotated MainActor.assumeIsolated { // @MainActor isolated assert(num == 0) - Task.startSynchronously { @MainActor in + Task.startSynchronously { // @MainActor isolated num +=1 // ✅ ok assert(num == 1) // since we are guaranteed nothing else executed since the 'num == 0' assertion @@ -248,15 +352,50 @@ func alwaysCalledFromMainActor() { // we know this because e.g. documentation, b } ``` -The synchronously started task will not suspend and context switch until any of the called async methods does. For example, we are guaranteed that there will be no interleaved code execution between the `assert(num == 0)` in our example, and the `num += 1` inside the synchronously started task. +The immediately started task will not suspend and context switch until any of the called async methods does. For example, we are guaranteed that there will be no interleaved code execution between the `assert(num == 0)` in our example, and the `num += 1` inside the synchronously started task. After the suspension point though, there may have been other tasks executed on the main actor, and we should check the value of `num` again. -### Structured concurrency semantics +### Immediate child tasks + +Immediate child tasks tasks can be created using the various `*TaskGroup/addImmediateTask*` methods behave similarily to their normal structured child task API counterparts (`*TaskGroup/addTask*`). + +Child tasks, including immediate child tasks, do not infer their isolation from the enclosing context, and by default are `nonisolated`. + +```swift +actor Worker { + func workIt(work: Work) async { + await withDiscardingTaskGroup { + group.addImmediateTask { // nonisolated + work.synchronousWork() + } + } + } +} +``` + +While the immediate task in the above example is indeed `nonisolated` and does not inherit the Worker's explicit isolation, it will start out immediately on the Worker's executor. Since this example features _no suspension points_ in the task group child tasks, this is effectively synchronously going to execute those child tasks on the caller (`self`). In other words, this is not performing any of its work in parallel. + +If we were to modify the work to have potential suspension points like so: + +```swift +actor Worker { + func workIt(work: Work) async { + await withDiscardingTaskGroup { + group.addImmediateTask { // nonisolated + // [1] starts on caller immediately + let partialResult = await work.work() // [2] actually suspends + // [3] resumes on global executor (or task executor, if there was one set) + work.moreWork(partialResult) + } + } + } +} +``` -Synchronously started tasks behave exactly the same as their fully asynchronous equivalents. +The actual suspension happening in the `work()` call, means that this task group actually would exhibit some amount of concurrent execution with the calling actor -- the remainder between `[2]` and `[3]` would execute on the global concurrent pool -- concurrently to the enclosing actor. -In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual. +Cancellation, task locals, priority escalation, and any other structured concurrency semantics remain the same for structured child tasks automatically for unstructured tasks created using the `Task/immediate[Detached]` APIs. The only difference in behavior is where these synchronously started tasks _begin_ their execution. @@ -283,14 +422,14 @@ The dynamically asserting version would be something like this: func onSomethingHappenedAlwaysOnMainThread(something: Something) { // we "know" we are on the MainActor, however this is a legacy API that is not an 'async' method // so we cannot call any other async APIs unless we create a new task. - Task.startSynchronously { @MainActor in + Task.immediate { @MainActor in await showThingy() } } func onSomethingHappenedSometimesOnMainThread(something: Something) { // 💥 Must assert at runtime if not on main thread - Task.startSynchronously { @MainActor in + Task.immediate { @MainActor in await showThingy() } } @@ -323,7 +462,7 @@ actor Caplin { var num: Int = 0 func check() { - Task.startSynchronouslyDetached { + Task.immediateDetached { num += 1 // could be ok; we know we're synchronously executing on caller try await Task.sleep(for: .seconds(1)) @@ -336,52 +475,7 @@ actor Caplin { } ``` -### Dynamically "run synchronously if in right context, otherwise enqueue as usual" - -The proposed `startSynchronously` API is a tool to be used in performance and correctness work, and any "may sometimes run synchronously, it depends" is not a good solution to the task at hand. Because of that, we aim for this API to provide the _predictable_ behavior of running synchronously on the caller, without impacting the isolation, that can compose naturally with `assumeIsolated` that can recover dynamic into static isolation information. - -For example, we'll be able to build an API that composes the proposed `startSynchronously` with a not yet proposed but under investigation `Task/isIsolated(to: some Actor) -> Bool` API in order to offer an API that implements the semantics that some developers have been asking for a while: - -- if already dynamically isolated on the expected actor, run synchronously, -- if not, schedule a task to execute the same operation later. - -Using a combination of (a) `Task/startSynchronously`, (b) `Actor/assumeIsolated`, and some form of boolean returning the not yet proposed (c) `isIsolated` (which would be a `Bool` returning equivalent of `assumeIsolated`), we will be able to build such function by composing those more fundamental concurrency operations: - -```swift -func tryRunSynchronouslyOrAsynchronouslyOtherwise( - operation: sending @escaping () async -> Success -) -> Task { - guard let actor = operation.isolation else { - // no specific isolation, just run async - return Task { try await operation() } - } - - if Task.__current.__isIsolated(to: actor) { // (c) !!! does not exist yet !!! - // we definitely are executing on 'actor' - return actor.assumeIsolated { // (b) guaranteed to not crash - // recovered static isolation information about 'actor' - // (a) use startSynchronously with specific actor isolation - return Task.runSynchronously { - [isolated actor] in // !! does not exist yet (closure isolation control) !! - try await operation() - } - } - } else { - // we are not isolated to 'actor' and therefore must schedule a normal unstructured task - return Task { try await operation() } - } -} -``` - -Or even better we could build the same API with structured concurrency: - -```swift -func tryRunSynchronouslyOrAsynchronouslyOtherwise( - operation: sending @escaping () async throws -> Success -) async rethrows -> Success { /* same, but use TaskGroup inside */ } -``` - -### Expressing closure isolation tied to function parameter: `@isolated(to:)` +### Implementation detail: Expressing closure isolation tied to function parameter: `@isolated(to:)` The currently proposed API is working within the limitations of what is expressible in today's isolation model. It would be beneficial to be able to express the startSynchronously API if we could spell something like "this closure must be isolated to the same actor as the calling function" which would allow for the following code: @@ -409,3 +503,7 @@ public static func startSynchronously( The introduction of a hypothetical `@isolated(to:)` paired with an `isolated` `#isolation` defaulted actor parameter, would allow us to express "the *operation* closure statically inherits the exact same isolation as is passed to the isolation parameter of the startSynchronously method". This naturally expresses the semantics that the startSynchronously is offering, and would allow to _stay_ on that isolation context after resuming from the first suspension inside the operation closure. Implementing this feature is a large task, and while very desirable we are not ready yet to commit to implementing it as part of this proposal. If and when this feature would become available, we would adopt it in the startSynchronously APIs. + +### Changelog + +- Moved the alternative considered of "attempt to run immediately, or otherwise just enqueue as usual" into the proposal proper From 2add1051788c6e94cd761374724a1ddcf78b268f Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 1 May 2025 16:55:08 -0500 Subject: [PATCH 275/505] Change state of ST-0010 to Implemented (#2820) * Change state of ST-0010 to Implemented * Add second implementation PR link --- proposals/testing/0010-evaluate-condition.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0010-evaluate-condition.md b/proposals/testing/0010-evaluate-condition.md index b0ac6ecbaa..6a68caad10 100644 --- a/proposals/testing/0010-evaluate-condition.md +++ b/proposals/testing/0010-evaluate-condition.md @@ -3,9 +3,9 @@ * Proposal: [ST-0010](0010-evaluate-condition.md) * Authors: [David Catmull](https://github.com/Uncommon) * Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Bug: [swiftlang/swift-testing#903](https://github.com/swiftlang/swift-testing/issues/903) -* Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909) +* Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909), [swiftlang/swift-testing#1097](https://github.com/swiftlang/swift-testing/pull/1097) * Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)), ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)), ([acceptance](https://forums.swift.org/t/accepted-st-0010-public-api-to-evaluate-conditiontrait/79577)) ## Introduction From c3a4e6d50f314f54624eb14e8c15eddc6b91779a Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Fri, 2 May 2025 07:17:32 +0900 Subject: [PATCH 276/505] amend a few remaining startSynchronously words --- ...task-start-synchronously-on-caller-context.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 93cfb85323..75bfaec705 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -315,7 +315,7 @@ The same technique of specifying a required target isolation may be used with th In [SE-0392: Custom Actor Executors](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md) we introduced the ability to dynamically recover isolation information using the `Actor/assumeIsolated` API. It can be used to dynamically recover the runtime information about whether we are executing on some specific actor. -The `assumeIsolated` shares some ideas with `Task/immediate` however it is distinctly different. For example, while both APIs can effectively be used to "notice we are running on the expected actor, and therefore perform some work on its context". However, `assumeIsolated` does _not_ create a new asynchronous context, while `Task.startSynchronously` does: +The `assumeIsolated` shares some ideas with `Task/immediate` however it is distinctly different. For example, while both APIs can effectively be used to "notice we are running on the expected actor, and therefore perform some work on its context". However, `assumeIsolated` does _not_ create a new asynchronous context, while `Task.immediate` does: ```swift @MainActor @@ -342,7 +342,7 @@ We can compose `assumeIsolated` with `Task.immediate` to both assert that the cu func alwaysCalledFromMainActor() { // we know this because e.g. documentation, but the API wasn't annotated MainActor.assumeIsolated { // @MainActor isolated assert(num == 0) - Task.startSynchronously { // @MainActor isolated + Task.immediate { // @MainActor isolated num +=1 // ✅ ok assert(num == 1) // since we are guaranteed nothing else executed since the 'num == 0' assertion @@ -413,7 +413,7 @@ This proposal is purely ABI additive. An important use case of this API is to support calling into an actor isolated context when in a synchronous function that is dynamically already running on that actor. This situation can occur both with instance actors and global actors, however the most commonly requested situation where this shows up is synchronous handler methods in existing frameworks, and which often may have had assumptions about the main thread, and did not yet annotate their API surface with @MainActor annotations. -It would be possible to create a _dynamically asserting_ version of `Task.startSynchronously`, which does handle the happy path where indeed we "know" where we're going to be called quite well, but gives a *false sense of security* as it may crash at runtime, in the same way the `Actor/preconditionIsolated()` or `Actor/assumeIsolated` APIs do. We believe we should not add more such dynamically crashing APIs, but rather lean into the existing APIs and allow them compose well with any new APIs that should aim to complement them. +It would be possible to create a _dynamically asserting_ version of `Task.immediate`, which does handle the happy path where indeed we "know" where we're going to be called quite well, but gives a *false sense of security* as it may crash at runtime, in the same way the `Actor/preconditionIsolated()` or `Actor/assumeIsolated` APIs do. We believe we should not add more such dynamically crashing APIs, but rather lean into the existing APIs and allow them compose well with any new APIs that should aim to complement them. The dynamically asserting version would be something like this: @@ -477,12 +477,12 @@ actor Caplin { ### Implementation detail: Expressing closure isolation tied to function parameter: `@isolated(to:)` -The currently proposed API is working within the limitations of what is expressible in today's isolation model. It would be beneficial to be able to express the startSynchronously API if we could spell something like "this closure must be isolated to the same actor as the calling function" which would allow for the following code: +The currently proposed API is working within the limitations of what is expressible in today's isolation model. It would be beneficial to be able to express the immediate API if we could spell something like "this closure must be isolated to the same actor as the calling function" which would allow for the following code: ```swift @MainActor func test() { - Task.startSynchronously { /* inferred to be @MainActor */ + Task.immediate { /* inferred to be @MainActor */ num += 1 } } @@ -493,16 +493,16 @@ func test() { The way to spell this in an API could be something like this: ```swift -public static func startSynchronously( +public static func immediate( ... isolation: isolated (any Actor)? = #isolation, operation: @escaping @isolated(to: isolation) sending async throws(Failure) -> Success, ) -> Task ``` -The introduction of a hypothetical `@isolated(to:)` paired with an `isolated` `#isolation` defaulted actor parameter, would allow us to express "the *operation* closure statically inherits the exact same isolation as is passed to the isolation parameter of the startSynchronously method". This naturally expresses the semantics that the startSynchronously is offering, and would allow to _stay_ on that isolation context after resuming from the first suspension inside the operation closure. +The introduction of a hypothetical `@isolated(to:)` paired with an `isolated` `#isolation` defaulted actor parameter, would allow us to express "the *operation* closure statically inherits the exact same isolation as is passed to the isolation parameter of the `immediate` method". This naturally expresses the semantics that the `immediate` is offering, and would allow to _stay_ on that isolation context after resuming from the first suspension inside the operation closure. -Implementing this feature is a large task, and while very desirable we are not ready yet to commit to implementing it as part of this proposal. If and when this feature would become available, we would adopt it in the startSynchronously APIs. +Implementing this feature is a large task, and while very desirable we are not ready yet to commit to implementing it as part of this proposal. If and when this feature would become available, we would adopt it in the `immediate` APIs. ### Changelog From 0a99356424f0914e847451cc6706d8bb86fa3e97 Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Thu, 1 May 2025 20:41:18 -0700 Subject: [PATCH 277/505] Mark ST-0009 Attachments as Implemented in Swift 6.2 --- proposals/testing/0009-attachments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0009-attachments.md b/proposals/testing/0009-attachments.md index e8442b2a81..8fee84e792 100644 --- a/proposals/testing/0009-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -3,7 +3,7 @@ * Proposal: [ST-0009](0009-attachments.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Rachel Brindle](https://github.com/younata) -* Status: **Accepted with revisions** +* Status: **Implemented (Swift 6.2)** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) * Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0009-attachments/79193)), ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) From db11d70a85874baa9560e562315082fca89dd5dd Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Fri, 2 May 2025 09:54:09 +0200 Subject: [PATCH 278/505] Update 0008-exit-tests.md: update status to 'Implemented' --- proposals/testing/0008-exit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index 6a7849b0a6..ce4f95def1 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -3,7 +3,7 @@ * Proposal: [ST-0008](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0008-exit-tests.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Maarten Engels](https://github.com/maartene) -* Status: **Accepted with Modifications** +* Status: **Implemented (Swift 6.2)** * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/fdfc7867df4e35e29b2a24edee34ea4412ec15b0/proposals/testing/0008-exit-tests.md) From 74fd4e039859fa494bbacb5dc880d2eecd2721a4 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 12 Mar 2025 16:47:11 +0000 Subject: [PATCH 279/505] First draft of proposal for static library binary target on non apple platforms --- ...brary-binary-target-non-apple-platforms.md | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md diff --git a/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md new file mode 100644 index 0000000000..e9701dcc60 --- /dev/null +++ b/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -0,0 +1,161 @@ +# Binary Static Library Dependencies + +* Proposal: [SE-NNNN](NNNN-filename.md) +* Authors: +* Review Manager: TBD +* Status: **Awaiting implementation** + + + +* Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) +* Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) + + + + +## Introduction + +Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). +However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. +This proposal aims to make it possible to provide static library dependencies on non-Apple platforms. + +Swift-evolution thread: + +## Motivation + +The Swift Package Manager’s [`binaryTarget` type](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md) lets packages vend libraries that either cannot be built in Swift Package Manager for technical reasons, +or for which the source code cannot be published for legal or other reasons. + +In the current version of SwiftPM, binary targets support the following: + +* Libraries in an Xcode-oriented format called XCFramework, and only for Apple platforms, introduced in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md). +* Executables through the use of artifact bundles introduced in [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md). + +We aim here to bring a subset of the XCFramework capabilities to non-Apple platforms in a safe way. + +While this proposal is specifically focused on binary static library dependencies without unresolved external symbols on non-Apple platforms, +it tries to do so in a way that will not prevent broader future support for static libraries and dynamically linked libraries. + +## Proposed solution + +This proposal extends artifact bundles introduced by [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md) to include a new kind of artifact type to represent a binary library dependency: `staticLibrary`. +The artifact manifest would encode the following information for each variant: + +* The static library to pass to the linker. + On Apple and Linux platforms, this would be `.a` files and on Windows it would be a `.lib` file. +* Enough information to be able to use the library's API in the packages source code, + i.e., headers and module maps for libraries exporting a C-based interface. + +Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the platforms supported by the Swift project. +Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. + +## Detailed design + +This section describes the changes to artifact bundle manifests in detail, the semantic impact of the changes on SwiftPM's build infrastructure, and describes the operation of the auditing tool. + +### Artifact Manifest Semantics + +The artifact manifest JSON format for a static library is described below: + +```json +{ + "schemaVersion": "1.0", + "artifacts": { + "": { + "version": "", + "type": "staticLibrary", + "variants": [ + { + "path": "", + "headerPaths": [", ...], + "moduleMapPath": "", + "supportedTriples": ["", ... ], + }, + ... + ] + }, + ... + } +} +``` + +The additions are: + +* The `staticLibrary` artifact `type` that indicates this binary artifact is not an executable but rather a static library to link against. +* The `headerPaths` field specifies directory paths relative to the root of the artifact bundle that contain the header interfaces to the static library. + These are forwarded along to the swift compiler (or the C compiler) using the usual search path arguments. + Each of these directories can optionally contain a `module.modulemap` file that will be used for importing the API into Swift code. +* The optional `moduleMapPath` field specifies a custom module map to use if the header paths do not contain the module definitions or to provide custom overrides. + +As with executable binary artifacts, the `path` field represents the relative path to the binary from the root of the artifact bundle, +and the `supportedTriples` field provides information about the target triples supported by this variant. + +An example artifact might look like: +```json +{ + "schemaVersion": "1.0", + "artifacts": { + "my-artifact": { + "type": "staticLibrary", + "version": "1.0.0", + "variants": [ + { + "path": "artifact.a", + "headerPaths": ["include"], + "supportedTriples": ["aarch64-unknown-linux-gnu"] + } + ] + } + } +} +``` + +### Auditing tool + +Without proper auditing it would be very easy to provide binary static library artifacts that call into unresolved external symbols that are not available on the runtime platform, e.g., due to missing linkage to a system dynamic library. + +We propose the introduction of a new tool that can validate the "safety" of a binary library artifact across the platforms it supports and the corresponding runtime environment. + +In this proposal we restrict ourselves to static libraries that do not have any external dependencies. +To achieve this we need to be able to detect validate this property across the three object file formats used in static libraries on our supported platforms: [Mach-O](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/MachOOverview.html#//apple_ref/doc/uid/20001860-BAJGJEJC) on Apple platforms, [ELF](https://refspecs.linuxfoundation.org/elf/elf.pdf) on Linux-based platforms, and [COFF](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) on Windows. +All three formats express references to external symbols as _relocations_ which reside in a single section of each object file. + +The tool would scan every object file in the static library and construct a complete list of symbols defined and referenced across the entire library. +The tool would then check that the referenced symbols list is a subset of the set of defined symbols and emit an error otherwise. + +## Security + +This proposal brings the security implications outlined in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md#security) to non-Apple platforms, +namely that a malicious attacker having access to both the server hosting the artifact and the git repository that vends the Package Manifest could provide a malicious library. +Users should exercise caution when onboarding binary dependencies. + +## Impact on existing packages + +No current package should be affected by this change since this is only an additive change in enabling SwiftPM to use binary target library dependencies on non-Apple platforms. + +## Future directions + +### Extend binary compatibility guarantees + +This proposal makes no guarantees regarding the availability of symbols in the runtime environment and therefore the auditing tool validates that all referenced symbols in the binary dependency are already resolved. +In the future we would like to provide more exhaustive guarantees about core system libraries and symbols that are guaranteed to be present on supported runtime environments, e.g. `libc.so`. +This is very similar to the [`manylinux`](https://peps.python.org/pep-0513/) effort in the Python community, but the standardization effort would need to extend to Apple platforms and Windows platforms. +Specifically we would extend the auditing tool to allow unresolved external symbols to symbols that are known to exist. + +### Support Swift static libraries (needs fact checking) + +Today Swift static libraries can not be fully statically linked. +However, once binary compatibility guarantees are extended to include Swift SDK symbols, +static libraries exposing a purely Swift API should be supported. +To do this we would extend the static library binary artifact manifest to provide a `.swiftinterface` file that can be consumed by the Swift compiler. + +### Add support for dynamically linked dependencies + +On Windows dynamic linking requires an _import library_ which is a small static library that contains stubs for symbols exported by the dynamic library. +These stubs are roughly equivalent to a PLT entry in an ELF executable, but are generated during the build of the dynamic library and must be provided to clients of the library for linking purposes. +Similarly on Linux and Apple platforms binary artifact maintainers may wish to provide a dynamic library stub to improve link performance. +To support these use cases the library binary artifact manifest schema could be extended to provide facilities to provide both a link-time and runtime dependency. From 2ae6bde3b6c3a2e7d4c87c053786a8ed65f9c384 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 13 Mar 2025 15:45:06 +0000 Subject: [PATCH 280/505] Specify operation of auditing tool using llvm-objdump --- ...brary-binary-target-non-apple-platforms.md | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md index e9701dcc60..d01b826d3b 100644 --- a/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -1,7 +1,7 @@ # Binary Static Library Dependencies * Proposal: [SE-NNNN](NNNN-filename.md) -* Authors: +* Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) * Review Manager: TBD * Status: **Awaiting implementation** @@ -21,7 +21,7 @@ Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. -This proposal aims to make it possible to provide static library dependencies on non-Apple platforms. +This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms. Swift-evolution thread: @@ -37,7 +37,7 @@ In the current version of SwiftPM, binary targets support the following: We aim here to bring a subset of the XCFramework capabilities to non-Apple platforms in a safe way. -While this proposal is specifically focused on binary static library dependencies without unresolved external symbols on non-Apple platforms, +While this proposal is specifically focused on binary static library dependencies without unexpected unresolved external symbols on non-Apple platforms, it tries to do so in a way that will not prevent broader future support for static libraries and dynamically linked libraries. ## Proposed solution @@ -50,7 +50,7 @@ The artifact manifest would encode the following information for each variant: * Enough information to be able to use the library's API in the packages source code, i.e., headers and module maps for libraries exporting a C-based interface. -Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the platforms supported by the Swift project. +Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. ## Detailed design @@ -120,13 +120,20 @@ Without proper auditing it would be very easy to provide binary static library a We propose the introduction of a new tool that can validate the "safety" of a binary library artifact across the platforms it supports and the corresponding runtime environment. -In this proposal we restrict ourselves to static libraries that do not have any external dependencies. +In this proposal we restrict ourselves to static libraries that do not have any external dependencies beyond the C standard library and runtime. To achieve this we need to be able to detect validate this property across the three object file formats used in static libraries on our supported platforms: [Mach-O](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/MachOOverview.html#//apple_ref/doc/uid/20001860-BAJGJEJC) on Apple platforms, [ELF](https://refspecs.linuxfoundation.org/elf/elf.pdf) on Linux-based platforms, and [COFF](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) on Windows. All three formats express references to external symbols as _relocations_ which reside in a single section of each object file. -The tool would scan every object file in the static library and construct a complete list of symbols defined and referenced across the entire library. +We propose adding the `llvm-objdump` to the toolchain to provide the capability to inspect relocations across all three supported object file formats. The tool would use `llvm-objdump` every object file in the static library and construct a complete list of symbols defined and referenced across the entire library. +Additionally, the tool would construct a simple C compiler invocation to derive to generate a default linker invocation. +This would be used to derive the libraries linked by default in a C program, these libraries would then be scanned to contribute to the list of defined symbols. The tool would then check that the referenced symbols list is a subset of the set of defined symbols and emit an error otherwise. +This would be sufficient to guarantee that all symbols from the static library would be available at runtime for statically linked executables or for ones running on the build host. +To ensure maximum runtime compatibility we would also provide a Linux-based Docker image that uses the oldest supported `glibc` for a given Swift version. +As `glibc` is backwards compatible, a container running the audit on a given static library would ensure that the version of `glibc` on any runtime platform would be compatible with the binary artifact. +This strategy as been succesfully employed in the Python community with [`manylinux`](https://peps.python.org/pep-0513/). + ## Security This proposal brings the security implications outlined in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md#security) to non-Apple platforms, @@ -139,19 +146,16 @@ No current package should be affected by this change since this is only an addit ## Future directions -### Extend binary compatibility guarantees +### Support Swift static libraries -This proposal makes no guarantees regarding the availability of symbols in the runtime environment and therefore the auditing tool validates that all referenced symbols in the binary dependency are already resolved. -In the future we would like to provide more exhaustive guarantees about core system libraries and symbols that are guaranteed to be present on supported runtime environments, e.g. `libc.so`. -This is very similar to the [`manylinux`](https://peps.python.org/pep-0513/) effort in the Python community, but the standardization effort would need to extend to Apple platforms and Windows platforms. -Specifically we would extend the auditing tool to allow unresolved external symbols to symbols that are known to exist. +To do this we would extend the static library binary artifact manifest to provide a `.swiftinterface` file that can be consumed by the Swift compiler to import the Swift APIs. +Additionally we would extend the auditing tool to validate the usage of Swift standard library and runtime symbols, e.g., from `libSwiftCore`. -### Support Swift static libraries (needs fact checking) +### Extend binary compatibility guarantees -Today Swift static libraries can not be fully statically linked. -However, once binary compatibility guarantees are extended to include Swift SDK symbols, -static libraries exposing a purely Swift API should be supported. -To do this we would extend the static library binary artifact manifest to provide a `.swiftinterface` file that can be consumed by the Swift compiler. +This proposal limits itself to providing facilities for binary compatibility only with the C standard library and runtime. +In the future we could provide a system to allow binary artifact distributors to specify additional linkage dependencies for their binary artifacts. +These would be used to customize the operation of the audit tool and perform automatic linking of them in any client target that depends on the binary artifact, in the same way [CMake](https://cmake.org/cmake/help/v4.0/prop_tgt/INTERFACE_LINK_LIBRARIES.html) propagates link dependencies transitively. ### Add support for dynamically linked dependencies From 191d46102c66b12fb615bb4eb204d1573a5dff0e Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 2 May 2025 14:13:08 +0100 Subject: [PATCH 281/505] Updated PR with number. --- ...tpm-static-library-binary-target-non-apple-platforms.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/{XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md => 0467-swiftpm-static-library-binary-target-non-apple-platforms.md} (98%) diff --git a/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md similarity index 98% rename from proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md rename to proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md index d01b826d3b..d453502706 100644 --- a/proposals/XXXX-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -1,9 +1,9 @@ # Binary Static Library Dependencies -* Proposal: [SE-NNNN](NNNN-filename.md) +* Proposal: [SE-0467](0467-swiftpm-static-library-binary-target-non-apple-platforms.md) * Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) -* Review Manager: TBD -* Status: **Awaiting implementation** +* Review Manager: [Kuba Mracek](https://github.com/kubamracek) +* Status: **Active Review (2 May...15 May, 2005)** From 55867ad901067022312c81c548bfddf96ac5afe1 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 2 May 2025 14:15:26 +0100 Subject: [PATCH 282/505] Revert "[SE-0467] Binary Static Library Artifacts Proposal" --- ...brary-binary-target-non-apple-platforms.md | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md diff --git a/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md deleted file mode 100644 index d453502706..0000000000 --- a/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md +++ /dev/null @@ -1,165 +0,0 @@ -# Binary Static Library Dependencies - -* Proposal: [SE-0467](0467-swiftpm-static-library-binary-target-non-apple-platforms.md) -* Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) -* Review Manager: [Kuba Mracek](https://github.com/kubamracek) -* Status: **Active Review (2 May...15 May, 2005)** - - - -* Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) -* Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) - - - - -## Introduction - -Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). -However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. -This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms. - -Swift-evolution thread: - -## Motivation - -The Swift Package Manager’s [`binaryTarget` type](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md) lets packages vend libraries that either cannot be built in Swift Package Manager for technical reasons, -or for which the source code cannot be published for legal or other reasons. - -In the current version of SwiftPM, binary targets support the following: - -* Libraries in an Xcode-oriented format called XCFramework, and only for Apple platforms, introduced in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md). -* Executables through the use of artifact bundles introduced in [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md). - -We aim here to bring a subset of the XCFramework capabilities to non-Apple platforms in a safe way. - -While this proposal is specifically focused on binary static library dependencies without unexpected unresolved external symbols on non-Apple platforms, -it tries to do so in a way that will not prevent broader future support for static libraries and dynamically linked libraries. - -## Proposed solution - -This proposal extends artifact bundles introduced by [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md) to include a new kind of artifact type to represent a binary library dependency: `staticLibrary`. -The artifact manifest would encode the following information for each variant: - -* The static library to pass to the linker. - On Apple and Linux platforms, this would be `.a` files and on Windows it would be a `.lib` file. -* Enough information to be able to use the library's API in the packages source code, - i.e., headers and module maps for libraries exporting a C-based interface. - -Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. -Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. - -## Detailed design - -This section describes the changes to artifact bundle manifests in detail, the semantic impact of the changes on SwiftPM's build infrastructure, and describes the operation of the auditing tool. - -### Artifact Manifest Semantics - -The artifact manifest JSON format for a static library is described below: - -```json -{ - "schemaVersion": "1.0", - "artifacts": { - "": { - "version": "", - "type": "staticLibrary", - "variants": [ - { - "path": "", - "headerPaths": [", ...], - "moduleMapPath": "", - "supportedTriples": ["", ... ], - }, - ... - ] - }, - ... - } -} -``` - -The additions are: - -* The `staticLibrary` artifact `type` that indicates this binary artifact is not an executable but rather a static library to link against. -* The `headerPaths` field specifies directory paths relative to the root of the artifact bundle that contain the header interfaces to the static library. - These are forwarded along to the swift compiler (or the C compiler) using the usual search path arguments. - Each of these directories can optionally contain a `module.modulemap` file that will be used for importing the API into Swift code. -* The optional `moduleMapPath` field specifies a custom module map to use if the header paths do not contain the module definitions or to provide custom overrides. - -As with executable binary artifacts, the `path` field represents the relative path to the binary from the root of the artifact bundle, -and the `supportedTriples` field provides information about the target triples supported by this variant. - -An example artifact might look like: -```json -{ - "schemaVersion": "1.0", - "artifacts": { - "my-artifact": { - "type": "staticLibrary", - "version": "1.0.0", - "variants": [ - { - "path": "artifact.a", - "headerPaths": ["include"], - "supportedTriples": ["aarch64-unknown-linux-gnu"] - } - ] - } - } -} -``` - -### Auditing tool - -Without proper auditing it would be very easy to provide binary static library artifacts that call into unresolved external symbols that are not available on the runtime platform, e.g., due to missing linkage to a system dynamic library. - -We propose the introduction of a new tool that can validate the "safety" of a binary library artifact across the platforms it supports and the corresponding runtime environment. - -In this proposal we restrict ourselves to static libraries that do not have any external dependencies beyond the C standard library and runtime. -To achieve this we need to be able to detect validate this property across the three object file formats used in static libraries on our supported platforms: [Mach-O](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/MachOOverview.html#//apple_ref/doc/uid/20001860-BAJGJEJC) on Apple platforms, [ELF](https://refspecs.linuxfoundation.org/elf/elf.pdf) on Linux-based platforms, and [COFF](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) on Windows. -All three formats express references to external symbols as _relocations_ which reside in a single section of each object file. - -We propose adding the `llvm-objdump` to the toolchain to provide the capability to inspect relocations across all three supported object file formats. The tool would use `llvm-objdump` every object file in the static library and construct a complete list of symbols defined and referenced across the entire library. -Additionally, the tool would construct a simple C compiler invocation to derive to generate a default linker invocation. -This would be used to derive the libraries linked by default in a C program, these libraries would then be scanned to contribute to the list of defined symbols. -The tool would then check that the referenced symbols list is a subset of the set of defined symbols and emit an error otherwise. - -This would be sufficient to guarantee that all symbols from the static library would be available at runtime for statically linked executables or for ones running on the build host. -To ensure maximum runtime compatibility we would also provide a Linux-based Docker image that uses the oldest supported `glibc` for a given Swift version. -As `glibc` is backwards compatible, a container running the audit on a given static library would ensure that the version of `glibc` on any runtime platform would be compatible with the binary artifact. -This strategy as been succesfully employed in the Python community with [`manylinux`](https://peps.python.org/pep-0513/). - -## Security - -This proposal brings the security implications outlined in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md#security) to non-Apple platforms, -namely that a malicious attacker having access to both the server hosting the artifact and the git repository that vends the Package Manifest could provide a malicious library. -Users should exercise caution when onboarding binary dependencies. - -## Impact on existing packages - -No current package should be affected by this change since this is only an additive change in enabling SwiftPM to use binary target library dependencies on non-Apple platforms. - -## Future directions - -### Support Swift static libraries - -To do this we would extend the static library binary artifact manifest to provide a `.swiftinterface` file that can be consumed by the Swift compiler to import the Swift APIs. -Additionally we would extend the auditing tool to validate the usage of Swift standard library and runtime symbols, e.g., from `libSwiftCore`. - -### Extend binary compatibility guarantees - -This proposal limits itself to providing facilities for binary compatibility only with the C standard library and runtime. -In the future we could provide a system to allow binary artifact distributors to specify additional linkage dependencies for their binary artifacts. -These would be used to customize the operation of the audit tool and perform automatic linking of them in any client target that depends on the binary artifact, in the same way [CMake](https://cmake.org/cmake/help/v4.0/prop_tgt/INTERFACE_LINK_LIBRARIES.html) propagates link dependencies transitively. - -### Add support for dynamically linked dependencies - -On Windows dynamic linking requires an _import library_ which is a small static library that contains stubs for symbols exported by the dynamic library. -These stubs are roughly equivalent to a PLT entry in an ELF executable, but are generated during the build of the dynamic library and must be provided to clients of the library for linking purposes. -Similarly on Linux and Apple platforms binary artifact maintainers may wish to provide a dynamic library stub to improve link performance. -To support these use cases the library binary artifact manifest schema could be extended to provide facilities to provide both a link-time and runtime dependency. From a1fa71db11a6211e59cc574e51d76ab6f7ec81c7 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 2 May 2025 14:15:55 +0100 Subject: [PATCH 283/505] Revert "Revert "[SE-0467] Binary Static Library Artifacts Proposal"" --- ...brary-binary-target-non-apple-platforms.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md diff --git a/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md new file mode 100644 index 0000000000..d453502706 --- /dev/null +++ b/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -0,0 +1,165 @@ +# Binary Static Library Dependencies + +* Proposal: [SE-0467](0467-swiftpm-static-library-binary-target-non-apple-platforms.md) +* Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) +* Review Manager: [Kuba Mracek](https://github.com/kubamracek) +* Status: **Active Review (2 May...15 May, 2005)** + + + +* Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) +* Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) + + + + +## Introduction + +Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). +However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. +This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms. + +Swift-evolution thread: + +## Motivation + +The Swift Package Manager’s [`binaryTarget` type](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md) lets packages vend libraries that either cannot be built in Swift Package Manager for technical reasons, +or for which the source code cannot be published for legal or other reasons. + +In the current version of SwiftPM, binary targets support the following: + +* Libraries in an Xcode-oriented format called XCFramework, and only for Apple platforms, introduced in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md). +* Executables through the use of artifact bundles introduced in [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md). + +We aim here to bring a subset of the XCFramework capabilities to non-Apple platforms in a safe way. + +While this proposal is specifically focused on binary static library dependencies without unexpected unresolved external symbols on non-Apple platforms, +it tries to do so in a way that will not prevent broader future support for static libraries and dynamically linked libraries. + +## Proposed solution + +This proposal extends artifact bundles introduced by [SE-0305](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0305-swiftpm-binary-target-improvements.md) to include a new kind of artifact type to represent a binary library dependency: `staticLibrary`. +The artifact manifest would encode the following information for each variant: + +* The static library to pass to the linker. + On Apple and Linux platforms, this would be `.a` files and on Windows it would be a `.lib` file. +* Enough information to be able to use the library's API in the packages source code, + i.e., headers and module maps for libraries exporting a C-based interface. + +Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. +Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. + +## Detailed design + +This section describes the changes to artifact bundle manifests in detail, the semantic impact of the changes on SwiftPM's build infrastructure, and describes the operation of the auditing tool. + +### Artifact Manifest Semantics + +The artifact manifest JSON format for a static library is described below: + +```json +{ + "schemaVersion": "1.0", + "artifacts": { + "": { + "version": "", + "type": "staticLibrary", + "variants": [ + { + "path": "", + "headerPaths": [", ...], + "moduleMapPath": "", + "supportedTriples": ["", ... ], + }, + ... + ] + }, + ... + } +} +``` + +The additions are: + +* The `staticLibrary` artifact `type` that indicates this binary artifact is not an executable but rather a static library to link against. +* The `headerPaths` field specifies directory paths relative to the root of the artifact bundle that contain the header interfaces to the static library. + These are forwarded along to the swift compiler (or the C compiler) using the usual search path arguments. + Each of these directories can optionally contain a `module.modulemap` file that will be used for importing the API into Swift code. +* The optional `moduleMapPath` field specifies a custom module map to use if the header paths do not contain the module definitions or to provide custom overrides. + +As with executable binary artifacts, the `path` field represents the relative path to the binary from the root of the artifact bundle, +and the `supportedTriples` field provides information about the target triples supported by this variant. + +An example artifact might look like: +```json +{ + "schemaVersion": "1.0", + "artifacts": { + "my-artifact": { + "type": "staticLibrary", + "version": "1.0.0", + "variants": [ + { + "path": "artifact.a", + "headerPaths": ["include"], + "supportedTriples": ["aarch64-unknown-linux-gnu"] + } + ] + } + } +} +``` + +### Auditing tool + +Without proper auditing it would be very easy to provide binary static library artifacts that call into unresolved external symbols that are not available on the runtime platform, e.g., due to missing linkage to a system dynamic library. + +We propose the introduction of a new tool that can validate the "safety" of a binary library artifact across the platforms it supports and the corresponding runtime environment. + +In this proposal we restrict ourselves to static libraries that do not have any external dependencies beyond the C standard library and runtime. +To achieve this we need to be able to detect validate this property across the three object file formats used in static libraries on our supported platforms: [Mach-O](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/MachOOverview.html#//apple_ref/doc/uid/20001860-BAJGJEJC) on Apple platforms, [ELF](https://refspecs.linuxfoundation.org/elf/elf.pdf) on Linux-based platforms, and [COFF](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) on Windows. +All three formats express references to external symbols as _relocations_ which reside in a single section of each object file. + +We propose adding the `llvm-objdump` to the toolchain to provide the capability to inspect relocations across all three supported object file formats. The tool would use `llvm-objdump` every object file in the static library and construct a complete list of symbols defined and referenced across the entire library. +Additionally, the tool would construct a simple C compiler invocation to derive to generate a default linker invocation. +This would be used to derive the libraries linked by default in a C program, these libraries would then be scanned to contribute to the list of defined symbols. +The tool would then check that the referenced symbols list is a subset of the set of defined symbols and emit an error otherwise. + +This would be sufficient to guarantee that all symbols from the static library would be available at runtime for statically linked executables or for ones running on the build host. +To ensure maximum runtime compatibility we would also provide a Linux-based Docker image that uses the oldest supported `glibc` for a given Swift version. +As `glibc` is backwards compatible, a container running the audit on a given static library would ensure that the version of `glibc` on any runtime platform would be compatible with the binary artifact. +This strategy as been succesfully employed in the Python community with [`manylinux`](https://peps.python.org/pep-0513/). + +## Security + +This proposal brings the security implications outlined in [SE-0272](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0272-swiftpm-binary-dependencies.md#security) to non-Apple platforms, +namely that a malicious attacker having access to both the server hosting the artifact and the git repository that vends the Package Manifest could provide a malicious library. +Users should exercise caution when onboarding binary dependencies. + +## Impact on existing packages + +No current package should be affected by this change since this is only an additive change in enabling SwiftPM to use binary target library dependencies on non-Apple platforms. + +## Future directions + +### Support Swift static libraries + +To do this we would extend the static library binary artifact manifest to provide a `.swiftinterface` file that can be consumed by the Swift compiler to import the Swift APIs. +Additionally we would extend the auditing tool to validate the usage of Swift standard library and runtime symbols, e.g., from `libSwiftCore`. + +### Extend binary compatibility guarantees + +This proposal limits itself to providing facilities for binary compatibility only with the C standard library and runtime. +In the future we could provide a system to allow binary artifact distributors to specify additional linkage dependencies for their binary artifacts. +These would be used to customize the operation of the audit tool and perform automatic linking of them in any client target that depends on the binary artifact, in the same way [CMake](https://cmake.org/cmake/help/v4.0/prop_tgt/INTERFACE_LINK_LIBRARIES.html) propagates link dependencies transitively. + +### Add support for dynamically linked dependencies + +On Windows dynamic linking requires an _import library_ which is a small static library that contains stubs for symbols exported by the dynamic library. +These stubs are roughly equivalent to a PLT entry in an ELF executable, but are generated during the build of the dynamic library and must be provided to clients of the library for linking purposes. +Similarly on Linux and Apple platforms binary artifact maintainers may wish to provide a dynamic library stub to improve link performance. +To support these use cases the library binary artifact manifest schema could be extended to provide facilities to provide both a link-time and runtime dependency. From cba174878fc9a86c7b03c1c3746556d2c7c5317b Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 2 May 2025 14:17:56 +0100 Subject: [PATCH 284/505] Fix SE number --- ...swiftpm-static-library-binary-target-non-apple-platforms.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{0467-swiftpm-static-library-binary-target-non-apple-platforms.md => 0482-swiftpm-static-library-binary-target-non-apple-platforms.md} (99%) diff --git a/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md similarity index 99% rename from proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md rename to proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index d453502706..9e246c9afd 100644 --- a/proposals/0467-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -1,6 +1,6 @@ # Binary Static Library Dependencies -* Proposal: [SE-0467](0467-swiftpm-static-library-binary-target-non-apple-platforms.md) +* Proposal: [SE-0482](0482-swiftpm-static-library-binary-target-non-apple-platforms.md) * Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) * Review Manager: [Kuba Mracek](https://github.com/kubamracek) * Status: **Active Review (2 May...15 May, 2005)** From 94910c9b3d643355a2c721d19263010a0c693c13 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 2 May 2025 14:26:48 +0100 Subject: [PATCH 285/505] [SE-0482] Update review fields. --- ...tic-library-binary-target-non-apple-platforms.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index 9e246c9afd..6991b6f942 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -3,20 +3,11 @@ * Proposal: [SE-0482](0482-swiftpm-static-library-binary-target-non-apple-platforms.md) * Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) * Review Manager: [Kuba Mracek](https://github.com/kubamracek) -* Status: **Active Review (2 May...15 May, 2005)** - - - +* Status: **Active Review (May 2nd...May 15th, 2025)** * Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) +* Review: ([discussion](https://forums.swift.org/t/se-0482-binary-static-library-dependencies/79634)) ([pitch](https://forums.swift.org/t/pitch-swiftpm-support-for-binary-static-library-dependencies/78619)) * Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) - - - ## Introduction Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). From 83cd77fb448cba929fc222a66ea8afc40725d80a Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 2 May 2025 09:59:08 -0700 Subject: [PATCH 286/505] Update the SE-0443 proposal to reflect the style chosen for diagnostic group names. The text of SE-0443 uses snake case diagnostic group names, but in practice we've settled on using Pascal case for diagnostic group names. Additionally, the name `DeprecatedDeclaration` was chosen for the deprecation diagnostic group. I think it would be best for the proposal to reflect both of these stylistic choices so that it can serve as accurate documentation for the feature in practice. --- proposals/0443-warning-control-flags.md | 73 +++++++++++++------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/proposals/0443-warning-control-flags.md b/proposals/0443-warning-control-flags.md index 99562b689c..eb24169971 100644 --- a/proposals/0443-warning-control-flags.md +++ b/proposals/0443-warning-control-flags.md @@ -32,7 +32,7 @@ The `` parameter is a string identifier of the diagnostic group. A diagnostic group is a stable identifier for an error or warning. It is an abstraction layer over the diagnostic identifiers used within the compiler. This is necessary because diagnostics within the compiler may change, but we need to provide stable user-facing identifiers for them. -A diagnostic group may include errors, warnings, or other diagnostic groups. For example, the `availability_deprecated` diagnostic group includes warnings related to the use of an API marked with the `@available(..., deprecated: ...)` attribute. The `deprecated` diagnostic group includes the `availability_deprecated` group and other groups related to deprecation. +A diagnostic group may include errors, warnings, or other diagnostic groups. For example, the `DeprecatedDeclaration` diagnostic group includes warnings related to the use of an API marked with the `@available(..., deprecated: ...)` attribute. The `Deprecated` diagnostic group includes the `DeprecatedDeclaration` group and other groups related to deprecation. Diagnostic groups may expand over time, but they can never become narrower. When a new diagnostic is added to the compiler, it is either included in an existing group or a new group is created for it, which in turn can also be included in one of the broader groups, if appropriate. @@ -40,11 +40,11 @@ The order in which these flags are specified when invoking the compiler is impor We also retain the existing compiler options but modify their handling algorithm so that they are considered in the general list with the new options and follow the "last one wins" rule as well. -Thus, for example, you can use the combination `-warnings-as-errors -Wwarning deprecated`, which will upgrade all warnings to errors except for those in the `deprecated` group. However, if these flags are specified in the reverse order(`-Wwarning deprecated -warnings-as-errors`) it will be interpreted as upgrading all warnings to errors, as the `-warnings-as-errors` flag is the last one. +Thus, for example, you can use the combination `-warnings-as-errors -Wwarning Deprecated`, which will upgrade all warnings to errors except for those in the `Deprecated` group. However, if these flags are specified in the reverse order(`-Wwarning Deprecated -warnings-as-errors`) it will be interpreted as upgrading all warnings to errors, as the `-warnings-as-errors` flag is the last one. We are also introducing a new compiler flag, `-print-diagnostic-groups`, to display the names of diagnostic groups along with the textual representation of the warnings. When used, the warning message will be followed by the name of the narrowest group that includes that warning, enclosed in square brackets. For example: ``` -main.swift:33:1: warning: 'f()' is deprecated [availability_deprecated] +main.swift:33:1: warning: 'f()' is deprecated [#DeprecatedDeclaration] ``` ## Detailed design @@ -57,22 +57,22 @@ Diagnostic groups form an acyclic graph with the following properties: - When using the `-print-diagnostic-groups` flag, it would be inconvenient if a warning corresponded to multiple groups. - Documentation lookup will also be easier for the user if a diagnostic has only one identifier. -- A diagnostic group may include any number of other diagnostic groups. This will allow organizing groups into sets with similar meanings but different specific diagnostics. For example, the warnings `availability_deprecated` and `unsafe_global_actor_deprecated` are part of the supergroup `deprecated`. +- A diagnostic group may include any number of other diagnostic groups. This will allow organizing groups into sets with similar meanings but different specific diagnostics. For example, the warnings `DeprecatedDeclaration` and `UnsafeGlobalActorDeprecated` are part of the supergroup `Deprecated`. -- A diagnostic group can be included in any number of diagnostic groups. This allows expressing the membership of a group in multiple supergroups, where appropriate. For example, the group `unsafe_global_actor_deprecated` is part of both the `deprecated` and `concurrency` groups. +- A diagnostic group can be included in any number of diagnostic groups. This allows expressing the membership of a group in multiple supergroups, where appropriate. For example, the group `UnsafeGlobalActorDeprecated` is part of both the `Deprecated` and `Concurrency` groups. The internal structure of the graph may change to some extent. However, the set of diagnostics included in a diagnostic group (directly or transitively) should not shrink. There are two typical situations where the graph structure may change: -- When adding a new diagnostic to the compiler, consider creating a new group corresponding to that diagnostic. If the new group is created it can also be included in one or more existing groups if it belongs to them. For example, it is expected that the `deprecated` group will continuously include new subgroups. +- When adding a new diagnostic to the compiler, consider creating a new group corresponding to that diagnostic. If the new group is created it can also be included in one or more existing groups if it belongs to them. For example, it is expected that the `Deprecated` group will continuously include new subgroups. - If an existing diagnostic is split into more specific versions, and we want to allow users to use the more specific version in compiler options, a separate group is created for it, which **must** be included in the group of the original diagnostic. - For example, suppose we split the `availability_deprecated` warning into a general version and a specialized version `availability_deprecated_same_module`, which the compiler emits if the deprecated symbol is declared in the same module. In this case, the `availability_deprecated_same_module` group must be added to the `availability_deprecated` group to ensure that the overall composition of the `availability_deprecated` group does not change. The final structure should look like this: + For example, suppose we split the `DeprecatedDeclaration` warning into a general version and a specialized version `DeprecatedDeclarationSameModule`, which the compiler emits if the deprecated symbol is declared in the same module. In this case, the `DeprecatedDeclarationSameModule` group must be added to the `DeprecatedDeclaration` group to ensure that the overall composition of the `DeprecatedDeclaration` group does not change. The final structure should look like this: ``` - availability_deprecated (group) - ├─ availability_deprecated (internal diag id) - └─ availability_deprecated_same_module (group) - └─ availability_deprecated_same_module (internal diag id) + DeprecatedDeclaration (group) + ├─ DeprecatedDeclaration (internal diag id) + └─ DeprecatedDeclarationSameModule (group) + └─ DeprecatedDeclarationSameModule (internal diag id) ``` - Thus, invoking the compiler with the `-Werror availability_deprecated` parameter will cover both versions of the warning, and the behavior will remain unchanged. At the same time, the user can control the behavior of the narrower `availability_deprecated_same_module` group if they want to. + Thus, invoking the compiler with the `-Werror DeprecatedDeclaration` parameter will cover both versions of the warning, and the behavior will remain unchanged. At the same time, the user can control the behavior of the narrower `DeprecatedDeclarationSameModule` group if they want to. ### Compiler options evaluation @@ -87,20 +87,21 @@ Compiler options for controlling the behavior of groups are now processed as a s When these options are passed to the compiler, we sequentially apply the specified behavior to all warnings within the specified group from left to right. For `-warnings-as-errors` and `-no-warnings-as-errors`, we apply the behavior to all warnings. Examples of option combinations: -- `-warnings-as-errors -Wwarning deprecated` +- `-warnings-as-errors -Wwarning Deprecated` - Warnings from the `deprecated` group will be kept as warnings, but all the rest will be upgraded to errors. + Warnings from the `Deprecated` group will be kept as warnings, but all the rest will be upgraded to errors. -- `-Werror deprecated -Wwarning availability_deprecated` +- `-Werror Deprecated -Wwarning DeprecatedDeclaration` - Warnings from the `availability_deprecated` group will remain as warnings. Other warnings from the `deprecated` group will be upgraded to errors. All others will be kept as warnings. + Warnings from the `DeprecatedDeclaration` group will remain as warnings. Other warnings from the `Deprecated` group will be upgraded to errors. All others will be kept as warnings. It’s crucial to understand that the order in which these flags are applied can significantly affect the behavior of diagnostics. The rule is "the last one wins", meaning that if multiple flags apply to the same diagnostic group, the last one specified on the command line will determine the final behavior. It is also important to note that the order matters even if the specified groups are not explicitly related but have a common subgroup. -For example, as mentioned above, the `unsafe_global_actor_deprecated` group is part of both the `deprecated` and `concurrency` groups. So the order in which options for the `deprecated` and `concurrency` groups are applied will change the final behavior of the `unsafe_global_actor_deprecated` group. Specifically: -- `-Wwarning deprecated -Werror concurrency` will make it an error, -- `-Werror concurrency -Wwarning deprecated` will keep it as a warning. +For example, as mentioned above, the `UnsafeGlobalActorDeprecated` group is part of both the `Deprecated` and `Concurrency` groups. So the order in which options for the `Deprecated` and `Concurrency` groups are applied will change the final behavior of the `UnsafeGlobalActorDeprecated` group. Specifically: + +- `-Wwarning Deprecated -Werror Concurrency` will make it an error, +- `-Werror Concurrency -Wwarning Deprecated` will keep it as a warning. #### Interaction with `-suppress-warnings` @@ -123,15 +124,15 @@ oldFunction() ``` When compiled with the `-debug-diagnostic-names` option, the following message will be displayed: ``` -'oldFunction()' is deprecated: renamed to 'newFunction' [availability_deprecated_rename] +'oldFunction()' is deprecated: renamed to 'newFunction' [#RenamedDeprecatedDeclaration] ``` -The string `availability_deprecated_rename` is the internal identifier of this warning, not the group. Accordingly, it is not supported by the new compiler options. +The string `RenamedDeprecatedDeclaration` is the internal identifier of this warning, not the group. Accordingly, it is not supported by the new compiler options. When compiling the same code with the `-print-diagnostic-groups` option, the following message will be displayed: ``` -'oldFunction()' is deprecated: renamed to 'newFunction' [availability_deprecated] +'oldFunction()' is deprecated: renamed to 'newFunction' [#DeprecatedDeclaration] ``` -Here, the string `availability_deprecated` is the diagnostic group. +Here, the string `DeprecatedDeclaration` is the diagnostic group. Often, group names and internal diagnostic identifiers coincide, but this is not always the case. @@ -169,7 +170,7 @@ The lack of control over the behavior of specific diagnostics forces users to ab Warnings and errors in Swift can change as the compiler evolves. For example, one error might be renamed or split into two that are applied in different situations to improve the clarity of the text message depending on the context. Such a change would result in a new ID for the new error variant. -The example of `availability_deprecated_same_module` illustrates this well. If we used the warning ID, the behavior of the compiler with the `-Wwarning availability_deprecated` option would change when a new version of the warning is introduced, as this warning would no longer be triggered for the specific case of the same module. +The example of `DeprecatedDeclarationSameModule` illustrates this well. If we used the warning ID, the behavior of the compiler with the `-Wwarning DeprecatedDeclaration` option would change when a new version of the warning is introduced, as this warning would no longer be triggered for the specific case of the same module. Therefore, we need a solution that allows us to modify errors and warnings within the compiler while providing a reliable mechanism for identifying diagnostics that can be used by the user. @@ -177,23 +178,23 @@ Therefore, we need a solution that allows us to modify errors and warnings withi To solve this problem, we could use an additional alias-ID for diagnostics that does not change when the main identifier changes. -Suppose we split the `availability_deprecated` diagnostic into a generic variant and `availability_deprecated_same_module`. To retain the existing name for the new variant, we could describe these two groups as +Suppose we split the `DeprecatedDeclaration` diagnostic into a generic variant and `DeprecatedDeclarationSameModule`. To retain the existing name for the new variant, we could describe these two groups as ``` -availability_deprecated (alias: availability_deprecated) -availability_deprecated_same_module (alias: availability_deprecated) +DeprecatedDeclaration (alias: DeprecatedDeclaration) +DeprecatedDeclarationSameModule (alias: DeprecatedDeclaration) ``` -However, this solution would not allow specifying the narrower `availability_deprecated_same_module` or the broader group `deprecated`. +However, this solution would not allow specifying the narrower `DeprecatedDeclarationSameModule` or the broader group `Deprecated`. #### Using multiple alias IDs for diagnostics To express a diagnostic's membership in multiple groups, we could allow multiple alias-IDs to be listed. ``` -availability_deprecated aliases: - availability_deprecated - deprecated -availability_deprecated_same_module aliases: - availability_deprecated_same_module - availability_deprecated - deprecated +DeprecatedDeclaration aliases: + DeprecatedDeclaration + Deprecated +DeprecatedDeclarationSameModule aliases: + DeprecatedDeclarationSameModule + DeprecatedDeclaration + Deprecated ``` However, such a declaration lacks structure and makes it difficult to understand which alias-ID is the most specific. @@ -222,7 +223,7 @@ Since `-debug-diagnostic-names` has been available in the compiler for a long ti To avoid overlap, we would need to use a different format, for example: ``` -'foo()' is deprecated [availability_deprecated] [group:availability_deprecated] +'foo()' is deprecated [#DeprecatedDeclaration] [group:#DeprecatedDeclaration] ``` However, even this does not eliminate the possibility of breaking code that parses the compiler's output. From 02a4c0201ded1f9e547ccf4bf0e4c42469a22714 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Fri, 2 May 2025 12:08:22 -0700 Subject: [PATCH 287/505] InlineArray sugar proposal (#2776) * First draft of InlineArray sugar proposal * Add flattened array future direction * Add alternative of of * flesh out alternatives considered * Clarify x is a keyword * typo * Assign `InlineArray` type sugar to SE-0483 and put into review. * Fix a missing link to SE-0453. --------- Co-authored-by: Holly Borla --- proposals/0483-inline-array-sugar.md | 161 +++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 proposals/0483-inline-array-sugar.md diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md new file mode 100644 index 0000000000..c4ee2430cd --- /dev/null +++ b/proposals/0483-inline-array-sugar.md @@ -0,0 +1,161 @@ +# `InlineArray` Literal Syntax + +* Proposal: [SE-0483](0483-inline-array-sugar.md) +* Authors: [Hamish Knight](https://github.com/hamishknight), [Ben Cohen](https://github.com/airspeedswift) +* Review Manager: [Holly Borla](https://github.com/hborla) +* Status: **Active Review (May 2 - May 16, 2025)** +* Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. +* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) + +## Introduction + +We propose the introduction of type sugar for the `InlineArray` type, providing more succinct syntax for declaring an inline array. + +## Motivation + +[SE-0453](/proposals/0453-vector.md) introduced a new type, `InlineArray`, which includes a size parameter as part of its type: + +``` +let fiveIntegers: InlineArray<5, Int> = .init(repeating: 99) +``` + +Declaring this type is more cumbersome than its equivalent dyanmicaly-sized array, which has sugar for the type syntax: + +``` +let fiveIntegers: [Int] = .init(repeating: 99, count: 5) +``` + +This becomes more pronounced when dealing with multiple dimensions: + +``` +let fiveByFive: InlineArray<5, InlineArray<5, Int>> = .init(repeating: .init(repeating: 99)) +``` + +## Proposed solution + +A new sugared version of the `InlineArray` type is proposed: + +```swift +let fiveIntegers: [5 x Int] = .init(repeating: 99) +``` + +The `x` here is the ASCII character, and is chosen to evoke the common shorthand use to represent "by", as in "4x4" or "2 in x 4 in". + +Note that although it is used in the manner of an operator, `x` here serves more like a contextual keyword, similar to if the syntax were `[5 of Int]`. + +## Detailed design + +The new syntax consists of the value for the integer generic paramter and the type of the element generic paramter, separated by `x`. + +This will be added to the grammar alongside the current type sugar: + +> **Grammar of a type** +> _type → sized-array-type_ +> +> **Grammar of a sized array type** +> _sized-array-type → [ expression `x` type ]_ + +Note that while the grammar allows for any expression, this is currently limited to only integer literals. + +The new sugar is equivalent to declaring a type of `InlineArray`, so all rules that can be applied to the generic placeholders for the unsugared version also apply to the sugared version: + +``` +// Nesting +let fiveByFive: InlineArray<5, InlineArray<5, Int>> = .init(repeating: .init(repeating: 99)) +let fiveByFive: [5 x [5 x Int]] = .init(repeating: .init(repeating: 99)) + +// Inference from context: +let fiveIntegers: [5 x _] = .init(repeating: 99) +let fourBytes: [_ x Int8] = [1,2,3,4] +let fourIntegers: [_ x _] = [1,2,3,4] + +// use on rhs +let fiveDoubles = [5 x _](repeating: 1.23) +``` + +The sugar can also be used in place of the unsugared type wherever it might appear: + +``` +[5 x Int](repeating: 99) +MemoryLayout<[5 x Int]>.size +unsafeBitCast((1,2,3), to: [3 x Int].self) +``` + +There must be whitespace on either side of the separator i.e. you cannot write `[5x Int]`. There are no requirements to balance whitespace, `[5 x Int]` is permitted. A new line can appear after the `x` but not before it, as while this is not ambiguous, this aids with the parser recovery logic, leading to better syntax error diagnostics. + +## Source Compatibility + +Since it is not currently possible to write any form of the proposed syntax in Swift today, this proposal does not alter the meaning of any existing code. + +## Impact on ABI + +This is purely compile-time sugar for the existing type. It is resolved at compile time, and does not appear in the ABI nor rely on any version of the runtime. + +## Future Directions + +### Repeated value equivalent + +Analogous to arrays, there is an equivalent _value_ sugar for literals of a specific size: + +``` +// type inferred to be [5 x Int] +let fiveInts = [5 x 99] +// type inferred to be [5 x [5 x Int]] +let fiveByFive = [5 x [5 x 99]] +``` + +Unlike the sugar for the type, this would also have applicability for existing types: + +``` +// equivalent to .init(repeating: 99, count: 5) +let dynamic: [Int] = [5 x 99] +``` + +This is a much bigger design space, potentially requiring a new expressible-by-literal protocol and a way to map the literal to an initializer. As such, it is left for a future proposal. + +### Flattened multi-dimensional arrays + +For multi-dimensional arrays, `[5 x [5 x Int]]` could be flattened to `[5 x 5 x Int]` without any additional parsing issues. This could be an alternative considered, but is in future directions as it could also be introduced as sugar for the former case at a later date. + +## Alternatives Considered + +### Choice of delimiter + +The most obvious alternative here is the choice of separator. Other options include: + +- `[5 * Int]`, using the standard ASCII symbol for multiplication. +- `[5 ⨉ Int]`, the Unicode n-ary times operator. This looks nice but is impactical as not keyboard-accessible. +- `[5; Int]` is what Rust uses, but appears to have little association with "times" or "many". Similarly other arbitrary punctuation e.g. `,` or `/` or `#`. +- `[5 of Int]` is more verbose than `x` but could be considered more clear. It has the upside or downside, depending on your preference, of being almost, but not quite, grammatical. +- `:` is of course ruled out as it is used for dictionary literals. + +Note that `*` is an existing operator, and may lead to ambiguity in fuure when expressions can be used to determine the size: `[5 * N * Int]`. `x` is clearer in this case: `[5 * N x Int]`. It also avoids parsing ambiguity, as the grammar does not allow two identifiers in succession. But it would be less clear if `x` also appeared as an identifier: `[5 * x x Int]` (which is not yet permitted but may be in future use cases). + +This becomes more important if the future direction of a value equivalent is pursued. `[2 * 2 * 2]` could be interpreted as `[2, 2, 2, 2]`, `[4, 4,]`, or `[8]`. + +Since `x` cannot follow another identifier today, `[x x Int]` is unambiguous,[^type] but would clearly be hard to read. This is likely a hypothetical concern rather than a practical one. While `x` is used often in scratch code for a local variable, a more meaningful name is usually preferable, and this would be especially the case if it is found being used for the size of an array literal. In addition, while `i`, `j`, or `n` are often legitimate counters that might be suited to the size of an array, `x` is generally not used for such things. + +[^type]: or even `[x x x]`, since `x` can be a type name, albeit one that defies Swift's naming conventions. + +Another thing to consider is how that separator looks in the fully inferred version, which tend to start to look a little like ascii diagrams: + +``` +[_ x _] +[_ * _] +[_; _] +[_ of _] +``` + +### Order of size and type + +The order of size first, then type is determined by the ordering of the unsugared type, and deviating from this for the sugared version is not an option. + +### Whitespace around the delimeter + +In theory, when using integer literals or `_` the whitespace could be omitted (`[5x_]` is unabiguously `[5 x _]`). However, special casing allowing whitespace omission is not desirable. + +### Choice of brackets + +`InlineArray` has a lot in common with tuples – especially in sharing "copy on copy" behavior, unlike regular `Array`. So `(5 x Int)` may be an appropriate alternative to the square brackets, echoing this similarity. + +Beyond varying the separator, there may be other dramatically different syntax that moves further from the "like Array sugar, but with a size argument". From ffbbbec7678b23e427f9e53b42562de365d4dbd2 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 2 May 2025 12:12:34 -0700 Subject: [PATCH 288/505] Link SE-0483 review thread. (#2830) --- proposals/0483-inline-array-sugar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index c4ee2430cd..bd203ee27e 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -5,7 +5,7 @@ * Review Manager: [Holly Borla](https://github.com/hborla) * Status: **Active Review (May 2 - May 16, 2025)** * Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. -* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ## Introduction From 1915847451e06eb8a0f53538527b55973575c64d Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 2 May 2025 14:37:17 -0700 Subject: [PATCH 289/505] Accept SE-0476. (#2831) --- proposals/0476-abi-attr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0476-abi-attr.md b/proposals/0476-abi-attr.md index e7bea6bf57..6bd6c3efa6 100644 --- a/proposals/0476-abi-attr.md +++ b/proposals/0476-abi-attr.md @@ -3,9 +3,9 @@ * Proposal: [SE-0476](0476-abi-attr.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Active Review (April 11 - April 25, 2025)** +* Status: **Accepted** * Implementation: behind experimental feature `ABIAttribute` (refinements in [swiftlang/swift#80383](https://github.com/swiftlang/swift/pull/80383)) -* Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) ([review](https://forums.swift.org/t/se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79233)) +* Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) ([review](https://forums.swift.org/t/se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79233)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79644)) ## Introduction From 1267bbda5130cd94bd859c964b9d3437db433b08 Mon Sep 17 00:00:00 2001 From: Naoki Hiroshima Date: Fri, 2 May 2025 17:08:25 -0700 Subject: [PATCH 290/505] Update 0483-inline-array-sugar.md (#2832) Typos --- proposals/0483-inline-array-sugar.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index bd203ee27e..146174dc75 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -19,7 +19,7 @@ We propose the introduction of type sugar for the `InlineArray` type, providing let fiveIntegers: InlineArray<5, Int> = .init(repeating: 99) ``` -Declaring this type is more cumbersome than its equivalent dyanmicaly-sized array, which has sugar for the type syntax: +Declaring this type is more cumbersome than its equivalent dynamically-sized array, which has sugar for the type syntax: ``` let fiveIntegers: [Int] = .init(repeating: 99, count: 5) @@ -45,7 +45,7 @@ Note that although it is used in the manner of an operator, `x` here serves more ## Detailed design -The new syntax consists of the value for the integer generic paramter and the type of the element generic paramter, separated by `x`. +The new syntax consists of the value for the integer generic parameter and the type of the element generic parameter, separated by `x`. This will be added to the grammar alongside the current type sugar: @@ -124,12 +124,12 @@ For multi-dimensional arrays, `[5 x [5 x Int]]` could be flattened to `[5 x 5 x The most obvious alternative here is the choice of separator. Other options include: - `[5 * Int]`, using the standard ASCII symbol for multiplication. -- `[5 ⨉ Int]`, the Unicode n-ary times operator. This looks nice but is impactical as not keyboard-accessible. +- `[5 ⨉ Int]`, the Unicode n-ary times operator. This looks nice but is impractical as not keyboard-accessible. - `[5; Int]` is what Rust uses, but appears to have little association with "times" or "many". Similarly other arbitrary punctuation e.g. `,` or `/` or `#`. - `[5 of Int]` is more verbose than `x` but could be considered more clear. It has the upside or downside, depending on your preference, of being almost, but not quite, grammatical. - `:` is of course ruled out as it is used for dictionary literals. -Note that `*` is an existing operator, and may lead to ambiguity in fuure when expressions can be used to determine the size: `[5 * N * Int]`. `x` is clearer in this case: `[5 * N x Int]`. It also avoids parsing ambiguity, as the grammar does not allow two identifiers in succession. But it would be less clear if `x` also appeared as an identifier: `[5 * x x Int]` (which is not yet permitted but may be in future use cases). +Note that `*` is an existing operator, and may lead to ambiguity in future when expressions can be used to determine the size: `[5 * N * Int]`. `x` is clearer in this case: `[5 * N x Int]`. It also avoids parsing ambiguity, as the grammar does not allow two identifiers in succession. But it would be less clear if `x` also appeared as an identifier: `[5 * x x Int]` (which is not yet permitted but may be in future use cases). This becomes more important if the future direction of a value equivalent is pursued. `[2 * 2 * 2]` could be interpreted as `[2, 2, 2, 2]`, `[4, 4,]`, or `[8]`. @@ -152,7 +152,7 @@ The order of size first, then type is determined by the ordering of the unsugare ### Whitespace around the delimeter -In theory, when using integer literals or `_` the whitespace could be omitted (`[5x_]` is unabiguously `[5 x _]`). However, special casing allowing whitespace omission is not desirable. +In theory, when using integer literals or `_` the whitespace could be omitted (`[5x_]` is unambiguously `[5 x _]`). However, special casing allowing whitespace omission is not desirable. ### Choice of brackets From 63b8dfcdbdc1a8508ea185c6e32e9b4c6863e0d0 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 3 May 2025 06:14:29 -0700 Subject: [PATCH 291/505] Fix dates for active reviews show correctly in dashboard. --- proposals/0474-yielding-accessors.md | 2 +- proposals/0475-observed.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index 2e9f24d22d..fc8702d683 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -3,7 +3,7 @@ * Proposal: [SE-0474](0474-yielding-accessors.md) * Authors: [Ben Cohen](https://github.com/airspeedswift), [Nate Chandler](https://github.com/nate-chandler), [Joe Groff](https://github.com/jckarter/) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Active Review (Apr 8...22)** +* Status: **Active Review (April 8...22, 2025)** * Vision: [A Prospective Vision for Accessors in Swift](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) * Implementation: Partially available on main behind the frontend flag `-enable-experimental-feature CoroutineAccessors` * Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), ([review](https://forums.swift.org/t/se-0474-yielding-accessors/79170)) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index 2df388465f..4f944e3f18 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -3,7 +3,7 @@ * Proposal: [SE-0475](0475-observed.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active Review (Apr 10...24)** +* Status: **Active Review (April 10...24, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79817 * Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) From eeef3f49cfd264ba016f599358dccccdd702e17a Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 3 May 2025 06:18:37 -0700 Subject: [PATCH 292/505] Add explicit end months for proposals. --- proposals/0474-yielding-accessors.md | 2 +- proposals/0475-observed.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index fc8702d683..1c9754dbde 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -3,7 +3,7 @@ * Proposal: [SE-0474](0474-yielding-accessors.md) * Authors: [Ben Cohen](https://github.com/airspeedswift), [Nate Chandler](https://github.com/nate-chandler), [Joe Groff](https://github.com/jckarter/) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Active Review (April 8...22, 2025)** +* Status: **Active Review (April 8 ... April 22, 2025)** * Vision: [A Prospective Vision for Accessors in Swift](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) * Implementation: Partially available on main behind the frontend flag `-enable-experimental-feature CoroutineAccessors` * Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), ([review](https://forums.swift.org/t/se-0474-yielding-accessors/79170)) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index 4f944e3f18..ccb1901934 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -3,7 +3,7 @@ * Proposal: [SE-0475](0475-observed.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active Review (April 10...24, 2025)** +* Status: **Active Review (April 10 ... April 24, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79817 * Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) From b9fd2786e75b126081067e2e8607249ccad67207 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Mon, 5 May 2025 09:33:05 -0400 Subject: [PATCH 293/505] Add link to second review of SE-0472. --- proposals/0472-task-start-synchronously-on-caller-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 75bfaec705..d5a3acd522 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -5,7 +5,7 @@ * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Returned for revision** * Implementation: https://github.com/swiftlang/swift/pull/79608 -* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) +* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([first review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ([second review](https://forums.swift.org/t/second-review-se-0472-starting-tasks-synchronously-from-caller-context/79683)) ## Introduction From d095422ecd7dce88da35897aaf5c719e2a42f88a Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 6 May 2025 10:55:58 -0700 Subject: [PATCH 294/505] SE-0474: Fix typo --- proposals/0474-yielding-accessors.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index 1c9754dbde..ddc572f4a8 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -559,7 +559,7 @@ Since it would typically be ambiguous whether the `yielding borrow` or `get` sho A `yielding` accessor lends the value it yields to its caller. The caller only has access to that value until it resumes the coroutine. After the coroutine is resumed, it has the opportunity to clean up. -This enables a `yielding borrow` or `mutate` to do interesting work such as constructing aggregates from its base object's fields: +This enables a `yielding borrow` or `mutate` to do interesting work, such as constructing a temporary aggregate from its base object's fields: ```swift struct Pair : ~Copyable { @@ -567,16 +567,16 @@ struct Pair : ~Copyable { var right: Right var reversed: Pair { - yielding borrow { + yielding mutate { let result = Pair(left: right, right: left) - yield result + yield &result self = .init(left: result.right, right: result.left) } } } ``` -That the borrow ends when the coroutine is resumed means that the lifetime of the lent value is strictly shorter than that of the base value. +That the access ends when the coroutine is resumed means that the lifetime of the lent value is strictly shorter than that of the base value. In the example above, the lifetime of `reversed` is shorter than that of the `Pair` it is called on. As discussed in the [accessors vision](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md), when a value is merely being projected from the base object and does not need any cleanup after being accessed, this is undesirably limiting: From 5d03375330e975cec9aa105eae257179b4f91a98 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 7 May 2025 00:42:56 -0500 Subject: [PATCH 295/505] Consistently format the 'Review:' header field of all Swift Testing proposals (#2837) --- proposals/testing/0001-refactor-bug-inits.md | 2 +- proposals/testing/0002-json-abi.md | 2 +- proposals/testing/0003-make-serialized-trait-api.md | 4 +--- ...-constrain-the-granularity-of-test-time-limit-durations.md | 4 +--- proposals/testing/0005-ranged-confirmations.md | 3 +-- proposals/testing/0006-return-errors-from-expect-throws.md | 2 +- proposals/testing/0007-test-scoping-traits.md | 2 +- proposals/testing/0008-exit-tests.md | 2 +- proposals/testing/0009-attachments.md | 2 +- proposals/testing/0010-evaluate-condition.md | 2 +- 10 files changed, 10 insertions(+), 15 deletions(-) diff --git a/proposals/testing/0001-refactor-bug-inits.md b/proposals/testing/0001-refactor-bug-inits.md index 385047be48..4d9a77b5e7 100644 --- a/proposals/testing/0001-refactor-bug-inits.md +++ b/proposals/testing/0001-refactor-bug-inits.md @@ -4,7 +4,7 @@ * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Status: **Implemented (Swift 6.0)** * Implementation: [swiftlang/swift-testing#401](https://github.com/swiftlang/swift-testing/pull/401) -* Review: ([pitch](https://forums.swift.org/t/pitch-dedicated-bug-functions-for-urls-and-ids/71842)), ([acceptance](https://forums.swift.org/t/swt-0001-dedicated-bug-functions-for-urls-and-ids/71842/2)) +* Review: ([pitch](https://forums.swift.org/t/pitch-dedicated-bug-functions-for-urls-and-ids/71842)) ([acceptance](https://forums.swift.org/t/swt-0001-dedicated-bug-functions-for-urls-and-ids/71842/2)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0002-json-abi.md b/proposals/testing/0002-json-abi.md index e13bb1ad37..516b986838 100644 --- a/proposals/testing/0002-json-abi.md +++ b/proposals/testing/0002-json-abi.md @@ -5,7 +5,7 @@ * Status: **Implemented (Swift 6.0)** * Implementation: [swiftlang/swift-testing#383](https://github.com/swiftlang/swift-testing/pull/383), [swiftlang/swift-testing#402](https://github.com/swiftlang/swift-testing/pull/402) -* Review: ([pitch](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627)), ([acceptance](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627/4)) +* Review: ([pitch](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627)) ([acceptance](https://forums.swift.org/t/pitch-a-stable-json-based-abi-for-tools-integration/72627/4)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0003-make-serialized-trait-api.md b/proposals/testing/0003-make-serialized-trait-api.md index 73a6fbe1a2..488035bedf 100644 --- a/proposals/testing/0003-make-serialized-trait-api.md +++ b/proposals/testing/0003-make-serialized-trait-api.md @@ -5,9 +5,7 @@ * Status: **Implemented (Swift 6.0)** * Implementation: [swiftlang/swift-testing#535](https://github.com/swiftlang/swift-testing/pull/535) -* Review: -([pitch](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147)), -([acceptance](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147/5)) +* Review: ([pitch](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147)) ([acceptance](https://forums.swift.org/t/pitch-make-serialized-trait-public-api/73147/5)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md b/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md index 4817bc955c..ea00728fca 100644 --- a/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md +++ b/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md @@ -5,9 +5,7 @@ * Status: **Implemented (Swift 6.0)** * Implementation: [swiftlang/swift-testing#534](https://github.com/swiftlang/swift-testing/pull/534) -* Review: -([pitch](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146)), -([acceptance](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146/3)) +* Review: ([pitch](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146)) ([acceptance](https://forums.swift.org/t/pitch-constrain-the-granularity-of-test-time-limit-durations/73146/3)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0005-ranged-confirmations.md b/proposals/testing/0005-ranged-confirmations.md index 93997c86e9..7a53229ae2 100644 --- a/proposals/testing/0005-ranged-confirmations.md +++ b/proposals/testing/0005-ranged-confirmations.md @@ -5,8 +5,7 @@ * Status: **Implemented (Swift 6.1)** * Bug: rdar://138499457 * Implementation: [swiftlang/swift-testing#598](https://github.com/swiftlang/swift-testing/pull/598), [swiftlang/swift-testing#689](https://github.com/swiftlang/swift-testing/pull689) -* Review: ([pitch](https://forums.swift.org/t/pitch-range-based-confirmations/74589)), - ([acceptance](https://forums.swift.org/t/pitch-range-based-confirmations/74589/7)) +* Review: ([pitch](https://forums.swift.org/t/pitch-range-based-confirmations/74589)) ([acceptance](https://forums.swift.org/t/pitch-range-based-confirmations/74589/7)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0006-return-errors-from-expect-throws.md b/proposals/testing/0006-return-errors-from-expect-throws.md index c1ba77d5df..eee9037cd3 100644 --- a/proposals/testing/0006-return-errors-from-expect-throws.md +++ b/proposals/testing/0006-return-errors-from-expect-throws.md @@ -5,7 +5,7 @@ * Status: **Implemented (Swift 6.1)** * Bug: rdar://138235250 * Implementation: [swiftlang/swift-testing#780](https://github.com/swiftlang/swift-testing/pull/780) -* Review: ([pitch](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567)), ([acceptance](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567/5)) +* Review: ([pitch](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567)) ([acceptance](https://forums.swift.org/t/pitch-returning-errors-from-expect-throws/75567/5)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0007-test-scoping-traits.md b/proposals/testing/0007-test-scoping-traits.md index d397a792e9..619d1f48c6 100644 --- a/proposals/testing/0007-test-scoping-traits.md +++ b/proposals/testing/0007-test-scoping-traits.md @@ -4,7 +4,7 @@ * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Status: **Implemented (Swift 6.1)** * Implementation: [swiftlang/swift-testing#733](https://github.com/swiftlang/swift-testing/pull/733), [swiftlang/swift-testing#86](https://github.com/swiftlang/swift-testing/pull/86) -* Review: ([pitch](https://forums.swift.org/t/pitch-custom-test-execution-traits/75055)), ([review](https://forums.swift.org/t/proposal-test-scoping-traits/76676)), ([acceptance](https://forums.swift.org/t/proposal-test-scoping-traits/76676/3)) +* Review: ([pitch](https://forums.swift.org/t/pitch-custom-test-execution-traits/75055)) ([review](https://forums.swift.org/t/proposal-test-scoping-traits/76676)) ([acceptance](https://forums.swift.org/t/proposal-test-scoping-traits/76676/3)) > [!NOTE] > This proposal was accepted before Swift Testing began using the Swift diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index ce4f95def1..a543c03981 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -7,7 +7,7 @@ * Bug: [apple/swift-testing#157](https://github.com/apple/swift-testing/issues/157) * Implementation: [apple/swift-testing#324](https://github.com/swiftlang/swift-testing/pull/324) * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/fdfc7867df4e35e29b2a24edee34ea4412ec15b0/proposals/testing/0008-exit-tests.md) -* Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0008-exit-tests/79553)) ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)), ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)), ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) +* Review: ([pitch](https://forums.swift.org/t/pitch-exit-tests/78071)) ([review](https://forums.swift.org/t/st-0008-exit-tests/78692)) ([second review](https://forums.swift.org/t/second-review-st-0008-exit-tests/79198)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0008-exit-tests/79553)) ## Introduction diff --git a/proposals/testing/0009-attachments.md b/proposals/testing/0009-attachments.md index 8fee84e792..e9e23102ee 100644 --- a/proposals/testing/0009-attachments.md +++ b/proposals/testing/0009-attachments.md @@ -6,7 +6,7 @@ * Status: **Implemented (Swift 6.2)** * Bug: [swiftlang/swift-testing#714](https://github.com/swiftlang/swift-testing/issues/714) * Implementation: [swiftlang/swift-testing#973](https://github.com/swiftlang/swift-testing/pull/973) -* Review: ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0009-attachments/79193)), ([review](https://forums.swift.org/t/st-0009-attachments/78698)), ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) +* Review: ([pitch](https://forums.swift.org/t/pitch-attachments/78072)) ([review](https://forums.swift.org/t/st-0009-attachments/78698)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-st-0009-attachments/79193)) ## Introduction diff --git a/proposals/testing/0010-evaluate-condition.md b/proposals/testing/0010-evaluate-condition.md index 6a68caad10..d6a7336ff1 100644 --- a/proposals/testing/0010-evaluate-condition.md +++ b/proposals/testing/0010-evaluate-condition.md @@ -6,7 +6,7 @@ * Status: **Implemented (Swift 6.2)** * Bug: [swiftlang/swift-testing#903](https://github.com/swiftlang/swift-testing/issues/903) * Implementation: [swiftlang/swift-testing#909](https://github.com/swiftlang/swift-testing/pull/909), [swiftlang/swift-testing#1097](https://github.com/swiftlang/swift-testing/pull/1097) -* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)), ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)), ([acceptance](https://forums.swift.org/t/accepted-st-0010-public-api-to-evaluate-conditiontrait/79577)) +* Review: ([pitch](https://forums.swift.org/t/pitch-introduce-conditiontrait-evaluate/77242)) ([review](https://forums.swift.org/t/st-0010-public-api-to-evaluate-conditiontrait/79232)) ([acceptance](https://forums.swift.org/t/accepted-st-0010-public-api-to-evaluate-conditiontrait/79577)) ## Introduction From e649f9c15811672202be7e3786de3fd733f2609f Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Wed, 7 May 2025 13:03:47 -0700 Subject: [PATCH 296/505] Add use cases --- proposals/testing/XXXX-issue-severity-warning.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 05c122ff61..ed4c691d4d 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -15,6 +15,21 @@ I propose introducing a new API to Swift Testing that allows developers to recor Currently, when an issue arises during a test, the only possible outcome is to mark the test as failed. This presents a challenge for users who want a deeper insight into the events occurring within their tests. By introducing a dedicated mechanism to record issues that do not cause test failure, users can more effectively inspect and diagnose problems at runtime and review results afterward. This enhancement provides greater flexibility and clarity in test reporting, ultimately improving the debugging and analysis process. +### Use Cases + +- Warning about a Percentage Discrepancy in Image Comparison: + - Scenario: When comparing two images to assess their similarity, a warning can be triggered if there's a 95% pixel match, while a test failure is set at a 90% similarity threshold. + - Reason: In practices like snapshot testing, minor changes (such as a timestamp) might cause a discrepancy. Setting a 90% match as a pass ensures test integrity. However, a warning at 95% alerts testers that, although the images aren't identical, the test has passed, which may warrant further investigation. +- Warning for Duplicate Argument Inputs in Tests: + - Scenario: In a test library, issue a warning if a user inputs the same argument twice, rather than flagging an error. + - Reason: Although passing the same argument twice might not be typical, some users may have valid reasons for doing so. Thus, a warning suffices, allowing flexibility without compromising the test's execution. +- Warning for Recoverable Unexpected Events: + - Scenario: During an integration test where data is retrieved from a server, a warning can be issued if the primary server is down, prompting a switch to an alternative server. Usually mocking is the solution for this but may not test everything needed for an integration test. + - Reason: Since server downtime might happen and can be beyond the tester's control, issuing a warning rather than a failure helps in debugging and understanding potential issues without impacting the test's overall success. +- Warning for a retry during setup for a test: + - Scenario: During test setup part of your code may be configured to retry, it would be nice to notify in the results that a retry happened + - Reason: This makes sense to be a warning and not a failure because if the retry succeeds the test may still verify the code correctly + ## Proposed solution We propose introducing a new property on `Issue` in Swift Testing called `Severity`, that represents if an issue is a `warning` or an `error`. The default Issue severity will still be `error` and users can set the severity when they record an issue. From d51c8e8d9d58a0d062eaefadf5554edd6f29f7c6 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Wed, 7 May 2025 13:09:16 -0700 Subject: [PATCH 297/505] Updates based on comments and future direction --- .../testing/XXXX-issue-severity-warning.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index ed4c691d4d..6222ea240a 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -4,8 +4,8 @@ * Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) * Review Manager: TBD * Status: **Pitched** -* Bug: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) * Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) +* Review: ([pitch](https://forums.swift.org/...)) ## Introduction @@ -31,7 +31,7 @@ Currently, when an issue arises during a test, the only possible outcome is to m - Reason: This makes sense to be a warning and not a failure because if the retry succeeds the test may still verify the code correctly ## Proposed solution -We propose introducing a new property on `Issue` in Swift Testing called `Severity`, that represents if an issue is a `warning` or an `error`. +We propose introducing a new property on `Issue` in Swift Testing called `severity`, that represents if an issue is a `warning` or an `error`. The default Issue severity will still be `error` and users can set the severity when they record an issue. Test authors will be able to inspect if the issue is a failing issue and will be able to check the severity. @@ -45,8 +45,9 @@ We introduce a Severity enum to categorize issues detected during testing. This The `Severity` enum: ```swift - public enum Severity: Sendable { - /// The severity level for an issue which should be noted but is not +extension Issue { + // ... + public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { /// The severity level for an issue which should be noted but is not /// necessarily an error. /// /// An issue with warning severity does not cause the test it's associated @@ -59,6 +60,8 @@ The `Severity` enum: /// marked as a failure. case error } + // ... +} ``` *Recording Non-Failing Issues* @@ -121,6 +124,12 @@ This revision aims to clarify the functionality and usage of the `Severity` enum - Severity-Only Checking: We deliberated not exposing `isFailure` and relying solely on `severity` checks. However, this was rejected because it would require test authors to overhaul their code should we introduce additional severity levels in the future. By providing `isFailure`, we offer a straightforward way to determine test outcome impact, complementing the severity feature. +## Future directions + +- In the future I could see the warnings being able to be promoted to errors in order to run with a more strict testing configuration + +- In the future I could see adding other levels of severity such as Info and Debug for users to create issues with other information. + ## Acknowledgments Thanks to Stuart Montgomery for creating and implementing severity in Swift Testing. From a9cff4ff7ed87381028a38b9a844283404a79cb8 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Wed, 7 May 2025 13:11:20 -0700 Subject: [PATCH 298/505] Add pitch link --- proposals/testing/XXXX-issue-severity-warning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 6222ea240a..dee36e088a 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -5,7 +5,7 @@ * Review Manager: TBD * Status: **Pitched** * Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -* Review: ([pitch](https://forums.swift.org/...)) +* Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285) ## Introduction From 12448481de26eb801d4824bb4faa93b08e528906 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Wed, 7 May 2025 15:04:12 -0700 Subject: [PATCH 299/505] Address the rounds of feedback with some more behavioral refinements and an adjustment to the naming of `Observed` to now name as `Observations` (#2838) * Address the rounds of feedback with some more behavioral refinements and an adjustment to the naming of `Observed` to now name as `Observations` * Correct the next to last example to the latest mechansim's output --- proposals/0475-observed.md | 115 +++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 29 deletions(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index ccb1901934..d421aba55f 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -51,7 +51,7 @@ that do not use UI as seamlessly as those that do. ## Proposed solution -This proposal adds a straightforward new tool: a closure-initialized `Observed` +This proposal adds a straightforward new tool: a closure-initialized `Observations` type that acts as a sequence of closure-returned values, emitting new values when something within that closure changes. @@ -76,12 +76,12 @@ final class Person { } ``` -Creating an `Observed` asynchronous sequence is straightforward. This example +Creating an `Observations` asynchronous sequence is straightforward. This example creates an asynchronous sequence that yields a value every time the composed `name` property is updated: ```swift -let names = Observed { person.name } +let names = Observations { person.name } ``` However if the example was more complex and the `Person` type in the previous @@ -89,7 +89,7 @@ example had a `var pet: Pet?` property which was also `@Observable` then the closure can be written with a more complex expression. ```swift -let greetings = Observed { +let greetings = Observations { if let pet = person.pet { return "Hello \(person.name) and \(pet.name)" } else { @@ -158,7 +158,7 @@ is expected to emit the same values in both tasks. ```swift -let names = Observed { person.firstName + " " + person.lastName } +let names = Observations { person.firstName + " " + person.lastName } Task.detached { for await name in names { @@ -185,7 +185,7 @@ properties as a `String`. This has no sense of termination locally within the construction. Making the return value of that closure be a lifted `Optional` suffers the potential conflation of a terminal value and a value that just happens to be nil. This means that there is a need for a second construction mechanism that offers a -way of expressing that the `Observed` sequence iteration will run until finished. +way of expressing that the `Observations` sequence iteration will run until finished. For the example if `Person` then has a new optional field of `homePage` which is an optional URL it then means that the construction can disambiguate @@ -206,7 +206,7 @@ final class Person { } } -let hosts = Observed.untilFinished { [weak person] in +let hosts = Observations.untilFinished { [weak person] in if let person { .next(person.homePage?.host) } else { @@ -218,7 +218,7 @@ let hosts = Observed.untilFinished { [weak person] in Putting this together grants a signature as such: ```swift -public struct Observed: AsyncSequence, Sendable { +public struct Observations: AsyncSequence, Sendable { public init( @_inheritActorContext _ emit: @escaping @isolated(any) @Sendable () throws(Failure) -> Element ) @@ -230,12 +230,12 @@ public struct Observed: AsyncSequence, Sendab public static func untilFinished( @_inheritActorContext _ emit: @escaping @isolated(any) @Sendable () throws(Failure) -> Iteration - ) -> Observed + ) -> Observations } ``` Picking the initializer apart first captures the current isolation of the -creation of the `Observed` instance. Then it captures a `Sendable` closure that +creation of the `Observations` instance. Then it captures a `Sendable` closure that inherits that current isolation. This means that the closure may only execute on the captured isolation. That closure is run to determine which properties are accessed by using Observation's `withObservationTracking`. So any access to a @@ -253,19 +253,19 @@ The closure has two other features that are important for common usage; firstly the closure is typed-throws such that any access to that emission closure will potentially throw an error if the developer specifies. This allows for complex composition of potentially failable systems. Any thrown error will mean that the -`Observed` sequence is complete and loops that are currently iterating will +`Observations` sequence is complete and loops that are currently iterating will terminate with that given failure. Subsequent calls then to `next` on those iterators will return `nil` - indicating that the iteration is complete. ## Behavioral Notes -There are a number of scenarios of iteration that can occur. These can range from production rate to iteration rate differentials to isolation differentials to concurrent iterations. Enumerating all possible combinations is of course not possible but the following explanations should illustrate some key usages. `Observed` does not make unsafe code somehow safe - the concepts of isolation protection or exclusive access are expected to be brought to the table by the types involved. It does however require the enforcements via Swift Concurrency particularly around the marking of the types and closures being required to be `Sendable`. The following examples will only illustrate well behaved types and avoid fully unsafe behavior that would lead to crashes because the types being used are circumventing that language safety. +There are a number of scenarios of iteration that can occur. These can range from production rate to iteration rate differentials to isolation differentials to concurrent iterations. Enumerating all possible combinations is of course not possible but the following explanations should illustrate some key usages. `Observations` does not make unsafe code somehow safe - the concepts of isolation protection or exclusive access are expected to be brought to the table by the types involved. It does however require the enforcements via Swift Concurrency particularly around the marking of the types and closures being required to be `Sendable`. The following examples will only illustrate well behaved types and avoid fully unsafe behavior that would lead to crashes because the types being used are circumventing that language safety. The most trivial case is where a single produce and single consumer are active. In this case they both are isolated to the same isolation domain. For ease of reading; this example is limited to the `@MainActor` but could just as accurately be represented in some other actor isolation. ```swift @MainActor -func iterate(_ names: Observed) async { +func iterate(_ names: Observations) async { for await name in names { print(name) } @@ -276,7 +276,7 @@ func example() async throws { let person = Person(firstName: "", lastName: "") // note #2 - let names = Observed { + let names = Observations { person.name } @@ -311,7 +311,7 @@ Next is the case where the mutation of the properties out-paces the iteration. A ```swift @MainActor -func iterate(_ names: Observed) async { +func iterate(_ names: Observations) async { for await name in names { print(name) try? await Task.sleep(for: .seconds(0.095)) @@ -323,7 +323,7 @@ func example() async throws { let person = Person(firstName: "", lastName: "") // @MainActor is captured here as the isolation - let names = Observed { + let names = Observations { person.name } @@ -353,7 +353,7 @@ The result of the observation may print the following output, but the primary pr This case dropped the last value of the iteration because the accumulated differential exceeded the production; however the potentially confusing part here is that the sleep in the iterate competes with the scheduling in the emitter. This becomes clearer of a relationship when the boundaries of isolation are crossed. -Observed can be used across boundaries of concurrency. This is where the iteration is done on a different isolation than the mutations. The types however are accessed always in the isolation that the creation of the Observed closure is executed. This means that if the `Observed` instance is created on the main actor then the subsequent calls to the closure will be done on the main actor. +Observations can be used across boundaries of concurrency. This is where the iteration is done on a different isolation than the mutations. The types however are accessed always in the isolation that the creation of the Observations closure is executed. This means that if the `Observations` instance is created on the main actor then the subsequent calls to the closure will be done on the main actor. ```swift @globalActor @@ -362,7 +362,7 @@ actor ExcplicitlyAnotherActor: GlobalActor { } @ExcplicitlyAnotherActor -func iterate(_ names: Observed) async { +func iterate(_ names: Observations) async { for await name in names { print(name) } @@ -373,7 +373,7 @@ func example() async throws { let person = Person(firstName: "", lastName: "") // @MainActor is captured here as the isolation - let names = Observed { + let names = Observations { person.name } @@ -402,12 +402,12 @@ The values still will be conjoined as expected for their changes, however just l If the `iterate` function was altered to have a similar `sleep` call that exceeded the production then it would result in similar behavior of the previous producer/consumer rate case. -The next behavioral illustration is the value distribution behaviors; this is where two or more copies of an `Observed` are iterated concurrently. +The next behavioral illustration is the value distribution behaviors; this is where two or more copies of an `Observations` are iterated concurrently. ```swift @MainActor -func iterate1(_ names: Observed) async { +func iterate1(_ names: Observations) async { for await name in names { print("A", name) } @@ -415,7 +415,7 @@ func iterate1(_ names: Observed) async { @MainActor -func iterate2(_ names: Observed) async { +func iterate2(_ names: Observations) async { for await name in names { print("B", name) } @@ -426,7 +426,7 @@ func example() async throws { let person = Person(firstName: "", lastName: "") // @MainActor is captured here as the isolation - let names = Observed { + let names = Observations { person.name } @@ -452,18 +452,64 @@ This situation commonly comes up when the asynchronous sequence is stored as a p ``` A 0 0 +B 0 0 B 1 1 A 1 1 -B 2 2 A 2 2 +B 2 2 A 3 3 B 3 3 -A 4 4 B 4 4 +A 4 4 ``` The same rate commentary applies here as before but an additional wrinkle is that the delivery between the A and B sides is non-determinstic (in some cases it can deliver as A then B and other cases B then A). +There is one additional clarification of expected behaviors - the iterators should have an initial state to determine if that specific iterator is active yet or not. This means that upon the first call to next the value will be obtained by calling into the isolation of the constructing closure to "prime the pump" for observation and obtain a first value. This can be encapsulated into an exaggerated test example as the following: + +```swift + +@MainActor +func example() async { + let person = Person(firstName: "0", lastName: "0") + + // @MainActor is captured here as the isolation + let names = Observations { + person.name + } + Task { + try await Task.sleep(for: .seconds(2)) + person.firstName = "1" + person.lastName = "1" + + } + Task { + for await name in names { + print("A = \(name)") + } + } + Task { + for await name in names { + print("B = \(name)") + } + } + try? await Task.sleep(for: .seconds(10)) +} + +await example() +``` + +Which results in the following output: + +``` +A = 0 0 +B = 0 0 +B = 1 1 +A = 1 1 +``` + +This ensures the first value is produced such that every sequence will always be primed with a value and will eventually come to a mutual consistency to the values no matter the isolation. + ## Effect on ABI stability & API resilience This provides no alteration to existing APIs and is purely additive. However it @@ -478,19 +524,19 @@ need to be disambiguated. This proposal does not change the fact that the spectrum of APIs may range from favoring `AsyncSequence` properties to purely `@Observable` models. They both have their place. However the calculus of determining the best exposition may -be slightly more refined now with `Observed`. +be slightly more refined now with `Observations`. If a type is representative of a model and is either transactional in that some properties may be linked in their meaning and would be a mistake to read in a disjoint manner (the tearing example from previous sections), or if the model interacts with UI systems it now more so than ever makes sense to use -`@Observable` especially with `Observed` now as an option. Some cases may have +`@Observable` especially with `Observations` now as an option. Some cases may have previously favored exposing those `AsyncSequence` properties and would now -instead favor allowing the users of those APIs compose things by using `Observed`. +instead favor allowing the users of those APIs compose things by using `Observations`. The other side of the spectrum will still exist but now is more strongly relegated to types that have independent value streams that are more accurately described as `AsyncSequence` types being exposed. The suggestion for API authors -is that now with `Observed` favoring `@Observable` perhaps should take more +is that now with `Observations` favoring `@Observable` perhaps should take more of a consideration than it previously did. ## Alternatives Considered @@ -527,3 +573,14 @@ parameter of an isolation that was non-nullable this could be achieved for that however up-coming changes to Swift's Concurrency will make this approach less appealing. If this route would be taken it would restrict the potential advanced uses cases where the construction would be in an explicitly non-isolated context. + +A name of `Observed` was considered, however that type name led to some objections that +rightfully claimed it was a bit odd as a name since it is bending the "nouning" of names +pretty strongly. This lead to the alternate name `Observations` which strongly leans +into the plurality of the name indicating that it is more than one observation - lending +to the sequence nature. + +It was seriously considered during the feedback to remove the initializer methods and only +have construction by two global functions named `observe` and `observeUntilFinished` +that would act as the current initializer methods. Since the types must still be returned +to allow for storing that return into a property it does not offer a distinct advantage. From cc662fd86b38401b70a73e679829b9b167761e61 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Wed, 7 May 2025 18:07:45 -0400 Subject: [PATCH 300/505] Extend review of SE-0475 (#2839) --- proposals/0475-observed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index d421aba55f..f176573c28 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -3,7 +3,7 @@ * Proposal: [SE-0475](0475-observed.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active Review (April 10 ... April 24, 2025)** +* Status: **Active Review (April 10 ... May 13, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/79817 * Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) From a8eb41111d916b5a4f1a24fb3969fcba9e0a9057 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 9 May 2025 10:53:50 -0700 Subject: [PATCH 301/505] Add a review proposal announcement template for Swift Testing to process documentation (#2842) --- process.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/process.md b/process.md index fe32a48828..3408e2d567 100644 --- a/process.md +++ b/process.md @@ -241,7 +241,7 @@ A given proposal can be in one of several states: [swift-evolution-repo]: https://github.com/swiftlang/swift-evolution "Swift evolution repository" [swift-evolution-staging]: https://github.com/swiftlang/swift-evolution-staging "Swift evolution staging repository" -[proposal-reviews]: https://forums.swift.org/c/evolution/proposal-reviews "'Proposal reviews' category of the Swift forums" +[proposal-reviews]: https://forums.swift.org/c/evolution/proposal-reviews "'Proposal reviews' subcategory of the Swift forums" [status-page]: https://www.swift.org/swift-evolution [preview-package]: https://github.com/apple/swift-standard-library-preview/ [language-steering-group]: https://www.swift.org/language-steering-group @@ -253,11 +253,15 @@ A given proposal can be in one of several states: ## Review announcement -When a proposal enters review, a new topic will be posted to the ["Proposal Reviews" section of the Swift forums][proposal-reviews] -using the following template: +When a proposal enters review, a new topic will be posted to the +["Proposal Reviews" subcategory of the Swift forums][proposal-reviews] using the +relevant announcement template below: --- +

    +Swift language, compiler, and standard library + Hello Swift community, The review of "\<\>" begins now and runs through \<\ + +
    +Swift Testing public interfaces and features + +Hello Swift community, + +The review of "\<\>" begins now and runs through \<\>. +The proposal is available here: + +> https://linkToProposal + +Reviews are an important part of the Swift evolution process. All review +feedback should be either on this forum thread or, if you would like to keep +your feedback private, directly to the review manager. When emailing the review +manager directly, please keep the proposal link at the top of the message. + +##### Trying it out + +To try this feature out, add a dependency to the `main` branch of +`swift-testing` to your package: + +```swift +dependencies: [ + ... + .package(url: "https://github.com/swiftlang/swift-testing.git", branch: "main"), +] +``` + +Then, add a target dependency to your test target: + +```swift +.testTarget( + ... + dependencies: [ + ... + .product(name: "Testing", package: "swift-testing"), + ] +``` + +Finally, import Swift Testing using `@_spi(Experimental) import Testing`. + +##### What goes into a review? + +The goal of the review process is to improve the proposal under review through +constructive criticism and, eventually, determine the direction of Swift. When +writing your review, here are some questions you might want to answer in your +review: + +* What is your evaluation of the proposal? +* Is the problem being addressed significant enough to warrant a change to Swift + Testing? +* Does this proposal fit well with the feel and direction of Swift Testing? +* If you have used other languages or libraries with a similar feature, how do + you feel that this proposal compares to those? +* How much effort did you put into your review? A glance, a quick reading, or an + in-depth study? + +More information about the Swift evolution process is available at + +> https://github.com/swiftlang/swift-evolution/blob/main/process.md + +Thank you, + +-\<\> + +Review Manager + +
    From 2668f20b72bcb1c224fddea8846990488398288f Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 12 May 2025 08:24:36 -0700 Subject: [PATCH 302/505] Mark SE-0461 as implemented in Swift 6.2. (#2844) --- proposals/0461-async-function-isolation.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index f8712cde7d..b81520083c 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -3,10 +3,9 @@ * Proposal: [SE-0461](0461-async-function-isolation.md) * Authors: [Holly Borla](https://github.com/hborla), [John McCall](https://github.com/rjmccall) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Accepted with modifications** +* Status: **Implemented (Swift 6.2)** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) -* Implementation: On `main` behind `-enable-experimental-feature NonIsolatedAsyncInheritsIsolationFromContext` -* Upcoming Feature Flag: `AsyncCallerExecution` +* Upcoming Feature Flag: `NonisolatedNonsendingByDefault` * Previous Proposal: [SE-0338](0338-clarify-execution-non-actor-async.md) * Review: ([pitch](https://forums.swift.org/t/pitch-inherit-isolation-by-default-for-async-functions/74862)) ([first review](https://forums.swift.org/t/se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/77987)) ([acceptance with focused re-review](https://forums.swift.org/t/accepted-with-modifications-and-focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78920)) ([second review](https://forums.swift.org/t/focused-re-review-se-0461-run-nonisolated-async-functions-on-the-callers-actor-by-default/78921)) ([second acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0461-run-nonisolated-async-functions-on-the-caller-s-actor-by-default/79117)) From 5ff1fa18664ca5277d35fd6eb757082d0eee441b Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Mon, 12 May 2025 20:13:20 +0200 Subject: [PATCH 303/505] [SE-0461] Fix typo (#2834) --- proposals/0461-async-function-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index b81520083c..c123ce36b7 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -288,7 +288,7 @@ actor MyActor { In the above code, the call to `x.performAsync()` continues running on the `self` actor instance. The code does not produce a data-race safety error, because the `NotSendable` instance `x` does not leave the actor. In other -words, the arguments are not send across an isolation boundary when calling +words, the arguments are not sent across an isolation boundary when calling `performAsync` by default. This behavior is accomplished by implicitly passing an optional actor parameter From 408dd1640e8cf434a33c8be0893356499f12fb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C5=93ur?= Date: Mon, 12 May 2025 20:15:12 +0200 Subject: [PATCH 304/505] typo: ends -> begins (#2840) --- proposals/0433-mutex.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0433-mutex.md b/proposals/0433-mutex.md index f98a9cef27..cdb7946574 100644 --- a/proposals/0433-mutex.md +++ b/proposals/0433-mutex.md @@ -330,7 +330,7 @@ mutex.withLock { // borrow access ends do { - // borrow access ends + // borrow access begins let locked = mutex.lock() ... From 1190985f0afada80964b9a91208fb73eb2ea830e Mon Sep 17 00:00:00 2001 From: Itai Ferber Date: Mon, 12 May 2025 18:48:49 -0400 Subject: [PATCH 305/505] Allow Additional Arguments to `@dynamicMemberLookup` Subscripts (#2814) * Add proposal for Allow Additional Arguments to `@dynamicMemberLookup` Subscripts * Incorporate pitch thread feedback * Update review manager * Assign SE-0484 --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- ...-args-to-dynamicmemberlookup-subscripts.md | 281 ++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md diff --git a/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md new file mode 100644 index 0000000000..a6664a2b3d --- /dev/null +++ b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md @@ -0,0 +1,281 @@ +# Allow Additional Arguments to `@dynamicMemberLookup` Subscripts + +* Proposal: [SE-0484](0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md) +* Authors: [Itai Ferber](https://github.com/itaiferber) +* Review Manager: [Xiaodi Wu](https://github.com/xwu) +* Status: **Active review (May 12...25, 2025)** +* Implementation: [swiftlang/swift#81148](https://github.com/swiftlang/swift/pull/81148) +* Previous Proposals: [SE-0195](0195-dynamic-member-lookup.md), [SE-0252](0252-keypath-dynamic-member-lookup.md) +* Review: ([pitch](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558)) + +## Introduction + +SE-0195 and SE-0252 introduced and refined `@dynamicMemberLookup` to provide type-safe "dot"-syntax access to arbitrary members of a type by reflecting the existence of certain `subscript(dynamicMember:)` methods on that type, turning + +```swift +let _ = x.member +x.member = 42 +ƒ(&x.member) +``` + +into + +```swift +let _ = x[dynamicMember: ] +x[dynamicMember: ] = 42 +ƒ(&x[dynamicMember: ]) +``` + +when `x.member` doesn't otherwise exist statically. Currently, in order to be eligible to satisfy `@dynamicMemberLookup` requirements, a subscript must: + +1. Take _exactly one_ argument with an explicit `dynamicMember` argument label, +2. Whose type is non-variadic and is either + * A `{{Reference}Writable}KeyPath`, or + * A concrete type conforming to `ExpressibleByStringLiteral` + +This proposal intends to relax the "exactly one" requirement above to allow eligible subscripts to take additional arguments after `dynamicMember` as long as they have a default value (or are variadic, and thus have an implicit default value). + +## Motivation + +Dynamic member lookup is often used to provide expressive and succinct API in wrapping some underlying data, be it a type-erased foreign language object (e.g., a Python `PyVal` or a JavaScript `JSValue`) or a native Swift type. This (and [`callAsFunction()`](0253-callable.md)) allow a generalized API interface such as + +```swift +struct Value { + subscript(_ property: String) -> Value { + get { ... } + set { ... } + } + + func invoke(_ method: String, _ args: Any...) -> Value { + ... + } +} + +let x: Value = ... +let _ = x["member"] +x["member"] = Value(42) +x.invoke("someMethod", 1, 2, 3) +``` + +to be expressed much more naturally: + +```swift +@dynamicMemberLookup +struct Value { + struct Method { + func callAsFunction(_ args: Any...) -> Value { ... } + } + + subscript(dynamicMember property: String) -> Value { + get { ... } + set { ... } + } + + subscript(dynamicMember method: String) -> Method { ... } +} + +let x: Value = ... +let _ = x.member +x.member = Value(42) +x.someMethod(1, 2, 3) +``` + +However, as wrappers for underlying data, sometimes interfaces like this need to be able to "thread through" additional information. For example, it might be helpful to provide information about call sites for debugging purposes: + +```swift +struct Value { + subscript( + _ property: String, + function: StaticString = #function, + file: StaticString = #fileID, + line: UInt = #line + ) -> Value { + ... + } + + func invokeMethod( + _ method: String, + function: StaticString = #function, + file: StaticString = #fileID, + line: UInt = #line, + _ args: Any... + ) -> Value { + ... + } +} +``` + +When additional arguments like this have default values, they don't affect the appearance of call sites at all: + +```swift +let x: Value = ... +let _ = x["member"] +x["member"] = Value(42) +x.invoke("someMethod", 1, 2, 3) +``` + +However, these are not valid for use with dynamic member lookup subscripts, since the additional arguments prevent subscripts from being eligible for dynamic member lookup: + +```swift +@dynamicMemberLookup // error: @dynamicMemberLookupAttribute requires 'Value' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path +struct Value { + subscript( + dynamicMember property: String, + function: StaticString = #function, + file: StaticString = #fileID, + line: UInt = #line + ) -> Value { + ... + } + + subscript( + dynamicMember method: String, + function: StaticString = #function, + file: StaticString = #fileID, + line: UInt = #line + ) -> Method { + ... + } +} +``` + +## Proposed solution + +We can amend the rules for such subscripts to make them eligible. With this proposal, in order to be eligible to satisfy `@dynamicMemberLookup` requirements, a subscript must: + +1. Take an initial argument with an explicit `dynamicMember` argument label, +2. Whose parameter type is non-variadic and is either: + * A `{{Reference}Writable}KeyPath`, or + * A concrete type conforming to `ExpressibleByStringLiteral`, +3. And whose following arguments (if any) are all either variadic or have a default value + +## Detailed design + +Since compiler support for dynamic member lookup is already robust, implementing this requires primarily: + +1. Type-checking of `@dynamicMemberLookup`-annotated declarations to also consider `subscript(dynamicMember:...)` methods following the above rules as valid, and +2. Syntactic transformation of `T.` to `T[dynamicMember:...]` in the constraint system to fill in default arguments expressions for any following arguments + +## Source compatibility + +This is largely an additive change with minimal impact to source compatibility. Types which do not opt in to `@dynamicMemberLookup` are unaffected, as are types which do opt in and only offer `subscript(dynamicMember:)` methods which take a single argument. + +However, types which opt in to `@dynamicMemberLookup` and currently offer an overload of `subscript(dynamicMember:...)`—which today is not eligible for consideration for dynamic member lookup—_may_ now select this overload when they wouldn't have before. + +### Overload resolution + +Dynamic member lookups go through regular overload resolution, with an additional disambiguation rule that prefers keypath-based subscript overloads over string-based ones. Since the `dynamicMember` argument to dynamic member subscripts is implicit, overloads of `subscript(dynamicMember:)` are primarily selected based on their return type (and typically for keypath-based subscripts, how that return type is used in forming the type of a keypath parameter). + +With this proposal, all arguments to `subscript(dynamicMember:...)` are still implicit, so overloads are still primarily selected based on return type, with the additional disambiguation rule that prefers overloads with fewer arguments over overloads with more arguments. (This rule applies "for free" since it already applies to method calls, which dynamic member lookups are transformed into.) + +This means that if a type today offers a valid `subscript(dynamicMember:) -> T` and a (currently-unconsidered) `subscript(dynamicMember:...) -> U`, + +1. If `T == U` then the former will still be the preferred overload in all circumstances +2. If `T` and `U` are compatible (and equally-specific) at a callsite then the former will still be the preferred overload +3. If `T` and `U` are incompatible, or if one is more specific than the other, then the more specific type will be preferred + +For example: + +```swift +@dynamicMemberLookup +struct A { + /* (1) */ subscript(dynamicMember member: String) -> String { ... } + /* (2) */ subscript(dynamicMember member: String, _: StaticString = #function) -> String { ... } +} + +@dynamicMemberLookup +struct B { + /* (3) */ subscript(dynamicMember member: String) -> String { ... } + /* (4) */ subscript(dynamicMember member: String, _: StaticString = #function) -> Int { ... } +} + +@dynamicMemberLookup +struct C { + /* (5) */ subscript(dynamicMember member: String) -> String { ... } + /* (6) */ subscript(dynamicMember member: String, _: StaticString = #function) -> String? { ... } +} + +// T == U +let _ = A().member // (1) preferred over (2); no ambiguity +let _: String = A().member // (1) preferred over (2); no ambiguity + +// T and U are compatible +let _: Any = A().member // (1) preferred over (2); no ambiguity +let _: Any = B().member // (3) preferred over (4); no ambiguity +let _: Any = C().member // (5) preferred over (6); no ambiguity + +// T and U are incompatible/differently-specific +let _: String = B().member // (3) +let _: Int = B().member // (4);️ would not previously compile +let _: String = C().member // (5); no ambiguity +let _: String? = C().member // (6) preferred over (5); ⚠️ previously (5) ⚠️ +``` + +This last case is the only source of behavior change: (6) was previously not considered a valid candidate, but has a return type more specific than (5), and is now picked at a callsite. + +In practice, it is expected that this situation is exceedingly rare. + +## ABI compatibility + +This feature is implemented entirely in the compiler as a syntactic transformation and has no impact on the ABI. + +## Implications on adoption + +The changes in this proposal require the adoption of a new version of the Swift compiler. + +## Alternatives considered + +The main alternative to this proposal is to not implement it, as: +1. It was noted in [the pitch thread](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558) that allowing additional arguments to dynamic member lookup widens the gap in capabilities between dynamic members and regular members — dynamic members would be able to + + 1. Have caller side effects (i.e., have access to `#function`, `#file`, `#line`, etc.), + 2. Constrain themselves via generics, and + 3. Apply isolation to themselves via `#isolation` + + where regular members cannot. However, (i) and (iii) are not considered an imbalance in functionality but instead are the raison d'être of this proposal. (ii) is also already possible today as dynamic member subscripts can be constrained via generics (and this is often used with keypath-based lookup). +2. This is possible to work around using explicit methods such as `get()` and `set(_:)`: + + ```swift + @dynamicMemberLookup + struct Value { + struct Property { + func get( + function: StaticString = #function, + file: StaticString = #file, + line: UInt = #line + ) -> Value { + ... + } + + func set( + _ value: Value, + function: StaticString = #function, + file: StaticString = #file, + line: UInt = #line + ) { + ... + } + } + + subscript(dynamicMember member: String) -> Property { ... } + } + + let x: Value = ... + let _ = x.member.get() // x.member + x.member.set(Value(42)) // x.member = Value(42) + ``` + + However, this feels non-idiomatic, and for long chains of getters and setters, can become cumbersome: + + ```swift + let x: Value = ... + let _ = x.member.get().inner.get().nested.get() // x.member.inner.nested + x.member.get().inner.get().nested.set(Value(42)) // x.member.inner.nested = Value(42) + ``` + +### Source compatibility + +It is possible to avoid the risk of the behavior change noted above by adjusting the constraint system to always prefer `subscript(dynamicMember:) -> T` overloads over `subscript(dynamicMember:...) -> U` overloads (if `T` and `U` are compatible), even if `U` is more specific than `T`. However, + +1. This would be a departure from the normal method overload resolution behavior that Swift developers are familiar with, and +2. If `T` were a supertype of `U`, it would be impossible to ever call the more specific overload except by direct subscript access From 624d429bf0c4adbdf7d0c1f448f8d771bcc56e11 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Mon, 12 May 2025 18:53:47 -0400 Subject: [PATCH 306/505] Add review link for SE-0484 (#2845) --- ...4-allow-additional-args-to-dynamicmemberlookup-subscripts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md index a6664a2b3d..1e3d05745c 100644 --- a/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md +++ b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md @@ -6,7 +6,7 @@ * Status: **Active review (May 12...25, 2025)** * Implementation: [swiftlang/swift#81148](https://github.com/swiftlang/swift/pull/81148) * Previous Proposals: [SE-0195](0195-dynamic-member-lookup.md), [SE-0252](0252-keypath-dynamic-member-lookup.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558)) +* Review: ([pitch](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558)) ([review](https://forums.swift.org/t/se-0484-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79853)) ## Introduction From d829c9777f6f3ec5d2a2781ae198665235a3ba2b Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 13 May 2025 04:46:57 -0700 Subject: [PATCH 307/505] Updates and edits for `OutputSpan` proposal --- proposals/nnnn-outputspan.md | 348 +++++++++++++++++++++++++++++------ 1 file changed, 291 insertions(+), 57 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index c642798fe3..0b8fb73d29 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -18,31 +18,31 @@ ## Introduction -Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. The memory represented by `OutputSpan` consists of a number of initialized elements, followed by uninitialized memory. The operations of `OutputSpan` can change the number of initialized elements in memory, unlike `MutableSpan` which always represents memory that is initialized. +Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. The memory represented by `OutputSpan` consists of a number of initialized elements, followed by uninitialized memory. The operations of `OutputSpan` can change the number of initialized elements in memory, unlike `MutableSpan` which always represent initialized memory representing a fixed number of elements. ## Motivation -Some standard library container types can delegate initialization of some or all of their storage to user code. Up to now, it has only been possible to do so with explicitly unsafe ways, which have also proven error-prone. The standard library provides this unsafe functionality with the closure-taking initializers `Array.init(unsafeUninitializedCapacity:initializingWith:)` and `String.init(unsafeUninitializedCapacity:initializingUTF8With:)`. +Some standard library container types can delegate initialization of some or all of their storage to user code. Up to now, it has only been possible to do so with explicitly unsafe functions, which have also proven error-prone. The standard library provides this unsafe functionality with the closure-taking initializers `Array.init(unsafeUninitializedCapacity:initializingWith:)` and `String.init(unsafeUninitializedCapacity:initializingUTF8With:)`. These functions have a few different drawbacks, most prominently their reliance on unsafe types, which makes them unpalatable in security-conscious environments. We continue addressing these issues with `OutputSpan` and `OutputRawSpan`, new non-copyable and non-escapable types that manage initialization of typed and untyped memory. -In addition to the new types, we will propose adding new API for some standard library types to take advantage of `OutputSpan` and `OutputRawSpan`, and improve upon the `Array` and `String` initializers mentioned above. +In addition to the new types, we propose adding new API for some standard library types to take advantage of `OutputSpan` and `OutputRawSpan`. ## Proposed solution #### OutputSpan -`OutputSpan` allows delegating the initialization of a type's memory, by providing access to an exclusively-borrowed view of a range of contiguous memory. `OutputSpan`'s contiguous memory consists of a prefix of initialized memory, followed by a suffix of uninitialized memory. Like `MutableSpan`, `OutputSpan` relies on two guarantees: (a) that it has exclusive access to the range of memory it represents, and (b) that the memory locations it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. `OutputSpan` performs bounds-checking on every access to preserve spatial safety. +`OutputSpan` allows delegating the initialization of a type's memory, by providing access to an exclusively-borrowed view of a range of contiguous memory. `OutputSpan`'s contiguous memory always consists of a prefix of initialized memory, followed by a suffix of uninitialized memory. `OutputSpan`'s operations manage the initialization state in order to preserve that invariant. The common usage pattern we expect to see for `OutputSpan` consists of passing it as an `inout` parameter to a function, allowing the function to produce an output by writing into a previously uninitialized region. -An `OutputSpan` provided by a container represents a mutation of that container, and is therefore an exclusive access. +Like `MutableSpan`, `OutputSpan` relies on two guarantees: (a) that it has exclusive access to the range of memory it represents, and (b) that the memory locations it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. `OutputSpan` performs bounds-checking on every access to preserve spatial safety. `OutputSpan` manages the initialization state of the memory in represents on behalf of the memory's owner. #### OutputRawSpan -`OutputRawSpan` allows delegating the initialization of heterogeneously-typed memory, such as memory being prepared by an encoder. It makes the same safety guarantees as `OutputSpan`. +`OutputRawSpan` allows delegating the initialization of heterogeneously-typed memory, such as memory being prepared by an encoder. It makes the same safety guarantees as `OutputSpan`, but manages untyped memory. #### Extensions to standard library types -The standard library will provide new container initializers that delegate to an `OutputSpan`. Delegated initialization generally requires a container to perform some operations after the initialization has happened. In the case of `Array` this is simply noting the number of initialized elements; in the case of `String` this consists of validating the input. This post-processing implies the need for a scope, and we believe that scope is best represented by a closure. The `Array` initializer will be as follows: +The standard library will provide new container initializers that delegate to an `OutputSpan`. Delegated initialization generally requires a container to perform some operations after the initialization has happened. In the case of `Array` this is simply noting the number of initialized elements; in the case of `String` this consists of validating the input, then noting metadata about the input. This post-processing implies the need for a scope, and we believe that scope is best represented by a closure. The `Array` initializer will be as follows: ```swift extension Array { @@ -65,7 +65,7 @@ Note: The eventual lifetime annotations proposal may adopt a syntax different th #### OutputSpan -`OutputSpan` is a simple representation of a partially-initialized region of memory. It is non-copyable in order to enforce exclusive access for mutations of its memory, as required by the law of exclusivity: +`OutputSpan` is a simple representation of a partially-initialized region of memory. It is non-copyable in order to enforce exclusive access during mutations of its memory, as required by the law of exclusivity: ````swift @frozen @@ -132,7 +132,7 @@ extension OutputSpan { @discardableResult @lifetime(self: copy self) public mutating func append( - from source: inout some IteratorProtocol + contentsOf source: inout some IteratorProtocol ) -> Bool /// Initialize this span's suffix with every element of the source. @@ -141,7 +141,7 @@ extension OutputSpan { /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( - fromContentsOf source: some Sequence + contentsOf source: some Sequence ) /// Initialize this span's suffix with every element of the source. @@ -150,7 +150,7 @@ extension OutputSpan { /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( - fromContentsOf source: Span + copying source: Span ) /// Initialize this span's suffix with every element of the source. @@ -159,7 +159,7 @@ extension OutputSpan { /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( - fromContentsOf source: UnsafeBufferPointer + copying source: UnsafeBufferPointer ) } @@ -169,8 +169,8 @@ extension OutputSpan where Element: ~Copyable { /// It is a precondition that the `OutputSpan`'s uninitialized suffix /// can contain every element of the source. @lifetime(self: copy self) - public mutating func moveAppend( - fromContentsOf source: inout OutputSpan + public mutating func append( + moving source: inout OutputSpan ) /// Initialize this span's suffix by moving every element from the source. @@ -178,8 +178,8 @@ extension OutputSpan where Element: ~Copyable { /// It is a precondition that the `OutputSpan`'s uninitialized suffix /// can contain every element of the source. @lifetime(self: copy self) - public mutating func moveAppend( - fromContentsOf source: UnsafeMutableBufferPointer + public mutating func append( + consuming source: UnsafeMutableBufferPointer ) } @@ -189,13 +189,13 @@ extension OutputSpan { /// It is a precondition that the `OutputSpan`'s uninitialized suffix /// can contain every element of the source. @lifetime(self: copy self) - public mutating func moveAppend( - fromContentsOf source: Slice> + public mutating func append( + consuming source: Slice> ) } ``` -Bulk operations to deinitialize some or all of an `OutputSpan`'s memory is also available: +Bulk operations to deinitialize some or all of an `OutputSpan`'s memory are also available: ```swift extension OutputSpan where Element: ~Copyable { /// Remove the last N elements, returning the memory they occupy @@ -204,7 +204,7 @@ extension OutputSpan where Element: ~Copyable { /// `n` must not be greater than `count` @lifetime(self: copy self) public mutating func removeLast(_ n: Int) - + /// Remove all this span's elements and return its memory to the uninitialized state. @lifetime(self: copy self) public mutating func removeAll() @@ -230,7 +230,6 @@ extension OutputSpan where Element: ~Copyable { ``` - ##### Interoperability with unsafe code We provide a method to process or populate an `OutputSpan` using unsafe operations, which can also be used for out-of-order initialization. @@ -269,7 +268,6 @@ extension OutputSpan where Element: ~Copyable { ``` - ##### Creating an `OutputSpan` instance: Creating an `OutputSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized instances of `Element`, and the second region is uninitialized. The number of initialized instances is passed to the `OutputSpan` initializer through its `initializedCount` argument. @@ -321,10 +319,9 @@ extension OutputSpan { ``` - ##### Retrieving initialized memory from an `OutputSpan` -Once memory has been initialized using `OutputSpan`, the owner of the memory must consume the `OutputSpan` in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps. `finalize()` consumes the `OutputSpan` instance and returns the number of initialized elements. +Once memory has been initialized using `OutputSpan`, the owner of the memory must consume the `OutputSpan` in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps. `finalize(for:)` consumes the `OutputSpan` instance and returns the number of initialized elements. If `finalize(for:)` is not called, the initialized portion of `OutputSpan`'s memory will be deinitialized when the binding goes out of scope. ```swift extension OutputSpan where Element: ~Copyable { @@ -355,10 +352,9 @@ extension OutputSpan { ``` - - #### `OutputRawSpan` -`OutputRawSpan` is similar to `OutputSpan`, but represents an untyped partially-initialized region of memory. Its API supports appending the bytes of instances of `BitwiseCopyable` types, as well as a variety of bulk initialization operations. +`OutputRawSpan` is similar to `OutputSpan`, but its initialized memory is untyped. Its API supports appending the bytes of instances of `BitwiseCopyable` types, as well as a variety of bulk initialization operations. + ```swift @frozen public struct OutputRawSpan: ~Copyable, ~Escapable { @@ -387,7 +383,6 @@ extension OutputRawSpan { ``` - ##### Appending to `OutputRawSpan` The basic operation is to append the bytes of some value to an `OutputRawSpan`: @@ -395,7 +390,7 @@ The basic operation is to append the bytes of some value to an `OutputRawSpan`: extension OutputRawSpan { /// Appends the given value's bytes to this span's initialized bytes @lifetime(self: copy self) - public mutating func appendBytes( + public mutating func append( of value: T, as type: T.Type ) } @@ -406,38 +401,40 @@ This is also supported with bulk operations. Initializing an `OutputRawSpan` fro extension OutputRawSpan /// Initialize this span's suffix to the repetitions of the given value's bytes. @lifetime(self: copy self) - public mutating func append(repeating repeatedValue: T, count: Int) + public mutating func append( + repeating repeatedValue: T, count: Int, as type: T.Type + ) /// Initialize the span's bytes with the bytes of the elements of the source. /// /// Returns true if the iterator has filled all the free capacity in the span. @lifetime(self: copy self) - public mutating func append( - from source: inout some IteratorProtocol + public mutating func append, as type: T.Type ) -> Bool /// Initialize the span's bytes with every byte of the source. @lifetime(self: copy self) - public mutating func append( - fromContentsOf source: some Sequence + public mutating func append, as type: T.Type ) /// Initialize the span's bytes with every byte of the source. @lifetime(self: copy self) - public mutating func append( - fromContentsOf source: Span + public mutating func append, as type: T.Type ) /// Initialize the span's bytes with every byte of the source. @lifetime(self: copy self) public mutating func append( - fromContentsOf source: RawSpan + contentsOf source: RawSpan ) /// Initialize the span's bytes with every byte of the source. @lifetime(self: copy self) public mutating func append( - fromContentsOf source: UnsafeRawBufferPointer + contentsOf source: UnsafeRawBufferPointer ) } ``` @@ -459,7 +456,6 @@ extension OutputRawSpan { ``` - ##### Interoperability with unsafe code We provide a method to process or populate an `OutputRawSpan` using unsafe operations, which can also be used for out-of-order initialization. @@ -498,7 +494,6 @@ extension OutputRawSpan { ``` - ##### Creating `OutputRawSpan` instances Creating an `OutputRawSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized bytes, and the second region is uninitialized. The number of initialized bytes is passed to the `OutputRawSpan` initializer through its `initializedCount` argument. @@ -579,18 +574,49 @@ extension OutputRawSpan { ``` - #### Extensions to Standard Library types The standard library and Foundation will add a few initializers that enable initialization in place, intermediated by an `OutputSpan` instance, passed as a parameter to a closure: ```swift extension Array { + /// Creates an array with the specified capacity, then calls the given + /// closure with an OutputSpan to initialize the array's contents. public init( capacity: Int, initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) - + + /// Grows the array to ensure capacity for the specified number of elements, + /// then calls the closure with an OutputSpan covering the array's + /// uninitialized memory. + public mutating func append( + addingCapacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) +} + +extension ContiguousArray { + /// Creates an array with the specified capacity, then calls the given + /// closure with an OutputSpan to initialize the array's contents. + public init( + capacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) + + /// Grows the array to ensure capacity for the specified number of elements, + /// then calls the closure with an OutputSpan covering the array's + /// uninitialized memory. + public mutating func append( + addingCapacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) +} + +extension ArraySlice { + /// Grows the array to ensure capacity for the specified number of elements, + /// then calls the closure with an OutputSpan covering the array's + /// uninitialized memory. public mutating func append( addingCapacity: Int, initializingWith initializer: (inout OutputSpan) throws(E) -> Void @@ -598,40 +624,84 @@ extension Array { } extension String { + /// Creates a new string with the specified capacity in UTF-8 code units, and + /// then calls the given closure with a OutputSpan to initialize the string's contents. + /// + /// This initializer replaces ill-formed UTF-8 sequences with the Unicode + /// replacement character (`"\u{FFFD}"`). This may require resizing + /// the buffer beyond its original capacity. public init( - utf8Capacity: Int, - initializingUTF8With initializer: (inout OutputSpan) throws(E) -> Void - ) + repairingUTF8WithCapacity capacity: Int, + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void + ) throws(E) + /// Creates a new string with the specified capacity in UTF-8 code units, and + /// then calls the given closure with a OutputSpan to initialize the string's contents. + /// + /// This initializer does not try to repair ill-formed code unit sequences. + /// If any are found, the result of the initializer is `nil`. public init?( - utf8Capacity: Int, - initializingValidUTF8With initializer: (inout OutputSpan) throws(E) -> Void + validatingUTF8WithCapacity capacity: Int, + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void ) throws(E) - + + /// Grows the string to ensure capacity for the specified number + /// of UTF-8 code units, then calls the closure with an OutputSpan covering the string's + /// uninitialized memory. public mutating func append( addingUTF8Capacity: Int, - initializingUTF8With initializer: (inout OUtputSpan) throws(E) -> Void + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void ) throws(E) } extension UnicodeScalarView { + /// Creates a new string with the specified capacity in UTF-8 code units, and + /// then calls the given closure with a OutputSpan to initialize the string's contents. + /// + /// This initializer replaces ill-formed UTF-8 sequences with the Unicode + /// replacement character (`"\u{FFFD}"`). This may require resizing + /// the buffer beyond its original capacity. public init( - utf8Capacity: Int, - initializingUTF8With initializer: (inout OutputSpan) throws(E) -> Void - ) + repairingUTF8WithCapacity capacity: Int, + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void + ) throws(E) + /// Creates a new string with the specified capacity in UTF-8 code units, and + /// then calls the given closure with a OutputSpan to initialize the string's contents. + /// + /// This initializer does not try to repair ill-formed code unit sequences. + /// If any are found, the result of the initializer is `nil`. public init?( - utf8Capacity: Int, - initializingValidUTF8With initializer: (inout OutputSpan) throws(E) -> Void + validatingUTF8WithCapacity capacity: Int, + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void ) throws(E) - + + /// Grows the string to ensure capacity for the specified number + /// of UTF-8 code units, then calls the closure with an OutputSpan covering the string's + /// uninitialized memory. public mutating func append( addingUTF8Capacity: Int, - initializingUTF8With initializer: (inout OUtputSpan) throws(E) -> Void + initializingUTF8With initializer: ( + inout OutputSpan + ) throws(E) -> Void ) throws(E) } extension InlineArray { + /// Creates an array, then calls the given closure with an OutputSpan + /// to initialize the array's elements. + /// + /// NOTE: This initializer will trap if the closure fails to initialize every element. public init( initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) @@ -652,9 +722,86 @@ extension Data { rawCapacity: Int, initializingWith initializer: (inout OutputRawSpan) throws(E) -> Void ) throws(E) + + public mutating func append( + addingCapacity: Int, + initializingWith initializer: (inout OutputSpan) throws(E) -> Void + ) throws(E) + + public mutating func append( + addingRawCapacity: Int, + initializingWith initializer: (inout OutputRawSpan) throws(E) -> Void + ) throws(E) } ``` +#### Changes to `MutableSpan` and `MutableRawSpan` + +This proposal considers the naming of `OutputSpan`'s bulk-copying methods more carefully than [SE-0467][SE-0467] about `MutableSpan`. Accordingly, we would like to replace the `update()` functions proposed there in accordance with the scheme proposed in this proposal: + +```swift +extension MutableSpan where Element: Copyable { + public mutating func update( + fromContentsOf source: inout some IteratorProtocol + ) -> Index + + public mutating func update( + fromContentsOf source: some Sequence + ) -> Index + + public mutating func update( + copying source: borrowing Span + ) -> Index + + public mutating func update( + copying source: UnsafeBufferPointer + ) -> Index +} + +extension MutableSpan where Element: ~Copyable { + public mutating func update( + moving source: inout OutputSpan + ) -> Index + + public mutating func update( + consuming source: UnsafeMutableBufferPointer + ) -> Index +} + +extension MutableSpan { + public mutating func append( + consuming source: Slice> + ) +} +``` + +Similarly, `MutableRawSpan`'s bulk-copying methods would be replaced by + +```swift +extension MutableRawSpan { + public mutating func update( + fromContentsOf source: inout some IteratorProtocol, as type: T.Type + ) -> Index + + public mutating func update( + fromContentsOf source: some Sequence, as type: T.Type + ) -> Index + + public mutating func update( + fromContentsOf source: borrowing Span, as type: T.Type + ) -> Index + + public mutating func update( + fromContentsOf source: borrowing RawSpan + ) -> Index + + public mutating func append( + fromContentsOf source: UnsafeRawBufferPointer + ) -> Index +} +``` + + ## Source compatibility This proposal is additive and source-compatible with existing code. @@ -672,8 +819,46 @@ The additions described in this proposal require a new version of the Swift stan #### Vending `OutputSpan` as a property -`OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and it fits the needs of `OutputSpan` well. +`OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and that pattern fits the needs of `OutputSpan` well. + +#### Alternative names for `append()` methods + +`OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be applicable types The origin of the `append(contentsOf:)` method we are expanding upon is the `RangeReplaceableCollection` protocol, which always represents copyable and escapable collections and copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This support copying elements from the source, while also destroying the source if we happen to own its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrow of the source. + +When the elements are non-copyable, we must append elements that are removed from the source. Afterwards, there are two possible dispositions of the source: destruction (`consuming`,) where the source can no longer be used, or mutation (`inout`,) where the source has been emptied but is still usable. + +When the elements are copyable, we can simply copy the elements from the source. Afterwards, there are two possible dispositions of the source: releasing a borrowed source, or `consuming`. The latter is approximately the same behaviour as `RangeReplaceableCollection`'s `append()` function shown above. + +In a more ideal world, we would like to use the same name for all of these variants: +```swift +extension OutputSpan { + mutating func append(contentsOf: some Sequence) + mutating func append(contentsOf: borrowing some Container) +} +extension OutputSpan where Element: ~Copyable { + mutating func append(contentsOf: consuming some ConsumableContainer) + mutating func append(contentsOf: inout some RangeReplaceableContainer) +} +``` + +However, this would break down in particular for `UnsafeMutableBufferPointer`, since it would make it impossible to differentiate between just copying the elements out of it, or moving its elements out (and deinitializing its memory). Once the `Container` protocols exist, we can expect that the same issue would exist for any type that conforms to more than one of the protocols involved in the list above. For example if a type conforms to `Container` as well as `Sequence`, then there would be an ambiguity. +We could fix this by extending the syntax of the language. It is already possible to overload two functions where they differ only by whether a parameter is `inout`, for example. This is a future direction. + +Instead of the "ideal" solution above, this proposal includes `append()` functions in the following form: + +```swift +extension OutputSpan { + mutating func append(contentsOf: some Sequence) + mutating func append(copying: borrowing some Container) +} +extension OutputSpan where Element: ~Copyable { + mutating func append(consuming: consuming some ConsumableContainer) + mutating func append(moving: inout some RangeReplaceableContainer) +} +``` + +The `update()` methods of `MutableSpan` are updated in a similar manner for the same reasons. ## Future directions @@ -681,6 +866,55 @@ The additions described in this proposal require a new version of the Swift stan Some applications may benefit from the ability to initialize a range of memory in a different order than implemented by `OutputSpan`. This may be from back-to-front or even arbitrary order. There are many possible forms such an initialization helper can take, depending on how much memory safety the application is willing to give up in the process of initializing the memory. At the unsafe end, this can be delegating to an `UnsafeMutableBufferPointer` along with a set of requirements; this option is proposed here. At the safe end, this could be delegating to a data structure which keeps track of initialized memory using a bitmap. It is unclear how much need there is for this more heavy-handed approach, so we leave it as a future enhancement if it is deemed useful. +#### Insertions and indexing + +A use case similar to appending is insertions. Appending is simply inserting at the end. Inserting at positions other than the end is an important capability. It requires an indexing model, which we do not propose here. We expect to add indexing and insertions soon if `OutputSpan` is accepted. Until then, a workaround is to append, then rotate the elements to the desired position using the `mutableSpan` view. The current proposal does not add a concept of indexing to `OutputSpan`, though that is required in order to support insertions at an arbitrary position. We defer this discussion in order to focus on the basic functionality of the type. + +#### Generalized removals + +Similarly to generalized insertions (i.e. not from the end,) we can think about removals of one or more elements starting at a given position. This also requires adding indexing. We expect to add generalized removals along with insertions if `OutputSpan` is accepted. + +#### Variations on `Array.append(addingCapacity:initializingWith:)` + +The function proposed here only exposes uninitialized capacity in the `OutputSpan` parameter to its closure. A different function (perhaps named `edit()`) could also pass the initialized portion of the container, allowing an algorithm to remove _or_ add elements. This could be considered in addition to `append()`. + +#### Method to distinguish between ownership modes for function arguments + +In the "Alternates Considered" subsection about [naming the `append()` methods](#contentsOf), we suggest a currently unachievable naming scheme: +```swift +extension OutputSpan { + mutating func append(contentsOf: some Sequence) + mutating func append(contentsOf: borrowing some Container) +} +extension OutputSpan where Element: ~Copyable { + mutating func append(contentsOf: consuming some ConsumableContainer) + mutating func append(contentsOf: inout some RangeReplaceableContainer) +} +``` + +The language partially support disambiguating this naming scheme, in that we can already distinguish functions over the mutability of a single parameter: + +```swift +func foo(_ a: borrowing A) {} +func foo(_ a: inout A) {} + +var a = A() +foo(a) +foo(&a) +``` + +We could expand upon this ability to disambiguate by using keywords or even new sigils: + +```swift +let buffer: UnsafeMutableBufferPointer = ... +let array = Array(capacity: buffer.count*2) { + (o: inout OutputSpan) in + o.append(contentsOf: borrowing buffer) + o.append(contentsOf: consuming buffer) +} +``` + + ## Acknowledgements Thanks to Karoy Lorentey, Nate Cook and Tony Parker for their feedback. From 74e6ab7e1fe648bae1af38d6eca63f570a36fd9c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 14 May 2025 10:15:05 -0700 Subject: [PATCH 308/505] Accept SE-0471: Improved Custom SerialExecutor isolation checking for Concurrency Runtime --- proposals/0471-SerialExecutor-isIsolated.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index e20eecdae0..d5e38f80a8 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -3,9 +3,9 @@ * Proposal: [SE-0471](0471-SerialExecutor-isIsolated.md) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Active Review (March 25...April 29, 2025)** +* Status: **Accepted** * Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 -* Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834) +* Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834), [Acceptance](https://forums.swift.org/t/accepted-se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/79894) ## Introduction From 4517a7aa726030b6c214a83747c825976888cb4f Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 14 May 2025 14:22:53 -0400 Subject: [PATCH 309/505] Accept SE-0481 --- proposals/0481-weak-let.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0481-weak-let.md b/proposals/0481-weak-let.md index 60a15f1884..03a4cb4e5b 100644 --- a/proposals/0481-weak-let.md +++ b/proposals/0481-weak-let.md @@ -3,9 +3,9 @@ * Proposal: [SE-0481](0481-weak-let.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) * Review Manager: [John McCall](https://github.com/rjmccall) -* Status: **Active review (April 30th...May 13th, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift#80440](https://github.com/swiftlang/swift/pull/80440) -* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) +* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) ([acceptance](https://forums.swift.org/t/accepted-se-0481-weak-let/79895)) [SE-0302]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md From 836e1cbcda549e4228c46adba37cc389e872a45c Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Wed, 14 May 2025 22:00:03 +0200 Subject: [PATCH 310/505] [SE-0478] Fix typo (#2847) --- proposals/0478-default-isolation-typealias.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0478-default-isolation-typealias.md b/proposals/0478-default-isolation-typealias.md index 3d29a4932a..590ea5fd7b 100644 --- a/proposals/0478-default-isolation-typealias.md +++ b/proposals/0478-default-isolation-typealias.md @@ -93,7 +93,7 @@ This proposal does not change the adoption implications of adding `@MainActor` t ## Alternatives considered -Adding a typealias named `nonisolated` to `Never` to the Concurrency library to enable writing it as the underlying type of a typealias is pretty strange; this approach leveraging the fact that `nonisolated` is a contextual keyword, so it's valid to use `nonisolated` as an identifier. This proposal uses a typealias instead of an empty struct or enum type to avoid the complications of having a new type be only available with the Swift 6.2 standard library. +Adding a typealias named `nonisolated` to `Never` to the Concurrency library to enable writing it as the underlying type of a typealias is pretty strange; this approach leverages the fact that `nonisolated` is a contextual keyword, so it's valid to use `nonisolated` as an identifier. This proposal uses a typealias instead of an empty struct or enum type to avoid the complications of having a new type be only available with the Swift 6.2 standard library. It's extremely valuable to have a consistent way to spell `nonisolated`. Introducing a type that follows standard naming conventions, such as `Nonisolated`, or using an existing type like `Never` is more consistent with recommended style, but overall complicates the concurrency model because it means you need to spell `nonisolated` differently when specifying it per file versus writing it on a declaration. And because the underlying type of this typealias is used to infer actor isolation, it's not used as a type in the same way that other typealiases are. From 5355577663dfb711f1b02cf48c160ecb2c173e1e Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Wed, 14 May 2025 22:00:51 +0200 Subject: [PATCH 311/505] [SE-0466] Remove "prospective" when referring to vision doc (#2846) The proposal refers to the vision for approachable data-race safety as "prospective" in one place, but the vision has been accepted. So remove the "prospective". Also fixes a few typos. --- proposals/0466-control-default-actor-isolation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 8fb8015003..763a1ff12d 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -13,7 +13,7 @@ This proposal introduces a new compiler setting for inferring `@MainActor` isola ## Motivation -> Note: This motivation section was adapted from the [prospective vision for approachable data-race safety](https://github.com/hborla/swift-evolution/blob/approachable-concurrency-vision/visions/approachable-concurrency.md#mitigating-false-positive-data-race-safety-errors-in-sequential-code). Please see the vision document for extended motivation. +> Note: This motivation section was adapted from the [vision for approachable data-race safety](https://github.com/hborla/swift-evolution/blob/approachable-concurrency-vision/visions/approachable-concurrency.md#mitigating-false-positive-data-race-safety-errors-in-sequential-code). Please see the vision document for extended motivation. A lot of code is effectively “single-threaded”. For example, most executables, such as apps, command-line tools, and scripts, start running on the main actor and stay there unless some part of the code does something concurrent (like creating a `Task`). If there isn’t any use of concurrency, the entire program will run sequentially, and there’s no risk of data races — every concurrency diagnostic is necessarily a false positive! It would be good to be able to take advantage of that in the language, both to avoid annoying programmers with unnecessary diagnostics and to reinforce progressive disclosure. Many people get into Swift by writing these kinds of programs, and if we can avoid needing to teach them about concurrency straight away, we’ll make the language much more approachable. @@ -156,7 +156,7 @@ There are some build settings that are applicable on a per-file basis, including The `-default-isolation` flag could allow a custom global actor as the argument, and the `SwiftSetting` API could be updated to accept a string that represents a custom global actor in the target. -This proposal only supports `MainActor` because any other global actor does not help with progressive disclosure. It has the opposite effect - it forces asynchrony on any main-actor-isolated caller. However, there's nothing in this proposal prohibits generalizing these settings to supporting arbitrary global actors in the future if a compelling use case arises. +This proposal only supports `MainActor` because any other global actor does not help with progressive disclosure. It has the opposite effect - it forces asynchrony on any main-actor-isolated caller. However, there's nothing in this proposal that prohibits generalizing these settings to supporting arbitrary global actors in the future if a compelling use case arises. ### Infer `MainActor` by default as an upcoming feature @@ -168,7 +168,7 @@ See the approachable data-race safety vision document for an [analysis on the ri ### Don't apply default actor isolation to explicitly `Sendable` types -This proposal includes few excepts where the specified default actor isolation does not apply. An additional case that should be considered is types with a conformance to `Sendable`: +This proposal includes few exceptions where the specified default actor isolation does not apply. An additional case that should be considered is types with a conformance to `Sendable`: ```swift struct SimpleValue: Sendable { From 84c2fca68b0009733702aaa8727a1459faed8a84 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 16 May 2025 11:01:23 -0700 Subject: [PATCH 312/505] Add Alternatives Considered section for `swift migrate` vs. `swift package migrate` --- proposals/NNNN-adoption-tooling-for-swift-features.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index 3a118f1190..93aed515e5 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -1,7 +1,7 @@ # Migration tooling for Swift features * Proposal: [SE-NNNN](NNNN-filename.md) -* Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) +* Authors: [Anthony Latsis](https://github.com/AnthonyLatsis), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: TBD * Status: **Awaiting implementation** * Implementation: TBD @@ -344,6 +344,12 @@ The next candidates in line per discussions are ***adopt***, ***audit***, or rules. To illustrate, this mode could appropriately suggest switching from `any P` to `some P` for `ExistentialAny`. + +### `swift migrate` vs. `swift package migrate` + +Rather than have migrate as a subcommand (ie. `swift package migrate`), another option is add another top level command, ie. `swift migrate`. + +As the command applies to the current package, we feel a `swift package` sub-command fits better than a new top-level command. This also aligns with the recently added package refactorings (eg. `add-target`). ## Acknowledgements From bb4248a4144cd92307476a901f20d3e5f5ec9a2c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 16 May 2025 13:48:57 -0700 Subject: [PATCH 313/505] SE-0472: Add missing `()` to function type in `Task.immediate{Detached}` declarations --- proposals/0472-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index d5a3acd522..c7f0701080 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -107,7 +107,7 @@ extension Task { name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - @_inheritActorContext(always) operation: sending @escaping async throws(Failure) -> Success + @_inheritActorContext(always) operation: sending @escaping () async throws(Failure) -> Success ) -> Task @discardableResult @@ -115,7 +115,7 @@ extension Task { name: String? = nil, // Introduced by SE-0469 priority: TaskPriority? = nil, executorPreference taskExecutor: consuming (any TaskExecutor)? = nil, - @_inheritActorContext(always) operation: sending @escaping async throws(Failure) -> Success + @_inheritActorContext(always) operation: sending @escaping () async throws(Failure) -> Success ) -> Task } ``` From bd7c340a6e7effca825614da5d0d40dd89be002c Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Fri, 16 May 2025 15:56:20 -0700 Subject: [PATCH 314/505] More updates and edits for `OutputSpan` --- proposals/nnnn-outputspan.md | 224 ++++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 69 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 0b8fb73d29..7f8ffa6665 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -16,6 +16,30 @@ [Forum-LifetimeAnnotations]: https://forums.swift.org/t/78638 [SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md + +#### Table of Contents + +- [Introduction](#introduction) + +- [Motivation](#motivation) + +- [Proposed solution](#proposed-solution) + +- [Detailed Design](#detailed-design) + +- [Source compatibility](#source-compatibility) + +- [ABI compatibility](#abi-compatibility) + +- [Implications on adoption](#implications-on-adoption) + +- [Alternatives Considered](#alternatives-considered) + +- [Future directions](#future-directions) + +- [Acknowledgements](#acknowledgements) + + ## Introduction Following the introduction of [`Span`][SE-0447] and [`MutableSpan`][SE-0467], this proposal adds a general facility for initialization of exclusively-borrowed memory with the `OutputSpan` and `OutputRawSpan` types. The memory represented by `OutputSpan` consists of a number of initialized elements, followed by uninitialized memory. The operations of `OutputSpan` can change the number of initialized elements in memory, unlike `MutableSpan` which always represent initialized memory representing a fixed number of elements. @@ -102,6 +126,10 @@ extension OutputSpan where Element: ~Copyable { /// Append a single element to this `OutputSpan`. @lifetime(self: copy self) public mutating func append(_ value: consuming Element) + + /// Repeatedly append an element to this `OutputSpan`. + @lifetime(self: copy self) + public mutating func append(repeating repeatedValue: Element, count: Int) } ``` The converse operation `removeLast()` is also supported, and returns the removed element if `count` was greater than zero. @@ -109,39 +137,47 @@ The converse operation `removeLast()` is also supported, and returns the removed extension OutputSpan where Element: ~Copyable { /// Remove the last initialized element from this `OutputSpan`. /// - /// Returns the last element. The `OutputSpan` must not be empty + /// Returns the last element. The `OutputSpan` must not be empty. @discardableResult @lifetime(self: copy self) public mutating func removeLast() -> Element } ``` +`OutputSpan` provides the ability to access its initialized elements by index: +```swift +extension OutputSpan wehre Element: ~Copyable { + /// The type that represents an initialized position in an `OutputSpan`. + typealias Index = Int + + /// The range of initialized positions for this `OutputSpan`. + var indices: Range { get } + + /// Accesses the element at the specified initialized position. + subscript(_ index: Index) -> Element { borrow; mutate } + // accessor syntax from accessors roadmap (https://forums.swift.org/t/76707) + + /// Exchange the elements at the two given offsets + mutating func swapAt(_ i: Index, _ j: Index) +} +``` + + ##### Bulk initialization of an `OutputSpan`'s memory: -We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from a `Sequence` or a fixed-size source must use every element of the source. Initializing an `OutputSpan` from `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. +We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from a `Sequence` must use every element of the source. Initializing an `OutputSpan` from `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. + +See [below](#contentsOf) for a discussion of the argument labels used with the `append()` functions. ```swift extension OutputSpan { - /// Initialize this span's suffix to the repetitions of the given value. - @lifetime(self: copy self) - public mutating func append(repeating repeatedValue: Element, count: Int) - - /// Initialize this span's suffix with the elements from the source. - /// - /// Returns true if the iterator has filled all the free capacity in the span. - @discardableResult - @lifetime(self: copy self) - public mutating func append( - contentsOf source: inout some IteratorProtocol - ) -> Bool - /// Initialize this span's suffix with every element of the source. /// /// It is a precondition that the `OutputSpan`'s uninitialized suffix /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( - contentsOf source: some Sequence + contentsOf source: consuming some Sequence ) /// Initialize this span's suffix with every element of the source. @@ -159,7 +195,7 @@ extension OutputSpan { /// can contain every element of the source. @lifetime(self: copy self) public mutating func append( - copying source: UnsafeBufferPointer + contentsOf source: UnsafeBufferPointer ) } @@ -173,6 +209,15 @@ extension OutputSpan where Element: ~Copyable { moving source: inout OutputSpan ) + /// Initialize this span's suffix by moving every element from the source. + /// + /// It is a precondition that the `OutputSpan`'s uninitialized suffix + /// can contain every element of the source. + @lifetime(self: copy self) + public mutating func append( + consuming source: consuming InlineArray + ) + /// Initialize this span's suffix by moving every element from the source. /// /// It is a precondition that the `OutputSpan`'s uninitialized suffix @@ -192,6 +237,21 @@ extension OutputSpan { public mutating func append( consuming source: Slice> ) + + /// Initialize this span's suffix with the elements from the source. + /// + /// Use this function if it isn't possible to fulfill the precondition + /// of the other `append()` functions, and to contain every element + /// of the source. + /// + /// Returns true if the iterator has filled all the free capacity in the span. + /// When the free capacity has been filled, there may be some elements + /// remaining in the iterator. + @discardableResult + @lifetime(self: copy self) + public mutating func append( + from source: inout some IteratorProtocol + ) -> Bool } ``` @@ -321,15 +381,15 @@ extension OutputSpan { ##### Retrieving initialized memory from an `OutputSpan` -Once memory has been initialized using `OutputSpan`, the owner of the memory must consume the `OutputSpan` in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps. `finalize(for:)` consumes the `OutputSpan` instance and returns the number of initialized elements. If `finalize(for:)` is not called, the initialized portion of `OutputSpan`'s memory will be deinitialized when the binding goes out of scope. +Once memory has been initialized using `OutputSpan`, the owner of the memory must consume the `OutputSpan` in order to retake ownership of the initialized memory. The owning type must pass the memory used to initialize the `OutputSpan` to the `finalize(for:)` function. Passing the wrong buffer is a programmer error and the function traps; this requirement also ensures that user code does not wrongly replace the `OutputSpan` with an unrelated instance. The `finalize(for:)` function consumes the `OutputSpan` instance and returns the number of initialized elements. If `finalize(for:)` is not called, the initialized portion of `OutputSpan`'s memory will be deinitialized when the binding goes out of scope. ```swift extension OutputSpan where Element: ~Copyable { /// Consume the OutputSpan and return the number of initialized elements. - /// + /// /// Parameters: - /// - buffer: The buffer being finalized. This must be the same buffer as used to - /// initialize the `OutputSpan` instance. + /// - buffer: The buffer being finalized. This must be the same buffer as used + /// to initialize the `OutputSpan` instance. /// Returns: The number of elements that were initialized. @unsafe public consuming func finalize( @@ -339,10 +399,10 @@ extension OutputSpan where Element: ~Copyable { extension OutputSpan { /// Consume the OutputSpan and return the number of initialized elements. - /// + /// /// Parameters: - /// - buffer: The buffer being finalized. This must be the same buffer as used to - /// initialize the `OutputSpan` instance. + /// - buffer: The buffer being finalized. This must be the same buffer as used + /// to initialize the `OutputSpan` instance. /// Returns: The number of bytes that were initialized. @unsafe public consuming func finalize( @@ -385,7 +445,7 @@ extension OutputRawSpan { ##### Appending to `OutputRawSpan` -The basic operation is to append the bytes of some value to an `OutputRawSpan`: +The basic operation is to append the bytes of some value to an `OutputRawSpan`. Note that since the fundamental operation is appending bytes, `OutputRawSpan` does not concern itself with memory alignment. ```swift extension OutputRawSpan { /// Appends the given value's bytes to this span's initialized bytes @@ -393,30 +453,23 @@ extension OutputRawSpan { public mutating func append( of value: T, as type: T.Type ) -} -``` -This is also supported with bulk operations. Initializing an `OutputRawSpan` from known-sized sources (such as `Collection` or `Span`) uses every element of the source. It is an error to do so when the available storage of the `OutputRawSpan` is too little to contain every element from the source. Initializing an `OutputRawSpan` from `Sequence` or `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputRawSpan` has too few bytes available to store another element. -```swift -extension OutputRawSpan - /// Initialize this span's suffix to the repetitions of the given value's bytes. + /// Appends the given value's bytes repeatedly to this span's initialized bytes @lifetime(self: copy self) public mutating func append( repeating repeatedValue: T, count: Int, as type: T.Type ) +} +``` - /// Initialize the span's bytes with the bytes of the elements of the source. - /// - /// Returns true if the iterator has filled all the free capacity in the span. - @lifetime(self: copy self) - public mutating func append, as type: T.Type - ) -> Bool +Initializing an `OutputRawSpan` from a `Sequence` or other container type must use every element of the source. Initializing an `OutputRawSpan` from an `IteratorProtocol` instance will copy as many items as possible, either until the input is empty or the `OutputRawSpan` cannot contain another element. +```swift +extension OutputRawSpan { /// Initialize the span's bytes with every byte of the source. @lifetime(self: copy self) public mutating func append, as type: T.Type + contentsOf source: consuming some Sequence, as type: T.Type ) /// Initialize the span's bytes with every byte of the source. @@ -436,6 +489,20 @@ extension OutputRawSpan public mutating func append( contentsOf source: UnsafeRawBufferPointer ) + + /// Initialize the span's bytes with the bytes of the elements of the source. + /// + /// Use this function if it isn't possible to fulfill the precondition + /// of the other `append()` functions, and to contain every element + /// of the source. + /// + /// Returns true if the iterator has filled all the free capacity in the span. + /// When the free capacity has been filled, there may be some elements + /// remaining in the iterator. + @lifetime(self: copy self) + public mutating func append, as type: T.Type + ) -> Bool } ``` @@ -550,10 +617,10 @@ Once memory has been initialized using `OutputRawSpan`, the owner of the memory ```swift extension OutputRawSpan { /// Consume the OutputRawSpan and return the number of initialized bytes. - /// + /// /// Parameters: - /// - buffer: The buffer being finalized. This must be the same buffer as used to - /// create the `OutputRawSpan` instance. + /// - buffer: The buffer being finalized. This must be the same buffer as used + /// to create the `OutputRawSpan` instance. /// Returns: The number of initialized bytes. @unsafe public consuming func finalize( @@ -561,10 +628,10 @@ extension OutputRawSpan { ) -> Int /// Consume the OutputRawSpan and return the number of initialized bytes. - /// + /// /// Parameters: - /// - buffer: The buffer being finalized. This must be the same buffer as used to - /// create the `OutputRawSpan` instance. + /// - buffer: The buffer being finalized. This must be the same buffer as used + /// to create the `OutputRawSpan` instance. /// Returns: The number of initialized bytes. @unsafe public consuming func finalize( @@ -625,8 +692,9 @@ extension ArraySlice { extension String { /// Creates a new string with the specified capacity in UTF-8 code units, and - /// then calls the given closure with a OutputSpan to initialize the string's contents. - /// + /// then calls the given closure with a OutputSpan to initialize the string's + /// contents. + /// /// This initializer replaces ill-formed UTF-8 sequences with the Unicode /// replacement character (`"\u{FFFD}"`). This may require resizing /// the buffer beyond its original capacity. @@ -638,8 +706,9 @@ extension String { ) throws(E) /// Creates a new string with the specified capacity in UTF-8 code units, and - /// then calls the given closure with a OutputSpan to initialize the string's contents. - /// + /// then calls the given closure with a OutputSpan to initialize the string's + /// contents. + /// /// This initializer does not try to repair ill-formed code unit sequences. /// If any are found, the result of the initializer is `nil`. public init?( @@ -650,8 +719,8 @@ extension String { ) throws(E) /// Grows the string to ensure capacity for the specified number - /// of UTF-8 code units, then calls the closure with an OutputSpan covering the string's - /// uninitialized memory. + /// of UTF-8 code units, then calls the closure with an OutputSpan covering + /// the string's uninitialized memory. public mutating func append( addingUTF8Capacity: Int, initializingUTF8With initializer: ( @@ -662,8 +731,9 @@ extension String { extension UnicodeScalarView { /// Creates a new string with the specified capacity in UTF-8 code units, and - /// then calls the given closure with a OutputSpan to initialize the string's contents. - /// + /// then calls the given closure with a OutputSpan to initialize + /// the string's contents. + /// /// This initializer replaces ill-formed UTF-8 sequences with the Unicode /// replacement character (`"\u{FFFD}"`). This may require resizing /// the buffer beyond its original capacity. @@ -675,8 +745,9 @@ extension UnicodeScalarView { ) throws(E) /// Creates a new string with the specified capacity in UTF-8 code units, and - /// then calls the given closure with a OutputSpan to initialize the string's contents. - /// + /// then calls the given closure with a OutputSpan to initialize + /// the string's contents. + /// /// This initializer does not try to repair ill-formed code unit sequences. /// If any are found, the result of the initializer is `nil`. public init?( @@ -687,8 +758,8 @@ extension UnicodeScalarView { ) throws(E) /// Grows the string to ensure capacity for the specified number - /// of UTF-8 code units, then calls the closure with an OutputSpan covering the string's - /// uninitialized memory. + /// of UTF-8 code units, then calls the closure with an OutputSpan covering + /// the string's uninitialized memory. public mutating func append( addingUTF8Capacity: Int, initializingUTF8With initializer: ( @@ -701,7 +772,8 @@ extension InlineArray { /// Creates an array, then calls the given closure with an OutputSpan /// to initialize the array's elements. /// - /// NOTE: This initializer will trap if the closure fails to initialize every element. + /// NOTE: The closure must initialize every element of the `OutputSpan`. + /// If the closure does not do so, the initializer will trap. public init( initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) @@ -713,21 +785,33 @@ extension InlineArray { While the `swift-foundation` package and the `Foundation` framework are not governed by the Swift evolution process, `Data` is similar in use to standard library types, and the project acknowledges that it is desirable for it to have similar API when appropriate. Accordingly, we plan to propose the following additions to `Foundation.Data`: ```swift extension Data { + /// Creates a data instance with the specified capacity, then calls + /// the given closure with an OutputSpan to initialize the instances's + /// contents. public init( capacity: Int, initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) + /// Creates a data instance with the specified capacity, then calls + /// the given closure with an OutputSpan to initialize the instances's + /// contents. public init( rawCapacity: Int, initializingWith initializer: (inout OutputRawSpan) throws(E) -> Void ) throws(E) + /// Ensures the data instance has enough capacity for the specified + /// number of bytes, then calls the closure with an OutputSpan covering + /// the uninitialized memory. public mutating func append( addingCapacity: Int, initializingWith initializer: (inout OutputSpan) throws(E) -> Void ) throws(E) + /// Ensures the data instance has enough capacity for the specified + /// number of bytes, then calls the closure with an OutputSpan covering + /// the uninitialized memory. public mutating func append( addingRawCapacity: Int, initializingWith initializer: (inout OutputRawSpan) throws(E) -> Void @@ -742,7 +826,7 @@ This proposal considers the naming of `OutputSpan`'s bulk-copying methods more c ```swift extension MutableSpan where Element: Copyable { public mutating func update( - fromContentsOf source: inout some IteratorProtocol + from source: inout some IteratorProtocol ) -> Index public mutating func update( @@ -762,7 +846,7 @@ extension MutableSpan where Element: ~Copyable { public mutating func update( moving source: inout OutputSpan ) -> Index - + public mutating func update( consuming source: UnsafeMutableBufferPointer ) -> Index @@ -775,12 +859,12 @@ extension MutableSpan { } ``` -Similarly, `MutableRawSpan`'s bulk-copying methods would be replaced by +Similarly, `MutableRawSpan`'s bulk-copying methods would be replaced by the following: ```swift extension MutableRawSpan { public mutating func update( - fromContentsOf source: inout some IteratorProtocol, as type: T.Type + from source: inout some IteratorProtocol, as type: T.Type ) -> Index public mutating func update( @@ -832,7 +916,7 @@ When the elements are copyable, we can simply copy the elements from the source. In a more ideal world, we would like to use the same name for all of these variants: ```swift extension OutputSpan { - mutating func append(contentsOf: some Sequence) + mutating func append(contentsOf: consuming some Sequence) mutating func append(contentsOf: borrowing some Container) } extension OutputSpan where Element: ~Copyable { @@ -849,7 +933,7 @@ Instead of the "ideal" solution above, this proposal includes `append()` functio ```swift extension OutputSpan { - mutating func append(contentsOf: some Sequence) + mutating func append(contentsOf: consuming some Sequence) mutating func append(copying: borrowing some Container) } extension OutputSpan where Element: ~Copyable { @@ -858,7 +942,9 @@ extension OutputSpan where Element: ~Copyable { } ``` -The `update()` methods of `MutableSpan` are updated in a similar manner for the same reasons. +The `update()` methods of `MutableSpan` are updated in a similar manner, for the same reasons. + +We note that the four variants of `append()` are required for generalized containers. We can therefore expect that the names we choose will later appear on many types of collections that interact with the future `Container` protocols. This proposal's `append()` nomenclature could become ubiquitous when interacting with `Collection` instances, once it is applied to the `Container` protocol family. ## Future directions @@ -876,14 +962,14 @@ Similarly to generalized insertions (i.e. not from the end,) we can think about #### Variations on `Array.append(addingCapacity:initializingWith:)` -The function proposed here only exposes uninitialized capacity in the `OutputSpan` parameter to its closure. A different function (perhaps named `edit()`) could also pass the initialized portion of the container, allowing an algorithm to remove _or_ add elements. This could be considered in addition to `append()`. +The function proposed here only exposes uninitialized capacity in the `OutputSpan` parameter to its closure. A different function (perhaps named `edit()`) could also pass the initialized portion of the container, allowing an algorithm to remove or to add elements. This could be considered in addition to `append()`. -#### Method to distinguish between ownership modes for function arguments +#### Language syntax to distinguish between ownership modes for function arguments In the "Alternates Considered" subsection about [naming the `append()` methods](#contentsOf), we suggest a currently unachievable naming scheme: ```swift extension OutputSpan { - mutating func append(contentsOf: some Sequence) + mutating func append(contentsOf: consuming some Sequence) mutating func append(contentsOf: borrowing some Container) } extension OutputSpan where Element: ~Copyable { @@ -892,7 +978,7 @@ extension OutputSpan where Element: ~Copyable { } ``` -The language partially support disambiguating this naming scheme, in that we can already distinguish functions over the mutability of a single parameter: +The language partially supports disambiguating this naming scheme, in that we can already distinguish functions over the mutability of a single parameter: ```swift func foo(_ a: borrowing A) {} From 5585bc6269b07177b31eb0f52d09c3c3076916d9 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Fri, 16 May 2025 16:50:34 -0700 Subject: [PATCH 315/505] Move a section --- proposals/nnnn-outputspan.md | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 7f8ffa6665..e829fbf6af 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -25,7 +25,7 @@ - [Proposed solution](#proposed-solution) -- [Detailed Design](#detailed-design) +- [Detailed Design](#design) - [Source compatibility](#source-compatibility) @@ -144,24 +144,6 @@ extension OutputSpan where Element: ~Copyable { } ``` -`OutputSpan` provides the ability to access its initialized elements by index: -```swift -extension OutputSpan wehre Element: ~Copyable { - /// The type that represents an initialized position in an `OutputSpan`. - typealias Index = Int - - /// The range of initialized positions for this `OutputSpan`. - var indices: Range { get } - - /// Accesses the element at the specified initialized position. - subscript(_ index: Index) -> Element { borrow; mutate } - // accessor syntax from accessors roadmap (https://forums.swift.org/t/76707) - - /// Exchange the elements at the two given offsets - mutating func swapAt(_ i: Index, _ j: Index) -} -``` - ##### Bulk initialization of an `OutputSpan`'s memory: @@ -289,6 +271,24 @@ extension OutputSpan where Element: ~Copyable { } ``` +`OutputSpan` also provides the ability to access its individual initialized elements by index: +```swift +extension OutputSpan wehre Element: ~Copyable { + /// The type that represents an initialized position in an `OutputSpan`. + typealias Index = Int + + /// The range of initialized positions for this `OutputSpan`. + var indices: Range { get } + + /// Accesses the element at the specified initialized position. + subscript(_ index: Index) -> Element { borrow; mutate } + // accessor syntax from accessors roadmap (https://forums.swift.org/t/76707) + + /// Exchange the elements at the two given offsets + mutating func swapAt(_ i: Index, _ j: Index) +} +``` + ##### Interoperability with unsafe code From e5fa401a583ea4e2874fd2689063109f04e56733 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Fri, 16 May 2025 17:53:30 -0700 Subject: [PATCH 316/505] A few more updates, and omissions remedied --- proposals/nnnn-outputspan.md | 49 ++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index e829fbf6af..1a56f51f51 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -273,7 +273,7 @@ extension OutputSpan where Element: ~Copyable { `OutputSpan` also provides the ability to access its individual initialized elements by index: ```swift -extension OutputSpan wehre Element: ~Copyable { +extension OutputSpan where Element: ~Copyable { /// The type that represents an initialized position in an `OutputSpan`. typealias Index = Int @@ -448,6 +448,10 @@ extension OutputRawSpan { The basic operation is to append the bytes of some value to an `OutputRawSpan`. Note that since the fundamental operation is appending bytes, `OutputRawSpan` does not concern itself with memory alignment. ```swift extension OutputRawSpan { + /// Append a single byte to this span + @lifetime(self: copy self) + public mutating func append(_ value: UInt8) + /// Appends the given value's bytes to this span's initialized bytes @lifetime(self: copy self) public mutating func append( @@ -522,6 +526,29 @@ extension OutputRawSpan { } ``` +Methods to deinitialize memory from an `OutputRawSpan`: + +```swift +extension OutputRawSpan { + + /// Remove the last byte from this span + @lifetime(self: copy self) + public mutating func removeLast() -> UInt8 { + + /// Remove the last N elements, returning the memory they occupy + /// to the uninitialized state. + /// + /// `n` must not be greater than `count` + @lifetime(self: copy self) + public mutating func removeLast(_ n: Int) + + /// Remove all this span's elements and return its memory + /// to the uninitialized state. + @lifetime(self: copy self) + public mutating func removeAll() +} +``` + ##### Interoperability with unsafe code @@ -825,10 +852,6 @@ This proposal considers the naming of `OutputSpan`'s bulk-copying methods more c ```swift extension MutableSpan where Element: Copyable { - public mutating func update( - from source: inout some IteratorProtocol - ) -> Index - public mutating func update( fromContentsOf source: some Sequence ) -> Index @@ -856,6 +879,10 @@ extension MutableSpan { public mutating func append( consuming source: Slice> ) + + public mutating func update( + from source: inout some IteratorProtocol + ) -> Index } ``` @@ -863,10 +890,6 @@ Similarly, `MutableRawSpan`'s bulk-copying methods would be replaced by the foll ```swift extension MutableRawSpan { - public mutating func update( - from source: inout some IteratorProtocol, as type: T.Type - ) -> Index - public mutating func update( fromContentsOf source: some Sequence, as type: T.Type ) -> Index @@ -882,6 +905,10 @@ extension MutableRawSpan { public mutating func append( fromContentsOf source: UnsafeRawBufferPointer ) -> Index + + public mutating func update( + from source: inout some IteratorProtocol, as type: T.Type + ) -> Index } ``` @@ -995,8 +1022,8 @@ We could expand upon this ability to disambiguate by using keywords or even new let buffer: UnsafeMutableBufferPointer = ... let array = Array(capacity: buffer.count*2) { (o: inout OutputSpan) in - o.append(contentsOf: borrowing buffer) - o.append(contentsOf: consuming buffer) + o.append(contentsOf: borrow buffer) + o.append(contentsOf: consume buffer) } ``` From d693d3f3248769a81a921a7987d6399af2f851d1 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Fri, 16 May 2025 18:08:46 -0700 Subject: [PATCH 317/505] Even more edits --- proposals/nnnn-outputspan.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/nnnn-outputspan.md b/proposals/nnnn-outputspan.md index 1a56f51f51..6412770deb 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/nnnn-outputspan.md @@ -934,7 +934,7 @@ The additions described in this proposal require a new version of the Swift stan #### Alternative names for `append()` methods -`OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be applicable types The origin of the `append(contentsOf:)` method we are expanding upon is the `RangeReplaceableCollection` protocol, which always represents copyable and escapable collections and copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This support copying elements from the source, while also destroying the source if we happen to own its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrow of the source. +`OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be generally applicable. The origin of the `append(contentsOf:)` method we are expanding upon is the `RangeReplaceableCollection` protocol, which always represents copyable and escapable collections with copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This supports copying elements from the source, while also destroying the source if we happen to hold its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrow of the source. When the elements are non-copyable, we must append elements that are removed from the source. Afterwards, there are two possible dispositions of the source: destruction (`consuming`,) where the source can no longer be used, or mutation (`inout`,) where the source has been emptied but is still usable. @@ -979,9 +979,9 @@ We note that the four variants of `append()` are required for generalized contai Some applications may benefit from the ability to initialize a range of memory in a different order than implemented by `OutputSpan`. This may be from back-to-front or even arbitrary order. There are many possible forms such an initialization helper can take, depending on how much memory safety the application is willing to give up in the process of initializing the memory. At the unsafe end, this can be delegating to an `UnsafeMutableBufferPointer` along with a set of requirements; this option is proposed here. At the safe end, this could be delegating to a data structure which keeps track of initialized memory using a bitmap. It is unclear how much need there is for this more heavy-handed approach, so we leave it as a future enhancement if it is deemed useful. -#### Insertions and indexing +#### Insertions -A use case similar to appending is insertions. Appending is simply inserting at the end. Inserting at positions other than the end is an important capability. It requires an indexing model, which we do not propose here. We expect to add indexing and insertions soon if `OutputSpan` is accepted. Until then, a workaround is to append, then rotate the elements to the desired position using the `mutableSpan` view. The current proposal does not add a concept of indexing to `OutputSpan`, though that is required in order to support insertions at an arbitrary position. We defer this discussion in order to focus on the basic functionality of the type. +A use case similar to appending is insertions. Appending is simply inserting at the end. Inserting at positions other than the end is an important capability. We expect to add insertions soon if `OutputSpan` is accepted. Until then, a workaround is to append, then rotate the elements to the desired position using the `mutableSpan` view. The current proposal does not add a concept of indexing to `OutputSpan`, though that is required in order to support insertions at an arbitrary position. We defer this discussion in order to focus on the basic functionality of the type. #### Generalized removals @@ -993,7 +993,7 @@ The function proposed here only exposes uninitialized capacity in the `OutputSpa #### Language syntax to distinguish between ownership modes for function arguments -In the "Alternates Considered" subsection about [naming the `append()` methods](#contentsOf), we suggest a currently unachievable naming scheme: +In the "Alternatives Considered" subsection about [naming the `append()` methods](#contentsOf), we suggest a currently unachievable naming scheme: ```swift extension OutputSpan { mutating func append(contentsOf: consuming some Sequence) From 9f94d22a9254231742f4f7c51b59cc9f1f483d06 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 14:22:21 +0100 Subject: [PATCH 318/505] Mention limitations on artifacts in introduction --- ...tpm-static-library-binary-target-non-apple-platforms.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index 6991b6f942..ab1ec702f7 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -10,11 +10,10 @@ ## Introduction -Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). +Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. -This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms. - -Swift-evolution thread: +This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms that depend only the standard C library. +Unfortunately, this proposal doesn't provide support for distributing Swift libraries built in this way due to the Swift ABI not being stable on all platforms. ## Motivation From 40c804ed669b726160b6bfef740d9328a855099c Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 14:27:11 +0100 Subject: [PATCH 319/505] Update json schema for artifact bundle --- ...brary-binary-target-non-apple-platforms.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index ab1ec702f7..bc47042fbb 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -61,9 +61,11 @@ The artifact manifest JSON format for a static library is described below: "variants": [ { "path": "", - "headerPaths": [", ...], - "moduleMapPath": "", "supportedTriples": ["", ... ], + "staticLibraryMetadata": { + "headerPaths": [", ...], + "moduleMapPath": "" + } }, ... ] @@ -71,6 +73,7 @@ The artifact manifest JSON format for a static library is described below: ... } } + ``` The additions are: @@ -85,18 +88,22 @@ As with executable binary artifacts, the `path` field represents the relative pa and the `supportedTriples` field provides information about the target triples supported by this variant. An example artifact might look like: + ```json { "schemaVersion": "1.0", "artifacts": { - "my-artifact": { + "example": { "type": "staticLibrary", "version": "1.0.0", "variants": [ { - "path": "artifact.a", - "headerPaths": ["include"], - "supportedTriples": ["aarch64-unknown-linux-gnu"] + "path": "libExample.a", + "supportedTriples": ["aarch64-unknown-linux-gnu"], + "staticLibraryMetadata": { + "headerPaths": ["include"], + "moduleMapPath": "include/example.modulemap" + } } ] } From 3fbde18ad0690e55a67b9416c65a91fba038703f Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 14:31:06 +0100 Subject: [PATCH 320/505] Call out requirement to provide a modulemap for Swift imports --- ...wiftpm-static-library-binary-target-non-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index bc47042fbb..bae28fb457 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -81,8 +81,8 @@ The additions are: * The `staticLibrary` artifact `type` that indicates this binary artifact is not an executable but rather a static library to link against. * The `headerPaths` field specifies directory paths relative to the root of the artifact bundle that contain the header interfaces to the static library. These are forwarded along to the swift compiler (or the C compiler) using the usual search path arguments. - Each of these directories can optionally contain a `module.modulemap` file that will be used for importing the API into Swift code. -* The optional `moduleMapPath` field specifies a custom module map to use if the header paths do not contain the module definitions or to provide custom overrides. +* The optional `moduleMapPath` field specifies the path relative to the root of the artifact bundle that contains a custom module map to use if the header paths do not contain the module definitions or to provide custom overrides. + This field is required if the library's API is to be imported into Swift code. As with executable binary artifacts, the `path` field represents the relative path to the binary from the root of the artifact bundle, and the `supportedTriples` field provides information about the target triples supported by this variant. From d55587e70cd33b73460d7bed0f5703697453ee8f Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 15:00:16 +0100 Subject: [PATCH 321/505] Call out options for distributing artifacts with known dependencies --- ...-swiftpm-static-library-binary-target-non-apple-platforms.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index bae28fb457..b45c555874 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -42,6 +42,8 @@ The artifact manifest would encode the following information for each variant: Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. +However when an artifact isn't widely consumed and all dependent packages are known, +artifact vendors can provide artifacts with dependencies on other C libraries provided that each client target depends explicitly on all required dependencies of the artifact. ## Detailed design From 51edf3a6ba888cc00a5411569eae5bd72403f9a1 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 15:01:24 +0100 Subject: [PATCH 322/505] Fix typos --- ...wiftpm-static-library-binary-target-non-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index b45c555874..1557019a3b 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -40,7 +40,7 @@ The artifact manifest would encode the following information for each variant: * Enough information to be able to use the library's API in the packages source code, i.e., headers and module maps for libraries exporting a C-based interface. -Additionnaly, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. +Additionally, we propose the addition of an auditing tool that can validate the library artifact is safe to use across the Linux-based platforms supported by the Swift project. Such a tool would ensure that people do not accidentally distribute artifacts that require dependencies that are not met on the various deployment platforms. However when an artifact isn't widely consumed and all dependent packages are known, artifact vendors can provide artifacts with dependencies on other C libraries provided that each client target depends explicitly on all required dependencies of the artifact. @@ -131,7 +131,7 @@ The tool would then check that the referenced symbols list is a subset of the se This would be sufficient to guarantee that all symbols from the static library would be available at runtime for statically linked executables or for ones running on the build host. To ensure maximum runtime compatibility we would also provide a Linux-based Docker image that uses the oldest supported `glibc` for a given Swift version. As `glibc` is backwards compatible, a container running the audit on a given static library would ensure that the version of `glibc` on any runtime platform would be compatible with the binary artifact. -This strategy as been succesfully employed in the Python community with [`manylinux`](https://peps.python.org/pep-0513/). +This strategy as been successfully employed in the Python community with [`manylinux`](https://peps.python.org/pep-0513/). ## Security From aa82059073d9f994046f1c3b36dce9c2e420fd42 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 19 May 2025 17:37:12 +0100 Subject: [PATCH 323/505] fixup! Mention limitations on artifacts in introduction --- ...wiftpm-static-library-binary-target-non-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index 1557019a3b..59ac4ad8d8 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -12,8 +12,8 @@ Swift continues to grow as a cross-platform language supporting a wide variety of use cases from [programming embedded device](https://www.swift.org/blog/embedded-swift-examples/) to [server-side development](https://www.swift.org/documentation/server/) across a multitude of [operating systems](https://www.swift.org/documentation/articles/static-linux-getting-started.html). However, currently SwiftPM supports linking against binary dependencies on Apple platforms only. -This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms that depend only the standard C library. -Unfortunately, this proposal doesn't provide support for distributing Swift libraries built in this way due to the Swift ABI not being stable on all platforms. +This proposal aims to make it possible to provide static library dependencies exposing a C interface on non-Apple platforms that depend only on the standard C library. +The scope of this proposal is C libraries only, distributing Swift libraries has additional challenges (see [Future directions](#future-directions). ## Motivation From e4b25834c1cddd254bedd6497b2534190b712c31 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 19 May 2025 13:35:03 -0700 Subject: [PATCH 324/505] Replace `swift migrate` with `swift package migrate` --- .../NNNN-adoption-tooling-for-swift-features.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/NNNN-adoption-tooling-for-swift-features.md index 93aed515e5..38217aac80 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/NNNN-adoption-tooling-for-swift-features.md @@ -1,6 +1,6 @@ # Migration tooling for Swift features -* Proposal: [SE-NNNN](NNNN-filename.md) +* Proposal: [SE-NNNN](NNNN-migratable-features.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: TBD * Status: **Awaiting implementation** @@ -160,16 +160,16 @@ belong to a diagnostic group named after the feature. The names of diagnostic groups can be displayed alongside diagnostic messages using `-print-diagnostic-groups` and used to associate messages with features. -### `swift migrate` command +### `swift package migrate` command -To enable seemless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - `swift migrate` to complement the Swift compiler-side changes. +To enable seemless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - `swift package migrate` to complement the Swift compiler-side changes. The command would accept one or more features that have migration mode enabled and optionally a set of targets to migrate, if no targets are specified the whole package is going to be migrated to use new features. #### Interface ``` -USAGE: swift migrate [] --to-feature ... +USAGE: swift package migrate [] --to-feature ... OPTIONS: --targets The targets to migrate to specified set of features or a new language mode. @@ -181,7 +181,7 @@ OPTIONS: #### Use case ``` -swift migrate --targets MyTarget,MyTest --to-feature ExistentialAny +swift package migrate --targets MyTarget,MyTest --to-feature ExistentialAny ``` This command would attempt to build `MyTarget` and `MyTest` targets with `ExistentialAny:migrate` feature flag, apply any fix-its associated with @@ -211,7 +211,7 @@ enable the feature(s) if both of the previous actions are successful: In the "whole package" mode, every target is going to be updated to include new feature flag(s). This is supported by the same functionality as `swift package add-setting` command. -If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. `...; please add '.enableUpcomingFeature("ExistentialAny")' to `MyTarget` target manually`. +If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. `...; please add 'ExistentialAny' feature to `MyTarget` target manually`. #### Impact on Interface @@ -345,7 +345,7 @@ The next candidates in line per discussions are ***adopt***, ***audit***, To illustrate, this mode could appropriately suggest switching from `any P` to `some P` for `ExistentialAny`. -### `swift migrate` vs. `swift package migrate` +### `swift package migrate` vs. `swift migrate` Rather than have migrate as a subcommand (ie. `swift package migrate`), another option is add another top level command, ie. `swift migrate`. From 0accc4c2dd2a45e13c189734e02fe317aea73464 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 16 May 2025 12:55:11 -0500 Subject: [PATCH 325/505] Add proposal for Issue Handling Traits --- .../testing/NNNN-issue-handling-traits.md | 495 ++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 proposals/testing/NNNN-issue-handling-traits.md diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md new file mode 100644 index 0000000000..ff73502ab4 --- /dev/null +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -0,0 +1,495 @@ +# Issue Handling Traits + +* Proposal: [ST-NNNN](NNNN-issue-handling-trait.md) +* Authors: [Stuart Montgomery](https://github.com/stmontgomery) +* Review Manager: TBD +* Status: **Awaiting review** +* Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121) +* Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) + +## Introduction + +This proposal introduces a built-in trait for handling issues in Swift Testing, +enabling test authors to customize how expectation failures and other issues +recorded by tests are represented. Using a custom issue handler, developers can +transform issue details, perform additional actions, or suppress certain issues. + +## Motivation + +Swift Testing offers ways to customize test attributes and perform custom logic +using traits, but there's currently no way to customize how issues (such as +`#expect` failures) are handled when they occur during testing. + +The ability to handle issues using custom logic would enable test authors to +modify, supplement, or filter issues based on their specific requirements before +the testing library processes them. This capability could open the door to more +flexible testing approaches, improve integration with external reporting systems, +or improve the clarity of results in complex testing scenarios. The sections +below discuss several potential use cases for this functionality. + +### Adding information to issues + +#### Comments + +Sometimes test authors want to include context-specific information to certain +types of failures. For example, they might want to automatically add links to +documentation for specific categories of test failures, or include supplemental +information about the history of a particular expectation in case it fails. An +issue handler could intercept issues after they're recorded and add these +details to the issue's comments before the testing library processes them. + +#### Attachments + +Test failures often benefit from additional diagnostic data beyond the basic +issue description. Swift Testing now supports attachments (as of +[ST-0009](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0009-attachments.md)), +and the ability to add an attachment to an indiviual issue was mentioned as a +future direction in that proposal. The general capability of adding attachments +to issues is outside the scope of this proposal, but if such a capability were +introduced, an issue handler could programmatically attach log files, +screenshots, or other diagnostic artifacts when specific issues occur, making it +easier to diagnose test failures. + +### Suppressing warnings + +Recently, a new API was [pitched][severity-proposal] which would introduce the +concept of severity to issues, along with a new _warning_ severity level, making +it possible to record warnings that do not cause a test to be marked as a +failure. If that feature is accepted, there may be cases where a test author +wants to suppress certain warnings entirely or in specific contexts. + +For instance, they might choose to suppress warnings recorded by the testing +library indicating that two or more arguments to a parameterized test appear +identical, or for one of the other scenarios listed as potential use cases for +warning issues in that proposal. An issue handler would provide a mechanism to +filter issues. + +### Raising or lowering an issue's severity + +Beyond suppressing issues altogether, a test author might want to modify the +severity of an issue (again, assuming the recently pitched +[Issue Severity][severity-proposal] proposal is accepted). They might wish to +either _lower_ an issue with the default error-level severity to a warning (but +not suppress it), or conversely _raise_ a warning issue to an error. + +The Swift compiler now allows control over warning diagnostics (as of +[SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md)). +An issue handling trait would offer analogous functionality for test issues. + +### Normalizing issue details + +Tests that involve randomized or non-deterministic inputs can generate different +issue descriptions on each run, making it difficult to identify duplicates or +recognize patterns in failures. For example, a test verifying random number +generation might produce an expectation failure with different random values +each time: + +``` +Expectation failed: (randomValue → 0.8234) > 0.5 +Expectation failed: (randomValue → 0.6521) > 0.5 +``` + +An issue handler could normalize these issues to create a more consistent +representation: + +``` +Expectation failed: (randomValue → 0.NNNN) > 0.5 +``` + +The original numeric value could be preserved via a comment after being +obfuscated—see [Comments](#comments) under [Adding information to issues](#adding-information-to-issues) +above. + +> [!NOTE] +> This example involves an expectation failure. The value of the `kind` property +> for such an issue would be `.expectationFailed(_:)` and it would have an +> associated value of type `Expectation`. To transform the issue in the way +> described above would require modifying details of the associated `Expectation` +> and its substructure, but these details are currently SPI so test authors +> cannot modify them directly. +> +> Exposing these details is out of scope for this proposal, but a test author +> could still transform this issue to achieve a similar result by changing the +> issue's kind from `.expectationFailed(_:)` to `.unconditional`. This +> experience could be improved in the future in subsequent proposals if desired. + +This normalization can significantly improve the ability to triage failures, as +it becomes easier to recognize when multiple test failures have the same root +cause despite different specific values. + +## Proposed solution + +This proposal introduces a new trait type that can customize how issues are +processed during test execution. + +Here's one contrived example showing how this could be used to add a comment to +each issue recorded by a test: + +```swift +@Test(.transformIssues { issue in + var issue = issue + issue.comments.append("Checking whether two literals are equal") + return issue +}) +func literalComparisons() { + #expect(1 == 1) // ✅ + #expect(2 == 3) // ❌ Will invoke issue handler + #expect("a" == "b") // ❌ Will invoke issue handler again +} +``` + +Here's an example showing how warning issues matching a specific criteria could +be suppressed using `.filterIssues`. It also showcases a technique for reusing +an issue handler across multiple tests, by defining it as a computed property in +an extension on `Trait`: + +```swift +extension Trait where Self == IssueHandlingTrait { + static var ignoreSensitiveWarnings: Self { + .filterIssues { issue in + let description = String(describing: issue) + + // Note: 'Issue.severity' has been pitched but not accepted. + return issue.severity <= .warning && SensitiveTerms.all.contains { description.contains($0) } + } + } +} + +@Test(.ignoreSensitiveWarnings) func exampleA() { + ... +} + +@Test(.ignoreSensitiveWarnings) func exampleB() { + ... +} +``` + +The sections below discuss some of the proposed new trait's behavioral details. + +### Precedence order of handlers + +If multiple issue handling traits are applied to or inherited by a test, they +are executed in trailing-to-leading, innermost-to-outermost order. For example, +given the following code: + +```swift +@Suite(.transformIssues { ... /* A */ }) +struct ExampleSuite { + @Test(.filterIssues { ... /* B */ }, + .transformIssues { ... /* C */ }) + func example() { + ... + } +} +``` + +If an issue is recorded in `example()`, it's processed first by closure C, then +by B, and finally by A. (Unless an issue is suppressed, in which case it will +not advance to any subsequent handler's closure.) This ordering provides +predictable behavior and allows more specific handlers to process issues before +more general ones. + +### Accessing task-local context from handlers + +The closure of an issue handler is invoked synchronously at the point where an +issue is recorded. This means the closure can access task local state from that +context, and potentially use that to augment issues with extra information. +Here's an example: + +```swift +// In module under test: +actor Session { + @TaskLocal static var current: Session? + + let id: String + func connect() { ... } + var isConnected: Bool { ... } + ... +} + +// In test code: +@Test(.transformIssues { issue in + var issue = issue + if let session = Session.current { + issue.comments.append("Current session ID: \(session.id)") + } + return issue +}) +func example() async { + let session = Session(id: "ABCDEF") + await Session.$current.withValue(session) { + await session.connect() + #expect(await session.isConnected) // ❌ Expectation failed: await session.isConnected + // Current session ID: ABCDEF + } +} +``` + +### Recording issues from handlers + +Issue handling traits can record additional issues during their execution. These +newly recorded issues will be processed by any later issue handling traits in +the processing chain (see [Precedence order of handlers](#precedence-order-of-handlers)). +This capability allows handlers to augment or provide context to existing issues +by recording related information. + +For example: + +```swift +@Test( + .transformIssues { issue in + // This closure will be called for any issue recorded by the test function + // or by the `.filterIssues` trait below. + ... + }, + .filterIssues { issue in + guard let terms = SensitiveTerms.all else { + Issue.record("Cannot determine the set of sensitive terms. Filtering issue by default.") + return true + } + + let description = String(describing: issue).lowercased() + return terms.contains { description.contains($0) } + } +) +func example() { + ... +} +``` + +### Handling issues from other traits + +Issue handling traits process all issues recorded in the context of a test, +including those generated by other traits applied to the test. For instance, if +a test uses the `.enabled(if:)` trait and the condition closure throws an error, +that error will be recorded as an issue, the test will be skipped, and the issue +will be passed to any issue handling traits for processing. + +This comprehensive approach ensures that all issues related to a test, +regardless of their source, are subject to the same customized handling. It +provides a unified mechanism for issue processing that works consistently across +the testing library. + +### Effects in issue handler closures + +The closure of an issue handling trait must be: + +- **Non-`async`**: This reflects the fact that events in + Swift Testing are posted synchronously, which is a fundamental design decision + that, among other things, avoids the need for `await` before every `#expect`. + + While this means that issue handlers cannot directly perform asynchronous work + when processing an individual issue, future enhancements could offer + alternative mechanisms for asynchronous issue processing work at the end of a + test. See the [Future directions](#future-directions) section for more + discussion about this. + +- **Non-`throws`**: Since these handlers are already + being called in response to a failure (the recorded issue), allowing them to + throw errors would introduce ambiguity about how such errors should be + interpreted and reported. + + If an issue handler encounters an error, it can either: + + - Return a modified issue that includes information about the problem, or + - Record a separate issue using the standard issue recording mechanisms (as + [discussed](#recording-issues-from-handlers) above). + +## Detailed design + +This proposal includes the following: + +* A new `IssueHandlingTrait` type that conforms to `TestTrait` and `SuiteTrait`. + * An instance method `handleIssue(_:)` which can be called directly on a + handler trait. This may be useful for composing multiple issue handling + traits. +* Static functions on `Trait` for creating instances of this type with the + following capabilities: + * A function `transformIssues(_:)` which returns a trait that can transform + recorded issues. The function takes a closure which is passed an issue and + returns either a modified issue or `nil` to suppress it. + * A function `filterIssues(_:)` which returns a trait that can filter recorded + issues. The function takes a predicate closure that returns a boolean + indicating whether to keep (`true`) or suppress (`false`) an issue. + +Below are the proposed interfaces: + +```swift +/// A type that allows transforming or filtering the issues recorded by a test. +/// +/// Use this type to observe or customize the issue(s) recorded by the test this +/// trait is applied to. You can transform a recorded issue by copying it, +/// modifying one or more of its properties, and returning the copy. You can +/// observe recorded issues by returning them unmodified. Or you can suppress an +/// issue by either filtering it using ``Trait/filterIssues(_:)`` or returning +/// `nil` from the closure passed to ``Trait/transformIssues(_:)``. +/// +/// When an instance of this trait is applied to a suite, it is recursively +/// inherited by all child suites and tests. +/// +/// To add this trait to a test, use one of the following functions: +/// +/// - ``Trait/transformIssues(_:)`` +/// - ``Trait/filterIssues(_:)`` +public struct IssueHandlingTrait: TestTrait, SuiteTrait { + /// Handle a specified issue. + /// + /// - Parameters: + /// - issue: The issue to handle. + /// + /// - Returns: An issue to replace `issue`, or else `nil` if the issue should + /// not be recorded. + public func handleIssue(_ issue: Issue) -> Issue? +} + +extension Trait where Self == IssueHandlingTrait { + /// Constructs an trait that transforms issues recorded by a test. + /// + /// - Parameters: + /// - transformer: The closure called for each issue recorded by the test + /// this trait is applied to. It is passed a recorded issue, and returns + /// an optional issue to replace the passed-in one. + /// + /// - Returns: An instance of ``IssueHandlingTrait`` that transforms issues. + /// + /// The `transformer` closure is called synchronously each time an issue is + /// recorded by the test this trait is applied to. The closure is passed the + /// recorded issue, and if it returns a non-`nil` value, that will be recorded + /// instead of the original. Otherwise, if the closure returns `nil`, the + /// issue is suppressed and will not be included in the results. + /// + /// The `transformer` closure may be called more than once if the test records + /// multiple issues. If more than one instance of this trait is applied to a + /// test (including via inheritance from a containing suite), the `transformer` + /// closure for each instance will be called in right-to-left, innermost-to- + /// outermost order, unless `nil` is returned, which will skip invoking the + /// remaining traits' closures. + /// + /// Within `transformer`, you may access the current test or test case (if any) + /// using ``Test/current`` ``Test/Case/current``, respectively. You may also + /// record new issues, although they will only be handled by issue handling + /// traits which precede this trait or were inherited from a containing suite. + public static func transformIssues(_ transformer: @escaping @Sendable (Issue) -> Issue?) -> Self + + /// Constructs a trait that filters issues recorded by a test. + /// + /// - Parameters: + /// - isIncluded: The predicate with which to filter issues recorded by the + /// test this trait is applied to. It is passed a recorded issue, and + /// should return `true` if the issue should be included, or `false` if it + /// should be suppressed. + /// + /// - Returns: An instance of ``IssueHandlingTrait`` that filters issues. + /// + /// The `isIncluded` closure is called synchronously each time an issue is + /// recorded by the test this trait is applied to. The closure is passed the + /// recorded issue, and if it returns `true`, the issue will be preserved in + /// the test results. Otherwise, if the closure returns `false`, the issue + /// will not be included in the test results. + /// + /// The `isIncluded` closure may be called more than once if the test records + /// multiple issues. If more than one instance of this trait is applied to a + /// test (including via inheritance from a containing suite), the `isIncluded` + /// closure for each instance will be called in right-to-left, innermost-to- + /// outermost order, unless `false` is returned, which will skip invoking the + /// remaining traits' closures. + /// + /// Within `isIncluded`, you may access the current test or test case (if any) + /// using ``Test/current`` ``Test/Case/current``, respectively. You may also + /// record new issues, although they will only be handled by issue handling + /// traits which precede this trait or were inherited from a containing suite. + public static func filterIssues(_ isIncluded: @escaping @Sendable (Issue) -> Bool) -> Self +} +``` + +## Source compatibility + +This new trait is additive and should not affect source compatibility of +existing test code. + +If any users have an existing extension on `Trait` containing a static function +whose name conflicts with one in this proposal, the standard technique of +fully-qualifying its callsite with the relevant module name can be used to +resolve any ambiguity, but this should be rare. + +## Integration with supporting tools + +Most tools which integrate with the testing library interpret recorded issues in +some way, whether by writing them to a persistent data file or presenting them +in UI. These mechanisms will continue working as before, but the issues they act +on will be the result of any issue handling traits. If an issue handler +transforms an issue, the integrated tool will only receive the transformed issue, +and if a trait suppresses an issue, the tool will not be notified about the +issue at all. + +## Future directions + +### "Test ended" trait + +The current proposal does not allow `await` in an issue handling closure--see +[Non-`async`](#non-async) above. In addition to not allowing concurrency, the +proposed behavior is that the issue handler is called once for _each_ issue +recorded. + +Both of these policies could be problematic for some use cases. Some users may +want to collect additional diagnostics if a test fails, but only do so once per +per test (typically after it finishes) instead of once per _issue_, since the +latter may lead to redundant or wasteful work. Also, collecting diagnostics may +require calling `async` APIs. + +In the future, a new trait could be added which offers a closure that is +unconditionally called once after a test ends. The closure could be provided the +result of the test (e.g. pass/fail/skip) and access to all the issues it +recorded. This hypothetical trait's closure could be safely made `async`, since +it wouldn't be subject to the same limitations as event delivery, and this could +complement the APIs proposed above. + +### Comprehensive event observation API + +As a more generalized form of the ["Test ended" trait](#test-ended-trait) idea +above, Swift Testing could offer a more comprehensive suite of APIs for +observing test events of all kinds. This would a much larger effort, but was +[mentioned](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md#flexibility) +as a goal in the +[Swift Testing vision document](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md). + +## Alternatives considered + +### Allow issue handler closures to throw errors + +The current proposal does not allow throwing an error from an issue handling +closure--see [Non-`throws`](#non-throws) above. This artificial restriction +could be lifted, and errors thrown by issue handler closures could be caught +and recorded as issues, matching the behavior of test functions. + +As mentioned earlier, allowing thrown errors could make test results more +confusing. We expect that most often, a test author will add an issue handler +because they want to make failures easier to interpret, and they generally won't +want an issue handler to record _more_ issues while doing so even if it can. Not +allowing errors to be thrown forces the author of the issue handler to make an +explicit decision about whether they want an additional issue to be recorded if +the handler encounters an error. + +### Alternate names for the static trait functions + +We could choose different names for the static `transformIssues(_:)` or +`filterIssues(_:)` functions. Some alternate names considered were: + +- `compactMapIssues` instead of `transformIssues`. This arguably aligns better + with the word "filter" of `filterIssues`, but it felt strange since often, + "map" is used to return a value of a _different_ type, whereas here it must + return a value of the same type, it's just that it can be mutated. +- `handleIssues` instead of `transformIssues`. The word "handle" is in the name + of the trait type already; it's a more general word for what all of these + usage patterns enable, so it felt too broad. +- Using singular "issue" rather than plural "issues" in both APIs. This may not + adequately convey that the closure can be invoked more than once. + +## Acknowledgments + +Thanks to [Brian Croom](https://github.com/briancroom) for feedback on the +initial concept, and for making a suggestion which led to the +["Test ended" trait](#test-ended-trait) idea mentioned in Alternatives +considered. + +[severity-proposal]: https://forums.swift.org/t/pitch-test-issue-warnings/79285 From aa91afb097ffe1d21b955a05dede0309eae4814d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 21 May 2025 08:36:16 +0100 Subject: [PATCH 326/505] [SE-0485] Initiate review of OutputSpan: delegate initialization of contiguous memory --- proposals/{nnnn-outputspan.md => 0485-outputspan.md} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename proposals/{nnnn-outputspan.md => 0485-outputspan.md} (98%) diff --git a/proposals/nnnn-outputspan.md b/proposals/0485-outputspan.md similarity index 98% rename from proposals/nnnn-outputspan.md rename to proposals/0485-outputspan.md index 6412770deb..3d244045ea 100644 --- a/proposals/nnnn-outputspan.md +++ b/proposals/0485-outputspan.md @@ -1,9 +1,9 @@ # OutputSpan: delegate initialization of contiguous memory -* Proposal: TBD +* Proposal: [SE-0485](0485-outputspan.md) * Author: [Guillaume Lessard](https://github.com/glessard) -* Review Manager: TBD -* Status: **Pitch** +* Review Manager: [Doug Gregor](https://github.com/DougGregor) +* Status: **Active Review (May 20...June 3, 2025)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) * Review: [Pitch](https://forums.swift.org/) @@ -58,7 +58,7 @@ In addition to the new types, we propose adding new API for some standard librar `OutputSpan` allows delegating the initialization of a type's memory, by providing access to an exclusively-borrowed view of a range of contiguous memory. `OutputSpan`'s contiguous memory always consists of a prefix of initialized memory, followed by a suffix of uninitialized memory. `OutputSpan`'s operations manage the initialization state in order to preserve that invariant. The common usage pattern we expect to see for `OutputSpan` consists of passing it as an `inout` parameter to a function, allowing the function to produce an output by writing into a previously uninitialized region. -Like `MutableSpan`, `OutputSpan` relies on two guarantees: (a) that it has exclusive access to the range of memory it represents, and (b) that the memory locations it represents will remain valid for the duration of the access. These guarantee data race safety and temporal safety. `OutputSpan` performs bounds-checking on every access to preserve spatial safety. `OutputSpan` manages the initialization state of the memory in represents on behalf of the memory's owner. +Like `MutableSpan`, `OutputSpan` relies on two guarantees: (a) that it has exclusive access to the range of memory it represents, and (b) that the memory locations it represents will remain valid for the duration of the access. These guarantee data race safety and lifetime safety. `OutputSpan` performs bounds-checking on every access to preserve bounds safety. `OutputSpan` manages the initialization state of the memory in represents on behalf of the memory's owner. #### OutputRawSpan @@ -936,7 +936,7 @@ The additions described in this proposal require a new version of the Swift stan `OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be generally applicable. The origin of the `append(contentsOf:)` method we are expanding upon is the `RangeReplaceableCollection` protocol, which always represents copyable and escapable collections with copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This supports copying elements from the source, while also destroying the source if we happen to hold its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrow of the source. -When the elements are non-copyable, we must append elements that are removed from the source. Afterwards, there are two possible dispositions of the source: destruction (`consuming`,) where the source can no longer be used, or mutation (`inout`,) where the source has been emptied but is still usable. +When the elements are non-copyable, we must append elements that are removed from the source. Afterwards, there are two possible dispositions of the source: destruction (`consuming`), where the source can no longer be used, or mutation (`inout`), where the source has been emptied but is still usable. When the elements are copyable, we can simply copy the elements from the source. Afterwards, there are two possible dispositions of the source: releasing a borrowed source, or `consuming`. The latter is approximately the same behaviour as `RangeReplaceableCollection`'s `append()` function shown above. @@ -985,7 +985,7 @@ A use case similar to appending is insertions. Appending is simply inserting at #### Generalized removals -Similarly to generalized insertions (i.e. not from the end,) we can think about removals of one or more elements starting at a given position. This also requires adding indexing. We expect to add generalized removals along with insertions if `OutputSpan` is accepted. +Similarly to generalized insertions (i.e. not from the end), we can think about removals of one or more elements starting at a given position. This also requires adding indexing. We expect to add generalized removals along with insertions if `OutputSpan` is accepted. #### Variations on `Array.append(addingCapacity:initializingWith:)` From 4ecced2d14aa8b1c82349f3434a4ffc14db65957 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 21 May 2025 08:40:04 +0100 Subject: [PATCH 327/505] Add review thread for SE-0485 --- proposals/0485-outputspan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 3d244045ea..d9b05b8e4c 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -6,7 +6,7 @@ * Status: **Active Review (May 20...June 3, 2025)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) -* Review: [Pitch](https://forums.swift.org/) +* Review: [Pitch](https://forums.swift.org/), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md From f67e90e55379259524d6491e5c666eb1bcac42d9 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 21 May 2025 09:54:51 -0400 Subject: [PATCH 328/505] Accept SE-0472. --- proposals/0472-task-start-synchronously-on-caller-context.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index c7f0701080..1f47857b65 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -3,9 +3,9 @@ * Proposal: [SE-0472](0472-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Returned for revision** +* Status: **Accepted** * Implementation: https://github.com/swiftlang/swift/pull/79608 -* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([first review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ([second review](https://forums.swift.org/t/second-review-se-0472-starting-tasks-synchronously-from-caller-context/79683)) +* Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([first review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ([second review](https://forums.swift.org/t/second-review-se-0472-starting-tasks-synchronously-from-caller-context/79683)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0472-starting-tasks-synchronously-from-caller-context/80037)) ## Introduction From acca3fd80d2eefb9c22fc6147ab688b429760933 Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Wed, 21 May 2025 17:53:55 +0200 Subject: [PATCH 329/505] [SE-0485] Initiate review of Migration tooling for Swift featuress --- ...tures.md => 0486-adoption-tooling-for-swift-features.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/{NNNN-adoption-tooling-for-swift-features.md => 0486-adoption-tooling-for-swift-features.md} (99%) diff --git a/proposals/NNNN-adoption-tooling-for-swift-features.md b/proposals/0486-adoption-tooling-for-swift-features.md similarity index 99% rename from proposals/NNNN-adoption-tooling-for-swift-features.md rename to proposals/0486-adoption-tooling-for-swift-features.md index 38217aac80..bf50318ac3 100644 --- a/proposals/NNNN-adoption-tooling-for-swift-features.md +++ b/proposals/0486-adoption-tooling-for-swift-features.md @@ -1,9 +1,9 @@ # Migration tooling for Swift features -* Proposal: [SE-NNNN](NNNN-migratable-features.md) +* Proposal: [SE-0486](0486-adoption-tooling-for-swift-features.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis), [Pavel Yaskevich](https://github.com/xedin) -* Review Manager: TBD -* Status: **Awaiting implementation** +* Review Manager: [Franz Busch](https://github.com/FranzBusch) +* Status: **Active Review (May 21...June 4, 2025)** * Implementation: TBD * Review: [pitch](https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936) From 772d03cc3f44488b653f2757639a3df481e07cfa Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 21 May 2025 17:00:54 +0100 Subject: [PATCH 330/505] [SE-0461] Update remaining mentions of old feature name (#2856) --- proposals/0461-async-function-isolation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proposals/0461-async-function-isolation.md b/proposals/0461-async-function-isolation.md index c123ce36b7..47633dda33 100644 --- a/proposals/0461-async-function-isolation.md +++ b/proposals/0461-async-function-isolation.md @@ -204,7 +204,7 @@ actor MyActor { Changing the default execution semantics of async functions can change the behavior of existing code, so the change is gated behind the -`AsyncCallerExecution` upcoming feature flag. To help stage in the new +`NonisolatedNonsendingByDefault` upcoming feature flag. To help stage in the new behavior, new syntax can be used to explicitly specify the execution semantics of an async function in any language mode. @@ -249,15 +249,15 @@ actor MyActor { `@concurrent` is the current default for nonisolated async functions. `nonisolated(nonsending)` will become the default for async functions -when the `AsyncCallerExecution` upcoming feature is enabled. +when the `NonisolatedNonsendingByDefault` upcoming feature is enabled. ## Detailed design The sections below will explicitly use `@concurrent` and `nonisolated(nonsending)` to demonstrate examples that will behave consistently independent of upcoming features or language modes. However, note that the -end state under the `AsyncCallerExecution` upcoming feature will mean that -`(nonsending)` is not necessary to explicitly write, and +end state under the `NonisolatedNonsendingByDefault` upcoming feature will mean +that `(nonsending)` is not necessary to explicitly write, and `@concurrent` will likely be used sparingly because it has far stricter data-race safety requirements. @@ -1119,8 +1119,8 @@ The proposal was revised with the following changes after the first review: The proposal was revised with the following changes after the pitch discussion: -* Gate the behavior change behind an `AsyncCallerExecution` upcoming feature - flag. +* Gate the behavior change behind an `NonisolatedNonsendingByDefault` upcoming + feature flag. * Change the spelling of `@concurrent` to `@execution(concurrent)`, and add an `@execution(caller)` attribute to allow expressing the new behavior this proposal introduces when the upcoming feature flag is not enabled. From 085467aa13398f263b813f850a2f9a6b4c152ea6 Mon Sep 17 00:00:00 2001 From: "Kuba (Brecka) Mracek" Date: Wed, 21 May 2025 09:44:37 -0700 Subject: [PATCH 331/505] Accept SE-0482 --- ...wiftpm-static-library-binary-target-non-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index 59ac4ad8d8..569c018de1 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -3,9 +3,9 @@ * Proposal: [SE-0482](0482-swiftpm-static-library-binary-target-non-apple-platforms.md) * Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) * Review Manager: [Kuba Mracek](https://github.com/kubamracek) -* Status: **Active Review (May 2nd...May 15th, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) -* Review: ([discussion](https://forums.swift.org/t/se-0482-binary-static-library-dependencies/79634)) ([pitch](https://forums.swift.org/t/pitch-swiftpm-support-for-binary-static-library-dependencies/78619)) +* Review: ([discussion](https://forums.swift.org/t/se-0482-binary-static-library-dependencies/79634)) ([pitch](https://forums.swift.org/t/pitch-swiftpm-support-for-binary-static-library-dependencies/78619)) ([acceptance](https://forums.swift.org/t/accepted-se-0482-binary-static-library-dependencies/80042)) * Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) ## Introduction From eed1fed8339f3919cf5c0f36b804431022d44720 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 23 May 2025 13:52:34 -0400 Subject: [PATCH 332/505] Return SE-0480 for revision --- proposals/0480-swiftpm-warning-control.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 47598f0973..18157ce824 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -3,9 +3,9 @@ * Proposal: [SE-0480](0480-swiftpm-warning-control.md) * Authors: [Dmitrii Galimzianov](https://github.com/DmT021) * Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch](https://github.com/FranzBusch) -* Status: **Active review (April 23...May 5th, 2025)** +* Status: **Returned for revision** * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) -* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) +* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) ## Introduction From 9c93e5734b5b52d9a9b53710cfc33c9b9febf277 Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Sun, 25 May 2025 23:36:13 +0200 Subject: [PATCH 333/505] Pitch for extensible enums (#2679) * Extensible enums * Review * Reviews and same module/package enums * Clarify API impact of `@extensible` and add alternatives considered section * More review comments * Pitch feedback * Pitch feedback: Adding migration path and expand on implications inside the same package * Fix small mistake * Address adding associated values * Remove new annotations and re-use `@frozen` * Update metadata with implementation and pitch * Small fixups * Add migration paths * Minor spelling fix ups * Update proposal to focus on `@extensible` attribute * Change implementation link * Add `@preEnumExtensibility` to the proposal * Source compat section for preEnumExtensibility * Kick off review Also rewords opening description of resilience. --------- Co-authored-by: Ben Cohen --- proposals/NNNN-extensible-enums.md | 319 +++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 proposals/NNNN-extensible-enums.md diff --git a/proposals/NNNN-extensible-enums.md b/proposals/NNNN-extensible-enums.md new file mode 100644 index 0000000000..1878defc70 --- /dev/null +++ b/proposals/NNNN-extensible-enums.md @@ -0,0 +1,319 @@ +# Extensible enums + +* Proposal: [SE-NNNN](NNNN-extensible-enums.md) +* Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) +* Review Manager: [Ben Cohen](https://github.com/airspeedswift) +* Status: **In active review (May 25—Jun 5, 2025)** +* Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) +* Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) +* Upcoming Feature Flag: `ExtensibleAttribute` +* Review: ([pitch](https://forums.swift.org/t/pitch-extensible-enums-for-non-resilient-modules/77649)) + +Previously pitched in: + +- https://forums.swift.org/t/extensible-enumerations-for-non-resilient-libraries/35900 +- https://forums.swift.org/t/pitch-non-frozen-enumerations/68373 + +Revisions: +- Re-focused this proposal on introducing a new `@extensible` attribute and + moved the language feature to a future direction +- Introduced a second annotation `@nonExtensible` to allow a migration path into + both directions +- Added future directions for adding additional associated values +- Removed both the `@extensible` and `@nonExtensible` annotation in favour of + re-using the existing `@frozen` annotation +- Added the high level goals that this proposal aims to achieve +- Expanded on the proposed migration path for packages with regards to their + willingness to break API +- Added future directions for exhaustive matching for larger compilation units +- Added alternatives considered section for a hypothetical + `@preEnumExtensibility` +- Added a section for `swift package diagnose-api-breaking-changes` + +## Introduction + +This proposal provides developers the capabilities to mark public enums in +non-resilient Swift libraries as extensible. This makes Swift `enum`s vastly +more useful in public API of such libraries. + +## Motivation + +When Swift was enhanced to add support for ABI-stable libraries that were built with +"library evolution" enabled ("resilient" libraries as we call them in this proposal), +the Swift language had to support these libraries vending enums that might have cases +added to them in a later version. Swift supports exhaustive switching over cases. +When binaries are compiled against a ABI-stable library they need to be able to handle the +addition of a new case by that library later on, without needing to be rebuilt. + +Consider the following simple library to your favorite pizza place: + +```swift +public enum PizzaFlavor { + case hawaiian + case pepperoni + case cheese +} +``` + +In the standard "non-resilient" mode, users of the library can write exhaustive switch +statements over the enum `PizzaFlavor`: + +```swift +switch pizzaFlavor { +case .hawaiian: + throw BadFlavorError() +case .pepperoni: + try validateNoVegetariansEating() + return .delicious +case .cheese: + return .delicious +} +``` + +Swift requires switches to be exhaustive i.e. the must handle every possibility. +If the author of the above switch statement was missing a case (perhaps they forgot +`.hawaiian` is a flavor), the compiler will error, and force the user to either add a +`default:` clause, or to add the missing case. + +If later a new case is added to the enum (maybe `.veggieSupreme`), exhaustive switches +over that enum might no longer be exhaustive. This is often _desirable_ within a single +codebase (even one split up into multiple modules). A case is added, and the compiler will +assist in finding all the places where this new case must be handled. + +But it presents a problem for authors of both resilient and non-resilient libraries: + +- For non-resilient libraries, adding a case is a source-breaking API change: clients +exhaustively switching over the enum will no longer compile. So can only be done with +a major semantic version bump. +- For resilient libraries, even that is not an option. An ABI-stable library cannot allow +a situation where a binary that has not yet been recompiled can no longer rely on its +switches over an enum are exhaustive. + +Because of the implications on ABI and the requirement to be able to evolve +libraries with public enumerations in their API, the resilient language dialect introduced +"non-exhaustive enums" in [SE-0192](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md). + +If the library was compiled with `-enable-library-evolution`, when a user attempts to +exhaustively switch over the `PizzaFlavor` enum the compiler will emit an error +(when in Swift 6 language mode, a warning in prior language modes), requiring users +to add an `@unknown default:` clause: + +```swift +switch pizzaFlavor { +case .hawaiian: + throw BadFlavorError() +case .pepperoni: + try validateNoVegetariansEating() + return .delicious +case .cheese: + return .delicious +@unknown default: + try validateNoVegetariansEating() + return .delicious +} +``` + +The user is forced to specify how cases are handled if they are introduced later. This +allows ABI-stable libraries to add cases without risking undefined behavior in client +binaries that haven't yet been recompiled. + +When a resilient library knows that an enumeration will never be extended, the author +can annotate the enum with `@frozen`, which in the case of enums is a guarantee that no +further cases can be added. For example, the `Optional` type in the standard library is +frozen, as no third option beyond `some` and `none` will ever be added. This brings +performance benefits, and also the convenience of not requiring an `@unknown default` case. + +`@frozen` is a powerful attribute that can be applied to both structs and enums. It has a +wide ranging number of effects, including exposing their size directly as part of the ABI +and providing direct access to stored properties. However, on enums it happens to +have source-level effects on the behavior of switch statements by clients of a library. +This difference was introduced late in the process of reviewing SE-0192. + +Extensibility of enums is also desirable for non-resilient libraries. Without it, there is no +way for a Swift package to be able to evolve a public enumeration without breaking the API. +However, in Swift today it is not possible for the default, "non-resilient" dialect to opt-in +to the extensible enumeration behavior. This is a substantial limitation, and greatly reduces +the utility of enumerations in non-resilient Swift. + +Over the past years, many packages have run into this limitation when trying to express APIs +using enums. As a non-exhaustive list of problems this can cause: + +- Using enumerations to represent `Error`s is inadvisable, as if new errors need + to be introduced they cannot be added to existing enumerations. This leads to + a proliferation of `Error` enumerations. "Fake" enumerations can be made using + `struct`s and `static let`s, but these do not work with the nice `Error` + pattern-match logic in catch blocks, requiring type casts. +- Using an enumeration to refer to a group of possible ideas without entirely + exhaustively evaluating the set is potentially dangerous, requiring a + deprecate-and-replace if any new elements appear. +- Using an enumeration to represent any concept that is inherently extensible is + tricky. For example, `SwiftNIO` uses an enumeration to represent HTTP status + codes. If new status codes are added, SwiftNIO needs to either mint new + enumerations and do a deprecate-and-replace, or it needs to force these new + status codes through the .custom enum case. + +This proposal plans to address these limitations on enumerations in +non-resilient Swift. + +## Proposed solution + +We propose to introduce a new `@extensible` attribute that can be applied to +enumerations to mark them as extensible. Such enums will behave the same way as +non-frozen enums from resilient Swift libraries. + +An example of using the new attribute is below: + +```swift +/// Module A +@extensible +public enum PizzaFlavor { + case hawaiian + case pepperoni + case cheese +} + +/// Module B +switch pizzaFlavor { // error: Switch covers known cases, but 'MyEnum' may have additional unknown values, possibly added in future versions +case .hawaiian: + throw BadFlavorError() +case .pepperoni: + try validateNoVegetariansEating() + return .delicious +case .cheese: + return .delicious +} +``` + +### Exhaustive switching inside same module/package + +Code inside the same module or package can be thought of as one co-developed +unit of code. Inside the same module or package, switching exhaustively over an +`@extensible` enum inside will not require an`@unknown default`, and using +one will generate a warning. + +### `@extensible` and `@frozen` + +An enum cannot be `@frozen` and `@extensible` at the same time. Thus, marking an +enum both `@extensible` and `@frozen` is not allowed and will result in a +compiler error. + +### API breaking checker + +The behavior of `swift package diagnose-api-breaking-changes` is also updated +to understand the new `@extensible` attribute. + +### Staging in using `@preEnumExtensibility` + +We also propose adding a new `@preEnumExtensibility` attribute that can be used +to mark enumerations as pre-existing to the `@extensible` attribute. This allows +developers to mark existing public enumerations as `@preEnumExtensibility` in +addition to `@extensible`. This is useful for developers that want to stage in +changing an existing non-extensible enum to be extensible over multiple +releases. Below is an example of how this can be used: + +```swift +// Package A +public enum Foo { + case foo +} + +// Package B +switch foo { +case .foo: break +} + +// Package A wants to make the existing enum extensible +@preEnumExtensibility @extensible +public enum Foo { + case foo +} + +// Package B now emits a warning downgraded from an error +switch foo { // warning: Enum might be extended later. Add an @unknown default case. +case .foo: break +} + +// Later Package A decides to extend the enum and releases a new major version +@preEnumExtensibility @extensible +public enum Foo { + case foo + case bar +} + +// Package B didn't add the @unknown default case yet. So now we we emit a warning and an error +switch foo { // error: Unhandled case bar & warning: Enum might be extended later. Add an @unknown default case. +case .foo: break +} +``` + +While the `@preEnumExtensibility` attribute doesn't solve the need of requiring +a new major when a new case is added it allows developers to stage in changing +an existing non-extensible enum to become extensible in a future release by +surfacing a warning about this upcoming break early. + +## Source compatibility + +### Resilient modules + +- Adding or removing the `@extensible` attribute has no-effect since it is the default in this language dialect. +- Adding the `@preEnumExtensibility` attribute has no-effect since it only downgrades the error to a warning. +- Removing the `@preEnumExtensibility` attribute is an API breaking since it upgrades the warning to an error again. + +### Non-resilient modules + +- Adding the `@extensible` attribute is an API breaking change. +- Removing the `@extensible` attribute is an API stable change. +- Adding the `@preEnumExtensibility` attribute has no-effect since it only downgrades the error to a warning. +- Removing the `@preEnumExtensibility` attribute is an API breaking since it upgrades the warning to an error again. + +## ABI compatibility + +The new attribute does not affect the ABI of an enum since it is already the +default in resilient modules. + +## Future directions + +### Aligning the language dialects + +In a previous iteration of this proposal, we proposed to add a new language +feature to align the language dialects in a future language mode. The main +motivation behind this is that the current default of non-extensible enums is a +common pitfall and results in tremendous amounts of unnoticed API breaks in the +Swift package ecosystem. We still believe that a future proposal should try +aligning the language dialects. This proposal is focused on providing a first +step to allow extensible enums in non-resilient modules. + +Regardless of whether a future language mode changes the default for non-resilient +libraries, a way of staging in this change will be required (similar to how the +`@preconcurency` attribute facilitated incremental adoption of Swift concurrency). + +### `@unknown catch` + +Enums can be used for errors. Catching and pattern matching enums could add +support for an `@unknown catch` to make pattern matching of typed throws align +with `switch` pattern matching. + +### Allow adding additional associated values + +Adding additional associated values to an enum can also be seen as extending it +and we agree that this is interesting to explore in the future. However, this +proposal focuses on solving the primary problem of the usability of public +enumerations in non-resilient modules. + +### Larger compilation units than packages + +During the pitch it was brought up that a common pattern for application +developers is to split an application into multiple smaller packages. Those +packages are versioned together and want to have the same exhaustive matching +behavior as code within a single package. As a future direction, build and +package tooling could allow to define larger compilation units to express this. +Until then developers are encouraged to use `@frozen` attributes on their +enumerations to achieve the same effect. + +## Alternatives considered + +### Different names for the attribute + +We considered different names for the attribute such as `@nonFrozen`; however, +we felt that `@extensible` communicates the idea of an extensible enum more +clearly. From c306f2216d53175ab13f2f2900c58080ab7a26bd Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Sun, 25 May 2025 14:38:34 -0700 Subject: [PATCH 334/505] Number SE 0487-extensible-enums.md (#2862) --- .../{NNNN-extensible-enums.md => 0487-extensible-enums.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{NNNN-extensible-enums.md => 0487-extensible-enums.md} (99%) diff --git a/proposals/NNNN-extensible-enums.md b/proposals/0487-extensible-enums.md similarity index 99% rename from proposals/NNNN-extensible-enums.md rename to proposals/0487-extensible-enums.md index 1878defc70..d218c50789 100644 --- a/proposals/NNNN-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -1,6 +1,6 @@ # Extensible enums -* Proposal: [SE-NNNN](NNNN-extensible-enums.md) +* Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) * Status: **In active review (May 25—Jun 5, 2025)** From 1c8e13f914c31f39f6d8826c95cb8e8b09c55e8b Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Mon, 26 May 2025 11:24:16 +0200 Subject: [PATCH 335/505] Add forum review link to 0486-adoption-tooling-for-swift-features.md --- proposals/0486-adoption-tooling-for-swift-features.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0486-adoption-tooling-for-swift-features.md b/proposals/0486-adoption-tooling-for-swift-features.md index bf50318ac3..1e3038e362 100644 --- a/proposals/0486-adoption-tooling-for-swift-features.md +++ b/proposals/0486-adoption-tooling-for-swift-features.md @@ -3,9 +3,9 @@ * Proposal: [SE-0486](0486-adoption-tooling-for-swift-features.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: [Franz Busch](https://github.com/FranzBusch) -* Status: **Active Review (May 21...June 4, 2025)** -* Implementation: TBD -* Review: [pitch](https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936) +* Status: **Active Review (May 26...June 8, 2025)** +* Implementation: https://github.com/swiftlang/swift-package-manager/pull/8613 +* Review: [Pitch](https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936), [Review](https://forums.swift.org/t/se-0486-migration-tooling-for-swift-features/80121) ## Introduction From 74112972c6b3284860574555ecc9d202309d30dd Mon Sep 17 00:00:00 2001 From: Jamie <2119834+jamieQ@users.noreply.github.com> Date: Mon, 26 May 2025 11:53:55 -0500 Subject: [PATCH 336/505] [gardening]: minor typo fixes/edits for SE-0486 --- .../0486-adoption-tooling-for-swift-features.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/0486-adoption-tooling-for-swift-features.md b/proposals/0486-adoption-tooling-for-swift-features.md index 1e3038e362..a2def8fc49 100644 --- a/proposals/0486-adoption-tooling-for-swift-features.md +++ b/proposals/0486-adoption-tooling-for-swift-features.md @@ -162,7 +162,7 @@ using `-print-diagnostic-groups` and used to associate messages with features. ### `swift package migrate` command -To enable seemless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - `swift package migrate` to complement the Swift compiler-side changes. +To enable seamless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - `swift package migrate` to complement the Swift compiler-side changes. The command would accept one or more features that have migration mode enabled and optionally a set of targets to migrate, if no targets are specified the whole package is going to be migrated to use new features. @@ -211,11 +211,11 @@ enable the feature(s) if both of the previous actions are successful: In the "whole package" mode, every target is going to be updated to include new feature flag(s). This is supported by the same functionality as `swift package add-setting` command. -If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. `...; please add 'ExistentialAny' feature to `MyTarget` target manually`. +If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. `...; please add 'ExistentialAny' feature to 'MyTarget' target manually`. #### Impact on Interface -This proposal introduces a new command but does that does not interfere with existing commands. It follows the same pattern as `swift build` and `swift test` in a consistent manner. +This proposal introduces a new command but does not interfere with existing commands. It follows the same pattern as `swift build` and `swift test` in a consistent manner. ## Source compatibility @@ -278,20 +278,20 @@ is essential for future tools built around migration mode: ### A distinct `-migrate` option -This direction has a questionably balanced set of advantanges and downsides. +This direction has a questionably balanced set of advantages and downsides. On one hand, it would provide an adequate foundation for invoking migration for a language mode in addition to individual features. On the other hand, an independent option is less discoverable, has a steeper learning curve, and makes the necessary relationships between it and the existing `-enable-*-feature` options harder to infer. Perhaps more notably, a bespoke option by itself would not scale to any future -modes, setting what might be an unfortunate example for further decentralizion +modes, setting what might be an unfortunate example for further decentralization of language feature control. ### API for package manifests The decision around surfacing migration mode in the `PackageDescription` -library depends on whether there is a concensus on the value of enabling it as +library depends on whether there is a consensus on the value of enabling it as a persistent setting as opposed to an automated procedure in the long run. Here is how an API change could look like for the proposed solution: @@ -347,7 +347,7 @@ The next candidates in line per discussions are ***adopt***, ***audit***, ### `swift package migrate` vs. `swift migrate` -Rather than have migrate as a subcommand (ie. `swift package migrate`), another option is add another top level command, ie. `swift migrate`. +Rather than have migrate as a subcommand (ie. `swift package migrate`), another option is to add another top level command, ie. `swift migrate`. As the command applies to the current package, we feel a `swift package` sub-command fits better than a new top-level command. This also aligns with the recently added package refactorings (eg. `add-target`). From 5914796ecc445e40671a7d67ba64a45295d61527 Mon Sep 17 00:00:00 2001 From: Mahdi Bahrami Date: Mon, 26 May 2025 22:23:52 +0330 Subject: [PATCH 337/505] Fix `SE-0487` status code fixes: ```bash curl https://download.swift.org/swift-evolution/v1/evolution.json | jq '.proposals[] | select(.id == "SE-0487") | .errors' % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 696k 100 696k 0 0 771k 0 --:--:-- --:--:-- --:--:-- 770k [ { "code": 0, "kind": "error", "message": "Missing or invalid proposal status.", "suggestion": "" } ] ``` --- proposals/0487-extensible-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index d218c50789..9381a96d7f 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -3,7 +3,7 @@ * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **In active review (May 25—Jun 5, 2025)** +* Status: **Active Review (May 25 - Jun 5, 2025)** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` From a8f5279f553c3f386c0b072730b30c8196e40929 Mon Sep 17 00:00:00 2001 From: Mahdi Bahrami Date: Tue, 27 May 2025 14:26:42 +0330 Subject: [PATCH 338/505] Update proposals/0487-extensible-enums.md Co-authored-by: Ben Rimmington --- proposals/0487-extensible-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index 9381a96d7f..9860b441e9 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -3,7 +3,7 @@ * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Active Review (May 25 - Jun 5, 2025)** +* Status: **Active Review (May 25 - June 5, 2025)** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` From 8cbeeb767b936059279aefb764c331c2c30cc00b Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Tue, 27 May 2025 16:34:49 -0400 Subject: [PATCH 339/505] Accept SE-0484 (#2867) --- ...allow-additional-args-to-dynamicmemberlookup-subscripts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md index 1e3d05745c..744cebb58b 100644 --- a/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md +++ b/proposals/0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md @@ -3,10 +3,10 @@ * Proposal: [SE-0484](0484-allow-additional-args-to-dynamicmemberlookup-subscripts.md) * Authors: [Itai Ferber](https://github.com/itaiferber) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (May 12...25, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift#81148](https://github.com/swiftlang/swift/pull/81148) * Previous Proposals: [SE-0195](0195-dynamic-member-lookup.md), [SE-0252](0252-keypath-dynamic-member-lookup.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558)) ([review](https://forums.swift.org/t/se-0484-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79853)) +* Review: ([pitch](https://forums.swift.org/t/pitch-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79558)) ([review](https://forums.swift.org/t/se-0484-allow-additional-arguments-to-dynamicmemberlookup-subscripts/79853)) ([acceptance](https://forums.swift.org/t/accepted-se-0484-allow-additional-arguments-to-dynamicmemberlookup-subscripts/80167)) ## Introduction From 5a3aafa47f0258f9035e14e0c3fc5d8e6e0f3210 Mon Sep 17 00:00:00 2001 From: Dmitrii Galimzianov Date: Wed, 28 May 2025 03:14:13 +0200 Subject: [PATCH 340/505] [SE-0480] Add Future Directions for compiler support and dev-only settings Based on the review discussion, this change expands the "Future Directions" section to include: - Considerations for supporting C/C++ compilers beyond Clang. - A discussion on formalizing "development-only" build settings. Minor fixes for clarity in the API section are also included. --- proposals/0480-swiftpm-warning-control.md | 90 ++++++++++++++++++----- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 18157ce824..9915b62708 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -7,6 +7,7 @@ * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) * Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) +* Previous revisions: [1](https://github.com/swiftlang/swift-evolution/blob/eed1fed8339f3919cf5c0f36b804431022d44720/proposals/0480-swiftpm-warning-control.md) ## Introduction @@ -38,16 +39,18 @@ public enum WarningLevel: String { case error } -public static func treatAllWarnings( - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil -) -> SwiftSetting // or CSetting or CXXSetting - -public static func treatWarning( - _ name: String, - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil -) -> SwiftSetting // or CSetting or CXXSetting +extension SwiftSetting { // Same for CSetting and CXXSetting + public static func treatAllWarnings( + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting // or CSetting or CXXSetting + + public static func treatWarning( + _ name: String, + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil + ) -> SwiftSetting // or CSetting or CXXSetting +} ``` #### C/C++-specific API @@ -55,15 +58,17 @@ public static func treatWarning( In C/C++ targets, we can also enable or disable specific warning groups, in addition to controlling their severity. ```swift -public static func enableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil -) -> CSetting // or CXXSetting - -public static func disableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil -) -> CSetting // or CXXSetting +extension CSetting { // Same for CXXSetting + public static func enableWarning( + _ name: String, + _ condition: BuildSettingCondition? = nil + ) -> CSetting // or CXXSetting + + public static func disableWarning( + _ name: String, + _ condition: BuildSettingCondition? = nil + ) -> CSetting // or CXXSetting +} ``` _The necessity of these functions is also explained below in the Alternatives considered section._ @@ -280,6 +285,53 @@ This necessitates separate functions to enable and disable warnings. Therefore, It has been noted that warning control settings are often similar across all targets. It makes sense to declare them at the package level while allowing target-level customizations. However, many other settings would also likely benefit from such inheritance, and SwiftPM doesn't currently provide such an option. Therefore, it was decided to factor this improvement out and look at all the settings holistically in the future. +### Support for other C/C++ Compilers + +The C/C++ warning control settings introduced in this proposal are initially implemented with Clang's warning flag syntax as the primary target. However, the API itself is largely compiler-agnostic, and there's potential to extend support to other C/C++ compilers in the future. + +For instance, many of the proposed functions could be mapped to flags for other compilers like MSVC: + +| SwiftPM Setting | Clang | MSVC (Potential Mapping) | +| :-------------------------------- | :---------------- | :----------------------- | +| `.treatAllWarnings(as: .error)` | `-Werror` | `/WX` | +| `.treatAllWarnings(as: .warning)` | `-Wno-error` | `/WX-` | +| `.treatWarning("name", as: .error)`| `-Werror=name` | `/we####` (where `####` is MSVC warning code) | +| `.treatWarning("name", as: .warning)`| `-Wno-error=name` | No direct equivalent | +| `.enableWarning("name")` | `-Wname` | `/wL####` (e.g., `/w4####` to enable at level 4) | +| `.disableWarning("name")` | `-Wno-name` | `/wd####` | + +Where direct mappings are incomplete (like `.treatWarning(as: .warning)` for MSVC, which doesn't have a per-warning equivalent to Clang's `-Wno-error=XXXX`), SwiftPM could emit diagnostics indicating the setting is not fully supported by the current compiler. If more fine-grained control is needed for a specific compiler (e.g., MSVC's warning levels `0-4` for `enableWarning`), future enhancements could introduce compiler-specific settings or extend the existing API. + +A key consideration is the handling of warning names or codes (the `"name"` parameter in the API). SwiftPM does not maintain a comprehensive list of all possible warning identifiers and their mapping across different compilers. Instead, package authors would be responsible for providing the correct warning name or code for the intended compiler. + +To facilitate this, if support for other C/C++ compilers is added, the existing `BuildSettingCondition` API could be extended to allow settings to be applied conditionally based on the active C/C++ compiler. For example: + +```swift +cxxSettings: [ + // Clang-specific warning + .enableWarning("unused-variable", .when(cxxCompiler: .clang)), + // MSVC-specific warning (using its numeric code) + .enableWarning("4101", .when(cxxCompiler: .msvc)), + // Common setting that maps well + .treatAllWarnings(as: .error) +] +``` + +This approach, combined with the existing behavior where remote (dependency) packages have their warning control flags stripped and replaced with suppression flags, would allow projects to adopt new compilers. Even if a dependency uses Clang-specific warning flags, it would not cause build failures when the main project is built with a different compiler like MSVC, as those flags would be ignored. + +### Formalizing "Development-Only" Build Settings + +The warning control settings introduced by this proposal only apply when a package is built directly and are suppressed when the package is consumed as a remote dependency. + +During the review of this proposal, it was suggested that this "development-only" characteristic could be made more explicit, perhaps by introducing a distinct category of settings (e.g., `devSwiftSettings`). This is an interesting avenue for future exploration. SwiftPM already has a few other settings that exhibit similar behavior. A dedicated future proposal for "development-only" settings could address all such use cases holistically, providing a clearer and more general mechanism for package authors to distinguish between "dev-only" settings and those that propagate to consumers. + +## Revision History + +Revisions based on review feedback: + +- Added a future direction discussing potential support for C/C++ compilers beyond Clang. +- Added a future direction to explore formalizing "dev-only" build settings. + ## Acknowledgments Thank you to [Doug Gregor](https://github.com/douggregor) for the motivation, and to both [Doug Gregor](https://github.com/douggregor) and [Holly Borla](https://github.com/hborla) for their guidance during the implementation of this API. From ee052bb9fb6674b92b7087bc2f2f320ed1d27a83 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 27 May 2025 21:26:31 -0400 Subject: [PATCH 341/505] Remove revision information --- proposals/0480-swiftpm-warning-control.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 9915b62708..9183b1091a 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -7,7 +7,6 @@ * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) * Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) -* Previous revisions: [1](https://github.com/swiftlang/swift-evolution/blob/eed1fed8339f3919cf5c0f36b804431022d44720/proposals/0480-swiftpm-warning-control.md) ## Introduction @@ -325,13 +324,6 @@ The warning control settings introduced by this proposal only apply when a packa During the review of this proposal, it was suggested that this "development-only" characteristic could be made more explicit, perhaps by introducing a distinct category of settings (e.g., `devSwiftSettings`). This is an interesting avenue for future exploration. SwiftPM already has a few other settings that exhibit similar behavior. A dedicated future proposal for "development-only" settings could address all such use cases holistically, providing a clearer and more general mechanism for package authors to distinguish between "dev-only" settings and those that propagate to consumers. -## Revision History - -Revisions based on review feedback: - -- Added a future direction discussing potential support for C/C++ compilers beyond Clang. -- Added a future direction to explore formalizing "dev-only" build settings. - ## Acknowledgments Thank you to [Doug Gregor](https://github.com/douggregor) for the motivation, and to both [Doug Gregor](https://github.com/douggregor) and [Holly Borla](https://github.com/hborla) for their guidance during the implementation of this API. From 4c4a56638f643c641dcb1c9cf9f3c2ef63258d6f Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 28 May 2025 16:20:37 -0700 Subject: [PATCH 342/505] [SE-0485] bugfix --- proposals/0485-outputspan.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index d9b05b8e4c..52b257a3c8 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -126,7 +126,9 @@ extension OutputSpan where Element: ~Copyable { /// Append a single element to this `OutputSpan`. @lifetime(self: copy self) public mutating func append(_ value: consuming Element) +} +extension OutputSpan { /// Repeatedly append an element to this `OutputSpan`. @lifetime(self: copy self) public mutating func append(repeating repeatedValue: Element, count: Int) From b833a2986a7cbd22f8cad6e9cb02ea8ddf6ddd0d Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 28 May 2025 16:20:49 -0700 Subject: [PATCH 343/505] [SE-0485] Clarification --- proposals/0485-outputspan.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 52b257a3c8..a4bfc9f67f 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -473,24 +473,36 @@ Initializing an `OutputRawSpan` from a `Sequence` or other container type must u ```swift extension OutputRawSpan { /// Initialize the span's bytes with every byte of the source. + /// + /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix + /// can contain every byte of the source. @lifetime(self: copy self) public mutating func append, as type: T.Type ) /// Initialize the span's bytes with every byte of the source. + /// + /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix + /// can contain every byte of the source. @lifetime(self: copy self) public mutating func append, as type: T.Type ) /// Initialize the span's bytes with every byte of the source. + /// + /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix + /// can contain every byte of the source. @lifetime(self: copy self) public mutating func append( contentsOf source: RawSpan ) /// Initialize the span's bytes with every byte of the source. + /// + /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix + /// can contain every byte of the source. @lifetime(self: copy self) public mutating func append( contentsOf source: UnsafeRawBufferPointer From b11e17be7b5475b4d6b06c82708b1d1d8d4b3e22 Mon Sep 17 00:00:00 2001 From: Ben Rimmington Date: Fri, 23 May 2025 09:28:22 +0100 Subject: [PATCH 344/505] [SE-0485] Update pitch and implementation links Also rename `available` to `freeCapacity`. --- proposals/0485-outputspan.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index a4bfc9f67f..2f790b1e39 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -5,8 +5,8 @@ * Review Manager: [Doug Gregor](https://github.com/DougGregor) * Status: **Active Review (May 20...June 3, 2025)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) -* Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) -* Review: [Pitch](https://forums.swift.org/), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032) +* Implementation: [swiftlang/swift#81637](https://github.com/swiftlang/swift/pull/81637) +* Review: [Pitch](https://forums.swift.org/t/pitch-outputspan/79473), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md @@ -439,8 +439,8 @@ extension OutputRawSpan { /// A Boolean value indicating whither the span is full. public var isFull: Bool { get } - /// The nmuber of uninitialized bytes remaining in this `OutputRawSpan` - public var available: Int { get } // capacity - byteCount + /// The number of uninitialized bytes remaining in this `OutputRawSpan` + public var freeCapacity: Int { get } // capacity - byteCount } ``` From 26d1699d59bd0942f7b116e50926455f488a9f4a Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 29 May 2025 15:05:57 -0700 Subject: [PATCH 345/505] [SE-0485] fix an argument label Co-authored-by: Ben Rimmington --- proposals/0485-outputspan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 2f790b1e39..1e4098b78f 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -457,7 +457,7 @@ extension OutputRawSpan { /// Appends the given value's bytes to this span's initialized bytes @lifetime(self: copy self) public mutating func append( - of value: T, as type: T.Type + _ value: T, as type: T.Type ) /// Appends the given value's bytes repeatedly to this span's initialized bytes From 37aafd3695a768bbb3cd32cdee4185a4ac5b85d4 Mon Sep 17 00:00:00 2001 From: Philipp Gabriel Date: Sun, 1 Jun 2025 02:21:22 +0200 Subject: [PATCH 346/505] Add Swift 6.1 release and 6.2 announcement (#2810) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bd24a420fa..e1f5fdb53b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ This repository tracks the ongoing evolution of the Swift programming language, | Version | Announced | Released | | :-------- | :----------------------------------------------------------------------- | :----------------------------------------------------------- | -| Swift 6.1 | [2024-10-17](https://forums.swift.org/t/swift-6-1-release-process/75442) | +| Swift 6.2 | [2025-03-08](https://forums.swift.org/t/swift-6-2-release-process/78371) | | +| Swift 6.1 | [2024-10-17](https://forums.swift.org/t/swift-6-1-release-process/75442) | [2025-03-31](https://www.swift.org/blog/swift-6.1-released/) | | Swift 6.0 | [2024-02-22](https://forums.swift.org/t/swift-6-0-release-process/70220) | [2024-09-17](https://www.swift.org/blog/announcing-swift-6/) | | Swift 5.10 | [2023-08-23](https://forums.swift.org/t/swift-5-10-release-process/66911) | [2024-03-05](https://www.swift.org/blog/swift-5.10-released/) | | Swift 5.9 | [2023-03-06](https://forums.swift.org/t/swift-5-9-release-process/63557) | [2023-09-18](https://www.swift.org/blog/swift-5.9-released/) | From 698b6ed4539e031f38e98324c0e2dd071b48a171 Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Sun, 1 Jun 2025 15:44:49 +0000 Subject: [PATCH 347/505] [SE-0481] Add link to review thread SE-0481 was missing a link to its review thread on the forums. --- proposals/0481-weak-let.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0481-weak-let.md b/proposals/0481-weak-let.md index 03a4cb4e5b..ca885adc1c 100644 --- a/proposals/0481-weak-let.md +++ b/proposals/0481-weak-let.md @@ -5,7 +5,7 @@ * Review Manager: [John McCall](https://github.com/rjmccall) * Status: **Accepted** * Implementation: [swiftlang/swift#80440](https://github.com/swiftlang/swift/pull/80440) -* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) ([acceptance](https://forums.swift.org/t/accepted-se-0481-weak-let/79895)) +* Review: ([discussion](https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498)) ([pitch](https://forums.swift.org/t/pitch-weak-let/79271)) ([review](https://forums.swift.org/t/se-0481-weak-let/79603)) ([acceptance](https://forums.swift.org/t/accepted-se-0481-weak-let/79895)) [SE-0302]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md From 02f6e1b97f4addf898652f6ee0df1592aedd697c Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 4 Jun 2025 16:23:14 -0500 Subject: [PATCH 348/505] Rename transformIssues to compactMapIssues --- .../testing/NNNN-issue-handling-traits.md | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index ff73502ab4..00bb26bc1d 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -126,7 +126,7 @@ Here's one contrived example showing how this could be used to add a comment to each issue recorded by a test: ```swift -@Test(.transformIssues { issue in +@Test(.compactMapIssues { issue in var issue = issue issue.comments.append("Checking whether two literals are equal") return issue @@ -173,10 +173,10 @@ are executed in trailing-to-leading, innermost-to-outermost order. For example, given the following code: ```swift -@Suite(.transformIssues { ... /* A */ }) +@Suite(.compactMapIssues { ... /* A */ }) struct ExampleSuite { @Test(.filterIssues { ... /* B */ }, - .transformIssues { ... /* C */ }) + .compactMapIssues { ... /* C */ }) func example() { ... } @@ -208,7 +208,7 @@ actor Session { } // In test code: -@Test(.transformIssues { issue in +@Test(.compactMapIssues { issue in var issue = issue if let session = Session.current { issue.comments.append("Current session ID: \(session.id)") @@ -237,7 +237,7 @@ For example: ```swift @Test( - .transformIssues { issue in + .compactMapIssues { issue in // This closure will be called for any issue recorded by the test function // or by the `.filterIssues` trait below. ... @@ -305,7 +305,7 @@ This proposal includes the following: traits. * Static functions on `Trait` for creating instances of this type with the following capabilities: - * A function `transformIssues(_:)` which returns a trait that can transform + * A function `compactMapIssues(_:)` which returns a trait that can transform recorded issues. The function takes a closure which is passed an issue and returns either a modified issue or `nil` to suppress it. * A function `filterIssues(_:)` which returns a trait that can filter recorded @@ -322,14 +322,14 @@ Below are the proposed interfaces: /// modifying one or more of its properties, and returning the copy. You can /// observe recorded issues by returning them unmodified. Or you can suppress an /// issue by either filtering it using ``Trait/filterIssues(_:)`` or returning -/// `nil` from the closure passed to ``Trait/transformIssues(_:)``. +/// `nil` from the closure passed to ``Trait/compactMapIssues(_:)``. /// /// When an instance of this trait is applied to a suite, it is recursively /// inherited by all child suites and tests. /// /// To add this trait to a test, use one of the following functions: /// -/// - ``Trait/transformIssues(_:)`` +/// - ``Trait/compactMapIssues(_:)`` /// - ``Trait/filterIssues(_:)`` public struct IssueHandlingTrait: TestTrait, SuiteTrait { /// Handle a specified issue. @@ -346,30 +346,34 @@ extension Trait where Self == IssueHandlingTrait { /// Constructs an trait that transforms issues recorded by a test. /// /// - Parameters: - /// - transformer: The closure called for each issue recorded by the test + /// - transform: A closure called for each issue recorded by the test /// this trait is applied to. It is passed a recorded issue, and returns /// an optional issue to replace the passed-in one. /// /// - Returns: An instance of ``IssueHandlingTrait`` that transforms issues. /// - /// The `transformer` closure is called synchronously each time an issue is + /// The `transform` closure is called synchronously each time an issue is /// recorded by the test this trait is applied to. The closure is passed the /// recorded issue, and if it returns a non-`nil` value, that will be recorded /// instead of the original. Otherwise, if the closure returns `nil`, the /// issue is suppressed and will not be included in the results. /// - /// The `transformer` closure may be called more than once if the test records + /// The `transform` closure may be called more than once if the test records /// multiple issues. If more than one instance of this trait is applied to a - /// test (including via inheritance from a containing suite), the `transformer` + /// test (including via inheritance from a containing suite), the `transform` /// closure for each instance will be called in right-to-left, innermost-to- /// outermost order, unless `nil` is returned, which will skip invoking the /// remaining traits' closures. /// - /// Within `transformer`, you may access the current test or test case (if any) + /// Within `transform`, you may access the current test or test case (if any) /// using ``Test/current`` ``Test/Case/current``, respectively. You may also /// record new issues, although they will only be handled by issue handling /// traits which precede this trait or were inherited from a containing suite. - public static func transformIssues(_ transformer: @escaping @Sendable (Issue) -> Issue?) -> Self + /// + /// - Note: `transform` will never be passed an issue for which the value of + /// ``Issue/kind`` is ``Issue/Kind/system``, and may not return such an + /// issue. + public static func compactMapIssues(_ transform: @escaping @Sendable (Issue) -> Issue?) -> Self /// Constructs a trait that filters issues recorded by a test. /// @@ -398,6 +402,9 @@ extension Trait where Self == IssueHandlingTrait { /// using ``Test/current`` ``Test/Case/current``, respectively. You may also /// record new issues, although they will only be handled by issue handling /// traits which precede this trait or were inherited from a containing suite. + /// + /// - Note: `isIncluded` will never be passed an issue for which the value of + /// ``Issue/kind`` is ``Issue/Kind/system``. public static func filterIssues(_ isIncluded: @escaping @Sendable (Issue) -> Bool) -> Self } ``` @@ -472,14 +479,12 @@ the handler encounters an error. ### Alternate names for the static trait functions -We could choose different names for the static `transformIssues(_:)` or +We could choose different names for the static `compactMapIssues(_:)` or `filterIssues(_:)` functions. Some alternate names considered were: -- `compactMapIssues` instead of `transformIssues`. This arguably aligns better - with the word "filter" of `filterIssues`, but it felt strange since often, - "map" is used to return a value of a _different_ type, whereas here it must - return a value of the same type, it's just that it can be mutated. -- `handleIssues` instead of `transformIssues`. The word "handle" is in the name +- `transformIssues` instead of `compactMapIssues`. "Compact map" seemed to align + better with "filter" of `filterIssues`, however. +- `handleIssues` instead of `compactMapIssues`. The word "handle" is in the name of the trait type already; it's a more general word for what all of these usage patterns enable, so it felt too broad. - Using singular "issue" rather than plural "issues" in both APIs. This may not From d537cca0d9c36e86071d2f20d3fbd38e5b236ec7 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 4 Jun 2025 16:23:25 -0500 Subject: [PATCH 349/505] Note latest implementation PR and reformat the list --- proposals/testing/NNNN-issue-handling-traits.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index 00bb26bc1d..3ac1bc4124 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -4,7 +4,9 @@ * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: TBD * Status: **Awaiting review** -* Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121) +* Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), + [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), + [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136) * Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) ## Introduction From 83fca406e047ed9b791d6360bb15302ee0d6b11d Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 4 Jun 2025 16:29:12 -0500 Subject: [PATCH 350/505] Document special handling of system issues --- proposals/testing/NNNN-issue-handling-traits.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index 3ac1bc4124..d048a1a6d4 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -297,6 +297,20 @@ The closure of an issue handling trait must be: - Record a separate issue using the standard issue recording mechanisms (as [discussed](#recording-issues-from-handlers) above). +### Handling of non-user issues + +Issue handling traits are applied to a test by a user, and are only intended for +handling issues recorded by tests written by the user. If an issue is recorded +by the testing library itself or the underlying system, not due to a failure +within the tests being run, such an issue will not be passed to an issue +handling trait. + +Concretely, this policy means that issues for which the value of the `kind` +property is `.system` will not be passed to the closure of an issue handling +trait. Similarly, it is not supported for a closure passed to +`compactMapIssues(_:)` to return an issue for which the value of `kind` is +`.system`. + ## Detailed design This proposal includes the following: From f5070955c1a97c6d67a34bd8c4c35583119b8f00 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Wed, 4 Jun 2025 15:11:46 -0700 Subject: [PATCH 351/505] [Observation]Add a few clarifications and refinements to address the last bits of feedback for the review thread (#2874) --- proposals/0475-observed.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index f176573c28..368c21ef23 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -173,7 +173,7 @@ Task.detached { } ``` -In this case both tasks will get the same values upon the same events. This can +In this case both tasks will get consistently safe accessed values. This can be achieved without needing an extra buffer since the suspension of each side of the iteration are continuations resuming all together upon the accessor's execution on the specified isolation. This facilitates subject-like behavior @@ -257,6 +257,12 @@ composition of potentially failable systems. Any thrown error will mean that the terminate with that given failure. Subsequent calls then to `next` on those iterators will return `nil` - indicating that the iteration is complete. +The type `Observations` will conform to `AsyncSequence`. This means that it +adheres to the cancellation behavior of other `AsyncSequence` types; if the task +is cancelled then the iterator will return nil, and any time it becomes +terminal for any reason that sequence will remain terminal and continue returning nil. +Termination by cancellation however is independent for each instance. + ## Behavioral Notes There are a number of scenarios of iteration that can occur. These can range from production rate to iteration rate differentials to isolation differentials to concurrent iterations. Enumerating all possible combinations is of course not possible but the following explanations should illustrate some key usages. `Observations` does not make unsafe code somehow safe - the concepts of isolation protection or exclusive access are expected to be brought to the table by the types involved. It does however require the enforcements via Swift Concurrency particularly around the marking of the types and closures being required to be `Sendable`. The following examples will only illustrate well behaved types and avoid fully unsafe behavior that would lead to crashes because the types being used are circumventing that language safety. @@ -351,7 +357,7 @@ The result of the observation may print the following output, but the primary pr 3 3 ``` -This case dropped the last value of the iteration because the accumulated differential exceeded the production; however the potentially confusing part here is that the sleep in the iterate competes with the scheduling in the emitter. This becomes clearer of a relationship when the boundaries of isolation are crossed. +The last value is never observed because the program ends before it would be. If the program did not terminate then another value would be observed. Observations can be used across boundaries of concurrency. This is where the iteration is done on a different isolation than the mutations. The types however are accessed always in the isolation that the creation of the Observations closure is executed. This means that if the `Observations` instance is created on the main actor then the subsequent calls to the closure will be done on the main actor. From e877721b93ef4df0711905717ecc2d3397e940de Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 4 Jun 2025 17:12:34 -0500 Subject: [PATCH 352/505] Note 'inout' as an alternative considered --- proposals/testing/NNNN-issue-handling-traits.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index d048a1a6d4..e9bc50af5c 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -493,6 +493,20 @@ allowing errors to be thrown forces the author of the issue handler to make an explicit decision about whether they want an additional issue to be recorded if the handler encounters an error. +### Make the closure's issue parameter `inout` + +The closure parameter of `compactMapIssues(_:)` currently has one parameter of +type `Issue` and returns an optional `Issue?` to support returning `nil` in +order to suppress an issue. This closure could instead have a `Void` return type +and its parameter could be `inout`, and this would mean that use cases that +involve modifying an issue would not need to first copy the issue to a variable +(`var`) before modifying it. + +However, in order to _suppress_ an issue, the parameter would also need to +become optional (`inout Issue?`) and this would mean that all usages would first +need to be unwrapped. This feels non-ergonomic, and would differ from the +standard library's typical pattern for `compactMap` functions. + ### Alternate names for the static trait functions We could choose different names for the static `compactMapIssues(_:)` or From f703cbc1a6c8aeff2818abd917819a57202ee943 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 5 Jun 2025 11:46:27 -0500 Subject: [PATCH 353/505] Mention the standalone function suggestion as a future direction --- proposals/testing/NNNN-issue-handling-traits.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index e9bc50af5c..c6967d3b72 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -476,6 +476,16 @@ observing test events of all kinds. This would a much larger effort, but was as a goal in the [Swift Testing vision document](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md). +### Standalone function + +It could be useful to offer the functionality of an issue handling trait as a +standalone function (similar to `withKnownIssue { }`) so that it could be +applied to a narrower section of code than an entire test or suite. This idea +came up during the pitch phase, and we believe that sort of pattern may be +useful more broadly for other kinds of traits. Accordingly, it may make more +sense to address this in a separate proposal and design it in a way that +encompasses any trait. + ## Alternatives considered ### Allow issue handler closures to throw errors From d6f8cd455e20d82dc29f817ac8129e8364516cd6 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 3 Jun 2025 17:56:53 -0700 Subject: [PATCH 354/505] initial pitch --- proposals/nnnn-extracting.md | 130 +++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 proposals/nnnn-extracting.md diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md new file mode 100644 index 0000000000..c097cb762b --- /dev/null +++ b/proposals/nnnn-extracting.md @@ -0,0 +1,130 @@ +# Expand the `extracting()` slicing pattern to more types + +* Proposal: [SE-0485](0485-outputspan.md) +* Author: [Guillaume Lessard](https://github.com/glessard) +* Review Manager: [Doug Gregor](https://github.com/DougGregor) +* Status: **Pitch** +* Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. +* Review: Pending + +[SE-0437]: proposals/0437-noncopyable-stdlib-primitives.md +[SE-0447]: proposals/0447-span-access-shared-contiguous-storage.md +[SE-0467]: proposals/0467-MutableSpan.md +[Forum-LifetimeAnnotations]: https://forums.swift.org/t/78638 + +## Introduction and Motivation + +Slicing containers is an important operation, and non-copyable values have introduced a significant change in the spelling of that operation. When we [introduced][SE-0437] non-copyable primitives to the standard library, we allowed slicing `UnsafeBufferPointer` and related types via a family of `extracting()` methods. We expanded upon these when introducing [`MutableSpan`][SE-0467]. + +Now that we have a [stable spelling][Forum-LifetimeAnnotations] for lifetime dependencies, we propose adding the `extracting()` methods to `Span` and `RawSpan`, as well as members of the `UnsafeBufferPointer` family that were missed in [SE-0437][SE-0437]. + + + +## Proposed solution + +The family of `extracting()` methods is as follows: +```swift +public func extracting(_ bounds: Range) -> Self +public func extracting(_ bounds: some RangeExpression) -> Self +public func extracting(_ UnboundedRange) -> Self +@unsafe public func extracting(unchecked bounds: Range) -> Self +@unsafe public func extracting(unchecked bounds: ClosedRange) -> Self + +public func extracting(first maxLength: Int) -> Self +public func extracting(droppingLast k: Int) -> Self +public func extracting(last maxLength: Int) -> Self +public func extracting(droppingFirst k: Int) -> Self +``` + +These should be provided for the following standard library types: +```swift +Span +RawSpan +UnsafeBufferPointer +UnsafeMutableBufferPointer +Slice> +Slice> +UnsafeRawBufferPointer +UnsafeMutableRawBufferPointer +Slice +Slice +``` +Some of the types in the list above already have a subset of the `extracting()` functions; their support will be rounded out to the full set. + +## Detailed design + +The general declarations for these functions is as follows: +```swift +/// Returns an extracted slice over the items within +/// the supplied range of positions. +/// +/// Traps if any position within the range is invalid. +@_lifetime(copy self) +public func extracting(_ byteOffsets: Range) -> Self + +/// Returns an extracted slice over the items within +/// the supplied range of positions. +/// +/// Traps if any position within the range is invalid. +@_lifetime(copy self) +public func extracting(_ byteOffsets: some RangeExpression) -> Self + +/// Returns an extracted slice over all items of this container. +@_lifetime(copy self) +public func extracting(_ UnboundedRange) -> Self + +/// Returns an extracted slice over the items within +/// the supplied range of positions. +/// +/// This function does not validate `bounds`; this is an unsafe operation. +@unsafe @_lifetime(copy self) +public func extracting(unchecked bounds: Range) -> Self + +/// Returns an extracted slice over the items within +/// the supplied range of positions. +/// +/// This function does not validate `bounds`; this is an unsafe operation. +@unsafe @_lifetime(copy self) +public func extracting(unchecked bounds: ClosedRange) -> Self + +/// Returns an extracted slice over the initial elements +/// of this container, up to the specified maximum length. +@_lifetime(copy self) +public func extracting(first maxLength: Int) -> Self + +/// Returns an extracted slice excluding +/// the given number of trailing elements. +@_lifetime(copy self) +public func extracting(droppingLast k: Int) -> Self + +/// Returns an extracted slice containing the final elements +/// of this container, up to the given maximum length. +@_lifetime(copy self) +public func extracting(last maxLength: Int) -> Self + +/// Returns an extracted slice excluding +/// the given number of initial elements. +@_lifetime(copy self) +public func extracting(droppingFirst k: Int) -> Self +``` +For non-escapable types, the `@_lifetime` attribute is ignored as being non-applicable. + +## Source compatibility +This proposal is additive and source-copmatible with existing code. + +## ABI compatibility +This proposal is additive and ABI-compatible with existing code. + +## Implications on adoption +The additions described in this proposal require a new version of the Swift standard library. + +## Alternatives considered +This is an extension of an existing pattern. We are not considering a different pattern at this time. + +## Future directions +#### Disambiguation over ownership type +The `extracting()` functions proposed here are semantically consuming. `MutableSpan` has versions defined as mutations, but it could benefit from consuming ones as well. In order to do this, we could establish a pattern for disambiguation by name, or we could invent new syntax to disambiguate by ownership type. This is a complex topic left to future proposals. + +## Acknowledgements +Thanks to Karoy Lorentey and Tony Parker. + From 54565a0f390f8b82b17aefd27c7a1b2686606e3c Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 12:26:07 -0700 Subject: [PATCH 355/505] sanitize copy-pasted information --- proposals/nnnn-extracting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index c097cb762b..b82eb09824 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -1,8 +1,8 @@ # Expand the `extracting()` slicing pattern to more types -* Proposal: [SE-0485](0485-outputspan.md) +* Proposal: TBD * Author: [Guillaume Lessard](https://github.com/glessard) -* Review Manager: [Doug Gregor](https://github.com/DougGregor) +* Review Manager: TBD * Status: **Pitch** * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. * Review: Pending From a4b2002c1e2789cf9d183bb83c80a98f9752ec3c Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 14:04:18 -0700 Subject: [PATCH 356/505] add usage hints --- proposals/nnnn-extracting.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index b82eb09824..e65bb0f56a 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -109,6 +109,18 @@ public func extracting(droppingFirst k: Int) -> Self ``` For non-escapable types, the `@_lifetime` attribute is ignored as being non-applicable. +#### Usage hints + +The `extracting()` pattern, while not completely new, is still a departure over the slice pattern established by the `Collection` protocol. For `Span`, `RawSpan`, `MutableSpan` and `MutableRawSpan`, we can add unavailable subscripts and function with hints towards the corresponding `extracting()` function: + +```swift +@available(*, unavailable, renamed: "extracting(_ bounds:)") +public subscript(bounds: Range) -> Self { extracting(bounds) } + +@available(*, unavailable, renamed: "extracting(first:)") +public func droppingFirst(_ k: Int) -> Self { extracting(first: k) } +``` + ## Source compatibility This proposal is additive and source-copmatible with existing code. From 38a77e9d017f278381ac947cb177a9e3edbe9730 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 14:04:58 -0700 Subject: [PATCH 357/505] improve opening graf of proposed solution --- proposals/nnnn-extracting.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index e65bb0f56a..4e96d807a7 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -22,7 +22,9 @@ Now that we have a [stable spelling][Forum-LifetimeAnnotations] for lifetime dep ## Proposed solution -The family of `extracting()` methods is as follows: +As previously discussed in [SE-0437][SE-0437], the slicing pattern established by the `Collection` protocol cannot be generalized for either non-copyable elements or non-escapable containers. The solution is a family of functions named `extracting()`, with appropriate argument labels. + +The family of `extracting()` methods established by the [`MutableSpan` proposal][SE-0467] is as follows: ```swift public func extracting(_ bounds: Range) -> Self public func extracting(_ bounds: some RangeExpression) -> Self From 0113278618391112020934bc939b7c26ee3a3f91 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 14:05:17 -0700 Subject: [PATCH 358/505] spelling and formatting --- proposals/nnnn-extracting.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 4e96d807a7..1e42a040c9 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -12,6 +12,7 @@ [SE-0467]: proposals/0467-MutableSpan.md [Forum-LifetimeAnnotations]: https://forums.swift.org/t/78638 + ## Introduction and Motivation Slicing containers is an important operation, and non-copyable values have introduced a significant change in the spelling of that operation. When we [introduced][SE-0437] non-copyable primitives to the standard library, we allowed slicing `UnsafeBufferPointer` and related types via a family of `extracting()` methods. We expanded upon these when introducing [`MutableSpan`][SE-0467]. @@ -19,7 +20,6 @@ Slicing containers is an important operation, and non-copyable values have intro Now that we have a [stable spelling][Forum-LifetimeAnnotations] for lifetime dependencies, we propose adding the `extracting()` methods to `Span` and `RawSpan`, as well as members of the `UnsafeBufferPointer` family that were missed in [SE-0437][SE-0437]. - ## Proposed solution As previously discussed in [SE-0437][SE-0437], the slicing pattern established by the `Collection` protocol cannot be generalized for either non-copyable elements or non-escapable containers. The solution is a family of functions named `extracting()`, with appropriate argument labels. @@ -28,7 +28,7 @@ The family of `extracting()` methods established by the [`MutableSpan` proposal] ```swift public func extracting(_ bounds: Range) -> Self public func extracting(_ bounds: some RangeExpression) -> Self -public func extracting(_ UnboundedRange) -> Self +public func extracting(_: UnboundedRange) -> Self @unsafe public func extracting(unchecked bounds: Range) -> Self @unsafe public func extracting(unchecked bounds: ClosedRange) -> Self @@ -38,7 +38,7 @@ public func extracting(last maxLength: Int) -> Self public func extracting(droppingFirst k: Int) -> Self ``` -These should be provided for the following standard library types: +These will be provided for the following standard library types: ```swift Span RawSpan @@ -53,6 +53,7 @@ Slice ``` Some of the types in the list above already have a subset of the `extracting()` functions; their support will be rounded out to the full set. + ## Detailed design The general declarations for these functions is as follows: @@ -73,7 +74,7 @@ public func extracting(_ byteOffsets: some RangeExpression) -> Self /// Returns an extracted slice over all items of this container. @_lifetime(copy self) -public func extracting(_ UnboundedRange) -> Self +public func extracting(_: UnboundedRange) -> Self /// Returns an extracted slice over the items within /// the supplied range of positions. @@ -109,7 +110,8 @@ public func extracting(last maxLength: Int) -> Self @_lifetime(copy self) public func extracting(droppingFirst k: Int) -> Self ``` -For non-escapable types, the `@_lifetime` attribute is ignored as being non-applicable. +For escapable types, the `@_lifetime` attribute is not applied. + #### Usage hints @@ -124,7 +126,7 @@ public func droppingFirst(_ k: Int) -> Self { extracting(first: k) } ``` ## Source compatibility -This proposal is additive and source-copmatible with existing code. +This proposal is additive and source-compatible with existing code. ## ABI compatibility This proposal is additive and ABI-compatible with existing code. From 495f9be58cde92318ed00889214c6758c99c9367 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 15:16:32 -0700 Subject: [PATCH 359/505] formatting --- proposals/nnnn-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 1e42a040c9..2c7e0cf4a7 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -113,7 +113,7 @@ public func extracting(droppingFirst k: Int) -> Self For escapable types, the `@_lifetime` attribute is not applied. -#### Usage hints +### Usage hints The `extracting()` pattern, while not completely new, is still a departure over the slice pattern established by the `Collection` protocol. For `Span`, `RawSpan`, `MutableSpan` and `MutableRawSpan`, we can add unavailable subscripts and function with hints towards the corresponding `extracting()` function: From 0184b3044b1d06a839e4bb6f08c6e2686575b8b8 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 15:16:43 -0700 Subject: [PATCH 360/505] clarification --- proposals/nnnn-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 2c7e0cf4a7..f455481523 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -139,7 +139,7 @@ This is an extension of an existing pattern. We are not considering a different ## Future directions #### Disambiguation over ownership type -The `extracting()` functions proposed here are semantically consuming. `MutableSpan` has versions defined as mutations, but it could benefit from consuming ones as well. In order to do this, we could establish a pattern for disambiguation by name, or we could invent new syntax to disambiguate by ownership type. This is a complex topic left to future proposals. +The `extracting()` functions proposed here are borrowing. `MutableSpan` has versions defined as mutating, but it could benefit from consuming ones as well. In general there could be a need for all three ownership variants of a given operation (`borrowing`, `consuming`, or `mutating`.) In order to handle these variants, we could establish a pattern for disambiguation by name, or we could invent new syntax to disambiguate by ownership type. This is a complex topic left to future proposals. ## Acknowledgements Thanks to Karoy Lorentey and Tony Parker. From 9a1371e1d4af3a9bba5ce4209f73ec6cdeece22a Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 15:39:28 -0700 Subject: [PATCH 361/505] tweak title --- proposals/nnnn-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index f455481523..059a458316 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -1,4 +1,4 @@ -# Expand the `extracting()` slicing pattern to more types +# Apply the extracting() slicing pattern more widely * Proposal: TBD * Author: [Guillaume Lessard](https://github.com/glessard) From cc360ddf41d12401a85109f23216f3c965b4e8ed Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 15:41:35 -0700 Subject: [PATCH 362/505] link to the proposal pull request --- proposals/nnnn-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 059a458316..27c39171ae 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -1,6 +1,6 @@ # Apply the extracting() slicing pattern more widely -* Proposal: TBD +* Proposal: [TBD](https://github.com/swiftlang/swift-evolution/pull/2877) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: TBD * Status: **Pitch** From fa3e8a4fcb8ff271853e38a0e3dafc7d0f15f348 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 15:51:08 -0700 Subject: [PATCH 363/505] fix from review comments --- proposals/nnnn-extracting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 27c39171ae..096fb65d36 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -63,14 +63,14 @@ The general declarations for these functions is as follows: /// /// Traps if any position within the range is invalid. @_lifetime(copy self) -public func extracting(_ byteOffsets: Range) -> Self +public func extracting(_ bounds: Range) -> Self /// Returns an extracted slice over the items within /// the supplied range of positions. /// /// Traps if any position within the range is invalid. @_lifetime(copy self) -public func extracting(_ byteOffsets: some RangeExpression) -> Self +public func extracting(_ bounds: some RangeExpression) -> Self /// Returns an extracted slice over all items of this container. @_lifetime(copy self) From 19c78ae5b5c46a48d2a2827bc90f10ad9292f808 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 5 Jun 2025 16:01:50 -0700 Subject: [PATCH 364/505] nit-picky wording change --- proposals/nnnn-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 096fb65d36..2bfcc556d7 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -17,7 +17,7 @@ Slicing containers is an important operation, and non-copyable values have introduced a significant change in the spelling of that operation. When we [introduced][SE-0437] non-copyable primitives to the standard library, we allowed slicing `UnsafeBufferPointer` and related types via a family of `extracting()` methods. We expanded upon these when introducing [`MutableSpan`][SE-0467]. -Now that we have a [stable spelling][Forum-LifetimeAnnotations] for lifetime dependencies, we propose adding the `extracting()` methods to `Span` and `RawSpan`, as well as members of the `UnsafeBufferPointer` family that were missed in [SE-0437][SE-0437]. +Now that we have a [supported spelling][Forum-LifetimeAnnotations] for lifetime dependencies, we propose adding the `extracting()` methods to `Span` and `RawSpan`, as well as members of the `UnsafeBufferPointer` family that were missed in [SE-0437][SE-0437]. ## Proposed solution From 73c18af6acb68df94b4f35b16d7eea8b2102383c Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 5 Jun 2025 22:34:02 -0400 Subject: [PATCH 365/505] Accept SE-0480 --- proposals/0480-swiftpm-warning-control.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 9183b1091a..5cdb54c201 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -3,9 +3,9 @@ * Proposal: [SE-0480](0480-swiftpm-warning-control.md) * Authors: [Dmitrii Galimzianov](https://github.com/DmT021) * Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch](https://github.com/FranzBusch) -* Status: **Returned for revision** +* Status: **Accepted** * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) -* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) +* Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) ([acceptance](https://forums.swift.org/t/accepted-se-0480-warning-control-settings-for-swiftpm/80327)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) ## Introduction From fe7db65a32433e4be5f100f9ba4838c9fd1fc672 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Fri, 6 Jun 2025 15:56:48 -0700 Subject: [PATCH 366/505] Update InlineArray sugar proposal from x to of (#2861) * Update 0483-inline-array-sugar.md Switch from `x` to `of` as the separator. Introduce an alternatives considered option that covers the naming of `InlineArray`. * Update 0483-inline-array-sugar.md * Update 0483-inline-array-sugar.md * Update 0483-inline-array-sugar.md * Update 0483-inline-array-sugar.md * Fix typos discovered by @ole and @benrimmington. * Minor editorial changes. * Update the review status in preparation for revision review. --------- Co-authored-by: Holly Borla --- proposals/0483-inline-array-sugar.md | 125 ++++++++++++++++++--------- 1 file changed, 82 insertions(+), 43 deletions(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index 146174dc75..48dcfd6a3b 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -1,11 +1,11 @@ -# `InlineArray` Literal Syntax +# `InlineArray` Type Sugar * Proposal: [SE-0483](0483-inline-array-sugar.md) * Authors: [Hamish Knight](https://github.com/hamishknight), [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Active Review (May 2 - May 16, 2025)** +* Status: **Active Review (June 6- June 16, 2025)** * Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. -* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ## Introduction @@ -21,31 +21,31 @@ let fiveIntegers: InlineArray<5, Int> = .init(repeating: 99) Declaring this type is more cumbersome than its equivalent dynamically-sized array, which has sugar for the type syntax: -``` +```swift let fiveIntegers: [Int] = .init(repeating: 99, count: 5) ``` This becomes more pronounced when dealing with multiple dimensions: -``` +```swift let fiveByFive: InlineArray<5, InlineArray<5, Int>> = .init(repeating: .init(repeating: 99)) ``` +Almost every other language in a similar category to Swift – C, C++, Objective-C, Pascal, Go, Rust, Zig, Java, C# – has a simple syntax for their fixed-size array type. The introduction of a fixed-size array type into Swift should also introduce a shorthand syntax, in keeping with Swift's general approach of low ceremony and concise syntax. Swift further deviates from its peer languages by giving its _dynamic_ array type, `Array` (known in many other languages as `vector`) a sugared form. This can lead to an assumption that `Array` should be used under almost all circumstances, despite it having significant downsides in many uses (see further discussion in alternatives considered). + ## Proposed solution A new sugared version of the `InlineArray` type is proposed: ```swift -let fiveIntegers: [5 x Int] = .init(repeating: 99) +let fiveIntegers: [5 of Int] = .init(repeating: 99) ``` -The `x` here is the ASCII character, and is chosen to evoke the common shorthand use to represent "by", as in "4x4" or "2 in x 4 in". - -Note that although it is used in the manner of an operator, `x` here serves more like a contextual keyword, similar to if the syntax were `[5 of Int]`. +The choice of `of` forms something close to a grammatical phrase ("an array of five ints"). A short contextual keyword is also in keeping with Swift's tradition in other areas such as `in` or `let`. ## Detailed design -The new syntax consists of the value for the integer generic parameter and the type of the element generic parameter, separated by `x`. +The new syntax consists of the value for the integer generic parameter and the type of the element generic parameter, separated by `of`. This will be added to the grammar alongside the current type sugar: @@ -53,35 +53,35 @@ This will be added to the grammar alongside the current type sugar: > _type → sized-array-type_ > > **Grammar of a sized array type** -> _sized-array-type → [ expression `x` type ]_ +> _sized-array-type → [ expression `of` type ]_ -Note that while the grammar allows for any expression, this is currently limited to only integer literals. +Note that while the grammar allows for any expression, this is currently limited to only integer literals or integer type parameters, as required by the current implementation of `InlineArray`. If that restriction changes, so would the value allowed in the expression in the sugar. The new sugar is equivalent to declaring a type of `InlineArray`, so all rules that can be applied to the generic placeholders for the unsugared version also apply to the sugared version: -``` +```swift // Nesting let fiveByFive: InlineArray<5, InlineArray<5, Int>> = .init(repeating: .init(repeating: 99)) -let fiveByFive: [5 x [5 x Int]] = .init(repeating: .init(repeating: 99)) +let fiveByFive: [5 of [5 of Int]] = .init(repeating: .init(repeating: 99)) // Inference from context: -let fiveIntegers: [5 x _] = .init(repeating: 99) -let fourBytes: [_ x Int8] = [1,2,3,4] -let fourIntegers: [_ x _] = [1,2,3,4] +let fiveIntegers: [5 of _] = .init(repeating: 99) +let fourBytes: [_ of Int8] = [1,2,3,4] +let fourIntegers: [_ of _] = [1,2,3,4] // use on rhs -let fiveDoubles = [5 x _](repeating: 1.23) +let fiveDoubles = [5 of _](repeating: 1.23) ``` The sugar can also be used in place of the unsugared type wherever it might appear: -``` -[5 x Int](repeating: 99) -MemoryLayout<[5 x Int]>.size -unsafeBitCast((1,2,3), to: [3 x Int].self) +```swift +[5 of Int](repeating: 99) +MemoryLayout<[5 of Int]>.size +unsafeBitCast((1,2,3), to: [3 of Int].self) ``` -There must be whitespace on either side of the separator i.e. you cannot write `[5x Int]`. There are no requirements to balance whitespace, `[5 x Int]` is permitted. A new line can appear after the `x` but not before it, as while this is not ambiguous, this aids with the parser recovery logic, leading to better syntax error diagnostics. +There must be whitespace on either side of the separator; i.e., you cannot write `[5of Int]`. There are no requirements to balance whitespace; `[5 of Int]` is permitted. A new line can appear after the `of` but not before it, as while this is not ambiguous, this aids with the parser recovery logic, leading to better syntax error diagnostics. ## Source Compatibility @@ -89,63 +89,102 @@ Since it is not currently possible to write any form of the proposed syntax in S ## Impact on ABI -This is purely compile-time sugar for the existing type. It is resolved at compile time, and does not appear in the ABI nor rely on any version of the runtime. +This is purely compile-time sugar for the existing type. It is resolved at compile time and does not appear in the ABI nor rely on any version of the runtime. ## Future Directions ### Repeated value equivalent -Analogous to arrays, there is an equivalent _value_ sugar for literals of a specific size: +Analogous to arrays, there is an equivalent *value* sugar for literals of a specific size: -``` -// type inferred to be [5 x Int] -let fiveInts = [5 x 99] -// type inferred to be [5 x [5 x Int]] -let fiveByFive = [5 x [5 x 99]] +```swift +// type inferred to be [5 of Int] +let fiveInts = [5 of 99] + +// type inferred to be [5 of [5 of Int]] +let fiveByFive = [5 of [5 of 99]] ``` Unlike the sugar for the type, this would also have applicability for existing types: -``` +```swift // equivalent to .init(repeating: 99, count: 5) -let dynamic: [Int] = [5 x 99] +let dynamic: [Int] = [5 of 99] ``` This is a much bigger design space, potentially requiring a new expressible-by-literal protocol and a way to map the literal to an initializer. As such, it is left for a future proposal. +However, the choice of syntax for the type sugar has a significant impact on the viability of this future direction (see alternatives considered). Given the potential benefit of such a value syntax, any choice for the type sugar should consider its future extension to value sugar. + +[^expressions]: It could also cause confusion once expressions are allowed for declaring an `InlineArray` i.e. `[5 * 5 * Int]` would be allowed. + ### Flattened multi-dimensional arrays -For multi-dimensional arrays, `[5 x [5 x Int]]` could be flattened to `[5 x 5 x Int]` without any additional parsing issues. This could be an alternative considered, but is in future directions as it could also be introduced as sugar for the former case at a later date. +For multi-dimensional arrays, `[5 of [5 of Int]]` could be flattened to `[5 of 5 of Int]` without any additional parsing issues. This could be an alternative considered but is in future directions as it could also be introduced as sugar for the former case at a later date. ## Alternatives Considered +### Indication of the "inline" nature via the sugar. + +The naming of `InlineArray` incorporates important information about the nature of the type – that it includes its values inline rather than indirectly via a pointer. This name was chosen over other alternatives such as `FixedSizeArray` because the "inline-ness" was considered the more fundamental property, and so a better driver for the name. + +This has led to suggestions that this inline nature is important to include in the sugar was well. However, the current state privileges the position of `Array` as the only array type that is sugared. This implies that `Array` is the right choice in all circumstances, with inline arrays being a rare micro-optimization. This is not the case. + +For example, consider a translation of this code from the popular [Ray Tracing in One Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html#thevec3class) tutorial: + +```cpp +class vec3 { + public: + double e[3]; + + double x() const { return e[0]; } + double y() const { return e[1]; } + double z() const { return e[2]; } + // etc +} +``` + +The way in which Swift privileges `[Double]` with sugar strongly implies you should use that in this translation. This would be the wrong choice. Every access to those coordinate accessors would need to check the bounds (because while the author might ensure that the value of `e` will only ever have length 3, the compiler cannot easily know this) and, in the case of mutation, a check for uniqueness of the pointer. It would also make `vec3` a nontrivial type, which has significant performance implications wherever it is used. `InlineArray<3, Double>` has none of these problems. + +Other examples include using nested `Array` types i.e. using `[[Double]]` to represent a matrix – which would also have significant negative consequences depending on the use case, compared to using an `InlineArray` to model the same values. In other cases, the "copy on write" nature of `Array` can mislead users into thinking that copies are risk-free, when actually copying an array can lead to "defeating" copy on write in subtle ways that can cause difficult-to-hunt-down performance issues. In all these cases, you need to pick the right one of two options for the performance goals you are trying to achieve. + +It is likely that Swift's choice (deviating from many of its peers) to emphasize its dynamic array through sugar, has led to a negative impact on the culture of writing performant Swift code, with the nicely sugared dynamic arrays (and array value literals) being over-favored. This is not intended to make the case that Swift should _not_ have this sugar. Dynamic arrays are widely useful and Swift's readability goals are improved by Swift having a concise syntax for creating them. But writing performant Swift code inevitably involves having an understanding of the underlying performance characteristics of _all_ the types you are using, and syntax or type naming alone cannot solve this. + +Of course, all this only matters when you are trying to write code that maximizes performance. But that is a really important use case for Swift. The goal for Swift is a language that is as safe and enjoyable to write as many high-level non-performant languages, but also can achieve peak performance when that is your goal. And the idea is that when you are targeting that level of performance, you don't have to go into "ugly, no longer nice swift" mode to do it, with nice sugared `[Double]` replaced with less pleasant full type name of `InlineArray` – something a user coming from Go or C++ or Rust might find a downgrade. Similarly, attempting to incorporate the word "inline" into the sugar e.g. `[5 inline Int]` creates a worst of both worlds solution that many would find offputting to use, without solving the fundamental issue. + +For these reasons, we should be considering `InlineArray` a peer of `Array` (even if the need for it is less common – just not "niche"), and providing a pleasant to use sugar for both types. + ### Choice of delimiter The most obvious alternative here is the choice of separator. Other options include: +- `[5 by Int]` is similar to `of`, but is less applicable to the value syntax (`[5 by 5]` doesn't read as an array of 5 instances of 5), without being clearer for the type syntax. +- `[5 x Int]`, using the ascii letter `x`, as an approximation for multiplication, reflecting common uses such as "a 4x4 vehicle". This was the choice of a previous revision of this proposal. - `[5 * Int]`, using the standard ASCII symbol for multiplication. - `[5 ⨉ Int]`, the Unicode n-ary times operator. This looks nice but is impractical as not keyboard-accessible. -- `[5; Int]` is what Rust uses, but appears to have little association with "times" or "many". Similarly other arbitrary punctuation e.g. `,` or `/` or `#`. -- `[5 of Int]` is more verbose than `x` but could be considered more clear. It has the upside or downside, depending on your preference, of being almost, but not quite, grammatical. -- `:` is of course ruled out as it is used for dictionary literals. +- `[5; Int]` is what Rust uses, but appears to have little association with "times" or "many". Similarly other arbitrary punctuation e.g. `,` or `/`. `:` is of course ruled out as it is used for dictionary literals. +- `#` does have an association with counts in some areas such as set theory, but is used as a prefix operator rather than infix i.e. `[#5 Int]`. This is less expected than the infix form, and could also be read as "the fifth `Int`". It is also unclear how this would work with expressions like an array of size `5*5`. +- No delimiter at all i.e. `[5 Int]`. While this might be made to parse, the lack of any separator is found unsettling by some users and is less visually clear, especially once expressions are allowed instead of the `5`. -Note that `*` is an existing operator, and may lead to ambiguity in future when expressions can be used to determine the size: `[5 * N * Int]`. `x` is clearer in this case: `[5 * N x Int]`. It also avoids parsing ambiguity, as the grammar does not allow two identifiers in succession. But it would be less clear if `x` also appeared as an identifier: `[5 * x x Int]` (which is not yet permitted but may be in future use cases). +Note that `*` is an existing operator, and may lead to ambiguity in future when expressions can be used to determine the size: `[5 * N * Int]`. `of` is clearer in this case: `[5 * N of Int]`. It also avoids parsing ambiguity, as the grammar does not allow two identifiers in succession. This becomes more important if the future direction of a value equivalent is pursued. `[2 * 2 * 2]` could be interpreted as `[2, 2, 2, 2]`, `[4, 4,]`, or `[8]`. -This becomes more important if the future direction of a value equivalent is pursued. `[2 * 2 * 2]` could be interpreted as `[2, 2, 2, 2]`, `[4, 4,]`, or `[8]`. +Since `of` cannot follow another identifier today, `[of of Int]` is unambiguous,[^type] but would clearly be hard to read. This is likely a hypothetical concern rather than a practical one since `of` is very rare as a variable name. The previous proposal's use of `x` involved a variable name that was more common. -Since `x` cannot follow another identifier today, `[x x Int]` is unambiguous,[^type] but would clearly be hard to read. This is likely a hypothetical concern rather than a practical one. While `x` is used often in scratch code for a local variable, a more meaningful name is usually preferable, and this would be especially the case if it is found being used for the size of an array literal. In addition, while `i`, `j`, or `n` are often legitimate counters that might be suited to the size of an array, `x` is generally not used for such things. +`x` is also less clear when used for the value version: `[5 x 5]` can be parsed unambiguously, but looks similar to five times five, and so visually has the same challenges as with the `*` operator, even if this isn't a problem for the compiler. -[^type]: or even `[x x x]`, since `x` can be a type name, albeit one that defies Swift's naming conventions. +[^type]: or even `[of of of]`, since `of` can be a type name, albeit one that defies Swift's naming conventions. Another thing to consider is how that separator looks in the fully inferred version, which tend to start to look a little like ascii diagrams: ``` +[_ of _] [_ x _] [_ * _] [_; _] -[_ of _] ``` +Of all these, the `of` choice is less susceptible to the ascii art problem. + ### Order of size and type The order of size first, then type is determined by the ordering of the unsugared type, and deviating from this for the sugared version is not an option. @@ -156,6 +195,6 @@ In theory, when using integer literals or `_` the whitespace could be omitted (` ### Choice of brackets -`InlineArray` has a lot in common with tuples – especially in sharing "copy on copy" behavior, unlike regular `Array`. So `(5 x Int)` may be an appropriate alternative to the square brackets, echoing this similarity. +`InlineArray` has a lot in common with tuples – especially in sharing "copy on copy" behavior, unlike regular `Array`. So `(5 of Int)` may be an appropriate alternative to the square brackets, echoing this similarity. However, tuples and `InlineArray`s remain very different types, and it could be misleading to imply that `InlineArray` is "just" a tuple. -Beyond varying the separator, there may be other dramatically different syntax that moves further from the "like Array sugar, but with a size argument". +Beyond varying the separator, there may be other dramatically different syntax that moves further from the "like Array sugar, but with a size argument". For example, dropping the brackets altogether (i.e. `let a: 5 of Int`). However, these are probably too much of a departure from the current Swift idioms, so likely to cause further confusion without any real upside. From 542a2a2cda2e078ffb095ed7fc8193d5ff732204 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 6 Jun 2025 17:58:24 -0500 Subject: [PATCH 367/505] Correct review period for SE-0483 (#2879) --- proposals/0483-inline-array-sugar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index 48dcfd6a3b..5c469f2b55 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -3,7 +3,7 @@ * Proposal: [SE-0483](0483-inline-array-sugar.md) * Authors: [Hamish Knight](https://github.com/hamishknight), [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Active Review (June 6- June 16, 2025)** +* Status: **Active Review (June 6- June 20, 2025)** * Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. * Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) From ea8178fe9213e566e6ef20fbe486484ca35e7276 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 6 Jun 2025 18:01:59 -0500 Subject: [PATCH 368/505] Link second review for SE-0483. (#2880) --- proposals/0483-inline-array-sugar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index 5c469f2b55..4b817e413e 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -5,7 +5,7 @@ * Review Manager: [Holly Borla](https://github.com/hborla) * Status: **Active Review (June 6- June 20, 2025)** * Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. -* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ([second review](https://forums.swift.org/t/second-review-se-0483-inlinearray-type-sugar/80337)) ## Introduction From ba32f1a22e0e3deae2797784764640403a4dcfe8 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 9 Jun 2025 07:37:58 -0700 Subject: [PATCH 369/505] Update proposals/nnnn-extracting.md Co-authored-by: Ben Rimmington --- proposals/nnnn-extracting.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/nnnn-extracting.md b/proposals/nnnn-extracting.md index 2bfcc556d7..e488808f98 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/nnnn-extracting.md @@ -7,9 +7,9 @@ * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. * Review: Pending -[SE-0437]: proposals/0437-noncopyable-stdlib-primitives.md -[SE-0447]: proposals/0447-span-access-shared-contiguous-storage.md -[SE-0467]: proposals/0467-MutableSpan.md +[SE-0437]: 0437-noncopyable-stdlib-primitives.md +[SE-0447]: 0447-span-access-shared-contiguous-storage.md +[SE-0467]: 0467-MutableSpan.md [Forum-LifetimeAnnotations]: https://forums.swift.org/t/78638 From ea042022ca92ab8a894f8ba7ffa283f55723f2e9 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 9 Jun 2025 19:00:31 -0700 Subject: [PATCH 370/505] [SE-0485] Post-review amendments and deferrals --- proposals/0485-outputspan.md | 340 +++++++---------------------------- 1 file changed, 67 insertions(+), 273 deletions(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 1e4098b78f..d6416839d5 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -79,9 +79,9 @@ extension Array { We will also extend `String`, `UnicodeScalarView` and `InlineArray` with similar initializers, and add append-in-place operations where appropriate. -#### `@lifetime` attribute +#### `@_lifetime` attribute -Some of the API presented here must establish a lifetime relationship between a non-escapable returned value and a callee binding. This relationship will be illustrated using the `@lifetime` attribute recently [pitched][PR-LifetimeAnnotations] and [formalized][Forum-LifetimeAnnotations]. For the purposes of this proposal, the lifetime attribute ties the lifetime of a function's return value to one of its input parameters. +Some of the API presented here must establish a lifetime relationship between a non-escapable returned value and a callee binding. This relationship will be illustrated using the `@_lifetime` attribute recently [pitched][PR-LifetimeAnnotations] and [formalized][Forum-LifetimeAnnotations]. For the purposes of this proposal, the lifetime attribute ties the lifetime of a function's return value to one of its input parameters. Note: The eventual lifetime annotations proposal may adopt a syntax different than the syntax used here. We expect that the Standard Library will be modified to adopt an updated lifetime dependency syntax as soon as it is finalized. @@ -124,13 +124,13 @@ The basic operation supported by `OutputSpan` is appending an element. When an e ```swift extension OutputSpan where Element: ~Copyable { /// Append a single element to this `OutputSpan`. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func append(_ value: consuming Element) } extension OutputSpan { /// Repeatedly append an element to this `OutputSpan`. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func append(repeating repeatedValue: Element, count: Int) } ``` @@ -141,103 +141,12 @@ extension OutputSpan where Element: ~Copyable { /// /// Returns the last element. The `OutputSpan` must not be empty. @discardableResult - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeLast() -> Element } ``` - -##### Bulk initialization of an `OutputSpan`'s memory: - -We include functions to perform bulk initialization of the memory represented by an `OutputSpan`. Initializing an `OutputSpan` from a `Sequence` must use every element of the source. Initializing an `OutputSpan` from `IteratorProtocol` will copy as many items as possible, either until the input is empty or the `OutputSpan`'s available storage is zero. - -See [below](#contentsOf) for a discussion of the argument labels used with the `append()` functions. - -```swift -extension OutputSpan { - /// Initialize this span's suffix with every element of the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - contentsOf source: consuming some Sequence - ) - - /// Initialize this span's suffix with every element of the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - copying source: Span - ) - - /// Initialize this span's suffix with every element of the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - contentsOf source: UnsafeBufferPointer - ) -} - -extension OutputSpan where Element: ~Copyable { - /// Initialize this span's suffix by moving every element from the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - moving source: inout OutputSpan - ) - - /// Initialize this span's suffix by moving every element from the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - consuming source: consuming InlineArray - ) - - /// Initialize this span's suffix by moving every element from the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - consuming source: UnsafeMutableBufferPointer - ) -} - -extension OutputSpan { - /// Initialize this span's suffix by moving every element from the source. - /// - /// It is a precondition that the `OutputSpan`'s uninitialized suffix - /// can contain every element of the source. - @lifetime(self: copy self) - public mutating func append( - consuming source: Slice> - ) - - /// Initialize this span's suffix with the elements from the source. - /// - /// Use this function if it isn't possible to fulfill the precondition - /// of the other `append()` functions, and to contain every element - /// of the source. - /// - /// Returns true if the iterator has filled all the free capacity in the span. - /// When the free capacity has been filled, there may be some elements - /// remaining in the iterator. - @discardableResult - @lifetime(self: copy self) - public mutating func append( - from source: inout some IteratorProtocol - ) -> Bool -} -``` +##### Bulk removals from an `OutputSpan`'s memory: Bulk operations to deinitialize some or all of an `OutputSpan`'s memory are also available: ```swift @@ -246,11 +155,11 @@ extension OutputSpan where Element: ~Copyable { /// to the uninitialized state. /// /// `n` must not be greater than `count` - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeLast(_ n: Int) /// Remove all this span's elements and return its memory to the uninitialized state. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeAll() } ``` @@ -263,12 +172,12 @@ The initialized elements are accessible for read-only or mutating access via the extension OutputSpan where Element: ~Copyable { /// Borrow the underlying initialized memory for read-only access. public var span: Span { - @lifetime(borrow self) borrowing get + @_lifetime(borrow self) borrowing get } /// Exclusively borrow the underlying initialized memory for mutation. public mutating var mutableSpan: MutableSpan { - @lifetime(&self) mutating get + @_lifetime(&self) mutating get } } ``` @@ -291,7 +200,6 @@ extension OutputSpan where Element: ~Copyable { } ``` - ##### Interoperability with unsafe code We provide a method to process or populate an `OutputSpan` using unsafe operations, which can also be used for out-of-order initialization. @@ -319,7 +227,7 @@ extension OutputSpan where Element: ~Copyable { /// This function cannot verify these two invariants, and therefore /// this is an unsafe operation. Violating the invariants of `OutputSpan` /// may result in undefined behavior. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func withUnsafeMutableBufferPointer( _ body: ( UnsafeMutableBufferPointer, @@ -329,7 +237,6 @@ extension OutputSpan where Element: ~Copyable { } ``` - ##### Creating an `OutputSpan` instance: Creating an `OutputSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized instances of `Element`, and the second region is uninitialized. The number of initialized instances is passed to the `OutputSpan` initializer through its `initializedCount` argument. @@ -348,15 +255,11 @@ extension OutputSpan where Element: ~Copyable { /// - initializedCount: the number of initialized elements /// at the beginning of `buffer`. @unsafe - @lifetime(borrow buffer) + @_lifetime(borrow buffer) public init( buffer: UnsafeMutableBufferPointer, initializedCount: Int ) - - /// Create an OutputSpan with zero capacity - @lifetime(immortal) - public init() } extension OutputSpan { @@ -372,7 +275,7 @@ extension OutputSpan { /// - initializedCount: the number of initialized elements /// at the beginning of `buffer`. @unsafe - @lifetime(borrow buffer) + @_lifetime(borrow buffer) public init( buffer: borrowing Slice>, initializedCount: Int @@ -380,6 +283,17 @@ extension OutputSpan { } ``` +We also provide a default (no-parameter) initializer to create an empty, zero-capacity `OutputSpan`. Such an initializer is useful in order to be able to materialize an empty span for the `nil` case of an Optional, for example, or to exchange with another span in a mutable struct. + +```swift +extension OutputSpan where Element: ~Copyable { + /// Create an OutputSpan with zero capacity + @_lifetime(immortal) + public init() +} +``` + +Such an empty `OutputSpan` does not depend on a memory allocation, and therefore has the longest lifetime possible :`immortal`. This capability is important enough that we also propose to immediately define similar empty initializers for `Span`, `RawSpan`, `MutableSpan` and `MutableRawSpan`. ##### Retrieving initialized memory from an `OutputSpan` @@ -451,119 +365,62 @@ The basic operation is to append the bytes of some value to an `OutputRawSpan`. ```swift extension OutputRawSpan { /// Append a single byte to this span - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func append(_ value: UInt8) /// Appends the given value's bytes to this span's initialized bytes - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func append( _ value: T, as type: T.Type ) /// Appends the given value's bytes repeatedly to this span's initialized bytes - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func append( repeating repeatedValue: T, count: Int, as type: T.Type ) } ``` -Initializing an `OutputRawSpan` from a `Sequence` or other container type must use every element of the source. Initializing an `OutputRawSpan` from an `IteratorProtocol` instance will copy as many items as possible, either until the input is empty or the `OutputRawSpan` cannot contain another element. - -```swift -extension OutputRawSpan { - /// Initialize the span's bytes with every byte of the source. - /// - /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix - /// can contain every byte of the source. - @lifetime(self: copy self) - public mutating func append, as type: T.Type - ) - - /// Initialize the span's bytes with every byte of the source. - /// - /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix - /// can contain every byte of the source. - @lifetime(self: copy self) - public mutating func append, as type: T.Type - ) - - /// Initialize the span's bytes with every byte of the source. - /// - /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix - /// can contain every byte of the source. - @lifetime(self: copy self) - public mutating func append( - contentsOf source: RawSpan - ) - - /// Initialize the span's bytes with every byte of the source. - /// - /// It is a precondition that the `OutputRawSpan`'s uninitialized suffix - /// can contain every byte of the source. - @lifetime(self: copy self) - public mutating func append( - contentsOf source: UnsafeRawBufferPointer - ) - - /// Initialize the span's bytes with the bytes of the elements of the source. - /// - /// Use this function if it isn't possible to fulfill the precondition - /// of the other `append()` functions, and to contain every element - /// of the source. - /// - /// Returns true if the iterator has filled all the free capacity in the span. - /// When the free capacity has been filled, there may be some elements - /// remaining in the iterator. - @lifetime(self: copy self) - public mutating func append, as type: T.Type - ) -> Bool -} -``` - An `OutputRawSpan`'s initialized memory is accessible for read-only or mutating access via the `bytes` and `mutableBytes` properties: ```swift extension OutputRawSpan { /// Borrow the underlying initialized memory for read-only access. public var bytes: RawSpan { - @lifetime(borrow self) borrowing get + @_lifetime(borrow self) borrowing get } /// Exclusively borrow the underlying initialized memory for mutation. public var mutableBytes: MutableRawSpan { - @lifetime(&self) mutating get + @_lifetime(&self) mutating get } } ``` -Methods to deinitialize memory from an `OutputRawSpan`: +Deinitializing memory from an `OutputRawSpan`: ```swift extension OutputRawSpan { /// Remove the last byte from this span - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeLast() -> UInt8 { /// Remove the last N elements, returning the memory they occupy /// to the uninitialized state. /// /// `n` must not be greater than `count` - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeLast(_ n: Int) /// Remove all this span's elements and return its memory /// to the uninitialized state. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func removeAll() } ``` - ##### Interoperability with unsafe code We provide a method to process or populate an `OutputRawSpan` using unsafe operations, which can also be used for out-of-order initialization. @@ -591,7 +448,7 @@ extension OutputRawSpan { /// This function cannot verify these two invariants, and therefore /// this is an unsafe operation. Violating the invariants of `OutputRawSpan` /// may result in undefined behavior. - @lifetime(self: copy self) + @_lifetime(self: copy self) public mutating func withUnsafeMutableBytes( _ body: ( UnsafeMutableRawBufferPointer, @@ -601,7 +458,6 @@ extension OutputRawSpan { } ``` - ##### Creating `OutputRawSpan` instances Creating an `OutputRawSpan` is an unsafe operation. It requires having knowledge of the initialization state of the range of memory being targeted. The range of memory must be in two regions: the first region contains initialized bytes, and the second region is uninitialized. The number of initialized bytes is passed to the `OutputRawSpan` initializer through its `initializedCount` argument. @@ -621,14 +477,14 @@ extension OutputRawSpan { /// - initializedCount: the number of initialized elements /// at the beginning of `buffer`. @unsafe - @lifetime(borrow buffer) + @_lifetime(borrow buffer) public init( buffer: UnsafeMutableRawBufferPointer, initializedCount: Int ) /// Create an OutputRawSpan with zero capacity - @lifetime(immortal) + @_lifetime(immortal) public init() /// Unsafely create an OutputRawSpan over partly-initialized memory. @@ -643,7 +499,7 @@ extension OutputRawSpan { /// - initializedCount: the number of initialized elements /// at the beginning of `buffer`. @unsafe - @lifetime(borrow buffer) + @_lifetime(borrow buffer) public init( buffer: Slice, initializedCount: Int @@ -860,101 +716,55 @@ extension Data { } ``` -#### Changes to `MutableSpan` and `MutableRawSpan` +## Source compatibility -This proposal considers the naming of `OutputSpan`'s bulk-copying methods more carefully than [SE-0467][SE-0467] about `MutableSpan`. Accordingly, we would like to replace the `update()` functions proposed there in accordance with the scheme proposed in this proposal: +This proposal is additive and source-compatible with existing code. -```swift -extension MutableSpan where Element: Copyable { - public mutating func update( - fromContentsOf source: some Sequence - ) -> Index - - public mutating func update( - copying source: borrowing Span - ) -> Index - - public mutating func update( - copying source: UnsafeBufferPointer - ) -> Index -} +## ABI compatibility -extension MutableSpan where Element: ~Copyable { - public mutating func update( - moving source: inout OutputSpan - ) -> Index +This proposal is additive and ABI-compatible with existing code. - public mutating func update( - consuming source: UnsafeMutableBufferPointer - ) -> Index -} +## Implications on adoption -extension MutableSpan { - public mutating func append( - consuming source: Slice> - ) +The additions described in this proposal require a new version of the Swift standard library and runtime. - public mutating func update( - from source: inout some IteratorProtocol - ) -> Index -} -``` -Similarly, `MutableRawSpan`'s bulk-copying methods would be replaced by the following: +## Alternatives Considered -```swift -extension MutableRawSpan { - public mutating func update( - fromContentsOf source: some Sequence, as type: T.Type - ) -> Index - - public mutating func update( - fromContentsOf source: borrowing Span, as type: T.Type - ) -> Index - - public mutating func update( - fromContentsOf source: borrowing RawSpan - ) -> Index - - public mutating func append( - fromContentsOf source: UnsafeRawBufferPointer - ) -> Index - - public mutating func update( - from source: inout some IteratorProtocol, as type: T.Type - ) -> Index -} -``` +#### Vending `OutputSpan` as a property +`OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and that pattern fits the needs of `OutputSpan` well. -## Source compatibility +## Future directions -This proposal is additive and source-compatible with existing code. +#### Helpers to initialize memory in an arbitrary order -## ABI compatibility +Some applications may benefit from the ability to initialize a range of memory in a different order than implemented by `OutputSpan`. This may be from back-to-front or even arbitrary order. There are many possible forms such an initialization helper can take, depending on how much memory safety the application is willing to give up in the process of initializing the memory. At the unsafe end, this can be delegating to an `UnsafeMutableBufferPointer` along with a set of requirements; this option is proposed here. At the safe end, this could be delegating to a data structure which keeps track of initialized memory using a bitmap. It is unclear how much need there is for this more heavy-handed approach, so we leave it as a future enhancement if it is deemed useful. -This proposal is additive and ABI-compatible with existing code. +#### Insertions -## Implications on adoption +A use case similar to appending is insertions. Appending is simply inserting at the end. Inserting at positions other than the end is an important capability. We expect to add insertions soon in a followup proposal if `OutputSpan` is accepted. Until then, a workaround is to append, then rotate the elements to the desired position using the `mutableSpan` view. -The additions described in this proposal require a new version of the Swift standard library and runtime. +#### Generalized removals +Similarly to generalized insertions (i.e. not from the end), we can think about removals of one or more elements starting at a given position. We expect to add generalized removals along with insertions in a followup proposal after `OutputSpan` is accepted. -## Alternatives Considered +#### Variations on `Array.append(addingCapacity:initializingWith:)` -#### Vending `OutputSpan` as a property +The function proposed here only exposes uninitialized capacity in the `OutputSpan` parameter to its closure. A different function (perhaps named `edit()`) could also pass the initialized portion of the container, allowing an algorithm to remove or to add elements. This could be considered in addition to `append()`. -`OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and that pattern fits the needs of `OutputSpan` well. +#### Methods to initialize or update in bulk -#### Alternative names for `append()` methods +The `RangeReplaceableCollection` protocol has a foundational method `append(contentsOf:)` for which this document does not propose a corresponding method. We expect to first add such bulk-copying functions as part of of a package. -`OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be generally applicable. The origin of the `append(contentsOf:)` method we are expanding upon is the `RangeReplaceableCollection` protocol, which always represents copyable and escapable collections with copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This supports copying elements from the source, while also destroying the source if we happen to hold its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrow of the source. +`OutputSpan` lays the groundwork for new, generalized `Container` protocols that will expand upon and succeed the `Collection` hierarchy while allowing non-copyability and non-escapability to be applied to both containers and elements. We hope to find method and property names that will be generally applicable. The `append(contentsOf:)` method we refer to above always represents copyable and escapable collections with copyable and escapable elements. The definition is as follows: `mutating func append(contentsOf newElements: __owned S)`. This supports copying elements from the source, while also destroying the source if we happen to hold its only copy. This is obviously not sufficient if the elements are non-copyable, or if we only have access to a borrowed source. When the elements are non-copyable, we must append elements that are removed from the source. Afterwards, there are two possible dispositions of the source: destruction (`consuming`), where the source can no longer be used, or mutation (`inout`), where the source has been emptied but is still usable. -When the elements are copyable, we can simply copy the elements from the source. Afterwards, there are two possible dispositions of the source: releasing a borrowed source, or `consuming`. The latter is approximately the same behaviour as `RangeReplaceableCollection`'s `append()` function shown above. +When the elements are copyable, we can simply copy the elements from the source. Afterwards, there are two possible dispositions of the source: releasing a borrowed source, or `consuming`. The latter is approximately the same behaviour as `RangeReplaceableCollection`'s `append(contentsOf:)` function shown above. + +In an ideal world, we would like to use the same name for all of these variants: -In a more ideal world, we would like to use the same name for all of these variants: ```swift extension OutputSpan { mutating func append(contentsOf: consuming some Sequence) @@ -968,9 +778,9 @@ extension OutputSpan where Element: ~Copyable { However, this would break down in particular for `UnsafeMutableBufferPointer`, since it would make it impossible to differentiate between just copying the elements out of it, or moving its elements out (and deinitializing its memory). Once the `Container` protocols exist, we can expect that the same issue would exist for any type that conforms to more than one of the protocols involved in the list above. For example if a type conforms to `Container` as well as `Sequence`, then there would be an ambiguity. -We could fix this by extending the syntax of the language. It is already possible to overload two functions where they differ only by whether a parameter is `inout`, for example. This is a future direction. +We could fix this by extending the syntax of the language. It is already possible to overload two functions where they differ only by whether a parameter is `inout`, for example. This is a more advanced [future direction](#contentsOf-syntax). -Instead of the "ideal" solution above, this proposal includes `append()` functions in the following form: +Instead of the "ideal" solution, we could propose `append()` functions in the following form: ```swift extension OutputSpan { @@ -983,31 +793,15 @@ extension OutputSpan where Element: ~Copyable { } ``` -The `update()` methods of `MutableSpan` are updated in a similar manner, for the same reasons. +In this form, we continue to use the `contentsOf` label for `Sequence` parameters, but use different labels for the other types of containers. The `update()` methods of `MutableSpan` could be updated in a similar manner, for the same reasons. -We note that the four variants of `append()` are required for generalized containers. We can therefore expect that the names we choose will later appear on many types of collections that interact with the future `Container` protocols. This proposal's `append()` nomenclature could become ubiquitous when interacting with `Collection` instances, once it is applied to the `Container` protocol family. +We note that the four variants of `append()` are required for generalized containers. We can therefore expect that the names we choose will appear later on many types of collections that interact with the future `Container` protocols. Since this nomenclature could become ubiquitous when interacting with `Collection` and `Container` instances, we defer a formal proposal until we have more experience and feedback. -## Future directions - -#### Helpers to initialize memory in an arbitrary order - -Some applications may benefit from the ability to initialize a range of memory in a different order than implemented by `OutputSpan`. This may be from back-to-front or even arbitrary order. There are many possible forms such an initialization helper can take, depending on how much memory safety the application is willing to give up in the process of initializing the memory. At the unsafe end, this can be delegating to an `UnsafeMutableBufferPointer` along with a set of requirements; this option is proposed here. At the safe end, this could be delegating to a data structure which keeps track of initialized memory using a bitmap. It is unclear how much need there is for this more heavy-handed approach, so we leave it as a future enhancement if it is deemed useful. - -#### Insertions - -A use case similar to appending is insertions. Appending is simply inserting at the end. Inserting at positions other than the end is an important capability. We expect to add insertions soon if `OutputSpan` is accepted. Until then, a workaround is to append, then rotate the elements to the desired position using the `mutableSpan` view. The current proposal does not add a concept of indexing to `OutputSpan`, though that is required in order to support insertions at an arbitrary position. We defer this discussion in order to focus on the basic functionality of the type. - -#### Generalized removals - -Similarly to generalized insertions (i.e. not from the end), we can think about removals of one or more elements starting at a given position. This also requires adding indexing. We expect to add generalized removals along with insertions if `OutputSpan` is accepted. - -#### Variations on `Array.append(addingCapacity:initializingWith:)` - -The function proposed here only exposes uninitialized capacity in the `OutputSpan` parameter to its closure. A different function (perhaps named `edit()`) could also pass the initialized portion of the container, allowing an algorithm to remove or to add elements. This could be considered in addition to `append()`. +In the meantime, many applications will work efficiently with repeated calls to `append()` in a loop. The bulk initialization functions are implementable by using `withUnsafeBufferPointer` as a workaround as well, if performance is an issue before a package-based solution is released. #### Language syntax to distinguish between ownership modes for function arguments -In the "Alternatives Considered" subsection about [naming the `append()` methods](#contentsOf), we suggest a currently unachievable naming scheme: +In the the previous "Future Direction" subsection about [bulk initialization methods](#contentsOf), we suggest a currently unachievable naming scheme: ```swift extension OutputSpan { mutating func append(contentsOf: consuming some Sequence) From dcd4e971b1819814352ce319dca18fa0c6d73016 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Tue, 10 Jun 2025 09:28:24 -0400 Subject: [PATCH 371/505] Accept SE-0475 (#2881) --- proposals/0475-observed.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index 368c21ef23..70095e746c 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -3,9 +3,9 @@ * Proposal: [SE-0475](0475-observed.md) * Authors: [Philippe Hausler](https://github.com/phausler) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Active Review (April 10 ... May 13, 2025)** +* Status: **Accepted** * Implementation: https://github.com/swiftlang/swift/pull/79817 -* Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) +* Review: ([pitch](https://forums.swift.org/t/pitch-transactional-observation-of-values/78315)) ([review](https://forums.swift.org/t/se-0475-transactional-observation-of-values/79224)) ([acceptance](https://forums.swift.org/t/accepted-se-0475-transactional-observation-of-values/80389)) ## Introduction From 79a1a8efa26f52612f18dbdedf776fc8d121afa3 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 10 Jun 2025 07:38:21 -0700 Subject: [PATCH 372/505] [SE-0485] add constructor pattern to alternatives considered --- proposals/0485-outputspan.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index d6416839d5..3466a57b89 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -735,6 +735,23 @@ The additions described in this proposal require a new version of the Swift stan `OutputSpan` changes the number of initialized elements in a container (or collection), and this requires some operation to update the container after the `OutputSpan` is consumed. Let's call that update operation a "cleanup" operation. The cleanup operation needs to be scheduled in some way. We could associate the cleanup with the `deinit` of `OutputSpan`, or the `deinit` of a wrapper of `OutputSpan`. Neither of these seem appealing; the mechanisms would involve an arbitrary closure executed at `deinit` time, or having to write a full wrapper for each type that vends an `OutputSpan`. We could potentially schedule the cleanup operation as part of a coroutine accessor, but these are not productized yet. The pattern established by closure-taking API is well established, and that pattern fits the needs of `OutputSpan` well. +#### Container construction pattern + +A constrained version of possible `OutputSpan` use consists of in-place container initialization. This proposal introduces a few initializers in this vein, such as `Array.init(capacity:initializingWith:)`, which rely on closure to establish a scope. A different approach would be to use intermediate types to perform such operations: + +```swift +struct ArrayConstructor: ~Copyable { + @_lifetime(&self) mutating var outputSpan: OutputSpan + private let _ArrayBuffer + + init(capacity: Int) +} + +extension Array { + init(_: consuming ArrayConstructor) +} +``` + ## Future directions #### Helpers to initialize memory in an arbitrary order @@ -835,7 +852,6 @@ let array = Array(capacity: buffer.count*2) { } ``` - ## Acknowledgements Thanks to Karoy Lorentey, Nate Cook and Tony Parker for their feedback. From c793e7cab939f99526c19a520cd11015c7dd4e60 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Tue, 10 Jun 2025 09:48:00 -0700 Subject: [PATCH 373/505] [SE-0485] notes about `MutableSpan` --- proposals/0485-outputspan.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 3466a57b89..d3c039734c 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -716,6 +716,10 @@ extension Data { } ``` +#### Changes to `MutableSpan` and `MutableRawSpan` + +This proposal considers the naming of `OutputSpan`'s bulk-initialization methods, and elects to defer their implementation until we have more experience with the various kinds of container we need to support. We also introduced bulk updating functions to `MutableSpan` and `MutableRawSpan` in [SE-0467][SE-0467]. It is clear that they have the same kinds of parameters as `OutputSpan`'s bulk-initialization methods, but the discussion has taken a [different direction](#contentsOf) in the latter case. We would like both of these sets of operations to match. Accordingly, we will remove the bulk `update()` functions proposedin [SE-0467][SE-0467], to be replaced with a better naming scheme later. Prototype bulk-update functionality will also be added via a package in the meantime. + ## Source compatibility This proposal is additive and source-compatible with existing code. From 4d70fc3ecc5f728f39f3ad5a153a2c049ba64186 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 12 Jun 2025 12:00:25 -0700 Subject: [PATCH 374/505] Add another alternative approach --- proposals/testing/XXXX-issue-severity-warning.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index dee36e088a..bc28ccd0eb 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -123,6 +123,7 @@ This revision aims to clarify the functionality and usage of the `Severity` enum - Naming of `isFailure` vs. `isFailing`: We evaluated whether to name the property `isFailing` instead of `isFailure`. The decision to use `isFailure` was made to adhere to naming conventions and ensure clarity and consistency within the API. - Severity-Only Checking: We deliberated not exposing `isFailure` and relying solely on `severity` checks. However, this was rejected because it would require test authors to overhaul their code should we introduce additional severity levels in the future. By providing `isFailure`, we offer a straightforward way to determine test outcome impact, complementing the severity feature. +- Naming `Severity.error` `Severity.failure` instead because this will always be a failing issue and test authors often think of test failures. Error and warning match build naming conventions so that is why we continued with this. ## Future directions From 98825de212306fd9d7bdf76c90d192339360b1c9 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 12 Jun 2025 12:07:31 -0700 Subject: [PATCH 375/505] Update Alternatives considered --- proposals/testing/XXXX-issue-severity-warning.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index bc28ccd0eb..5fcac65dc6 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -116,8 +116,6 @@ This revision aims to clarify the functionality and usage of the `Severity` enum ## Alternatives considered -- Doing Nothing: Although there have been recurring requests over the years to support non-failing issues, we did not have a comprehensive solution until now. This year, we finally had the necessary components to implement this feature effectively. - - Separate Issue Creation and Recording: We considered providing a mechanism to create issues independently before recording them, rather than passing the issue details directly to the `record` method. This approach was ultimately set aside in favor of simplicity and directness in usage. - Naming of `isFailure` vs. `isFailing`: We evaluated whether to name the property `isFailing` instead of `isFailure`. The decision to use `isFailure` was made to adhere to naming conventions and ensure clarity and consistency within the API. From baba8c7eb0c136bf112307aa29898cba8a5ad255 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 12 Jun 2025 12:09:38 -0700 Subject: [PATCH 376/505] Update format --- proposals/testing/XXXX-issue-severity-warning.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 5fcac65dc6..c190c65539 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -38,7 +38,7 @@ Test authors will be able to inspect if the issue is a failing issue and will be ## Detailed design -*Severity Enum* +###Severity Enum We introduce a Severity enum to categorize issues detected during testing. This enum is crucial for distinguishing between different levels of test issues and is defined as follows: @@ -64,14 +64,14 @@ extension Issue { } ``` -*Recording Non-Failing Issues* +###Recording Non-Failing Issues To enable test authors to log non-failing issues without affecting test results, we provide a method for recording such issues: ```swift Issue.record("My comment", severity: .warning) ``` -*Issue Type Enhancements* +###Issue Type Enhancements The Issue type is enhanced with two new properties to better handle and report issues: - `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. From c50f733d4dd703fcca78d3d150ba1ee13783b551 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 12 Jun 2025 12:12:21 -0700 Subject: [PATCH 377/505] update comment --- proposals/testing/XXXX-issue-severity-warning.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index c190c65539..e9bff1ce2c 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -47,7 +47,8 @@ The `Severity` enum: ```swift extension Issue { // ... - public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { /// The severity level for an issue which should be noted but is not + public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { + /// The severity level for an issue which should be noted but is not /// necessarily an error. /// /// An issue with warning severity does not cause the test it's associated From 7b35eac2aecb8738380a0ae5c62f91290fc6e40e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 12 Jun 2025 21:42:43 +0100 Subject: [PATCH 378/505] Accept SE-485: OutputSpan: delegate initialization of contiguous memory --- proposals/0485-outputspan.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index d3c039734c..8772bdecfb 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -3,10 +3,10 @@ * Proposal: [SE-0485](0485-outputspan.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Active Review (May 20...June 3, 2025)** +* Status: **Accepted** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: [swiftlang/swift#81637](https://github.com/swiftlang/swift/pull/81637) -* Review: [Pitch](https://forums.swift.org/t/pitch-outputspan/79473), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032) +* Review: [Pitch](https://forums.swift.org/t/pitch-outputspan/79473), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032), [Acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0485-outputspan-delegate-initialization-of-contiguous-memory/80435) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md [SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md @@ -822,7 +822,7 @@ In the meantime, many applications will work efficiently with repeated calls to #### Language syntax to distinguish between ownership modes for function arguments -In the the previous "Future Direction" subsection about [bulk initialization methods](#contentsOf), we suggest a currently unachievable naming scheme: +In the previous "Future Direction" subsection about [bulk initialization methods](#contentsOf), we suggest a currently unachievable naming scheme: ```swift extension OutputSpan { mutating func append(contentsOf: consuming some Sequence) From 46f5a206373cc6443bf3fdd10db9987ab7f964e9 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Thu, 12 Jun 2025 15:12:00 -0700 Subject: [PATCH 379/505] Fix spacing and definitions --- .../testing/XXXX-issue-severity-warning.md | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index e9bff1ce2c..510050352e 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -72,6 +72,30 @@ To enable test authors to log non-failing issues without affecting test results, Issue.record("My comment", severity: .warning) ``` +Here is the `Issue.record` method definition with severity as a parameter. +```swift + /// Record an issue when a running test fails unexpectedly. + /// + /// - Parameters: + /// - comment: A comment describing the expectation. + /// - severity: The severity of the issue. + /// - sourceLocation: The source location to which the issue should be + /// attributed. + /// + /// - Returns: The issue that was recorded. + /// + /// Use this function if, while running a test, an issue occurs that cannot be + /// represented as an expectation (using the ``expect(_:_:sourceLocation:)`` + /// or ``require(_:_:sourceLocation:)-5l63q`` macros.) + @discardableResult public static func record( + _ comment: Comment? = nil, + severity: Severity = .error, + sourceLocation: SourceLocation = #_sourceLocation + ) -> Self + + // ... +``` + ###Issue Type Enhancements The Issue type is enhanced with two new properties to better handle and report issues: @@ -80,13 +104,18 @@ The Issue type is enhanced with two new properties to better handle and report i ```swift // ... +extension Issue { + /// The severity of the issue. -public var severity: Severity +public var severity: Severity { get set } + +} ``` - `isFailure`: A boolean property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. ```swift -// ... +extension Issue { + // ... /// Whether or not this issue should cause the test it's associated with to be /// considered a failure. @@ -98,7 +127,8 @@ public var severity: Severity /// /// Use this property to determine if an issue should be considered a failure, instead of /// directly comparing the value of the ``severity`` property. -public var isFailure: Bool + public var isFailure: Bool { get } +} ``` Example usage of `severity` and `isFailure: From e481b32bdd2febc410a173d4e55971a6f0b0db17 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 13 Jun 2025 09:49:15 -0400 Subject: [PATCH 380/505] [ST] Tweak the calling convention of exit test closures. This change removes the use of `@convention(thin)` in exit tests' closures as it is not a stable language feature. (This is a technical adjustment only and does not affect the substance of the proposal as accepted.) --- proposals/testing/0008-exit-tests.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/testing/0008-exit-tests.md b/proposals/testing/0008-exit-tests.md index a543c03981..2a69716107 100644 --- a/proposals/testing/0008-exit-tests.md +++ b/proposals/testing/0008-exit-tests.md @@ -177,7 +177,7 @@ the testing library: observing observedValues: [any PartialKeyPath & Sendable] = [], _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, - performing expression: @convention(thin) () async throws -> Void + performing expression: @escaping @Sendable () async throws -> Void ) -> ExitTest.Result? = #externalMacro(module: "TestingMacros", type: "ExitTestExpectMacro") /// Check that an expression causes the process to terminate in a given fashion @@ -193,7 +193,7 @@ the testing library: observing observedValues: [any PartialKeyPath & Sendable] = [], _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, - performing expression: @convention(thin) () async throws -> Void + performing expression: @escaping @Sendable () async throws -> Void ) -> ExitTest.Result = #externalMacro(module: "TestingMacros", type: "ExitTestRequireMacro") ``` @@ -464,8 +464,8 @@ in: There are some constraints on valid exit tests: 1. Because exit tests are run in child processes, they cannot capture any state - from the calling context (hence their body closures are `@convention(thin)` - or `@convention(c)`.) See the **Future directions** for further discussion. + from the calling context. See the **Future directions** for further + discussion. 1. Exit tests cannot recursively invoke other exit tests; this is a constraint that could potentially be lifted in the future, but it would be technically complex to do so. @@ -840,7 +840,7 @@ protocol also requires some care to ensure that signal constants such as observing observedValues: (repeat (KeyPath)) = (), _ comment: @autoclosure () -> Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation, - performing expression: @escaping @Sendable @convention(thin) () async throws -> Void + performing expression: @escaping @Sendable () async throws -> Void ) -> (repeat each T) ``` From 8957b65eb91a644ace7d44ecf56653f995c4ec4c Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Fri, 13 Jun 2025 09:44:37 -0700 Subject: [PATCH 381/505] Mark SE-0465 as implemented --- proposals/0465-nonescapable-stdlib-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0465-nonescapable-stdlib-primitives.md b/proposals/0465-nonescapable-stdlib-primitives.md index 2f0c6540d8..798025fef9 100644 --- a/proposals/0465-nonescapable-stdlib-primitives.md +++ b/proposals/0465-nonescapable-stdlib-primitives.md @@ -3,7 +3,7 @@ * Proposal: [SE-0465](0465-nonescapable-stdlib-primitives.md) * Authors: [Karoy Lorentey](https://github.com/lorentey) * Review Manager: [Doug Gregor](https://github.com/douggregor) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [Improving Swift performance predictability: ARC improvements and ownership control][Roadmap] * Implementation: https://github.com/swiftlang/swift/pull/73258 * Review: ([Acceptance](https://forums.swift.org/t/accepted-se-0465-standard-library-primitives-for-nonescapable-type/78637)) ([Review](https://forums.swift.org/t/se-0465-standard-library-primitives-for-nonescapable-types/78310)) ([Pitch](https://forums.swift.org/t/pitch-nonescapable-standard-library-primitives/77253)) From 6331dfef5171918fa07676d2f81da853877fdd60 Mon Sep 17 00:00:00 2001 From: Jaeho Yoo Date: Sat, 14 Jun 2025 04:59:14 +0900 Subject: [PATCH 382/505] [SE-0439] Remove redundant generic where example (#2824) * [SE-0439] Restore generic where example * [SE-0439] Remove redundant generic where example --- proposals/0439-trailing-comma-lists.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/proposals/0439-trailing-comma-lists.md b/proposals/0439-trailing-comma-lists.md index 1c4ada76c5..1de9044bbb 100644 --- a/proposals/0439-trailing-comma-lists.md +++ b/proposals/0439-trailing-comma-lists.md @@ -43,7 +43,7 @@ let subsequences = numbers.split( ### The Language Evolved -Back in 2016, a similar [proposal](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0084-trailing-commas.md) with a narrower scope was reviewed and rejected for Swift 3. Since that time, the language has evolved substantially that challenges the basis for rejection. The code style that "puts the terminating right parenthesis on a line following the arguments to that call" has been widely adopted by community, Swift standard library codebase, swift-format, docc documentation and Xcode. Therefore, not encouraging or endorsing this code style doesn't hold true anymore. +Back in 2016, a similar [proposal](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0084-trailing-commas.md) with a narrower scope was reviewed and rejected for Swift 3. Since that time, the language has evolved substantially that challenges the basis for rejection. The code style that "puts the terminating right parenthesis on a line following the arguments to that call" has been widely adopted by community, Swift standard library codebase, swift-format, DocC documentation and Xcode. Therefore, not encouraging or endorsing this code style doesn't hold true anymore. The language has also seen the introduction of [parameter packs](https://github.com/apple/swift-evolution/blob/main/proposals/0393-parameter-packs.md), which enables APIs that are generic over variable numbers of type parameters, and code generation tools like plugins and macros that, with trailing comma support, wouldn't have to worry about a special condition for the last element when generating comma-separated lists. @@ -267,16 +267,7 @@ if This particular case can be handled but, given how complex conditions can be, it's hard to conclude that there's absolutely no corner case where ambiguity can arise in currently valid code. -Inheritance lists and generic `where` clauses can appear in protocol definitons where there's no clear delimiter, making it harder to disambiguate where the list ends. - -```swift -protocol Foo { - associatedtype T: - P1, - P2, ❌ Expected type - ... -} -``` +Inheritance lists and generic `where` clauses can appear in protocol definitions where there's no clear delimiter, making it harder to disambiguate where the list ends. ```swift protocol Foo { From 4d88a383038a288b3f3800a057987aa8181603de Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Mon, 16 Jun 2025 10:08:48 -0700 Subject: [PATCH 383/505] Mark SE-0467 and SE-0456 as implemented (#2882) * [SE-0467] Mark as implemented * [SE-0456] Mark as implemented --- proposals/0456-stdlib-span-properties.md | 4 ++-- proposals/0467-MutableSpan.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0456-stdlib-span-properties.md b/proposals/0456-stdlib-span-properties.md index 178da8f82b..bffb608e00 100644 --- a/proposals/0456-stdlib-span-properties.md +++ b/proposals/0456-stdlib-span-properties.md @@ -3,9 +3,9 @@ * Proposal: [SE-0456](0456-stdlib-span-properties.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) -* Implementation: [PR #78561](https://github.com/swiftlang/swift/pull/78561) +* Implementation: [swift PR #78561](https://github.com/swiftlang/swift/pull/78561), [swift PR #80116](https://github.com/swiftlang/swift/pull/80116), [swift-foundation PR#1276](https://github.com/swiftlang/swift-foundation/pull/1276) * Review: ([pitch](https://forums.swift.org/t/76138)) ([review](https://forums.swift.org/t/se-0456-add-span-providing-properties-to-standard-library-types/77233)) ([acceptance](https://forums.swift.org/t/77684)) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md diff --git a/proposals/0467-MutableSpan.md b/proposals/0467-MutableSpan.md index 75bb7f7b1e..846697c393 100644 --- a/proposals/0467-MutableSpan.md +++ b/proposals/0467-MutableSpan.md @@ -3,9 +3,9 @@ * Proposal: [SE-0467](0467-MutableSpan.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Joe Groff](https://github.com/jckarter) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) -* Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future) +* Implementation: [PR #79650](https://github.com/swiftlang/swift/pull/79650), [PR #80517](https://github.com/swiftlang/swift/pull/80517) * Review: ([Pitch](https://forums.swift.org/t/pitch-mutablespan/77790)) ([Review](https://forums.swift.org/t/se-0467-mutablespan/78454)) ([Acceptance](https://forums.swift.org/t/accepted-se-0467-mutablespan/78875)) [SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md From 9265769330635910e8789c7ec111b86a74e32b4f Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Mon, 16 Jun 2025 13:09:19 -0400 Subject: [PATCH 384/505] [SE-0475] Fix typo (#2854) --- proposals/0475-observed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0475-observed.md b/proposals/0475-observed.md index 70095e746c..7690394895 100644 --- a/proposals/0475-observed.md +++ b/proposals/0475-observed.md @@ -103,7 +103,7 @@ that pet's name. ## Detailed design -There a few behaviors that are prerequisites to understanding the requirements +There are a few behaviors that are prerequisites to understanding the requirements of the actual design. These two key behaviors are how the model handles tearing and how the model handles sharing. From 54d4b8d8ff9e7fa9984a323875cca456cd11b1ae Mon Sep 17 00:00:00 2001 From: Jamie <2119834+jamieQ@users.noreply.github.com> Date: Mon, 16 Jun 2025 12:10:34 -0500 Subject: [PATCH 385/505] [gardening]: minor copy edit in footnote of 0474-yielding-accessors.md (#2841) remove a superfluous word --- proposals/0474-yielding-accessors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index ddc572f4a8..6ede23b7cf 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -220,7 +220,7 @@ To fulfill such a requirement, the conformance must provide a getter, meaning it In practical terms, this means that the requirement cannot be witnessed by a stored property or a `yielding borrow` accessor when the result is of noncopyable type,[^2] since the storage of a stored property is owned by the containing aggregate and the result of a `yielding borrow` is owned by the suspended coroutine, and it would be necessary to copy to provide ownership to the caller. However, if the type of the `get` requirement is copyable, the compiler can synthesize the getter from the other accessor kinds by introducing copies as necessary. -[^2]: While the compiler does currently accept such code currently, it does so by interpreting that `get` as a `yielding borrow`, which is a bug. +[^2]: While the compiler does currently accept such code, it does so by interpreting that `get` as a `yielding borrow`, which is a bug. ### `yielding mutate` From 6bfef2b2e1228a560b0a02adcc89f999b049aa86 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 17 Jun 2025 02:11:08 +0900 Subject: [PATCH 386/505] Update 0468-async-stream-continuation-hashable-conformance.md (#2806) Was done in: https://github.com/swiftlang/swift/pull/79457 We missed the 6.2 cherry pick, I'll do that --- .../0468-async-stream-continuation-hashable-conformance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0468-async-stream-continuation-hashable-conformance.md b/proposals/0468-async-stream-continuation-hashable-conformance.md index e276c80235..5412d1734e 100644 --- a/proposals/0468-async-stream-continuation-hashable-conformance.md +++ b/proposals/0468-async-stream-continuation-hashable-conformance.md @@ -3,7 +3,7 @@ * Proposal: [SE-0468](0468-async-stream-continuation-hashable-conformance.md) * Authors: [Mykola Pokhylets](https://github.com/nickolas-pohilets) * Review Manager: [Freddy Kellison-Linn](https://github.com/Jumhyn) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#79457](https://github.com/swiftlang/swift/pull/79457) * Review: ([pitch](https://forums.swift.org/t/pitch-add-hashable-conformance-to-asyncstream-continuation/77897)) ([review](https://forums.swift.org/t/se-0468-hashable-conformance-for-async-throwing-stream-continuation/78487)) ([acceptance](https://forums.swift.org/t/accepted-se-0468-hashable-conformance-for-async-throwing-stream-continuation/79116)) From d89189e7b438d90fd121ead562530d13962f8a37 Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Mon, 16 Jun 2025 17:12:05 +0000 Subject: [PATCH 387/505] [SE-0471] Make diagram readable in dark mode (#2866) This change replaces the diagram embedded in "SE-0471: Improved Custom SerialExecutor isolation checking for Concurrency Runtime" with a version that is readable in dark mode. I did this by exporting the diagram from OmniGraffle with a solid white background. The previous version had a transparent background, which made the black arrows between the boxes invisible in dark mode. --- proposals/0471-is-isolated-flow.png | Bin 84869 -> 75134 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/proposals/0471-is-isolated-flow.png b/proposals/0471-is-isolated-flow.png index bdf5bb0ba8fcef956c2260bd085be3e9517bb7c2..6a9e939edf1a6de12e379be2b227a380d70dc14e 100644 GIT binary patch literal 75134 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 From 7b4215ebc83a2f5c591edc51690365e350c3901b Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Mon, 16 Jun 2025 13:17:02 -0400 Subject: [PATCH 388/505] [TWG] Exit test value capturing proposal Add the initial draft of ST-NNNN Capturing values in exit tests. --- .../testing/NNNN-exit-test-value-capturing.md | 264 ++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 proposals/testing/NNNN-exit-test-value-capturing.md diff --git a/proposals/testing/NNNN-exit-test-value-capturing.md b/proposals/testing/NNNN-exit-test-value-capturing.md new file mode 100644 index 0000000000..fc6af79558 --- /dev/null +++ b/proposals/testing/NNNN-exit-test-value-capturing.md @@ -0,0 +1,264 @@ +# Capturing values in exit tests + +* Proposal: [ST-NNNN](NNNN-filename.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Review Manager: TBD +* Status: **Awaiting review** +* Bug: [swiftlang/swift-testing#1157](https://github.com/swiftlang/swift-testing/issues/1157) +* Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040) _et al._ +* Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) + +## Introduction + +In Swift 6.2, we introduced the concept of an _exit test_: a section of code in +a test function that would run in an independent process and allow test authors +to test code that terminates the process. For example: + +```swift +enum Fruit: Sendable, Codable, Equatable { + case apple, orange, olive, tomato + var isSweet: Bool { get } + + consuming func feed(to bat: FruitBat) { + precondition(self.isSweet, "Fruit bats don't like savory fruits!") + ... + } +} + +@Test func `Fruit bats don't eat savory fruits`() async { + await #expect(processExitsWith: .failure) { + let fruit = Fruit.olive + let bat = FruitBat(named: "Chauncey") + fruit.feed(to: bat) // should trigger a precondition failure and process termination + } +} +``` + +This proposal extends exit tests to support capturing state from the enclosing +context (subject to several practical constraints.) + +## Motivation + +Exit tests in their current form are useful, but there is no reliable way to +pass non-constant information from the parent process to the child process, +which makes them difficult to use with parameterized tests. Consider: + +```swift +@Test(arguments: [Fruit.olive, .tomato]) +func `Fruit bats don't eat savory fruits`(_ fruit: Fruit) async { + await #expect(processExitsWith: .failure) { + let bat = FruitBat(named: "Chauncey") + fruit.feed(to: bat) // 🛑 can't capture 'fruit' from enclosing scope + } +} +``` + +In the above example, the test function's argument cannot be passed into the +exit test. In a trivial example like this one, it wouldn't be difficult to write +two tests that differ only in the case of `Fruit` they use in their exit test +bodies, but this approach doesn't scale very far and is generally an +anti-pattern when using Swift Testing. + +## Proposed solution + +We propose allowing the capture of values in an exit test when they are +specified in a closure capture list on the exit test's body. + +## Detailed design + +The signatures of the exit test macros `expect(processExitsWith:)` and +`require(processExitsWith:)` are unchanged. A test author may now add a closure +capture list to the body of an exit test: + +```swift +@Test(arguments: [Fruit.olive, .tomato]) +func `Fruit bats don't eat savory fruits`(_ fruit: Fruit) async { + await #expect(processExitsWith: .failure) { [fruit] in + let bat = FruitBat(named: "Chauncey") + fruit.feed(to: bat) + } +} +``` + +This feature has some necessary basic constraints: + +### Captured values must be explicitly listed in a closure capture list + +Swift Testing needs to know what values need to be encoded, sent to the child +process, and decoded. Swift macros including `#expect(processExitsWith:)` must +rely solely on syntax—that is, the code typed by a test author. An implicit +capture within an exit test body is indistinguishable from any other identifier +or symbol name. + +Hence, only values listed in the closure's capture list will be captured. +Implicitly captured values will produce a compile-time diagnostic as they do +today. + +### Captured values must conform to Sendable and Codable + +Captured values will be sent across process boundaries and, in order to support +that operation, must conform to `Codable`. As well, captured values need to make +their way through the various internal mechanisms of Swift Testing and its host +infrastructure, and so must conform to `Sendable`. Conformance to `Copyable` and +`Escapable` is implied. + +If a value that does _not_ conform to the above protocols is specified in an +exit test body's capture list, a diagnostic is emitted: + +```swift +let bat: FruitBat = ... +await #expect(processExitsWith: .failure) { [bat] in + // 🛑 Type of captured value 'bat' must conform to 'Sendable' and 'Codable' + ... +} +``` + +### Captured values' types must be visible to the exit test macro + +In order for us to successfully _decode_ captured values in the child process, +we must know their Swift types. Type information is not readily available during +macro expansion and we must, in general, rely on the parsed syntax tree for it. + +The type of `self` and the types of arguments to the calling function are, +generally, known and can be inferred from context[^shadows]. The types of other +values, including local variables and global state, are not visible in the +syntax tree and must be specified explicitly in the capture list using an `as` +expression: + +```swift +await #expect(processExitsWith: .failure) { [fruit = fruit as Fruit] in + ... +} +``` + +Finally, the types of captured literals (e.g. `[x = 123]`) are known at compile +time and can always be inferred as `IntegerLiteralType` etc., although we don't +anticipate this will be particularly useful in practice. + +If the type of a captured value cannot be resolved from context, the test author +will see an error at compile time: + +```swift +await #expect(processExitsWith: .failure) { [fruit] in + // 🛑 Type of captured value 'fruit' is ambiguous + // Fix-It: Add '= fruit as T' + ... +} +``` + +See the **Future directions** section of this proposal for more information on +how we hope to lift this constraint. If we are able to lift this constraint in +the future, we expect it will not require (no pun intended) a second Swift +Evolution proposal. + +[^shadows]: If a local variable is declared that shadows `self` or a function + argument, we may incorrectly infer the type of that value when captured. When + this occurs, Swift Testing emits a diagnostic of the form "🛑 Type of captured + value 'foo' is ambiguous". + +## Source compatibility + +This change is additive and relies on syntax that would previously be rejected +at compile time. + +## Integration with supporting tools + +Xcode, Swift Package Manager, and the Swift VS Code plugin _already_ support +captured values in exit tests as they use Swift Testing's built-in exit test +handling logic. + +Tools that implement their own exit test handling logic will need to account for +captured values. The `ExitTest` type now has a new SPI property: + +```swift +extension ExitTest { + /// The set of values captured in the parent process before the exit test is + /// called. + /// + /// This property is automatically set by the testing library when using the + /// built-in exit test handler and entry point functions. Do not modify the + /// value of this property unless you are implementing a custom exit test + /// handler or entry point function. + /// + /// The order of values in this array must be the same between the parent and + /// child processes. + @_spi(ForToolsIntegrationOnly) + public var capturedValues: [CapturedValue] { get set } +} +``` + +In the parent process (that is, for an instance of `ExitTest` passed to +`Configuration.exitTestHandler`), this property represents the values captured +at runtime by the exit test. In the child process (that is, for an instance of +`ExitTest` returned from `ExitTest.find(identifiedBy:)`), the elements in this +array do not have values associated with them until the hosting tool provides +them. + +## Future directions + +- Supporting captured values without requiring type information + + We need the types of captured values in order to successfully decode them, but + we are constrained by macros being syntax-only. In the future, the compiler + may gain a language feature similar to `decltype()` in C++ or `typeof()` in + C23, in which case we should be able to use it and avoid the need for explicit + types in the capture list. ([rdar://153389205](rdar://153389205)) + +- Supporting capturing values that do not conform to `Codable` + + Alternatives to `Codable` exist or have been proposed, such as + [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding) + or [`JSONCodable`](https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585). + In the future, we may want to extend support for values that conform to these + protocols instead of `Codable`. + +## Alternatives considered + +- Doing nothing. There is sufficient motivation to support capturing values in + exit tests and it is within our technical capabilities. + +- Passing captured values as arguments to `#expect(processExitsWith:)` and its + body closure. For example: + + ```swift + await #expect( + processExitsWith: .failure, + arguments: [fruit, bat] + ) { fruit, bat in + ... + } + ``` + + This is technically feasible, but: + + - It requires that the caller state the capture list twice; + - Type information still isn't available for captured values, so you'd still + need to _actually_ write `{ (fruit: Fruit, bat: Bat) in ... }` (or otherwise + specify the types somewhere in the macro invocation); and + - The language already has a dedicated syntax for specifying lists of values + that should be captured in a closure. + +- Supporting non-`Sendable` or non-`Codable` captured values. Since exit tests' + bodies are, by definition, in separate isolation domains from the caller, and + since they, by nature, run in separate processes, conformance to these + protocols is fundamentally necessary. + +- Implicitly capturing `self`. This would require us to statically detect during + macro expansion whether `self` conformed to the necessary protocols _and_ + would preclude capturing any state from static or free test functions. + +- Forking the exit test process such that all captured values are implicitly + copied by the kernel into the new process. Forking, in the UNIX fashion, is + fundamentally incompatible with the Swift runtime and the Swift thread pool. + On Darwin, you [cannot fork a process that links to Core Foundation without + immediately calling `exec()`](https://duckduckgo.com/?q=__THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__), + and `fork()` isn't even present on Windows. + +## Acknowledgments + +Thanks to @rintaro for assistance investigating swift-syntax diagnostic support +and to @xedin for humouring my questions about `decltype()`. + +Thanks to the Swift Testing team and the Testing Workgroup as always. And thanks +to those individuals, who shall remain unnamed, who nerd-sniped me into building +this feature. From b9981317f60d0f9e396eddadfba09089e7a61f8f Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Tue, 17 Jun 2025 16:25:29 -0700 Subject: [PATCH 389/505] Update 0486-adoption-tooling-for-swift-features.md --- proposals/0486-adoption-tooling-for-swift-features.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0486-adoption-tooling-for-swift-features.md b/proposals/0486-adoption-tooling-for-swift-features.md index a2def8fc49..81f3424f5e 100644 --- a/proposals/0486-adoption-tooling-for-swift-features.md +++ b/proposals/0486-adoption-tooling-for-swift-features.md @@ -3,7 +3,7 @@ * Proposal: [SE-0486](0486-adoption-tooling-for-swift-features.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis), [Pavel Yaskevich](https://github.com/xedin) * Review Manager: [Franz Busch](https://github.com/FranzBusch) -* Status: **Active Review (May 26...June 8, 2025)** +* Status: **Implemented (Swift 6.2)** * Implementation: https://github.com/swiftlang/swift-package-manager/pull/8613 * Review: [Pitch](https://forums.swift.org/t/pitch-adoption-tooling-for-upcoming-features/77936), [Review](https://forums.swift.org/t/se-0486-migration-tooling-for-swift-features/80121) @@ -172,7 +172,7 @@ The command would accept one or more features that have migration mode enabled a USAGE: swift package migrate [] --to-feature ... OPTIONS: - --targets The targets to migrate to specified set of features or a new language mode. + --target The targets to migrate to specified set of features or a new language mode. --to-feature The Swift language upcoming/experimental feature to migrate to. -h, --help Show help information. @@ -181,7 +181,7 @@ OPTIONS: #### Use case ``` -swift package migrate --targets MyTarget,MyTest --to-feature ExistentialAny +swift package migrate --target MyTarget,MyTest --to-feature ExistentialAny ``` This command would attempt to build `MyTarget` and `MyTest` targets with `ExistentialAny:migrate` feature flag, apply any fix-its associated with From 3abda053af70db36b8b1fb78e27a95cf0d8040cd Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 23 Jun 2025 18:32:36 -0700 Subject: [PATCH 390/505] [Memory safety vision] Fix typos --- visions/memory-safety.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/visions/memory-safety.md b/visions/memory-safety.md index 612695d7fe..69a206bc79 100644 --- a/visions/memory-safety.md +++ b/visions/memory-safety.md @@ -15,7 +15,7 @@ While there are a number of potential definitions for memory safety, the one pro * **Lifetime safety** : all accesses to a value are guaranteed to occur during its lifetime. Violations of this property, such as accessing a value after its lifetime has ended, are often called use-after-free errors. * **Bounds safety**: all accesses to memory are within the intended bounds of the memory allocation, such as accessing elements in an array. Violations of this property are called out-of-bounds accesses. * **Type safety** : all accesses to a value use the type to which it was initialized, or a type that is compatible with that type. For example, one cannot access a `String` value as if it were an `Array`. Violations of this property are called type confusions. -* **Initialization safety** : all values are initialized property to being used, so they cannot contain unexpected data. Violations of this property often lead to information disclosures (where data that should be invisible becomes available) or even other memory-safety issues like use-after-frees or type confusions. +* **Initialization safety** : all values are initialized prior to being used, so they cannot contain unexpected data. Violations of this property often lead to information disclosures (where data that should be invisible becomes available) or even other memory-safety issues like use-after-frees or type confusions. * **Thread safety:** all values are accessed concurrently in a manner that is synchronized sufficiently to maintain their invariants. Violations of this property are typically called data races, and can lead to any of the other memory safety problems. Since its inception, Swift has provided memory safety for the first four dimensions. Lifetime safety is provided for reference types by automatic reference counting and for value types via [memory exclusivity](https://www.swift.org/blog/swift-5-exclusivity/); bounds safety is provided by bounds-checking on `Array` and other collections; type safety is provided by safe features for casting (`as?` , `is` ) and `enum` s; and initialization safety is provided by “definite initialization”, which doesn’t allow a variable to be accessed until it has been defined. Swift 6’s strict concurrency checking extends Swift’s memory safety guarantees to the last dimension. @@ -134,10 +134,10 @@ One of the primary places where this doesn’t hold is with low-level access to [Non-escapable types](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md) provide the ability to create types whose instances cannot escape out of the context in which they were created with no runtime overhead. Non-escapable types allow the creation of a [memory-safe counterpart to the unsafe buffer types](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md), `Span` . With `Span` , it becomes possible to access contiguous memory in an array in a manner that maintains memory safety. For example: ```swift -let span = myInts.storage +let span = myInts.span globalSpan = span // error: span value cannot escape the scope of myInts -print(span[myArray.count]) // runtime error: out-of-bounds access +print(span[myInts.count]) // runtime error: out-of-bounds access print(span.first ?? 0) ``` From e1849d9cb0812e55451d3970197d4f880ff92623 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Tue, 24 Jun 2025 13:54:00 -0500 Subject: [PATCH 391/505] Set Paul as the review manager per our discussion --- proposals/testing/NNNN-issue-handling-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/NNNN-issue-handling-traits.md index c6967d3b72..27b2356d8d 100644 --- a/proposals/testing/NNNN-issue-handling-traits.md +++ b/proposals/testing/NNNN-issue-handling-traits.md @@ -2,7 +2,7 @@ * Proposal: [ST-NNNN](NNNN-issue-handling-trait.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) -* Review Manager: TBD +* Review Manager: [Paul LeMarquand](https://github.com/plemarquand) * Status: **Awaiting review** * Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), From 674cf6d292eb5917f91121cd7992a01412eb2305 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 24 Jun 2025 15:05:14 -0400 Subject: [PATCH 392/505] Rename to ST-0011 and add review dates --- ...NNN-issue-handling-traits.md => 0011-issue-handling-traits.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposals/testing/{NNNN-issue-handling-traits.md => 0011-issue-handling-traits.md} (100%) diff --git a/proposals/testing/NNNN-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md similarity index 100% rename from proposals/testing/NNNN-issue-handling-traits.md rename to proposals/testing/0011-issue-handling-traits.md From d9789c01f02e2bc81b4ca5e51d7962f8f5e0613f Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 24 Jun 2025 15:07:20 -0400 Subject: [PATCH 393/505] Update dates --- proposals/testing/0011-issue-handling-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index 27b2356d8d..5b18aeda58 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -3,7 +3,7 @@ * Proposal: [ST-NNNN](NNNN-issue-handling-trait.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) -* Status: **Awaiting review** +* Status: **Active Review (Jun 25 - July 8, 2025)** * Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136) From 6bdedfe3302f02b076c711f89db07afff09dd92e Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 24 Jun 2025 15:09:13 -0400 Subject: [PATCH 394/505] Update proposal name --- proposals/testing/0011-issue-handling-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index 5b18aeda58..4c2772415d 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -1,6 +1,6 @@ # Issue Handling Traits -* Proposal: [ST-NNNN](NNNN-issue-handling-trait.md) +* Proposal: [ST-0011](0011-issue-handling-trait.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) * Status: **Active Review (Jun 25 - July 8, 2025)** From 74e2de5f7222c5fe6828d12be0498c10f3feaac1 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 24 Jun 2025 15:12:15 -0400 Subject: [PATCH 395/505] Fixup proposal link --- proposals/testing/0011-issue-handling-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index 4c2772415d..3b4fbbaddf 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -1,6 +1,6 @@ # Issue Handling Traits -* Proposal: [ST-0011](0011-issue-handling-trait.md) +* Proposal: [ST-0011](0011-issue-handling-traits.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) * Status: **Active Review (Jun 25 - July 8, 2025)** From ee3d67091f543e798b9304de288f763ef8385be4 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 24 Jun 2025 15:25:26 -0400 Subject: [PATCH 396/505] ST-0011 - Add link to review forum post --- proposals/testing/0011-issue-handling-traits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index 3b4fbbaddf..d27f2e9a5f 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -3,11 +3,11 @@ * Proposal: [ST-0011](0011-issue-handling-traits.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) -* Status: **Active Review (Jun 25 - July 8, 2025)** +* Status: **Active Review (Jun 24 - July 8, 2025)** * Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136) -* Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) +* Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) ([review](https://forums.swift.org/t/st-0011-issue-handling-traits/80644)) ## Introduction From f80e78e1d902acd15c51d2ec65a03bc839cffa6b Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 30 Jun 2025 16:38:15 +0100 Subject: [PATCH 397/505] Mark `0474-yielding-accessors.md` as Accepted (#2892) Per https://forums.swift.org/t/accepted-se-0474-yielding-accessors/80273 --- proposals/0474-yielding-accessors.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0474-yielding-accessors.md b/proposals/0474-yielding-accessors.md index 6ede23b7cf..a109cee548 100644 --- a/proposals/0474-yielding-accessors.md +++ b/proposals/0474-yielding-accessors.md @@ -3,10 +3,10 @@ * Proposal: [SE-0474](0474-yielding-accessors.md) * Authors: [Ben Cohen](https://github.com/airspeedswift), [Nate Chandler](https://github.com/nate-chandler), [Joe Groff](https://github.com/jckarter/) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Active Review (April 8 ... April 22, 2025)** +* Status: **Accepted** * Vision: [A Prospective Vision for Accessors in Swift](https://github.com/rjmccall/swift-evolution/blob/accessors-vision/visions/accessors.md) * Implementation: Partially available on main behind the frontend flag `-enable-experimental-feature CoroutineAccessors` -* Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), ([review](https://forums.swift.org/t/se-0474-yielding-accessors/79170)) +* Review: ([pitch 1](https://forums.swift.org/t/modify-accessors/31872)), ([pitch 2](https://forums.swift.org/t/pitch-modify-and-read-accessors/75627)), ([pitch 3](https://forums.swift.org/t/pitch-3-yielding-coroutine-accessors/77956)), ([review](https://forums.swift.org/t/se-0474-yielding-accessors/79170)), [Acceptance](https://forums.swift.org/t/accepted-se-0474-yielding-accessors/80273) ## Introduction From ae3640f2d1df1660d4b0d0da6ad1284896991649 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Mon, 30 Jun 2025 12:05:33 -0700 Subject: [PATCH 398/505] Update Integration with supporting tools section --- .../testing/XXXX-issue-severity-warning.md | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 510050352e..a45511430c 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -145,6 +145,26 @@ For more details on `Issue`, refer to the [Issue Documentation](https://develope This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. +### Integration with supporting tools + +Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. + +The JSON event stream ABI will be amended correspondingly: + +``` + ::= { + "isKnown": , ; is this a known issue or not? ++ "severity": , ; the severity of the issue + ["sourceLocation": ,] ; where the issue occurred, if known +} +``` + +Example of an `issueRecorded` event in the json output: + +``` +{"kind":"event","payload":{"instant":{"absolute":302928.100968,"since1970":1751305230.364087},"issue":{"_backtrace":[{"address":4437724864},{"address":4427566652},{"address":4437724280},{"address":4438635916},{"address":4438635660},{"address":4440823880},{"address":4437933556},{"address":4438865080},{"address":4438884348},{"address":11151272236},{"address":4438862360},{"address":4438940324},{"address":4437817340},{"address":4438134208},{"address":4438132164},{"address":4438635048},{"address":4440836660},{"address":4440835536},{"address":4440834989},{"address":4438937653},{"address":4438963225},{"address":4438895773},{"address":4438896161},{"address":4438891517},{"address":4438937117},{"address":4438962637},{"address":4439236617},{"address":4438936181},{"address":4438962165},{"address":4438639149},{"address":4438935045},{"address":4438935513},{"address":11151270653},{"address":11151269797},{"address":4438738225},{"address":4438872065},{"address":4438933417},{"address":4438930265},{"address":4438930849},{"address":4438909741},{"address":4438965489},{"address":11151508333}],"_severity":"error","isKnown":false,"sourceLocation":{"_filePath":"\/Users\/swift-testing\/Tests\/TestingTests\/EntryPointTests.swift","column":23,"fileID":"TestingTests\/EntryPointTests.swift","line":46}},"kind":"issueRecorded","messages":[{"symbol":"fail","text":"Issue recorded"},{"symbol":"details","text":"Unexpected issue Issue recorded (warning) was recorded."}],"testID":"TestingTests.EntryPointTests\/warningIssues()\/EntryPointTests.swift:33:4"},"version":0} +``` + ## Alternatives considered - Separate Issue Creation and Recording: We considered providing a mechanism to create issues independently before recording them, rather than passing the issue details directly to the `record` method. This approach was ultimately set aside in favor of simplicity and directness in usage. @@ -152,7 +172,7 @@ This revision aims to clarify the functionality and usage of the `Severity` enum - Naming of `isFailure` vs. `isFailing`: We evaluated whether to name the property `isFailing` instead of `isFailure`. The decision to use `isFailure` was made to adhere to naming conventions and ensure clarity and consistency within the API. - Severity-Only Checking: We deliberated not exposing `isFailure` and relying solely on `severity` checks. However, this was rejected because it would require test authors to overhaul their code should we introduce additional severity levels in the future. By providing `isFailure`, we offer a straightforward way to determine test outcome impact, complementing the severity feature. -- Naming `Severity.error` `Severity.failure` instead because this will always be a failing issue and test authors often think of test failures. Error and warning match build naming conventions so that is why we continued with this. +- Naming `Severity.error` `Severity.failure` instead because this will always be a failing issue and test authors often think of test failures. Error and warning match build naming conventions and XCTest severity naming convention. ## Future directions From 3adec7d52f83ee08b126b9869457ed3b80634006 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Mon, 30 Jun 2025 13:50:00 -0700 Subject: [PATCH 399/505] Add console output and details to try this out --- .../testing/XXXX-issue-severity-warning.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index a45511430c..f8687a4c5e 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -165,6 +165,31 @@ Example of an `issueRecorded` event in the json output: {"kind":"event","payload":{"instant":{"absolute":302928.100968,"since1970":1751305230.364087},"issue":{"_backtrace":[{"address":4437724864},{"address":4427566652},{"address":4437724280},{"address":4438635916},{"address":4438635660},{"address":4440823880},{"address":4437933556},{"address":4438865080},{"address":4438884348},{"address":11151272236},{"address":4438862360},{"address":4438940324},{"address":4437817340},{"address":4438134208},{"address":4438132164},{"address":4438635048},{"address":4440836660},{"address":4440835536},{"address":4440834989},{"address":4438937653},{"address":4438963225},{"address":4438895773},{"address":4438896161},{"address":4438891517},{"address":4438937117},{"address":4438962637},{"address":4439236617},{"address":4438936181},{"address":4438962165},{"address":4438639149},{"address":4438935045},{"address":4438935513},{"address":11151270653},{"address":11151269797},{"address":4438738225},{"address":4438872065},{"address":4438933417},{"address":4438930265},{"address":4438930849},{"address":4438909741},{"address":4438965489},{"address":11151508333}],"_severity":"error","isKnown":false,"sourceLocation":{"_filePath":"\/Users\/swift-testing\/Tests\/TestingTests\/EntryPointTests.swift","column":23,"fileID":"TestingTests\/EntryPointTests.swift","line":46}},"kind":"issueRecorded","messages":[{"symbol":"fail","text":"Issue recorded"},{"symbol":"details","text":"Unexpected issue Issue recorded (warning) was recorded."}],"testID":"TestingTests.EntryPointTests\/warningIssues()\/EntryPointTests.swift:33:4"},"version":0} ``` +### Console output + +When there is an issue recorded with severity warning the output looks like this: + +```swift + Issue.record("My comment", severity: .warning) +``` + +``` +􀟈 Test "All elements of two ranges are equal" started. +􀄣 Test "All elements of two ranges are equal" recorded a warning at ZipTests.swift:32:17: Issue recorded +􀄵 My comment +􁁛 Test "All elements of two ranges are equal" passed after 0.001 seconds with 1 warning. +``` + +### Trying this out + +To use severity today, checkout the branch here: https://github.com/swiftlang/swift-testing/pull/1189 + +``` +.package(url: "https://github.com/swiftlang/swift-testing.git", branch: "suzannaratcliff:suzannaratcliff/enable-severity"), +``` + +For more details on how to checkout a branch for a package refer to this: https://developer.apple.com/documentation/packagedescription/package/dependency/package(url:branch:) + ## Alternatives considered - Separate Issue Creation and Recording: We considered providing a mechanism to create issues independently before recording them, rather than passing the issue details directly to the `record` method. This approach was ultimately set aside in favor of simplicity and directness in usage. From 53b3b52f40457be1332218c96a4d0c59f9e36a08 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 1 Jul 2025 11:19:24 +0900 Subject: [PATCH 400/505] Mark SE-0472 Task.immediate as implemented This was accepted and is implemented in 6.2 --- proposals/0472-task-start-synchronously-on-caller-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 1f47857b65..0aea24abbf 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -3,7 +3,7 @@ * Proposal: [SE-0472](0472-task-start-synchronously-on-caller-context.md) * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: https://github.com/swiftlang/swift/pull/79608 * Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([first review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ([second review](https://forums.swift.org/t/second-review-se-0472-starting-tasks-synchronously-from-caller-context/79683)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0472-starting-tasks-synchronously-from-caller-context/80037)) From b66be7ed65d237cf3eb7c13a29e5f520dcfe8503 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 1 Jul 2025 11:59:39 +0900 Subject: [PATCH 401/505] Include more implementation PRs --- proposals/0472-task-start-synchronously-on-caller-context.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/proposals/0472-task-start-synchronously-on-caller-context.md b/proposals/0472-task-start-synchronously-on-caller-context.md index 0aea24abbf..1d266bfba4 100644 --- a/proposals/0472-task-start-synchronously-on-caller-context.md +++ b/proposals/0472-task-start-synchronously-on-caller-context.md @@ -4,7 +4,10 @@ * Authors: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Implemented (Swift 6.2)** -* Implementation: https://github.com/swiftlang/swift/pull/79608 +* Implementation: + * https://github.com/swiftlang/swift/pull/79608 + * https://github.com/swiftlang/swift/pull/81428 + * https://github.com/swiftlang/swift/pull/81572 * Review: ([pitch](https://forums.swift.org/t/pitch-concurrency-starting-tasks-synchronously-from-caller-context/77960/)) ([first review](https://forums.swift.org/t/se-0472-starting-tasks-synchronously-from-caller-context/78883)) ([returned for revision](https://forums.swift.org/t/returned-for-revision-se-0472-starting-tasks-synchronously-from-caller-context/79311)) ([second review](https://forums.swift.org/t/second-review-se-0472-starting-tasks-synchronously-from-caller-context/79683)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0472-starting-tasks-synchronously-from-caller-context/80037)) ## Introduction From bc9dbf02bc2c11ad65e86f9fb23c132ab0ba9244 Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Tue, 1 Jul 2025 21:22:52 +0200 Subject: [PATCH 402/505] Rename `@extensible` to `@nonexhaustive` and `@nonexhaustive(warn)` (#2897) --- proposals/0487-extensible-enums.md | 54 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index d218c50789..7401fa8e0a 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -15,6 +15,7 @@ Previously pitched in: - https://forums.swift.org/t/pitch-non-frozen-enumerations/68373 Revisions: +- Renamed the attribute to `@nonexhaustive` and `@nonexhaustive(warn)` respectively - Re-focused this proposal on introducing a new `@extensible` attribute and moved the language feature to a future direction - Introduced a second annotation `@nonExtensible` to allow a migration path into @@ -157,7 +158,7 @@ non-resilient Swift. ## Proposed solution -We propose to introduce a new `@extensible` attribute that can be applied to +We propose to introduce a new `@nonexhaustive` attribute that can be applied to enumerations to mark them as extensible. Such enums will behave the same way as non-frozen enums from resilient Swift libraries. @@ -165,7 +166,7 @@ An example of using the new attribute is below: ```swift /// Module A -@extensible +@nonexhaustive public enum PizzaFlavor { case hawaiian case pepperoni @@ -188,28 +189,27 @@ case .cheese: Code inside the same module or package can be thought of as one co-developed unit of code. Inside the same module or package, switching exhaustively over an -`@extensible` enum inside will not require an`@unknown default`, and using +`@nonexhaustive` enum inside will not require an`@unknown default`, and using one will generate a warning. -### `@extensible` and `@frozen` +### `@nonexhaustive` and `@frozen` -An enum cannot be `@frozen` and `@extensible` at the same time. Thus, marking an -enum both `@extensible` and `@frozen` is not allowed and will result in a +An enum cannot be `@frozen` and `@nonexhaustive` at the same time. Thus, marking an +enum both `@nonexhaustive` and `@frozen` is not allowed and will result in a compiler error. ### API breaking checker The behavior of `swift package diagnose-api-breaking-changes` is also updated -to understand the new `@extensible` attribute. +to understand the new `@nonexhaustive` attribute. -### Staging in using `@preEnumExtensibility` +### Staging in using `@nonexhaustive(warn)` -We also propose adding a new `@preEnumExtensibility` attribute that can be used -to mark enumerations as pre-existing to the `@extensible` attribute. This allows -developers to mark existing public enumerations as `@preEnumExtensibility` in -addition to `@extensible`. This is useful for developers that want to stage in -changing an existing non-extensible enum to be extensible over multiple -releases. Below is an example of how this can be used: +We also propose adding a new `@nonexhaustive(warn)` attribute that can be used +to mark enumerations as pre-existing to when they became extensible.This is +useful for developers that want to stage in changing an existing non-extensible +enum to be extensible over multiple releases. Below is an example of how this +can be used: ```swift // Package A @@ -223,7 +223,7 @@ case .foo: break } // Package A wants to make the existing enum extensible -@preEnumExtensibility @extensible +@nonexhaustive(warn) public enum Foo { case foo } @@ -234,7 +234,7 @@ case .foo: break } // Later Package A decides to extend the enum and releases a new major version -@preEnumExtensibility @extensible +@nonexhaustive(warn) public enum Foo { case foo case bar @@ -246,7 +246,7 @@ case .foo: break } ``` -While the `@preEnumExtensibility` attribute doesn't solve the need of requiring +While the `@nonexhaustive(warn)` attribute doesn't solve the need of requiring a new major when a new case is added it allows developers to stage in changing an existing non-extensible enum to become extensible in a future release by surfacing a warning about this upcoming break early. @@ -255,16 +255,16 @@ surfacing a warning about this upcoming break early. ### Resilient modules -- Adding or removing the `@extensible` attribute has no-effect since it is the default in this language dialect. -- Adding the `@preEnumExtensibility` attribute has no-effect since it only downgrades the error to a warning. -- Removing the `@preEnumExtensibility` attribute is an API breaking since it upgrades the warning to an error again. +- Adding or removing the `@nonexhaustive` attribute has no-effect since it is the default in this language dialect. +- Adding the `@nonexhaustive(warn)` attribute has no-effect since it only downgrades the error to a warning. +- Removing the `@nonexhaustive(warn)` attribute is an API breaking since it upgrades the warning to an error again. ### Non-resilient modules -- Adding the `@extensible` attribute is an API breaking change. -- Removing the `@extensible` attribute is an API stable change. -- Adding the `@preEnumExtensibility` attribute has no-effect since it only downgrades the error to a warning. -- Removing the `@preEnumExtensibility` attribute is an API breaking since it upgrades the warning to an error again. +- Adding the `@nonexhaustive` attribute is an API breaking change. +- Removing the `@nonexhaustive` attribute is an API stable change. +- Adding the `@nonexhaustive(warn)` attribute has no-effect since it only downgrades the error to a warning. +- Removing the `@nonexhaustive(warn)` attribute is an API breaking since it upgrades the warning to an error again. ## ABI compatibility @@ -314,6 +314,6 @@ enumerations to achieve the same effect. ### Different names for the attribute -We considered different names for the attribute such as `@nonFrozen`; however, -we felt that `@extensible` communicates the idea of an extensible enum more -clearly. +We considered different names for the attribute such as `@nonFrozen` or +`@extensible`; however, we felt that `@nonexhaustive` communicates the idea of +an extensible enum more clearly. From 6699354f5c2c862658eb912d3381e06886a61118 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Tue, 1 Jul 2025 12:27:55 -0700 Subject: [PATCH 403/505] Kick off second review of SE-0487 (#2898) --- proposals/0487-extensible-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index 7401fa8e0a..beb87ecaf1 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -3,7 +3,7 @@ * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **In active review (May 25—Jun 5, 2025)** +* Status: **In active review (July 1—Jul 10, 2025)** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` From cf2bfb49c2ab191e8e545feb782a21d3ef472401 Mon Sep 17 00:00:00 2001 From: Mahdi Bahrami Date: Wed, 2 Jul 2025 14:47:57 +0330 Subject: [PATCH 404/505] Fix SE-487 status state --- proposals/0487-extensible-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index ed5ceaada9..f20b9363cc 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -3,7 +3,7 @@ * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **In active review (July 1 — July 10, 2025)** +* Status: **Active Review (July 1 — July 10, 2025)** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` From 47c86c579e8ee8ed98080278360ed02e9f6c6354 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 2 Jul 2025 08:36:50 -0400 Subject: [PATCH 405/505] Assign SE-0488. --- proposals/{nnnn-extracting.md => 0488-extracting.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{nnnn-extracting.md => 0488-extracting.md} (94%) diff --git a/proposals/nnnn-extracting.md b/proposals/0488-extracting.md similarity index 94% rename from proposals/nnnn-extracting.md rename to proposals/0488-extracting.md index e488808f98..0b1bf80595 100644 --- a/proposals/nnnn-extracting.md +++ b/proposals/0488-extracting.md @@ -1,11 +1,11 @@ # Apply the extracting() slicing pattern more widely -* Proposal: [TBD](https://github.com/swiftlang/swift-evolution/pull/2877) +* Proposal: [SE-0488](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0488-extracting.md) * Author: [Guillaume Lessard](https://github.com/glessard) -* Review Manager: TBD -* Status: **Pitch** +* Review Manager: [Tony Allevato](https://github.com/allevato) +* Status: **Active Review (July 2–July 16, 2025)** * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. -* Review: Pending +* Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) [SE-0437]: 0437-noncopyable-stdlib-primitives.md [SE-0447]: 0447-span-access-shared-contiguous-storage.md From 302aa1190ddf93ebde0810125b418f782d29d098 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 2 Jul 2025 08:40:44 -0400 Subject: [PATCH 406/505] Link to SE-0488 review thread. --- proposals/0488-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0488-extracting.md b/proposals/0488-extracting.md index 0b1bf80595..a4f00b6caa 100644 --- a/proposals/0488-extracting.md +++ b/proposals/0488-extracting.md @@ -5,7 +5,7 @@ * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Active Review (July 2–July 16, 2025)** * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. -* Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) +* Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) ([review](https://forums.swift.org/t/se-0488-apply-the-extracting-slicing-pattern-more-widely/80854)) [SE-0437]: 0437-noncopyable-stdlib-primitives.md [SE-0447]: 0447-span-access-shared-contiguous-storage.md From b9c88e9c41dc27e0a5db64f402d9f785cf1fa699 Mon Sep 17 00:00:00 2001 From: Mahdi Bahrami Date: Wed, 2 Jul 2025 17:41:24 +0330 Subject: [PATCH 407/505] [SE-488] Fix Proposal ID link --- proposals/0488-extracting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0488-extracting.md b/proposals/0488-extracting.md index a4f00b6caa..4bf57d7ec9 100644 --- a/proposals/0488-extracting.md +++ b/proposals/0488-extracting.md @@ -1,6 +1,6 @@ # Apply the extracting() slicing pattern more widely -* Proposal: [SE-0488](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0488-extracting.md) +* Proposal: [SE-0488](0488-extracting.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Active Review (July 2–July 16, 2025)** From e7f53cd073c4bf60114a987e18493d844912a9a0 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Fri, 4 Jul 2025 09:02:11 -0400 Subject: [PATCH 408/505] Rename to ST-0012 and add review dates --- ...value-capturing.md => 0012-exit-test-value-capturing.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/testing/{NNNN-exit-test-value-capturing.md => 0012-exit-test-value-capturing.md} (98%) diff --git a/proposals/testing/NNNN-exit-test-value-capturing.md b/proposals/testing/0012-exit-test-value-capturing.md similarity index 98% rename from proposals/testing/NNNN-exit-test-value-capturing.md rename to proposals/testing/0012-exit-test-value-capturing.md index fc6af79558..0f0043fd19 100644 --- a/proposals/testing/NNNN-exit-test-value-capturing.md +++ b/proposals/testing/0012-exit-test-value-capturing.md @@ -1,9 +1,9 @@ # Capturing values in exit tests -* Proposal: [ST-NNNN](NNNN-filename.md) +* Proposal: [ST-0012](0012-exit-test-value-capturing.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [Paul LeMarquand](https://github.com/plemarquand) +* Status: **Active Review (Jul 4 - July 18, 2025)** * Bug: [swiftlang/swift-testing#1157](https://github.com/swiftlang/swift-testing/issues/1157) * Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040) _et al._ * Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) From 4f55c8f8bad75083f7086b1fb3ffe05cde69a726 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Fri, 4 Jul 2025 09:12:27 -0400 Subject: [PATCH 409/505] Update dates --- proposals/testing/0012-exit-test-value-capturing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0012-exit-test-value-capturing.md b/proposals/testing/0012-exit-test-value-capturing.md index 0f0043fd19..593b866f90 100644 --- a/proposals/testing/0012-exit-test-value-capturing.md +++ b/proposals/testing/0012-exit-test-value-capturing.md @@ -3,7 +3,7 @@ * Proposal: [ST-0012](0012-exit-test-value-capturing.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) -* Status: **Active Review (Jul 4 - July 18, 2025)** +* Status: **Active Review (Jul 7 - July 21, 2025)** * Bug: [swiftlang/swift-testing#1157](https://github.com/swiftlang/swift-testing/issues/1157) * Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040) _et al._ * Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) From 18c1d98a4d377682ab1482d4c51ee7287e732681 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 4 Jul 2025 09:38:47 -0400 Subject: [PATCH 410/505] Add future direction --- proposals/testing/0012-exit-test-value-capturing.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/proposals/testing/0012-exit-test-value-capturing.md b/proposals/testing/0012-exit-test-value-capturing.md index 593b866f90..6a52b7d723 100644 --- a/proposals/testing/0012-exit-test-value-capturing.md +++ b/proposals/testing/0012-exit-test-value-capturing.md @@ -204,6 +204,18 @@ them. C23, in which case we should be able to use it and avoid the need for explicit types in the capture list. ([rdar://153389205](rdar://153389205)) +- Explicitly marking the body closure as requiring explicit captures + + Currently, if the body closure implicitly captures a value, the diagnostic the + compiler provides is a bit opaque: + + > 🛑 A C function pointer cannot be formed from a closure that captures context + + In the future, it may be possible to annotate the body closure with an + attribute, keyword, or other decoration that tells the compiler we need an + explicit capture list, which would allow it to provide a clearer diagnostic if + a value is implicitly captured. + - Supporting capturing values that do not conform to `Codable` Alternatives to `Codable` exist or have been proposed, such as From cd33d6611cbcbceb29d3a568c31d89cf3c7fb300 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Mon, 7 Jul 2025 11:46:00 -0400 Subject: [PATCH 411/505] Add review link for ST-0012 --- proposals/testing/0012-exit-test-value-capturing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0012-exit-test-value-capturing.md b/proposals/testing/0012-exit-test-value-capturing.md index 6a52b7d723..43c226b4ae 100644 --- a/proposals/testing/0012-exit-test-value-capturing.md +++ b/proposals/testing/0012-exit-test-value-capturing.md @@ -6,7 +6,7 @@ * Status: **Active Review (Jul 7 - July 21, 2025)** * Bug: [swiftlang/swift-testing#1157](https://github.com/swiftlang/swift-testing/issues/1157) * Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040) _et al._ -* Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) +* Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) ([review](https://forums.swift.org/t/st-0012-capturing-values-in-exit-tests/80963)) ## Introduction From 01b4631eab017d14686d807c4674d97e0d8b75f1 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Mon, 7 Jul 2025 14:40:02 -0400 Subject: [PATCH 412/505] Update 0464-utf8span-safe-utf8-processing.md (#2904) Mark UTF8 Span implemented. --- proposals/0464-utf8span-safe-utf8-processing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0464-utf8span-safe-utf8-processing.md b/proposals/0464-utf8span-safe-utf8-processing.md index bfc006ac3e..1f366a6004 100644 --- a/proposals/0464-utf8span-safe-utf8-processing.md +++ b/proposals/0464-utf8span-safe-utf8-processing.md @@ -3,7 +3,7 @@ * Proposal: [SE-0464](0464-utf8span-safe-utf8-processing.md) * Authors: [Michael Ilseman](https://github.com/milseman), [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Accepted** +* Status: **Implemented (6.2)** * Bug: rdar://48132971, rdar://96837923 * Implementation: [swiftlang/swift#78531](https://github.com/swiftlang/swift/pull/78531) * Review: ([first pitch](https://forums.swift.org/t/pitch-utf-8-processing-over-unsafe-contiguous-bytes/69715)) ([second pitch](https://forums.swift.org/t/pitch-safe-utf-8-processing-over-contiguous-bytes/72742)) ([third pitch](https://forums.swift.org/t/pitch-utf8span-safe-utf-8-processing-over-contiguous-bytes/77483)) ([review](https://forums.swift.org/t/se-0464-utf8span-safe-utf-8-processing-over-contiguous-bytes/78307)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0464-safe-utf-8-processing-over-contiguous-bytes/79218)) From e7004a141da364362af217be40ffcf471755bb2d Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Mon, 7 Jul 2025 20:18:10 -0700 Subject: [PATCH 413/505] Fix formatting --- proposals/testing/XXXX-issue-severity-warning.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index f8687a4c5e..3ba06650b4 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -5,7 +5,7 @@ * Review Manager: TBD * Status: **Pitched** * Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -* Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285) +* Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ## Introduction @@ -38,7 +38,7 @@ Test authors will be able to inspect if the issue is a failing issue and will be ## Detailed design -###Severity Enum +### Severity Enum We introduce a Severity enum to categorize issues detected during testing. This enum is crucial for distinguishing between different levels of test issues and is defined as follows: @@ -65,7 +65,7 @@ extension Issue { } ``` -###Recording Non-Failing Issues +### Recording Non-Failing Issues To enable test authors to log non-failing issues without affecting test results, we provide a method for recording such issues: ```swift @@ -96,7 +96,7 @@ Here is the `Issue.record` method definition with severity as a parameter. // ... ``` -###Issue Type Enhancements +### Issue Type Enhancements The Issue type is enhanced with two new properties to better handle and report issues: - `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. @@ -131,7 +131,7 @@ extension Issue { } ``` -Example usage of `severity` and `isFailure: +Example usage of `severity` and `isFailure`: ```swift // ... withKnownIssue { @@ -185,7 +185,7 @@ When there is an issue recorded with severity warning the output looks like this To use severity today, checkout the branch here: https://github.com/swiftlang/swift-testing/pull/1189 ``` -.package(url: "https://github.com/swiftlang/swift-testing.git", branch: "suzannaratcliff:suzannaratcliff/enable-severity"), +.package(url: "https://github.com/suzannaratcliff/swift-testing.git", branch: "suzannaratcliff:suzannaratcliff/enable-severity"), ``` For more details on how to checkout a branch for a package refer to this: https://developer.apple.com/documentation/packagedescription/package/dependency/package(url:branch:) From 6af9507551a69efca72c83f9a3073a7d47af17b9 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Mon, 7 Jul 2025 20:45:03 -0700 Subject: [PATCH 414/505] Add isFailure --- proposals/testing/XXXX-issue-severity-warning.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/XXXX-issue-severity-warning.md index 3ba06650b4..9681c60be3 100644 --- a/proposals/testing/XXXX-issue-severity-warning.md +++ b/proposals/testing/XXXX-issue-severity-warning.md @@ -147,7 +147,7 @@ This revision aims to clarify the functionality and usage of the `Severity` enum ### Integration with supporting tools -Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. +Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. The JSON event stream ABI will be amended correspondingly: @@ -155,6 +155,7 @@ The JSON event stream ABI will be amended correspondingly: ::= { "isKnown": , ; is this a known issue or not? + "severity": , ; the severity of the issue ++ "isFailure": , ; if the issue is a failing issue ["sourceLocation": ,] ; where the issue occurred, if known } ``` @@ -162,7 +163,7 @@ The JSON event stream ABI will be amended correspondingly: Example of an `issueRecorded` event in the json output: ``` -{"kind":"event","payload":{"instant":{"absolute":302928.100968,"since1970":1751305230.364087},"issue":{"_backtrace":[{"address":4437724864},{"address":4427566652},{"address":4437724280},{"address":4438635916},{"address":4438635660},{"address":4440823880},{"address":4437933556},{"address":4438865080},{"address":4438884348},{"address":11151272236},{"address":4438862360},{"address":4438940324},{"address":4437817340},{"address":4438134208},{"address":4438132164},{"address":4438635048},{"address":4440836660},{"address":4440835536},{"address":4440834989},{"address":4438937653},{"address":4438963225},{"address":4438895773},{"address":4438896161},{"address":4438891517},{"address":4438937117},{"address":4438962637},{"address":4439236617},{"address":4438936181},{"address":4438962165},{"address":4438639149},{"address":4438935045},{"address":4438935513},{"address":11151270653},{"address":11151269797},{"address":4438738225},{"address":4438872065},{"address":4438933417},{"address":4438930265},{"address":4438930849},{"address":4438909741},{"address":4438965489},{"address":11151508333}],"_severity":"error","isKnown":false,"sourceLocation":{"_filePath":"\/Users\/swift-testing\/Tests\/TestingTests\/EntryPointTests.swift","column":23,"fileID":"TestingTests\/EntryPointTests.swift","line":46}},"kind":"issueRecorded","messages":[{"symbol":"fail","text":"Issue recorded"},{"symbol":"details","text":"Unexpected issue Issue recorded (warning) was recorded."}],"testID":"TestingTests.EntryPointTests\/warningIssues()\/EntryPointTests.swift:33:4"},"version":0} +{"kind":"event","payload":{"instant":{"absolute":302928.100968,"since1970":1751305230.364087},"issue":{"_backtrace":[{"address":4437724864},{"address":4427566652},{"address":4437724280},{"address":4438635916},{"address":4438635660},{"address":4440823880},{"address":4437933556},{"address":4438865080},{"address":4438884348},{"address":11151272236},{"address":4438862360},{"address":4438940324},{"address":4437817340},{"address":4438134208},{"address":4438132164},{"address":4438635048},{"address":4440836660},{"address":4440835536},{"address":4440834989},{"address":4438937653},{"address":4438963225},{"address":4438895773},{"address":4438896161},{"address":4438891517},{"address":4438937117},{"address":4438962637},{"address":4439236617},{"address":4438936181},{"address":4438962165},{"address":4438639149},{"address":4438935045},{"address":4438935513},{"address":11151270653},{"address":11151269797},{"address":4438738225},{"address":4438872065},{"address":4438933417},{"address":4438930265},{"address":4438930849},{"address":4438909741},{"address":4438965489},{"address":11151508333}],"_severity":"error","isFailure":true, "isKnown":false,"sourceLocation":{"_filePath":"\/Users\/swift-testing\/Tests\/TestingTests\/EntryPointTests.swift","column":23,"fileID":"TestingTests\/EntryPointTests.swift","line":46}},"kind":"issueRecorded","messages":[{"symbol":"fail","text":"Issue recorded"},{"symbol":"details","text":"Unexpected issue Issue recorded (warning) was recorded."}],"testID":"TestingTests.EntryPointTests\/warningIssues()\/EntryPointTests.swift:33:4"},"version":0} ``` ### Console output From 90018998158955a91223440155726646e4cfe1b1 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 8 Jul 2025 21:05:19 +0200 Subject: [PATCH 415/505] Review preparation --- ...X-issue-severity-warning.md => 0013-issue-severity-warning.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposals/testing/{XXXX-issue-severity-warning.md => 0013-issue-severity-warning.md} (100%) diff --git a/proposals/testing/XXXX-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md similarity index 100% rename from proposals/testing/XXXX-issue-severity-warning.md rename to proposals/testing/0013-issue-severity-warning.md From 957cb3afb38e3fdc1aad89a5e51d52fee342d107 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 8 Jul 2025 21:05:51 +0200 Subject: [PATCH 416/505] Review preparation --- .../testing/0013-issue-severity-warning.md | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 9681c60be3..f5670187c7 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -1,11 +1,11 @@ # Test Issue Severity -* Proposal: [ST-XXXX](XXXX-issue-severity-warning.md) -* Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) -* Review Manager: TBD -* Status: **Pitched** -* Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -* Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) +- Proposal: [ST-0013](0013-issue-severity-warning.md) +- Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) +- Review Manager: [Maarten Engels](https://github.com/maartene) +- Status: **Awaiting Review** +- Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) +- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ## Introduction @@ -17,20 +17,21 @@ Currently, when an issue arises during a test, the only possible outcome is to m ### Use Cases -- Warning about a Percentage Discrepancy in Image Comparison: - - Scenario: When comparing two images to assess their similarity, a warning can be triggered if there's a 95% pixel match, while a test failure is set at a 90% similarity threshold. - - Reason: In practices like snapshot testing, minor changes (such as a timestamp) might cause a discrepancy. Setting a 90% match as a pass ensures test integrity. However, a warning at 95% alerts testers that, although the images aren't identical, the test has passed, which may warrant further investigation. +- Warning about a Percentage Discrepancy in Image Comparison: + - Scenario: When comparing two images to assess their similarity, a warning can be triggered if there's a 95% pixel match, while a test failure is set at a 90% similarity threshold. + - Reason: In practices like snapshot testing, minor changes (such as a timestamp) might cause a discrepancy. Setting a 90% match as a pass ensures test integrity. However, a warning at 95% alerts testers that, although the images aren't identical, the test has passed, which may warrant further investigation. - Warning for Duplicate Argument Inputs in Tests: - - Scenario: In a test library, issue a warning if a user inputs the same argument twice, rather than flagging an error. - - Reason: Although passing the same argument twice might not be typical, some users may have valid reasons for doing so. Thus, a warning suffices, allowing flexibility without compromising the test's execution. + - Scenario: In a test library, issue a warning if a user inputs the same argument twice, rather than flagging an error. + - Reason: Although passing the same argument twice might not be typical, some users may have valid reasons for doing so. Thus, a warning suffices, allowing flexibility without compromising the test's execution. - Warning for Recoverable Unexpected Events: - - Scenario: During an integration test where data is retrieved from a server, a warning can be issued if the primary server is down, prompting a switch to an alternative server. Usually mocking is the solution for this but may not test everything needed for an integration test. - - Reason: Since server downtime might happen and can be beyond the tester's control, issuing a warning rather than a failure helps in debugging and understanding potential issues without impacting the test's overall success. + - Scenario: During an integration test where data is retrieved from a server, a warning can be issued if the primary server is down, prompting a switch to an alternative server. Usually mocking is the solution for this but may not test everything needed for an integration test. + - Reason: Since server downtime might happen and can be beyond the tester's control, issuing a warning rather than a failure helps in debugging and understanding potential issues without impacting the test's overall success. - Warning for a retry during setup for a test: - - Scenario: During test setup part of your code may be configured to retry, it would be nice to notify in the results that a retry happened - - Reason: This makes sense to be a warning and not a failure because if the retry succeeds the test may still verify the code correctly + - Scenario: During test setup part of your code may be configured to retry, it would be nice to notify in the results that a retry happened + - Reason: This makes sense to be a warning and not a failure because if the retry succeeds the test may still verify the code correctly ## Proposed solution + We propose introducing a new property on `Issue` in Swift Testing called `severity`, that represents if an issue is a `warning` or an `error`. The default Issue severity will still be `error` and users can set the severity when they record an issue. @@ -47,7 +48,7 @@ The `Severity` enum: ```swift extension Issue { // ... - public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { + public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { /// The severity level for an issue which should be noted but is not /// necessarily an error. /// @@ -66,6 +67,7 @@ extension Issue { ``` ### Recording Non-Failing Issues + To enable test authors to log non-failing issues without affecting test results, we provide a method for recording such issues: ```swift @@ -73,6 +75,7 @@ Issue.record("My comment", severity: .warning) ``` Here is the `Issue.record` method definition with severity as a parameter. + ```swift /// Record an issue when a running test fails unexpectedly. /// @@ -92,13 +95,14 @@ Here is the `Issue.record` method definition with severity as a parameter. severity: Severity = .error, sourceLocation: SourceLocation = #_sourceLocation ) -> Self - + // ... ``` ### Issue Type Enhancements The Issue type is enhanced with two new properties to better handle and report issues: + - `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. ```swift @@ -112,7 +116,9 @@ public var severity: Severity { get set } } ``` + - `isFailure`: A boolean property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. + ```swift extension Issue { // ... @@ -132,6 +138,7 @@ extension Issue { ``` Example usage of `severity` and `isFailure`: + ```swift // ... withKnownIssue { @@ -147,7 +154,7 @@ This revision aims to clarify the functionality and usage of the `Severity` enum ### Integration with supporting tools -Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. +Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. The JSON event stream ABI will be amended correspondingly: @@ -198,7 +205,7 @@ For more details on how to checkout a branch for a package refer to this: https: - Naming of `isFailure` vs. `isFailing`: We evaluated whether to name the property `isFailing` instead of `isFailure`. The decision to use `isFailure` was made to adhere to naming conventions and ensure clarity and consistency within the API. - Severity-Only Checking: We deliberated not exposing `isFailure` and relying solely on `severity` checks. However, this was rejected because it would require test authors to overhaul their code should we introduce additional severity levels in the future. By providing `isFailure`, we offer a straightforward way to determine test outcome impact, complementing the severity feature. -- Naming `Severity.error` `Severity.failure` instead because this will always be a failing issue and test authors often think of test failures. Error and warning match build naming conventions and XCTest severity naming convention. +- Naming `Severity.error` `Severity.failure` instead because this will always be a failing issue and test authors often think of test failures. Error and warning match build naming conventions and XCTest severity naming convention. ## Future directions From 330023ddf86eb058a3d2c38429df4f8bd39ab27c Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 8 Jul 2025 21:11:22 +0200 Subject: [PATCH 417/505] Review preparation --- proposals/testing/0013-issue-severity-warning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index f5670187c7..67e25264e9 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -3,7 +3,7 @@ - Proposal: [ST-0013](0013-issue-severity-warning.md) - Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) - Review Manager: [Maarten Engels](https://github.com/maartene) -- Status: **Awaiting Review** +- Status: **Active Review (July 9...July 23, 2025)** - Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) - Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) From 5dc4dbc774b21a0c37aa4ceb34b633f7cf55f6f4 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 8 Jul 2025 21:20:39 +0200 Subject: [PATCH 418/505] ST-0013 review - add link to review thread --- proposals/testing/0013-issue-severity-warning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 67e25264e9..fe89f37c1f 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -5,7 +5,7 @@ - Review Manager: [Maarten Engels](https://github.com/maartene) - Status: **Active Review (July 9...July 23, 2025)** - Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) +- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ([review](https://forums.swift.org/t/st-0013-test-issue-warnings/80991)) ## Introduction From c1a42d47452c655830c8936d83dec81326019c72 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 8 Jul 2025 12:43:56 -0700 Subject: [PATCH 419/505] [SE-0466] Disable `@MainActor` inference when type conforms to a SendableMetatype protocol (#2894) * [SE-0466] Disable `@MainActor` inference when type conforms to a SendableMetatype protocol Libraries need a way to communicate that certain protocols can't reasonably be used with global-actor-isolated types. When the primary definition of a type conforms to such a protocol, it will disable `@MainActor` inference for that type. This has the effect of keeping more types `nonisolated` when there's signal that they should not be on the main actor. There are some protocols like this in the standard library (e.g., CodingKey, which was hardcoded to be nonisolated in the synthesis code), where the following code is ill-formed in with main-actor isolation by default: struct S: Codable { var a: Int // error: CodingKeys inferred to `@MainActor`, which makes the conformance // to CodingKey main-actor-isolated and then fails (because the requirements // need to be nonisolated). enum CodingKeys: CodingKey { case a } } With this amendment, the conformance to `CodingKey` (which inherits from `Sendable`), prevents `CodingKeys` from being inferred to be`@MainActor`. * Provide more extensive rationale for the design --- .../0466-control-default-actor-isolation.md | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 763a1ff12d..37f543ac54 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -65,6 +65,7 @@ When the default actor isolation is specified as `MainActor`, declarations are i * Declarations with inferred actor isolation from a superclass, overridden method, protocol conformance, or member propagation * All declarations inside an `actor` type, including static variables, methods, initializers, and deinitializers * Declarations that cannot have global actor isolation, including typealiases, import statements, enum cases, and individual accessors +* Declarations whose primary definition directly conforms to a protocol that inherits `SendableMetatype` The following code example shows the inferred actor isolation in comments given the code is built with `-default-isolation MainActor`: @@ -107,6 +108,16 @@ struct S: P { // @MyActor func f() { ... } } + +nonisolated protocol Q: Sendable { } + +// nonisolated +struct S2: Q { } + +// @MainActor +struct S3 { } + +extension S3: Q { } ``` This proposal does not change the default isolation inference rules for closures. Non-Sendable closures and closures passed to `Task.init` already have the same isolation as the enclosing context by default. When specifying `MainActor` isolation by default in a module, non-`@Sendable` closures and `Task.init` closures will have inferred `@MainActor` isolation when the default `@MainActor` inference rules apply to the enclosing context: @@ -166,23 +177,37 @@ Similarly, a future language mode could enable main actor isolation by default, See the approachable data-race safety vision document for an [analysis on the risks of introducing a language dialect](https://github.com/hborla/swift-evolution/blob/approachable-concurrency-vision/visions/approachable-concurrency.md#risks-of-a-language-dialect) for default actor isolation. -### Don't apply default actor isolation to explicitly `Sendable` types +### Alternative to `SendableMetatype` for suppressing main-actor inference + +The protocols to which a type conforms can affect the isolation of the type. Conforming to a global-actor-isolated protocol can infer global-actor isolatation for the type. When the default actor isolation is `MainActor`, it is valuable for protocols to be able to push inference toward keeping conforming types `nonisolated`, for example because conforming types are meant to be usable from any isolation domain. -This proposal includes few exceptions where the specified default actor isolation does not apply. An additional case that should be considered is types with a conformance to `Sendable`: +In this proposal, inheritance from `SendableMetatype` (introduced in [SE-0470](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0470-isolated-conformances.md)) is used as an indication that types conforming to the protocol should be `nonisolated`. The `SendableMetatype` marker protocol indicates when a type (but not necessarily its instances) can cross isolation domains, which implies that the type generally needs to be usable from any isolation domain. Additionally, protocols that inherit from `SendableMetatype` can only be meaningfully be used with nonisolated conformances, as discussed in SE-0470. Experience using default main actor isolation uncovered a number of existing protocols that reinforce the notion of `SendableMetatype` inheritance is a reasonable heuristic to indicate that a conforming type should be nonisolated: the standard library's [`CodingKey`](https://developer.apple.com/documentation/swift/codingkey) protocol inherits `Sendable` (which in turn inherits `SendableMetatype`) so a typical conformance will fail to compile with default main actor isolation: ```swift -struct SimpleValue: Sendable { - var value: Int +struct S: Codable { + var a: Int + + // error if CodingKeys is inferred to `@MainActor`. The conformance cannot be main-actor-isolated, and + // the requirements of the (nonisolated) CodingKey cannot be satisfied by main-actor-isolated members of + // CodingKeys. + enum CodingKeys: CodingKey { + case a + } } ``` -This is an attractive carve out upon first glance, but there are a number of downsides: +Other places that have similar issues with default main actor isolation include the [`Transferable`](https://developer.apple.com/documentation/coretransferable/transferable) protocol and the uses of key paths in the [`@Model` macro](https://developer.apple.com/documentation/swiftdata/model()). + +Instead of using `SendableMetatype` inheritance, this proposal could introduce new syntax for a protocol to explicitly indicate -* The carve out may be confusing if a conformance to `Sendable` is implied, e.g. through a conformance to another protocol. -* Global actor isolation implies a conformance to `Sendable`, so it's not clear that a `Sendable` type should not be global actor isolated. -* Methods on a `Sendable` type may still use other types and methods that have default actor isolation applied, which would lead to failures if the `Sendable` type was exempt from default isolation inference. +```swift +@nonisolatedConformingTypes +public protocol CodingKey { + // ... +} +``` -A middle ground might be to not apply default actor isolation to types with an explicit conformance to `Sendable` within the same source file as the type. This approach would still have some of the downsides listed above, but it would be more straightforward to spot types that have this exemption. +This would make the behavior pushing conforming types toward `nonisolated` opt-in. However, it means that existing protocols (such as the ones mentioned above) would all need to adopt this spelling before code using default main actor isolation will work well. Given the strong semantic link between `SendableMetatype` and `nonisolated` conformances and types, the proposed rule based on `SendableMetatype` inheritance is likely to make more code work well with default main actor isolation. An explicit opt-in attribute like the above could be added at a later time if needed. ### Use an enum for the package manifest API From cf2a0fa2ec5e338ace98b0cf988b6a63035f44a7 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Tue, 8 Jul 2025 15:56:27 -0400 Subject: [PATCH 420/505] Update 0466-control-default-actor-isolation.md (#2907) --- proposals/0466-control-default-actor-isolation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 37f543ac54..5c1c0a08ab 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -1,11 +1,11 @@ # Control default actor isolation inference * Proposal: [SE-0466](0466-control-default-actor-isolation.md) -* Authors: [Holly Borla](https://github.com/hborla) +* Authors: [Holly Borla](https://github.com/hborla), [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Implemented (Swift 6.2)** +* Status: **Implemented (Swift 6.2)**, **Amendmendment review July 8 - 15, 2025** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) -* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321))([acceptance](https://forums.swift.org/t/accepted-se-0466-control-default-actor-isolation-inference/78926)) +* Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321))([acceptance](https://forums.swift.org/t/accepted-se-0466-control-default-actor-isolation-inference/78926))([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854))([amendment review](https://forums.swift.org/t/amendment-se-0466-control-default-actor-isolation-inference/80994)) ## Introduction From 2b01fe103fd486155771b2d5ff60bc720e802d5e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 8 Jul 2025 19:43:21 -0700 Subject: [PATCH 421/505] [SE-0470] Infer `nonisolated` on conformances (#2893) * [SE-0470] Infer `nonisolated` on conformances Introduce two inference rules that infer `nonisolated` when `InferIsolatedConformances` is enabled. These inference rules ensure that most conformances that should be nonisolated remain nonisolated, particular when we're in the main-actor-by-default mode. The end result is that much less code needs to change when enabling isolated conformance inference (including via main-actor-by-default mode). The two rules are: * If the protocol inherits from `SendableMetatype` (including indirectly, e.g., from `Sendable`), then the isolated conformance could never be used, so it is inferred to be `nonisolated`. * If all of the declarations used to satisfy protocol requirements are `nonisolated`, the conformance will be assumed to be `nonisolated`. * More justification for why this feature is needed, and a possible future removing it * Fix typo * Clarify that a nonisolated conformance might evolve to an isolated one * Update headers and revision history --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- proposals/0470-isolated-conformances.md | 40 ++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index 83c4b3a51a..a1cb0750b4 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -3,11 +3,11 @@ * Proposal: [SE-0470](0470-isolated-conformances.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Implemented (Swift 6.2)** +* Status: **Active review (July 8...15, 2025)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` -* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854)) ## Introduction @@ -549,18 +549,21 @@ class MyModelType: /*inferred @MainActor*/ P { } ``` -If this inference is not desired, for example because the code will use `nonisolated` members to satisfy the requirements of the protocol, it can use `nonisolated` on the conformance: +If this inference is not desired, one can use `nonisolated` on the conformances: ```swift @MainActor -class MyModelType: nonisolated P { - nonisolated func f() { } // implements P.f, is non-isolated +class MyModelType: nonisolated Q { + nonisolated static func g() { } // implements Q.g, is non-isolated } ``` -This mirrors the rules for global actor inference elsewhere in the language, providing a more consistent answer. +There are two additional inference rules that imply `nonisolated` on a conformance of a global-actor-isolated type: -This proposed change is source-breaking, so it should be staged in via an upcoming feature (`InferIsolatedConformances`) that can be folded into a future language mode. Fortunately, it is mechanically migratable: existing code migrating to `InferIsolatedConformances` could introduce `nonisolated` for each conformance of a global-actor-isolated type. +* If the protocol inherits from `SendableMetatype` (including indirectly, e.g., from `Sendable`), then the isolated conformance could never be used, so it is inferred to be `nonisolated`. +* If all of the declarations used to satisfy protocol requirements are `nonisolated`, the conformance will be assumed to be `nonisolated`. The conformance of `MyModelType` to `Q` would be inferred to be `nonisolated` because the static method `g` used to satisfy `Q.g` is `nonisolated.` + +This proposed change is source-breaking in the cases where a conformance is currently `nonisolated`, the rules above would not infer `nonisolated`, and the conformance crosses isolation domains. There, conformance isolation inference is staged in via an upcoming feature (`InferIsolatedConformances`) that can be folded into a future language mode. Fortunately, it is mechanically migratable: existing code migrating to `InferIsolatedConformances` could introduce `nonisolated` for each conformance of a global-actor-isolated type. ### Infer `@MainActor` conformances @@ -662,7 +665,30 @@ This is a generalization of the proposed rules that makes more explicit when con The main down side of this alternative is the additional complexity it introduces into generic requirements. It should be possible to introduce this approach later if it proves to be necessary, by treating it as a generalization of the existing rules in this proposal. +### Require `nonisolated` rather than inferring it + +Under the upcoming feature `InferIsolatedConformances`, this proposal infers `nonisolated` for conformances when all of the declarations that satisfy requirements of a protocol are themselves `nonisolated`. For example: + +```swift +nonisolated protocol Q { + static func create() -> Self +} + +@MainActor struct MyType: /*infers nonisolated*/ Q { + nonisolated static func create() -> MyType { ... } +} +``` + +This inference is important for providing source compatibility with and without `InferIsolatedConformances`, and is especially useful useful when combined with default main-actor isolation ([SE-0466](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md)), where many more types will become main-actor isolated. Experience with using these features together also identified some macros (such as [`@Observable`](https://developer.apple.com/documentation/observation/observable())) that produced `nonisolated` members for a protocol conformances, but had not yet been updated to mark the conformance as `nonisolated`. Macro-generated code is much harder for users to update when a source-compatibility issue arises, which makes `nonisolated` conformance inference particularly important for source compatibility. + +However, this inference rule has downsides. It means one needs to examine a protocol and how a type conforms to that protocol to determine whether the conformance might be `nonisolated`, which can be a lot of work for the developer reading the code as well as the compiler. It can also change over time: for example, a default implementation of a protocol requirement will likely be `nonisolated`, but a user-written one within a main-actor-isolated type would be `@MainActor` and, therefore, make the conformance `@MainActor`. + +One alternative would be to introduce this inference rule for source compatibility, but treat it as a temporary measure to be disabled again in some future language mode. Introducing the inference rule in this proposal does not foreclose on that possibility: if we find that the `nonisolated` conformance inference rule here is harmful to readability, a separate proposal can deprecate it in a future language mode, providing a suitable migration timeframe. + ## Revision history +* Changes in amendment review: + * If the protocol inherits from `SendableMetatype` (including indirectly, e.g., from `Sendable`), then the isolated conformance could never be used, so it is inferred to be `nonisolated`. + * If all of the declarations used to satisfy protocol requirements are `nonisolated`, the conformance will be assumed to be `nonisolated`. * Changes in review: * Within a generic function, use sendability of metatypes of generic parameters as the basis for checking, rather than treating specific conformances as potentially isolated. This model is easier to reason about and fits better with `SendableMetatype`, and was used in earlier drafts of this proposal. From 2af25b6dcf694410d7d4270bb64848bc4c5b57d6 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:03:16 -0400 Subject: [PATCH 422/505] Add amendment review link for SE-0470 (#2909) --- proposals/0470-isolated-conformances.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index a1cb0750b4..0854f6da16 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -7,7 +7,7 @@ * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` -* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854)) +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854)) ([amendment review](https://forums.swift.org/t/amendment-se-0470-global-actor-isolated-conformances/80999)) ## Introduction From a828476fea297af3ac38889b39cbbbee3a08b3e0 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 9 Jul 2025 13:03:46 +0100 Subject: [PATCH 423/505] Fix sample code in `0428-resolve-distributed-actor-protocols.md` This code caused an error with `ActorSystem` type parameter unbound: ``` import Distributed @Resolvable protocol Greeter where ActorSystem: DistributedActorSystem { distributed func greet(name: String) -> String } ``` --- proposals/0428-resolve-distributed-actor-protocols.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0428-resolve-distributed-actor-protocols.md b/proposals/0428-resolve-distributed-actor-protocols.md index 52a6964f52..e7b4128e3d 100644 --- a/proposals/0428-resolve-distributed-actor-protocols.md +++ b/proposals/0428-resolve-distributed-actor-protocols.md @@ -90,7 +90,7 @@ The macro must be attached to the a `protocol` declaration that is a `Distribute import Distributed @Resolvable -protocol Greeter where ActorSystem: DistributedActorSystem { +protocol Greeter: DistributedActor where ActorSystem: DistributedActorSystem { distributed func greet(name: String) -> String } ``` From 1b1ab5ca1a3df162a580863065be9053e63c06f1 Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 9 Jul 2025 13:14:31 -0400 Subject: [PATCH 424/505] Add SE proposal for Codable error printing (#2843) * Add SE proposal for Codable error printing. * Claim SE-0489 --------- Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> --- proposals/0489-codable-error-printing.md | 160 +++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 proposals/0489-codable-error-printing.md diff --git a/proposals/0489-codable-error-printing.md b/proposals/0489-codable-error-printing.md new file mode 100644 index 0000000000..c7bbfa3673 --- /dev/null +++ b/proposals/0489-codable-error-printing.md @@ -0,0 +1,160 @@ +# Improve `EncodingError` and `DecodingError`'s printed descriptions + +* Proposal: [SE-0489](0489-codable-error-printing.md) +* Authors: [Zev Eisenberg](https://github.com/ZevEisenberg) +* Review Manager: [Xiaodi Wu](https://github.com/xwu) +* Status: **Active review (July 9...22, 2025)** +* Implementation: https://github.com/swiftlang/swift/pull/80941 +* Review: ([pitch](https://forums.swift.org/t/pitch-improve-encodingerror-and-decodingerror-s-printed-descriptions/79872)) ([review]()) + +## Introduction + +`EncodingError` and `DecodingError` do not specify any custom debug description. The default descriptions bury the useful information in a format that is difficult to read. Less experienced developers may assume they are not human-readable at all, even though they contain useful information. The proposal is to conform `EncodingError` and `DecodingError` to `CustomDebugStringConvertible` and provide nicely formatted debug output. + +## Motivation + +Consider the following example model structs: + +```swift +struct Person: Codable { + var name: String + var home: Home +} + +struct Home: Codable { + var city: String + var country: Country +} + +struct Country: Codable { + var name: String + var population: Int +} +``` + +Now let us attempt to decode some invalid JSON. In this case, it is missing a field in a deeply nested struct. + +```swift +// Note missing "population" field +let jsonData = Data(""" +[ + { + "name": "Ada Lovelace", + "home": { + "city": "London", + "country": { + "name": "England" + } + } + } +] +""".utf8) + +do { + _ = try JSONDecoder().decode([Person].self, from: jsonData) +} catch { + print(error) +} +``` + +This outputs the following: + +`keyNotFound(CodingKeys(stringValue: "population", intValue: nil), Swift.DecodingError.Context(codingPath: [_CodingKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "home", intValue: nil), CodingKeys(stringValue: "country", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"population\", intValue: nil) (\"population\").", underlyingError: nil))` + +All the information you need is there: +- The kind of error: a missing key +- Which key was missing: `"population"` +- The path of the value that had a missing key: index 0, then key `"home"`, then key `"country"` +- The underlying error: none, in this case + +However, it is not easy or pleasant to read such an error, particularly when dealing with large structures or long type names. It is common for newer developers to assume the above output is some kind of log spam and not even realize it contains exactly the information they are looking for. + +## Proposed solution + +Conform `EncodingError` and `DecodingError` to `CustomDebugStringConvertible` and provide a clean, readable debug description for each. Here is an example of the proposed change for the same decoding error as above. + +``` +Key 'population' not found in keyed decoding container. +Debug description: No value associated with key CodingKeys(stringValue: "population", intValue: nil) ("population"). +Path: [0]/home/country +``` + +Complete examples of the before/after diffs are available in the description of the [implementation pull request](https://github.com/swiftlang/swift/pull/80941) that accompanies this proposal. + +**Note 1:** this proposal is _not_ intended to specify an exact output format. The above is provided as an example, and is not a guarantee of current or future behavior. You are still free to inspect the contents of thrown errors directly if you need to detect specific problems. + +**Note 2:** the output could be further improved by modifying `JSONDecoder` to write a better debug description. See [Future Directions](#future-directions) for more. + +## Detailed design + +```swift +@available(SwiftStdlib 6.2, *) +extension EncodingError: CustomDebugStringConvertible { + public var debugDescription: String {...} +} + +@available(SwiftStdlib 6.2, *) +extension DecodingError: CustomDebugStringConvertible { + public var debugDescription: String {...} +} +``` + +## Source compatibility + +The new conformance changes the result of converting an `EncodingError` or `DecodingError` value to a string. This changes observable behavior: code that attempts to parse the result of `String(describing:)` or `String(reflecting:)` can be misled by the change of format. + +However, the documentation of these interfaces explicitly state that when the input type conforms to none of the standard string conversion protocols, then the result of these operations is unspecified. + +Changing the value of an unspecified result is not considered to be a source incompatible change. + +## ABI compatibility + +The proposal conforms two previously existing stdlib types to a previously existing stdlib protocol. This is technically an ABI breaking change: on ABI-stable platforms, we may have preexisting Swift binaries that implement a retroactive `CustomDebugStringConvertible` conformance, or binaries that assume that the existing error types do _not_ conform to the protocol. + +We do not expect this to be an issue in practice, since checking an arbitrary error for conformance to `CustomDebugStringConvertible` at run-time seems unlikely. In the event that it now conforms where it didn't before, it will presumably use the new implementation instead of whatever fallback was being provided previously. + +## Implications on adoption + +### Conformance to `CustomDebugStringConvertible` + +The conformance to `CustomDebugStringConvertible` is not backdeployable. As a result, code that runs on ABI-stable platforms with earlier versions of the standard library won't output the new debug descriptions. + +### `debugDescription` Property + +It is technically possible to backdeploy the `debugDescription` property, but without the protocol conformance, it is of limited utility. + +## Future directions + +### Better error generation from Foundation encoders/decoders + +The debug descriptions generated in Foundation sometimes contain the same information as the new debug descriptions from this proposal. A future change to the standard JSON and Plist encoders and decoders could provide more compact debug descriptions once they can be sure they have the new standard library descriptions available. They could also use a more compact description when rendering the description of a `CodingKey`. Using part of the example from above: + +``` +Debug description: No value associated with key CodingKeys(stringValue: "population", intValue: nil) ("population"). +``` + +The `CodingKeys(stringValue: "population", intValue: nil) ("population")` part is coming from the default `description` of `CodingKey`, plus an extra parenthesized string value at the end for good measure. The Foundation (de|en)coders could construct a more compact description that does not repeat the key, just like we do within this proposal in the context of printing a coding path. + +### Print context of surrounding lines in source data + +When a decoding error occurs, in addition to printing the path, the error message could include some surrounding lines from the source data. This was explored in this proposal's antecedent, [UsefulDecode](https://github.com/ZevEisenberg/UsefulDecode). But more detailed messages would require passing more context data from the decoder and changing the public interface of `DecodingError` to carry more data. This option is best left as something to think about as [we design `Codable`'s successor](https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585). But just to give an example of the _kind_ of context that could be provided (please do not read anything into the specifics of the syntax; this is a sketch, not a proposal): + +``` +Value not found: expected 'name' (String) at [0]/address/city/birds/[1]/name, got: +{ + "feathers" : "some", + "name" : null +} +``` + +## Alternatives considered + +We could conform `EncodingError` and `DecodingError` to `CustomStringConvertible` instead of `CustomDebugStringConvertible`. The use of the debug-flavored protocol emphasizes that the new descriptions aren't intended to be used outside debugging contexts. This is in keeping with the precedent set by [SE-0445](0445-string-index-printing.md). + +We could change `CodingKey.description` to return the bare string or int value, which would improve the formatting and reduce duplication as seen in [Proposed solution](#proposed-solution). But changing the exsting implementation of an existing public method seems needlessly risky, as existing code may (however inadvisably) be depending on the format of the current `description`. Additionally, the encoders and decoders in Foundation should not depend on implementation details of `CodingKey.description` that are not guaranteed. If we want the encoders/decoders to produce better formatting, they should be responsible for generating those strings directly. See [further discussion in the PR](https://github.com/swiftlang/swift/pull/80941#discussion_r2064277369). + +## Acknowledgments + +This proposal follows in the footsteps of [SE-0445](0445-string-index-printing.md). Thanks to [Karoy Lorentey](https://github.com/lorentey) for writing that proposal, and for flagging it as similar to this one. + +Thanks to Kevin Perry [for suggesting](https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585/77) that this would make a good standalone change regardless of the direction of future serialization tools, and for engaging with the PR from the beginning. From 06b13a1d2509d18a47bdbba9df80c7d7142c3b7f Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:22:33 -0400 Subject: [PATCH 425/505] Add review link for SE-0489 (#2911) --- proposals/0489-codable-error-printing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0489-codable-error-printing.md b/proposals/0489-codable-error-printing.md index c7bbfa3673..2d3968aea6 100644 --- a/proposals/0489-codable-error-printing.md +++ b/proposals/0489-codable-error-printing.md @@ -5,7 +5,7 @@ * Review Manager: [Xiaodi Wu](https://github.com/xwu) * Status: **Active review (July 9...22, 2025)** * Implementation: https://github.com/swiftlang/swift/pull/80941 -* Review: ([pitch](https://forums.swift.org/t/pitch-improve-encodingerror-and-decodingerror-s-printed-descriptions/79872)) ([review]()) +* Review: ([pitch](https://forums.swift.org/t/pitch-improve-encodingerror-and-decodingerror-s-printed-descriptions/79872)) ([review](https://forums.swift.org/t/se-0489-improve-encodingerror-and-decodingerrors-printed-descriptions/81021)) ## Introduction From 5a7b84c55915f8147eb5d16976eddac86b3ee7ee Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:45:27 -0400 Subject: [PATCH 426/505] Fixups for SE-0466 (#2908) * Fixups for SE-0466 * Edit a typo in the header field * Add a succinct revision history * Revise status for automated tooling --- proposals/0466-control-default-actor-isolation.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 5c1c0a08ab..0da31e90d4 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -3,7 +3,7 @@ * Proposal: [SE-0466](0466-control-default-actor-isolation.md) * Authors: [Holly Borla](https://github.com/hborla), [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Implemented (Swift 6.2)**, **Amendmendment review July 8 - 15, 2025** +* Status: **Active review (July 8...15, 2025)** * Vision: [Improving the approachability of data-race safety](/visions/approachable-concurrency.md) * Review: ([pitch](https://forums.swift.org/t/pitch-control-default-actor-isolation-inference/77482))([review](https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321))([acceptance](https://forums.swift.org/t/accepted-se-0466-control-default-actor-isolation-inference/78926))([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854))([amendment review](https://forums.swift.org/t/amendment-se-0466-control-default-actor-isolation-inference/80994)) @@ -238,6 +238,11 @@ The enum approach introduces a different way of writing main actor isolation tha The primary argument for using an enum is that it can be extended in the future to support custom global actor types. This proposal deliberately puts supporting custom global actors in the alternatives considered and not future directions, because defaulting a module to a different global actor does not help improve progressive disclosure for concurrency. +## Revision history + +* Changes in amendment review: + * Disable `@MainActor` inference when type conforms to a `SendableMetatype` protocol + ## Acknowledgments Thank you to John McCall for providing much of the motivation for this pitch in the approachable data-race safety vision document, and to Michael Gottesman for helping with the implementation. From 07e7020336a3760581e6bd4792bd598a7e9b43e8 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 10 Jul 2025 11:07:30 -0500 Subject: [PATCH 427/505] Additions and clarifications to ST-0011: Issue Handling Traits proposal (#2912) * Link to final enablement PR * Expand discussion of inout alternative to encompass the Void? suggestion * Clarify .system and .apiMisused policy --- .../testing/0011-issue-handling-traits.md | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index d27f2e9a5f..c6592bba6f 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -6,7 +6,8 @@ * Status: **Active Review (Jun 24 - July 8, 2025)** * Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), - [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136) + [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136), + [swiftlang/swift-testing#1198](https://github.com/swiftlang/swift-testing/pull/1198) * Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) ([review](https://forums.swift.org/t/st-0011-issue-handling-traits/80644)) ## Introduction @@ -303,13 +304,15 @@ Issue handling traits are applied to a test by a user, and are only intended for handling issues recorded by tests written by the user. If an issue is recorded by the testing library itself or the underlying system, not due to a failure within the tests being run, such an issue will not be passed to an issue -handling trait. +handling trait. Similarly, an issue handling trait should not return an issue +which represents a problem they could not have caused in their test. Concretely, this policy means that issues for which the value of the `kind` property is `.system` will not be passed to the closure of an issue handling -trait. Similarly, it is not supported for a closure passed to +trait. Also, it is not supported for a closure passed to `compactMapIssues(_:)` to return an issue for which the value of `kind` is -`.system`. +either `.system` or `.apiMisused` (unless the passed-in issue had that kind, +which should only be possible for `.apiMisused`). ## Detailed design @@ -507,15 +510,29 @@ the handler encounters an error. The closure parameter of `compactMapIssues(_:)` currently has one parameter of type `Issue` and returns an optional `Issue?` to support returning `nil` in -order to suppress an issue. This closure could instead have a `Void` return type -and its parameter could be `inout`, and this would mean that use cases that -involve modifying an issue would not need to first copy the issue to a variable -(`var`) before modifying it. - -However, in order to _suppress_ an issue, the parameter would also need to -become optional (`inout Issue?`) and this would mean that all usages would first -need to be unwrapped. This feels non-ergonomic, and would differ from the -standard library's typical pattern for `compactMap` functions. +order to suppress an issue. If an issue handler wants to modify an issue, it +first needs to copy it to a mutable variable (`var`), mutate it, then return the +modified copy. These copy and return steps require extra lines of code within +the closure, and they could be eliminated if the parameter was declared `inout`. + +The most straightforward way to achieve this would be for the closure to instead +have a `Void` return type and for its parameter to become `inout`. However, in +order to _suppress_ an issue, the parameter would also need to become optional +(`inout Issue?`) and this would mean that all usages would first need to be +unwrapped. This feels non-ergonomic, and would differ from the standard +library's typical pattern for `compactMap` functions. + +Another way to achieve this ([suggested](https://forums.swift.org/t/st-0011-issue-handling-traits/80644/3) +by [@Val](https://forums.swift.org/u/Val) during proposal review) could be to +declare the return type of the closure `Void?` and the parameter type +`inout Issue` (non-optional). This alternative would not require unwrapping the +issue first and would still permit suppressing issues by returning `nil`. It +could also make one of the alternative names (such as `transformIssues` +discussed below) more fitting. However, this is a novel API pattern which isn't +widely used in Swift, and may be confusing to users. There were also concerns +raised by other reviewers that the language's implicit return for `Void` may not +be intentionally applied to `Optional` and that this mechanism could break +in the future. ### Alternate names for the static trait functions From e95300cb1c50c88f189fcbc85837014a7906b933 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Thu, 10 Jul 2025 18:20:38 +0000 Subject: [PATCH 428/505] revise proposal --- ...-environment-dependent-shared-libraries.md | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/proposals/NNNN-environment-dependent-shared-libraries.md b/proposals/NNNN-environment-dependent-shared-libraries.md index d1068526ea..5c7a228bf9 100644 --- a/proposals/NNNN-environment-dependent-shared-libraries.md +++ b/proposals/NNNN-environment-dependent-shared-libraries.md @@ -1,21 +1,21 @@ -# Environment Dependent Shared Libraries +# Environment Constrained Shared Libraries -* Proposal: [SE-NNNN](NNNN-environment-dependent-shared-libraries.md) +* Proposal: [SE-NNNN](NNNN-environment-constrained-shared-libraries.md) * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) -* Documentation: [How to use Environment-Dependent Shared Libraries](https://github.com/swiftlang/swift-package-manager/blob/b586467575580f2365e8f5a29c949379724db795/Documentation/EDSLs.md) +* Documentation: [How to use Environment-Constrained Shared Libraries](https://github.com/swiftlang/swift-package-manager/blob/b586467575580f2365e8f5a29c949379724db795/Documentation/ECSLs.md) * Bugs: [SR-5714](https://github.com/swiftlang/swift-package-manager/issues/5714) ## Introduction -SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Environment Dependent Shared Libraries**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Environment Dependent Shared Libraries through the existing `.artifactbundle` format. +SwiftPM currently has no support for non-system binary library dependencies on Linux. This proposal adds support for **Environment Constrained Shared Libraries**, which are a type of dynamic library that is shared across a fleet of machines and can be upgraded without recompiling and redeploying all applications running on those machines. We will distribute Environment Constrained Shared Libraries through the existing `.artifactbundle` format. Swift-evolution thread: [Discussion thread](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605) -Example Producer: [swift-edsl-example](https://github.com/tayloraswift/swift-edsl-example) +Example Producer: [swift-ECSL-example](https://github.com/tayloraswift/swift-ECSL-example) -Example Consumer: [swift-edsl-example-client](https://github.com/tayloraswift/swift-edsl-example-client) +Example Consumer: [swift-ECSL-example-client](https://github.com/tayloraswift/swift-ECSL-example-client) ## Motivation @@ -30,51 +30,54 @@ While macOS has Dynamic Library support through XCFrameworks, on Linux we curren On Linux, there are a lot of obstacles to having fully general support for Dynamic Libraries. Swift is not ABI stable on Linux, and Linux itself is not a single platform but a wide range of similar platforms that provide few binary compatibility guarantees. This means it is pretty much impossible for a public Swift library to vend precompiled binaries that will Just Work for everyone, and we are not going to try to solve that problem in this proposal. -Instead, we will focus on **Environment Dependent Shared Libraries** (EDSLs). We choose this term to emphasize the distinction between our use case and fully general Dynamic Libraries. +Instead, we will focus on **Environment Constrained Shared Libraries** (ECSLs). We choose this term to emphasize the distinction between our use case and fully general Dynamic Libraries. -### Organization-Defined Platforms (ODPs) +### Target environment -Unlike fully general Dynamic Libraries, you would distribute Environment Dependent Shared Libraries strictly for internal consumption within an organization, or to a small set of paying clients. +Unlike fully general Dynamic Libraries, you would distribute Environment Constrained Shared Libraries strictly for controlled consumption within a known environment, such as a fleet of servers maintained by a single organization. -The organization that distributes an EDSL is responsible for defining what exactly constitutes a “platform” for their purposes. An Organization-Defined Platform (ODP) is not necessarily an operating system or architecture, or even a specific distribution of an operating system. A trivial example of two ODPs might be: +ECSLs are an advanced tool, and maintaining the prerequisite environment to deploy them safely is neither trivial nor recommended for most users. -1. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift` -2. Ubuntu 24.04 with the Swift 6.0.3 runtime installed at `/home/ubuntu/swift-runtime` +The organization that distributes an ECSL is responsible for defining what exactly constitutes a “platform” for their purposes. An organization-defined platform is not necessarily an operating system or architecture, or even a specific distribution of an operating system. A trivial example of two such platforms might be: -Concepts like Platform Triples are not sufficient to describe an ODP. Even though both ODPs above would probably share the Triple `aarch64-unknown-linux-gnu`, Swift code compiled (without `--static-swift-stdlib`) for one would never be able to run on the other. +1. Ubuntu 24.04 with the Swift 6.1.2 runtime installed at `/home/ubuntu/swift` +2. Ubuntu 24.04 with the Swift 6.1.2 runtime installed at `/home/ubuntu/swift-runtime` -Organizations add and remove ODPs as needed, and trying to define a global registry of all possible ODPs is a non-goal. +Concepts like Platform Triples are not sufficient to describe an ECSL deployment target. Even though both “platforms” above would probably share the Triple `aarch64-unknown-linux-gnu`, Swift code compiled (without `--static-swift-stdlib`) for one would never be able to run on the other. -To keep things simple, we identify ODPs by the URL of the Artifact Bundle that contains the EDSL. +Organizations will add and remove environments as needed, and trying to define a global registry of all possible environments is a non-goal. -### Creating EDSLs +The proposed ECSL distribution format does not support shipping multiple variants of ECSLs targeting multiple environments in the same Artifact Bundle, nor does it specify a standardized means for identifying the environment in which a particular ECSL is intended to execute in. +Users are responsible for computing the correct URL of the Artifact Bundle for the environment they are building for, possibly within the package manifest. Swift tooling will not, on its own, diagnose or prevent the installation of an incompatible ECSL. -To compile an EDSL, you just need to build an ordinary SwiftPM library product with the `-enable-library-evolution` flag. This requires no modifications to SwiftPM. +### Creating ECSLs -You would package an EDSL as an `.artifactbundle` just as you would an executable, with the following differences: +To compile an ECSL, you just need to build an ordinary SwiftPM library product with the `-enable-library-evolution` flag. This requires no modifications to SwiftPM. + +You would package an ECSL as an `.artifactbundle` just as you would an executable, with the following differences: - The `info.json` must have `schemaVersion` set to `1.2` or higher. - The artifact type must be `library`, a new enum case introduced in this proposal. - The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. - The artifact payload must include the `.swiftinterface` file corresponding to the actual library object. -Because SwiftPM is not (and cannot be) aware of a particular organization’s ODPs, this enforces the requirement that each ODP must have its own Artifact Bundle. +Because SwiftPM is not (and cannot be) aware of a particular organization’s set of deployment environments, this enforces the requirement that each environment must have its own Artifact Bundle. -The organization that distributes the EDSL is responsible for upholding ABI stability guarantees, including the exact Swift compiler and runtime versions needed to safely consume the EDSL. +The organization that distributes the ECSL is responsible for upholding ABI stability guarantees, including the exact Swift compiler and runtime versions needed to safely consume the ECSL. -### Consuming EDSLs +### Consuming ECSLs -To consume an EDSL, you would add a `binaryTarget` to your `Package.swift` manifest, just as you would for an executable. Because ODPs are identified by the URL of the Artifact Bundle, there are no new fields in the `PackageDescription` API. +To consume an ECSL, you would add a `binaryTarget` to your `Package.swift` manifest, just as you would for an executable. Because organizations are responsible for defining their set of supported environments, they are also responsible for defining the URLs that the Artifact Bundles for each environment are hosted under, so there are no new fields in the `PackageDescription` API. -We expect that the logic for selecting the correct EDSL for a given ODP would live within the `Package.swift` file, that it would be highly organization-specific, and that it would be manipulated using existing means such as environment variables. +We expect that the logic for selecting the correct ECSL for a given environment would live within the `Package.swift` file, that it would be highly organization-specific, and that it would be manipulated using existing means such as environment variables. -### Deploying EDSLs +### Deploying ECSLs -Deploying EDSLs does not involve SwiftPM or Artifact Bundles at all. You would deploy an EDSL by copying the latest binaries to the appropriate `@rpath` location on each machine in your fleet. The `@rpath` location is part of the ODP definition, and is not modeled by SwiftPM. +Deploying ECSLs does not involve SwiftPM or Artifact Bundles at all. You would deploy an ECSL by copying the latest binaries to the appropriate `@rpath` location on each machine in your fleet. The `@rpath` location is part of the organization-specific environment definition, and is not modeled by SwiftPM. -Some organizations might choose to forgo the `@rpath` mechanism entirely and simply install the EDSLs in a system-wide location. +Some organizations might choose to forgo the `@rpath` mechanism entirely and simply install the ECSLs in a system-wide location. ## Detailed design @@ -111,7 +114,7 @@ Below is an example of an `info.json` file for an Artifact Bundle containing a s } ``` -The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. An EDSL Artifact Bundle can contain multiple libraries at the top level. +The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. An ECSL Artifact Bundle can contain multiple libraries at the top level. Below is an example of the layout of an Artifact Bundle containing a single library called `MyLibrary`. Only the `info.json` must appear at the root of the Artifact Bundle; all other files can appear at whatever paths are defined in the `info.json`, as long as they are within the Artifact Bundle. @@ -123,12 +126,12 @@ Below is an example of the layout of an Artifact Bundle containing a single libr 📝 info.json ``` -A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. EDSLs will be supported on macOS, although we expect this will be an exceedingly rare use case. +A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. ECSLs will be supported on macOS, although we expect this will be an exceedingly rare use case. ## Security -EDSLs are not intended for public distribution, and are not subject to the same security concerns as public libraries. Organizations that distribute EDSLs are responsible for ensuring that the EDSLs are safe to consume. +ECSLs are not intended for public distribution, and are not subject to the same security concerns as public libraries. Organizations that distribute ECSLs are responsible for ensuring that the ECSLs are safe to consume. ## Impact on existing packages @@ -138,19 +141,19 @@ There will be no impact on existing packages. All Artifact Bundle schema changes ## Alternatives considered -### Extending Platform Triples to model ODPs +### Extending Platform Triples to model deployment targets SwiftPM currently uses Platform Triples to select among artifact variants when consuming executables. This is workable because it is usually feasible to build executables that are portable across the range of platforms encompassed by a single Platform Triple. -We could extend Platform Triples to model ODPs, but this would privilege a narrow set of predefined deployment architectures, and if you wanted to add a new ODP, you would have to modify SwiftPM to teach it to recognize the new ODP. +We could extend Platform Triples to model ECSL deployment targets, but this would privilege a narrow set of predefined deployment architectures, and if you wanted to add a new environment, you would have to modify SwiftPM to teach it to recognize the new environment. -### Supporting multiple variants of an EDSL in the same Artifact Bundle +### Supporting multiple variants of an ECSL in the same Artifact Bundle -We could allow an Artifact Bundle to contain multiple variants of an EDSL, but we would still need to support a way to identify those variants, which in practice makes SwiftPM aware of ODPs. +We could allow an Artifact Bundle to contain multiple variants of an ECSL, but we would still need to support a way to identify those variants, which in practice forces SwiftPM to become aware of organization-defined environments. -We also don’t see much value in this feature, as you would probably package and upload EDSLs using one CI/CD workflow per ODP anyway. Combining artifacts would require some kind of synchronization mechanism to await all pipelines before fetching and merging bundles. +We also don’t see much value in this feature, as you would probably package and upload ECSLs using one CI/CD workflow per environment anyway. Combining artifacts would require some kind of synchronization mechanism to await all pipelines before fetching and merging bundles. -One benefit of merging bundles would be that it reduces the number of checksums you need to keep track of, but we expect that most organizations will have a very small number of ODPs, with new ODPs continously phasing out old ODPs. +One benefit of merging bundles would be that it reduces the number of checksums you need to keep track of, but we expect that most organizations will have a very small number of supported environments, with new environments continously phasing out old environments. ### Using a different `ArtifactType` name besides `library` From e731f51d247ac853175f214c3b59f5b80a4c2f8d Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Thu, 10 Jul 2025 18:24:53 +0000 Subject: [PATCH 429/505] rename proposal --- ...raries.md => NNNN-environment-constrained-shared-libraries.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposals/{NNNN-environment-dependent-shared-libraries.md => NNNN-environment-constrained-shared-libraries.md} (100%) diff --git a/proposals/NNNN-environment-dependent-shared-libraries.md b/proposals/NNNN-environment-constrained-shared-libraries.md similarity index 100% rename from proposals/NNNN-environment-dependent-shared-libraries.md rename to proposals/NNNN-environment-constrained-shared-libraries.md From 345640f7a3d924a816a455ea21b8ba4245162514 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Thu, 10 Jul 2025 21:07:58 +0000 Subject: [PATCH 430/505] example URLs --- proposals/NNNN-environment-constrained-shared-libraries.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/NNNN-environment-constrained-shared-libraries.md b/proposals/NNNN-environment-constrained-shared-libraries.md index 5c7a228bf9..2d963c6c57 100644 --- a/proposals/NNNN-environment-constrained-shared-libraries.md +++ b/proposals/NNNN-environment-constrained-shared-libraries.md @@ -13,9 +13,9 @@ SwiftPM currently has no support for non-system binary library dependencies on L Swift-evolution thread: [Discussion thread](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605) -Example Producer: [swift-ECSL-example](https://github.com/tayloraswift/swift-ECSL-example) +Example Producer: [swift-dynamic-library-example](https://github.com/tayloraswift/swift-dynamic-library-example) -Example Consumer: [swift-ECSL-example-client](https://github.com/tayloraswift/swift-ECSL-example-client) +Example Consumer: [swift-dynamic-library-example-client](https://github.com/tayloraswift/swift-dynamic-library-example-client) ## Motivation From e3b6bb27df3f1992da04a2ae859d0ec74f5eb91e Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Thu, 10 Jul 2025 21:11:13 +0000 Subject: [PATCH 431/505] =?UTF-8?q?library=20=E2=86=92=20dynamicLibrary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NNNN-environment-constrained-shared-libraries.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/NNNN-environment-constrained-shared-libraries.md b/proposals/NNNN-environment-constrained-shared-libraries.md index 2d963c6c57..f2394d4d2f 100644 --- a/proposals/NNNN-environment-constrained-shared-libraries.md +++ b/proposals/NNNN-environment-constrained-shared-libraries.md @@ -57,7 +57,7 @@ To compile an ECSL, you just need to build an ordinary SwiftPM library product w You would package an ECSL as an `.artifactbundle` just as you would an executable, with the following differences: - The `info.json` must have `schemaVersion` set to `1.2` or higher. -- The artifact type must be `library`, a new enum case introduced in this proposal. +- The artifact type must be `dynamicLibrary`, a new enum case introduced in this proposal. - The artifact must have exactly one variant in the `variants` list, and the `supportedTriples` field is forbidden. - The artifact payload must include the `.swiftinterface` file corresponding to the actual library object. @@ -84,12 +84,12 @@ Some organizations might choose to forgo the `@rpath` mechanism entirely and sim ### Schema extensions -We will extend the `ArtifactsArchiveMetadata` schema to include a new `library` case in the `ArtifactType` enum. +We will extend the `ArtifactsArchiveMetadata` schema to include a new `dynamicLibrary` case in the `ArtifactType` enum. ```diff public enum ArtifactType: String, RawRepresentable, Decodable { case executable -+ case library ++ case dynamicLibrary case swiftSDK } ``` @@ -106,7 +106,7 @@ Below is an example of an `info.json` file for an Artifact Bundle containing a s "schemaVersion": "1.2", "artifacts": { "MyLibrary": { - "type": "library", + "type": "dynamicLibrary", "version": "1.0.0", "variants": [{ "path": "MyLibrary" }] } @@ -155,6 +155,6 @@ We also don’t see much value in this feature, as you would probably package an One benefit of merging bundles would be that it reduces the number of checksums you need to keep track of, but we expect that most organizations will have a very small number of supported environments, with new environments continously phasing out old environments. -### Using a different `ArtifactType` name besides `library` +### Using a different `ArtifactType` name besides `dynamicLibrary` We intentionally preserved the structure of the `variants` list in the `info.json` file, despite imposing the current restriction of one variant per library, in order to allow this format to be extended in the future to support fully general Dynamic Libraries. From e320e31d49ce6833736ab268368034f0fe68f0c6 Mon Sep 17 00:00:00 2001 From: Dianna Ma Date: Thu, 10 Jul 2025 21:13:29 +0000 Subject: [PATCH 432/505] ce --- proposals/NNNN-environment-constrained-shared-libraries.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/NNNN-environment-constrained-shared-libraries.md b/proposals/NNNN-environment-constrained-shared-libraries.md index f2394d4d2f..9a170b0058 100644 --- a/proposals/NNNN-environment-constrained-shared-libraries.md +++ b/proposals/NNNN-environment-constrained-shared-libraries.md @@ -90,6 +90,7 @@ We will extend the `ArtifactsArchiveMetadata` schema to include a new `dynamicLi public enum ArtifactType: String, RawRepresentable, Decodable { case executable + case dynamicLibrary + case staticLibrary case swiftSDK } ``` @@ -126,7 +127,7 @@ Below is an example of the layout of an Artifact Bundle containing a single libr 📝 info.json ``` -A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. ECSLs will be supported on macOS, although we expect this will be an exceedingly rare use case. +A macOS Artifact Bundle would contain a `.dylib` instead of a `.so`. ECSLs will be supported on macOS, although we expect this will be an exceedingly rare use case, as this need is already well-served by the XCFramework. ## Security From fa2415526f8ee8210fd3675ebb1581b967243cd3 Mon Sep 17 00:00:00 2001 From: Suzy Ratcliff Date: Tue, 15 Jul 2025 11:07:43 -0700 Subject: [PATCH 433/505] Updates to the issue severity proposal --- proposals/testing/0013-issue-severity-warning.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index fe89f37c1f..a48c3b1187 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -77,11 +77,11 @@ Issue.record("My comment", severity: .warning) Here is the `Issue.record` method definition with severity as a parameter. ```swift - /// Record an issue when a running test fails unexpectedly. + /// Record an issue when a running test and an issue occurs. /// /// - Parameters: /// - comment: A comment describing the expectation. - /// - severity: The severity of the issue. + /// - severity: The severity level of the issue. This factor impacts whether the issue constitutes a failure. /// - sourceLocation: The source location to which the issue should be /// attributed. /// @@ -117,7 +117,7 @@ public var severity: Severity { get set } ``` -- `isFailure`: A boolean property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. +- `isFailure`: A boolean computed property to determine if an issue results in a test failure, thereby helping in result aggregation and reporting. ```swift extension Issue { @@ -154,7 +154,7 @@ This revision aims to clarify the functionality and usage of the `Severity` enum ### Integration with supporting tools -Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. +Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. `isFailure` is a computed property. The JSON event stream ABI will be amended correspondingly: From f374c6c06f79b07e28615cbe29c8e3b5767b6921 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 15 Jul 2025 12:58:36 -0700 Subject: [PATCH 434/505] [SE-0446] Amend to clarify that types within nonisolated types don't get default main actor inference (#2915) --- proposals/0466-control-default-actor-isolation.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/proposals/0466-control-default-actor-isolation.md b/proposals/0466-control-default-actor-isolation.md index 0da31e90d4..5a1e975d25 100644 --- a/proposals/0466-control-default-actor-isolation.md +++ b/proposals/0466-control-default-actor-isolation.md @@ -66,6 +66,7 @@ When the default actor isolation is specified as `MainActor`, declarations are i * All declarations inside an `actor` type, including static variables, methods, initializers, and deinitializers * Declarations that cannot have global actor isolation, including typealiases, import statements, enum cases, and individual accessors * Declarations whose primary definition directly conforms to a protocol that inherits `SendableMetatype` +* Declarations that are types nested within a nonisolated type The following code example shows the inferred actor isolation in comments given the code is built with `-default-isolation MainActor`: @@ -112,7 +113,13 @@ struct S: P { nonisolated protocol Q: Sendable { } // nonisolated -struct S2: Q { } +struct S2: Q { + // nonisolated + struct Inner { } + + // @MyActor + struct IsolatedInner: P +} // @MainActor struct S3 { } From 6c2e08db9063e0ffa425dad9b6bab15d22ba4722 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:55:34 -0400 Subject: [PATCH 435/505] Accept SE-0470 amendment (#2917) --- proposals/0470-isolated-conformances.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0470-isolated-conformances.md b/proposals/0470-isolated-conformances.md index 0854f6da16..879bd8d05e 100644 --- a/proposals/0470-isolated-conformances.md +++ b/proposals/0470-isolated-conformances.md @@ -3,11 +3,11 @@ * Proposal: [SE-0470](0470-isolated-conformances.md) * Authors: [Doug Gregor](https://github.com/DougGregor) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (July 8...15, 2025)** +* Status: **Implemented (Swift 6.2)** * Vision: [Improving the approachability of data-race safety](https://github.com/swiftlang/swift-evolution/blob/main/visions/approachable-concurrency.md) * Implementation: On `main` with the experimental features `IsolatedConformances` and `StrictSendableMetatypes`. * Upcoming Feature Flag: `InferIsolatedConformances` -* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854)) ([amendment review](https://forums.swift.org/t/amendment-se-0470-global-actor-isolated-conformances/80999)) +* Review: ([pitch](https://forums.swift.org/t/pre-pitch-isolated-conformances/77726)) ([review](https://forums.swift.org/t/se-0470-global-actor-isolated-conformances/78704)) ([acceptance](https://forums.swift.org/t/accepted-se-0470-global-actor-isolated-conformances/79189)) ([amendment pitch](https://forums.swift.org/t/pitch-amend-se-0466-se-0470-to-improve-isolation-inference/79854)) ([amendment review](https://forums.swift.org/t/amendment-se-0470-global-actor-isolated-conformances/80999)) ([amendment acceptance](https://forums.swift.org/t/amendment-accepted-se-0470-global-actor-isolated-conformances/81144)) ## Introduction From b6a9bb7257d95d56ea5ea58114347a63dae9c9cb Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Thu, 17 Jul 2025 10:50:47 -0500 Subject: [PATCH 436/505] Update state of ST-0011 to Implemented and link to acceptance (#2918) --- proposals/testing/0011-issue-handling-traits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0011-issue-handling-traits.md b/proposals/testing/0011-issue-handling-traits.md index c6592bba6f..4d16da9c70 100644 --- a/proposals/testing/0011-issue-handling-traits.md +++ b/proposals/testing/0011-issue-handling-traits.md @@ -3,12 +3,12 @@ * Proposal: [ST-0011](0011-issue-handling-traits.md) * Authors: [Stuart Montgomery](https://github.com/stmontgomery) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) -* Status: **Active Review (Jun 24 - July 8, 2025)** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift-testing#1080](https://github.com/swiftlang/swift-testing/pull/1080), [swiftlang/swift-testing#1121](https://github.com/swiftlang/swift-testing/pull/1121), [swiftlang/swift-testing#1136](https://github.com/swiftlang/swift-testing/pull/1136), [swiftlang/swift-testing#1198](https://github.com/swiftlang/swift-testing/pull/1198) -* Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) ([review](https://forums.swift.org/t/st-0011-issue-handling-traits/80644)) +* Review: ([pitch](https://forums.swift.org/t/pitch-issue-handling-traits/80019)) ([review](https://forums.swift.org/t/st-0011-issue-handling-traits/80644)) ([acceptance](https://forums.swift.org/t/accepted-st-0011-issue-handling-traits/81112)) ## Introduction From 8653025fe43750a1aabd50bcd5d1a7748ea476bd Mon Sep 17 00:00:00 2001 From: taylorswift Date: Sat, 19 Jul 2025 16:38:31 -0500 Subject: [PATCH 437/505] =?UTF-8?q?Dianna=20=E2=86=92=20Diana=20(#2920)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- proposals/0184-unsafe-pointers-add-missing.md | 2 +- proposals/0243-codepoint-and-character-literals.md | 2 +- proposals/0266-synthesized-comparable-for-enumerations.md | 2 +- proposals/0370-pointer-family-initialization-improvements.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0184-unsafe-pointers-add-missing.md b/proposals/0184-unsafe-pointers-add-missing.md index 772376bbdb..a8cff99c6b 100644 --- a/proposals/0184-unsafe-pointers-add-missing.md +++ b/proposals/0184-unsafe-pointers-add-missing.md @@ -1,7 +1,7 @@ # Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size * Proposal: [SE-0184](0184-unsafe-pointers-add-missing.md) -* Author: [Dianna Ma (“Taylor Swift”)](https://github.com/tayloraswift) +* Author: [Diana Ma (“Taylor Swift”)](https://github.com/tayloraswift) * Review Manager: [Doug Gregor](https://github.com/DougGregor) * Status: **Implemented (Swift 4.1)** * Implementation: [apple/swift#12200](https://github.com/apple/swift/pull/12200) diff --git a/proposals/0243-codepoint-and-character-literals.md b/proposals/0243-codepoint-and-character-literals.md index 6890ca77cf..7df6c0ee75 100644 --- a/proposals/0243-codepoint-and-character-literals.md +++ b/proposals/0243-codepoint-and-character-literals.md @@ -1,7 +1,7 @@ # Integer-convertible character literals * Proposal: [SE-0243](0243-codepoint-and-character-literals.md) -* Authors: [Dianna Ma (“Taylor Swift”)](https://github.com/tayloraswift), [Chris Lattner](https://github.com/lattner), [John Holdsworth](https://github.com/johnno1962) +* Authors: [Diana Ma (“Taylor Swift”)](https://github.com/tayloraswift), [Chris Lattner](https://github.com/lattner), [John Holdsworth](https://github.com/johnno1962) * Review manager: [Ben Cohen](https://github.com/airspeedswift) * Status: **Rejected** ([Rationale](https://forums.swift.org/t/se-0243-codepoint-and-character-literals/21188/341)) * Implementation: [apple/swift#21873](https://github.com/apple/swift/pull/21873) diff --git a/proposals/0266-synthesized-comparable-for-enumerations.md b/proposals/0266-synthesized-comparable-for-enumerations.md index 2ed30a3bd4..1c43e83890 100644 --- a/proposals/0266-synthesized-comparable-for-enumerations.md +++ b/proposals/0266-synthesized-comparable-for-enumerations.md @@ -1,7 +1,7 @@ # Synthesized `Comparable` conformance for `enum` types * Proposal: [SE-0266](0266-synthesized-comparable-for-enumerations.md) -* Author: [Dianna Ma (taylorswift)](https://github.com/tayloraswift) +* Author: [Diana Ma (taylorswift)](https://github.com/tayloraswift) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) * Status: **Implemented (Swift 5.3)** * Implementation: [apple/swift#25696](https://github.com/apple/swift/pull/25696) diff --git a/proposals/0370-pointer-family-initialization-improvements.md b/proposals/0370-pointer-family-initialization-improvements.md index 4c107ed4ed..9786754117 100644 --- a/proposals/0370-pointer-family-initialization-improvements.md +++ b/proposals/0370-pointer-family-initialization-improvements.md @@ -1758,6 +1758,6 @@ One of the pre-existing returned tuples does not have element labels, and the or ## Acknowledgments -[Dianna Ma](https://github.com/tayloraswift) (aka [Taylor Swift](https://forums.swift.org/u/taylorswift/summary))'s initial versions of the pitch that became SE-0184 included more functions to manipulate initialization state. These were deferred, but much of the deferred functionality has not been pitched again until now. +[Diana Ma](https://github.com/tayloraswift) (aka [Taylor Swift](https://forums.swift.org/u/taylorswift/summary))'s initial versions of the pitch that became SE-0184 included more functions to manipulate initialization state. These were deferred, but much of the deferred functionality has not been pitched again until now. Members of the Swift Standard Library team for valuable discussions. From 7aaac24233e784295a25b1df0c8a0ed71472e34f Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Mon, 21 Jul 2025 13:28:13 -0400 Subject: [PATCH 438/505] Update 0488-extracting.md --- proposals/0488-extracting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0488-extracting.md b/proposals/0488-extracting.md index 4bf57d7ec9..351bae8bdd 100644 --- a/proposals/0488-extracting.md +++ b/proposals/0488-extracting.md @@ -3,9 +3,9 @@ * Proposal: [SE-0488](0488-extracting.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Active Review (July 2–July 16, 2025)** +* Status: **Accepted** * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. -* Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) ([review](https://forums.swift.org/t/se-0488-apply-the-extracting-slicing-pattern-more-widely/80854)) +* Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) ([review](https://forums.swift.org/t/se-0488-apply-the-extracting-slicing-pattern-more-widely/80854)) ([acceptance](https://forums.swift.org/t/accepted-se-0488-apply-the-extracting-slicing-pattern-more-widely/81235)) [SE-0437]: 0437-noncopyable-stdlib-primitives.md [SE-0447]: 0447-span-access-shared-contiguous-storage.md From f5c40777918924786dd687a715e9afb13d418361 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 25 Jul 2025 10:10:33 +0100 Subject: [PATCH 439/505] [Vision] Add Platform Support vision document. Publish the Platform Support vision document. --- visions/platform-support.md | 285 ++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 visions/platform-support.md diff --git a/visions/platform-support.md b/visions/platform-support.md new file mode 100644 index 0000000000..c413e252f1 --- /dev/null +++ b/visions/platform-support.md @@ -0,0 +1,285 @@ +# Swift Platform Support: A Vision for Evolution + +The Swift programming language has evolved into a versatile and powerful tool +for developers across a wide range of platforms. As the ecosystem continues to +grow, it is essential to establish a clear and forward-looking vision for +platform support. This vision has two main goals: + +1. To establish common terminology and definitions for platform support. + +2. To document a process for platforms to become officially supported in Swift. + +## Understanding Platforms in the Swift Ecosystem + +The term "platform" carries multiple interpretations. For our purposes, a +platform represents the confluence of operating system, architecture, and +environment where Swift code executes. Each platform is identified using a +version-stripped LLVM `Triple`—a precise technical identifier that captures the +essential characteristics of a host environment (e.g., +`x86_64-unknown-windows-msvc`). + +## The Anatomy of a `Triple` + +At its core, a `Triple` comprises 11 distinct elements arranged in a specific +pattern: + +``` +[architecture][sub-architecture][extensions][endian]-[vendor]-[kernel/OS][version]-[libc/environment][abi][version]-[object format] +``` + +This naming convention might initially appear complex, but it offers remarkable +precision. When a public entity isn't associated with a toolchain, the +placeholder `unknown` is used for the vendor field. Similarly, bare-metal +environments—those without an operating system—employ `none` as their OS/kernel +designation. + +While many of these fields may be elided, for use in Swift, the vendor and OS +fields are always included, even if they are placeholder values. + +Consider these illustrative examples: + +- `armv7eb-unknown-linux-uclibceabihf-coff`: A Linux system running on ARMv7 in big-endian mode, with the µClibc library and PE/COFF object format. +- `aarch64-unknown-windows-msvc-macho`: Windows NT on the ARM64 architecture using the MSVC runtime with Mach-O object format. +- `riscv64gcv-apple-ios14-macabi`: An iOS 14 environment running on a RISC-V processor with specific ISA extensions. + +This nomenclature creates a shared language for discussing platform capabilities +and constraints—an essential foundation for our support framework. + +## Distributions within Platforms + +A platform and distribution, while related, serve distinct roles in the Swift +ecosystem. A platform refers to the broader combination of Operating System, +architecture, and environment where Swift code executes and establishes the +foundational compatibility and functionality of Swift. + +A distribution, on the other hand, represents a specific implementation or +variant within a platform. For example, while Linux as a platform is supported, +individual distributions such as Ubuntu, Fedora, or Amazon Linux require +additional work to ensure that Swift integrates seamlessly. This includes +addressing distribution-specific configurations, dependencies, and conventions. + +Distributions are treated similarly to platforms in that they require a +designated owner. This owner is responsible for ensuring that Swift functions +properly on the distribution, adheres to the distribution's standards, and +remains a responsible citizen within that ecosystem. By assigning ownership, the +Swift community ensures that each distribution receives the attention and +stewardship necessary to maintain a high-quality experience for developers. + +## Platform Stewardship + +The health of each platform depends on active stewardship. Every platform in the +Swift ecosystem requires a designated owner who reviews platform-specific +changes and manages release activities. Platforms without active owners enter a +dormant state, reverting to exploratory status until new leadership emerges. + +This ownership model ensures that platform support remains intentional rather +than accidental—each supported environment has an advocate invested in its +success. + +The Platform Steering Group will regularly review the list of supported +platforms against the tier criteria below. While the Platform Steering Group +reserves the right to update the list or the tier criteria at any time, it is +expected that most such changes will be aligned with the Swift release cycle. + +## A Tiered Approach to Platform Support + +Swift's platform support strategy employs three distinct tiers, each +representing a different level of maturity. The requirements for each tier build +upon those of the previous tier. + +### Tier 1: "Supported" Platforms + +These are Swift's most mature environments, where the language must consistently +build successfully and pass comprehensive test suites. Swift on these platforms +offers the strongest guarantees of stability and performance. + +Platforms that are in Tier 1 should: + +- [ ] Digitally sign their release artifacts. +- [ ] Include a Software Bill of Materials (SBOM). + +- [ ] Include at a minimum the following Swift libraries: + + - [ ] Swift Standard Library + - [ ] Swift Supplemental Libraries + - [ ] Swift Core Libraries + - [ ] Swift Testing Frameworks (if applicable) + + (See [the Swift Runtime Libraries + document](https://github.com/swiftlang/swift/blob/main/Runtimes/Readme.md) + in [the Swift repository](https://github.com/swiftlang/swift).) + +- [ ] Maintain a three-version window of support, including: + + - [ ] At least one stable release. + - [ ] The next planned release. + - [ ] The development branch (`main`). + +- [ ] Have a clear, documented, story for debugging, to allow users to set up + an environment where their products can be executed on a device or + simulator and be debugged. + +- [ ] Have testing in CI, including PR testing. + +- [ ] Ship SDKs as regular release from [swift.org](https://swift.org) + +- [ ] Ensure that instructions needed to get started on the platform + are publicly available, ideally on or linked to from + [swift.org](https://swift.org). + +An important aspect of Tier 1 platforms is that maintenance of support +of these platforms is the collective responsibility of the Swift +project as a whole, rather than falling entirely on the platform +owner. This means: + +- Contributions should not be accepted if they break a Tier 1 platform. + +- If a Tier 1 platform does break, whoever is responsible for the code + that is breaking must work with the platform owner on some kind of + resolution, which may mean backing out the relevant changes. + +- New features should aim to function on all Tier 1 + platforms, subject to the availability of appropriate supporting + functionality on each platform. + +- There is a presumption that a release of Swift will be blocked if a + Tier 1 platform is currently broken. This is not a hard and fast + rule, and can be overridden if it is in the interests of the Swift + project as a whole. + +### Tier 1: "Supported" Toolchain Hosts + +Each toolchain host is an expensive addition to the testing matrix. +In addition to the requirements above, a toolchain host platform should: + +- [ ] Have CI coverage for the toolchain, including PR testing. + +- [ ] Offer toolchain distributions from + [swift.org](https://swift.org) as an official source, though + other distributions may also be available. + +- [ ] Include the following toolchain components: + + - [ ] Swift compiler (`swiftc`). + - [ ] C/C++ compiler (`clang`, `clang++`). + - [ ] Assembler (LLVM integrated assembler, built into `clang`). + - [ ] Linker (_typically_ `lld`). + - [ ] Debugger (`lldb`). + - [ ] Swift Package Manager (SwiftPM). + - [ ] Language Server (`sourcekit-lsp`). + - [ ] Debug Adapter (`lldb-dap`). + +- [ ] Code-sign individual tools as appropriate for the platform. + +Note that the bar for accepting a platform as a toolchain host is somewhat +higher than the bar for accepting a non-toolchain-host platform. + +### Tier 2: "Experimental" Platforms + +Experimental platforms occupy the middle ground—they must maintain the ability +to build but may experience occasional test failures. These platforms +represent Swift's expanding frontier. + +Platforms in this tier should: + +- [ ] Ensure that dependencies beyond the platform SDK can build from source. + +- [ ] Provide provenance information to validate the software supply chain. + +- [ ] Include at a minimum the following Swift libraries: + + - [ ] Swift Standard Library + - [ ] Swift Supplemental Libraries + - [ ] Swift Core Libraries + - [ ] Swift Testing Frameworks (if applicable) + + (See [the Swift Runtime Libraries + document](https://github.com/swiftlang/swift/blob/main/Runtimes/Readme.md) + in [the Swift repository](https://github.com/swiftlang/swift).) + +- [ ] Maintain at least a two-version window of support, including + + - [ ] The next planned release. + - [ ] The development branch (`main`). + +Unlike Tier 1, the Swift project does not assume collective +responsibility for experimental platforms. Platform owners should +work with individual contributors to keep their platform in a +buildable state. + +### Tier 3: "Exploratory" Platforms + +At the boundary of Swift's reach are exploratory platforms. +Exploratory status offers an entry point for platforms taking their +first steps into the Swift ecosystem. + +Platforms in this tier should: + +- [ ] Support reproducible builds without requiring external + patches, though there is no requirement that these build completely + or consistently. + +- [ ] Maintain support in the current development branch (`main`). + +The Swift Project does not assume collective responsibility for +exploratory platforms. Platform owners are responsible for keeping +their platform in a buildable state. + +## Platform Inclusion Process and Promotion + +Adding platform support begins with a formal request to the Platform Steering +Group, accompanied by a platform owner nomination. This structured yet +accessible approach balances Swift's need for stability with its aspiration for +growth. + +The request should include: + +- [ ] The preferred name of the platform. + +- [ ] The name and contact details of the platform owner. + +- [ ] The support tier into which the platform should be placed. + +- [ ] Instructions to build Swift for the platform, assuming someone + is starting from scratch, including any requirements for the + build system. + +- [ ] A list of tier requirements that are currently _not_ met by the + platform, including an explanation as to _why_ they are not met + and what the proposal is to meet them, if any. + +- [ ] Whether there has been any discussion about provisioning of CI + resources, and if so a copy of or link to that discussion. This + is particularly relevant for a Tier 1 platform request. + +Note that it is _not_ the case that a platform _must_ meet every +requirement of the requested tier in order to be placed into that +tier. The Platform Steering Group will consider each case on its +merits, and will make a decision based on the information at hand as +well as the overall benefit to the Swift Project. It should be +emphasized that the Platform Steering Group reserves the right to +consider factors other than those listed here when making decisions +about official platform support. + +The same process should be used to request a promotion to a higher +tier. + +## Grandfathering and Demotion + +The following platforms are grandfathered into Tier 1 regardless of +any text in this document: + +- All Apple platforms (macOS, iOS and so on). +- Linux +- Windows + +The Platform Steering Group reserves the right to demote any +platform to a lower tier, but regards demotion as a last resort +and will by preference work with platform owners to maintain +support appropriate for their platform's existing tier. + +Note that if your platform is one of the above special cases, and +there is some requirement in this document that is not being met, it +is expected that either there is a very good reason for the +requirement not being met, or that there is some plan to meet it in +future. From df4ef4cbbe372aa5d70232b286451cc3c1ad6b77 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Fri, 25 Jul 2025 07:12:01 -0700 Subject: [PATCH 440/505] Fix dead link in SE-0451 (#2924) --- proposals/0451-escaped-identifiers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0451-escaped-identifiers.md b/proposals/0451-escaped-identifiers.md index 639a1e1a9b..3105c97626 100644 --- a/proposals/0451-escaped-identifiers.md +++ b/proposals/0451-escaped-identifiers.md @@ -127,7 +127,7 @@ We propose extending the backtick-based syntax used to escape keywords as identi We will distinguish these two uses of backticks with the following terminology: * An **escaped identifier** is a sequence of characters surrounded by backticks that starts with `identifier-head` and is followed by zero or more `identifier-character`, as defined in the Swift [grammar](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/summaryofthegrammar/). This is what Swift supports today to treat keywords as identifiers. -* A **raw identifier** is a sequence of characters surrounded by backticks that contains characters other than those allowed in an escaped identifier. The exact contents are described in [Permissible Characters](#permissible-characters) below. +* A **raw identifier** is a sequence of characters surrounded by backticks that contains characters other than those allowed in an escaped identifier. The exact contents are described in [Permitted Characters](#permitted-characters) below. In both cases, the backticks are **not** considered part of the identifier; they only delimit the identifier from surrounding tokens. From a1b9559b75c4c140c5d35e609e623c06e9ae277e Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Mon, 28 Jul 2025 17:26:07 -0400 Subject: [PATCH 441/505] Update 0483-inline-array-sugar.md (#2896) * Update 0483-inline-array-sugar.md Update wording describing dynamic array downsides. * Update 0483-inline-array-sugar.md --- proposals/0483-inline-array-sugar.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index 4b817e413e..fe1be440da 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -144,11 +144,17 @@ class vec3 { } ``` -The way in which Swift privileges `[Double]` with sugar strongly implies you should use that in this translation. This would be the wrong choice. Every access to those coordinate accessors would need to check the bounds (because while the author might ensure that the value of `e` will only ever have length 3, the compiler cannot easily know this) and, in the case of mutation, a check for uniqueness of the pointer. It would also make `vec3` a nontrivial type, which has significant performance implications wherever it is used. `InlineArray<3, Double>` has none of these problems. +The way in which Swift privileges `[Double]` with sugar strongly implies you should use that in this translation. Doing so would have significant performance downsides: +- Creating new instances of `Vec3` requires a heap allocation, and destroying them require a free operation. +- `Vec3` could no longer be `BitwiseCopyable`, instead requiring a reference counting operation to make a copy. +- Access to a coordinate would require pointer chasing, and a contiguous array of `Vec3` objects would not be guaranteed to exist in contiguous memory. +- Every access to those coordinate accessors would need to check the bounds (because while the author might ensure that the value of `e` will only ever have length 3, the compiler cannot easily know this) and, in the case of mutation, a check for uniqueness of the pointer. `InlineArray<3, Double>` has none of these problems. -Other examples include using nested `Array` types i.e. using `[[Double]]` to represent a matrix – which would also have significant negative consequences depending on the use case, compared to using an `InlineArray` to model the same values. In other cases, the "copy on write" nature of `Array` can mislead users into thinking that copies are risk-free, when actually copying an array can lead to "defeating" copy on write in subtle ways that can cause difficult-to-hunt-down performance issues. In all these cases, you need to pick the right one of two options for the performance goals you are trying to achieve. +Other examples include the use of nested `Array` types i.e. using `[[Double]]` to represent a matrix of known size, which would also have noticeable negative performance impact depending on the use case, compared to using an `InlineArray>` (or perhaps `[InlineArray]`) to model the same values. Today, this is possible via custom subscripts that logically represent the inner array within a single `[Double]`, but the introduction of `InlineArray` introduces other potentially more ergonomic options. -It is likely that Swift's choice (deviating from many of its peers) to emphasize its dynamic array through sugar, has led to a negative impact on the culture of writing performant Swift code, with the nicely sugared dynamic arrays (and array value literals) being over-favored. This is not intended to make the case that Swift should _not_ have this sugar. Dynamic arrays are widely useful and Swift's readability goals are improved by Swift having a concise syntax for creating them. But writing performant Swift code inevitably involves having an understanding of the underlying performance characteristics of _all_ the types you are using, and syntax or type naming alone cannot solve this. +In other cases, the "copy on write" nature of `Array` can mislead users into thinking that copies are risk-free, when actually copying an array can lead to "defeating" copy on write in subtle ways that can cause difficult-to-hunt-down performance issues. In all these cases, you need to pick the right one of two options for the performance goals you are trying to achieve. + +Swift's choice (deviating from many of its peers) to only have a dynamic array type, and to emphasize the utility of this type through sugar, has led to a shaping of the culture of writing Swift code that favors the sugared dynamic array even when this leads to otherwise-avoidable negative performance impact. This is not intended to make the case that Swift should _not_ have this sugar. Dynamic arrays are widely useful and Swift's readability goals are improved by Swift having a concise syntax for creating them. But writing performant Swift code inevitably involves having an understanding of the underlying performance characteristics of _all_ the types you are using, and syntax or type naming alone cannot solve this. Of course, all this only matters when you are trying to write code that maximizes performance. But that is a really important use case for Swift. The goal for Swift is a language that is as safe and enjoyable to write as many high-level non-performant languages, but also can achieve peak performance when that is your goal. And the idea is that when you are targeting that level of performance, you don't have to go into "ugly, no longer nice swift" mode to do it, with nice sugared `[Double]` replaced with less pleasant full type name of `InlineArray` – something a user coming from Go or C++ or Rust might find a downgrade. Similarly, attempting to incorporate the word "inline" into the sugar e.g. `[5 inline Int]` creates a worst of both worlds solution that many would find offputting to use, without solving the fundamental issue. From 28e242fb99ae940c98beea6ef2ef64cd311c2330 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Tue, 29 Jul 2025 10:30:52 +0100 Subject: [PATCH 442/505] Update Platform Support document wording. Apparently "grandfathered" is associated with some unfortunate history. Replace it with other wording. --- visions/platform-support.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/visions/platform-support.md b/visions/platform-support.md index c413e252f1..0c38d50c52 100644 --- a/visions/platform-support.md +++ b/visions/platform-support.md @@ -264,10 +264,10 @@ about official platform support. The same process should be used to request a promotion to a higher tier. -## Grandfathering and Demotion +## Existing Platforms and Demotion -The following platforms are grandfathered into Tier 1 regardless of -any text in this document: +The following existing platforms are in Tier 1 regardless of any +text in this document: - All Apple platforms (macOS, iOS and so on). - Linux From 8c281796b4742fed8431dde4a94944be767840c1 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Wed, 30 Jul 2025 07:57:16 +0200 Subject: [PATCH 443/505] ST-0013 has been accepted Update status and added link to acceptance forum post --- proposals/testing/0013-issue-severity-warning.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index a48c3b1187..5c7f0751f7 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -3,9 +3,9 @@ - Proposal: [ST-0013](0013-issue-severity-warning.md) - Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) - Review Manager: [Maarten Engels](https://github.com/maartene) -- Status: **Active Review (July 9...July 23, 2025)** +- Status: **Accepted** - Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ([review](https://forums.swift.org/t/st-0013-test-issue-warnings/80991)) +- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ([review](https://forums.swift.org/t/st-0013-test-issue-warnings/80991)) ([accepted](https://forums.swift.org/t/accepted-st-0013-test-issue-severity/81385)) ## Introduction From 785f4edebb1af6d50aa6c869d6b86da8a3431dd7 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 2 Jul 2025 12:16:54 -0400 Subject: [PATCH 444/505] [WIP] Proposal to add image attachments support to Swift Testing. --- proposals/testing/NNNN-cgimage-attachments.md | 416 ++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 proposals/testing/NNNN-cgimage-attachments.md diff --git a/proposals/testing/NNNN-cgimage-attachments.md b/proposals/testing/NNNN-cgimage-attachments.md new file mode 100644 index 0000000000..28d8764372 --- /dev/null +++ b/proposals/testing/NNNN-cgimage-attachments.md @@ -0,0 +1,416 @@ +# Image attachments in Swift Testing (Apple platforms) + +* Proposal: [ST-NNNN](NNNN-cgimage-attachments.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Review Manager: TBD +* Status: **Awaiting review** +* Bug: rdar://154869058 +* Implementation: [swiftlang/swift-testing#827](https://github.com/swiftlang/swift-testing/pull/827), _et al._ +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) + +## Introduction + +We introduced the ability to add attachments to tests in Swift 6.2. This +proposal augments that feature to support attaching images on Apple platforms. + +## Motivation + +It is frequently useful to be able to attach images to tests for engineers to +review, e.g. if a UI element is not being drawn correctly. If something doesn't +render correctly in a CI environment, for instance, it is very useful to test +authors to be able to download the failed rendering and examine it at-desk. + +Today, Swift Testing offers support for **attachments** which allow a test +author to save arbitrary files created during a test run. However, if those +files are images, the test author must write their own code to encode them as +(for example) JPEG or PNG files before they can be attached to a test. + +## Proposed solution + +We propose adding support for images as a category of Swift type that can be +encoded using standard graphics formats such as JPEG or PNG. Image serialization +is beyond the purview of the testing library, so Swift Testing will defer to the +operating system to provide the relevant functionality. As such, this proposal +covers support for **Apple platforms** only. Support for other platforms such as +Windows is discussed in the **Future directions** section of this proposal. + +## Detailed design + +A new protocol is introduced for Apple platforms: + +```swift +/// A protocol describing images that can be converted to instances of +/// ``Testing/Attachment``. +/// +/// Instances of types conforming to this protocol do not themselves conform to +/// ``Testing/Attachable``. Instead, the testing library provides additional +/// initializers on ``Testing/Attachment`` that take instances of such types and +/// handle converting them to image data when needed. +/// +/// The following system-provided image types conform to this protocol and can +/// be attached to a test: +/// +/// - [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage) +/// - [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage) +/// - [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) +/// (macOS) +/// - [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) +/// (iOS, watchOS, tvOS, visionOS, and Mac Catalyst) +/// +/// You do not generally need to add your own conformances to this protocol. If +/// you have an image in another format that needs to be attached to a test, +/// first convert it to an instance of one of the types above. +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +public protocol AttachableAsCGImage { + /// An instance of `CGImage` representing this image. + /// + /// - Throws: Any error that prevents the creation of an image. + var attachableCGImage: CGImage { get throws } +} +``` + +And conformances are provided for the following types: + +- [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage) +- [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage) +- [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) + (macOS) +- [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) + (iOS, watchOS, tvOS, visionOS, and Mac Catalyst) + +The implementation of `CGImage.attachableCGImage` simply returns `self`, while +the other implementations extract an underlying `CGImage` instance if available +or render one on-demand. + +> [!NOTE] +> The list of conforming types may be extended in the future. The Testing +> Workgroup will determine if additional Swift Evolution reviews are needed. + +### Attaching a conforming image + +New overloads of `Attachment.init()` and `Attachment.record()` are provided: + +```swift +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +extension Attachment { + /// Initialize an instance of this type that encloses the given image. + /// + /// - Parameters: + /// - attachableValue: The value that will be attached to the output of + /// the test run. + /// - preferredName: The preferred name of the attachment when writing it + /// to a test report or to disk. If `nil`, the testing library attempts + /// to derive a reasonable filename for the attached value. + /// - imageFormat: The image format with which to encode `attachableValue`. + /// - sourceLocation: The source location of the call to this initializer. + /// This value is used when recording issues associated with the + /// attachment. + /// + /// The following system-provided image types conform to the + /// ``AttachableAsCGImage`` protocol and can be attached to a test: + /// + /// - [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage) + /// - [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage) + /// - [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) + /// (macOS) + /// - [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) + /// (iOS, watchOS, tvOS, visionOS, and Mac Catalyst) + /// + /// The testing library uses the image format specified by `imageFormat`. Pass + /// `nil` to let the testing library decide which image format to use. If you + /// pass `nil`, then the image format that the testing library uses depends on + /// the path extension you specify in `preferredName`, if any. If you do not + /// specify a path extension, or if the path extension you specify doesn't + /// correspond to an image format the operating system knows how to write, the + /// testing library selects an appropriate image format for you. + public init( + _ attachableValue: T, + named preferredName: String? = nil, + as imageFormat: AttachableImageFormat? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) where AttachableValue == _AttachableImageWrapper + + /// Attach an image to the current test. + /// + /// - Parameters: + /// - image: The value to attach. + /// - preferredName: The preferred name of the attachment when writing it to + /// a test report or to disk. If `nil`, the testing library attempts to + /// derive a reasonable filename for the attached value. + /// - imageFormat: The image format with which to encode `attachableValue`. + /// - sourceLocation: The source location of the call to this function. + /// + /// This function creates a new instance of ``Attachment`` wrapping `image` + /// and immediately attaches it to the current test. + /// + /// The following system-provided image types conform to the + /// ``AttachableAsCGImage`` protocol and can be attached to a test: + /// + /// - [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage) + /// - [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage) + /// - [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) + /// (macOS) + /// - [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) + /// (iOS, watchOS, tvOS, visionOS, and Mac Catalyst) + /// + /// The testing library uses the image format specified by `imageFormat`. Pass + /// `nil` to let the testing library decide which image format to use. If you + /// pass `nil`, then the image format that the testing library uses depends on + /// the path extension you specify in `preferredName`, if any. If you do not + /// specify a path extension, or if the path extension you specify doesn't + /// correspond to an image format the operating system knows how to write, the + /// testing library selects an appropriate image format for you. + public static func record( + _ image: T, + named preferredName: String? = nil, + as imageFormat: AttachableImageFormat? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) where AttachableValue == _AttachableImageWrapper +} +``` + +> [!NOTE] +> `_AttachableImageWrapper` is an implementation detail required by Swift's +> generic type system and is not itself part of this proposal. For completeness, +> its public interface is: +> +> ```swift +> @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +> public struct _AttachableImageWrapper: Sendable, AttachableWrapper where Image: AttachableAsCGImage { +> public var wrappedValue: Image { get } +> } +> ``` + +### Specifying image formats + +A test author can specify the image format to use with `AttachableImageFormat`. +This type abstractly represents the destination image format and, where +applicable, encoding quality: + +```swift +/// A type describing image formats supported by the system that can be used +/// when attaching an image to a test. +/// +/// When you attach an image to a test, you can pass an instance of this type to +/// ``Attachment/record(_:named:as:sourceLocation:)`` so that the testing +/// library knows the image format you'd like to use. If you don't pass an +/// instance of this type, the testing library infers which format to use based +/// on the attachment's preferred name. +/// +/// The PNG and JPEG image formats are always supported. The set of additional +/// supported image formats is platform-specific: +/// +/// - On Apple platforms, you can use [`CGImageDestinationCopyTypeIdentifiers()`](https://developer.apple.com/documentation/imageio/cgimagedestinationcopytypeidentifiers()) +/// from the [Image I/O framework](https://developer.apple.com/documentation/imageio) +/// to determine which formats are supported. +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +public struct AttachableImageFormat: Sendable { + /// The encoding quality to use for this image format. + /// + /// The meaning of the value is format-specific with `0.0` being the lowest + /// supported encoding quality and `1.0` being the highest supported encoding + /// quality. The value of this property is ignored for image formats that do + /// not support variable encoding quality. + public var encodingQuality: Float { get } +} +``` + +Conveniences for the PNG and JPEG formats are provided as they are very widely +used and supported across almost all modern platforms, Web browsers, etc.: + +```swift +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +extension AttachableImageFormat { + /// The PNG image format. + public static var png: Self { get } + + /// The JPEG image format with maximum encoding quality. + public static var jpeg: Self { get } + + /// The JPEG image format. + /// + /// - Parameters: + /// - encodingQuality: The encoding quality to use when serializing an + /// image. A value of `0.0` indicates the lowest supported encoding + /// quality and a value of `1.0` indicates the highest supported encoding + /// quality. + /// + /// - Returns: An instance of this type representing the JPEG image format + /// with the specified encoding quality. + public static func jpeg(withEncodingQuality encodingQuality: Float) -> Self +} +``` + +For instance, to save an image in the JPEG format with 50% image quality, you +can use `.jpeg(withEncodingQuality: 0.5)`. + +On Apple platforms, a convenience initializer that takes an instance of `UTType` +is also provided and lets you select any format supported by the underlying +Image I/O framework: + +```swift +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +extension AttachableImageFormat { + /// The content type corresponding to this image format. + /// + /// The value of this property always conforms to [`UTType.image`](https://developer.apple.com/documentation/uniformtypeidentifiers/uttype-swift.struct/image). + public var contentType: UTType { get } + + /// Initialize an instance of this type with the given content type and + /// encoding quality. + /// + /// - Parameters: + /// - contentType: The image format to use when encoding images. + /// - encodingQuality: The encoding quality to use when encoding images. For + /// the lowest supported quality, pass `0.0`. For the highest supported + /// quality, pass `1.0`. + /// + /// If the target image format does not support variable-quality encoding, + /// the value of the `encodingQuality` argument is ignored. + /// + /// If `contentType` does not conform to [`UTType.image`](https://developer.apple.com/documentation/uniformtypeidentifiers/uttype-swift.struct/image), + /// the result is undefined. + public init(_ contentType: UTType, encodingQuality: Float = 1.0) +} +``` + +### Example usage + +A developer may then easily attach an image to a test by calling +`Attachment.record()` and passing the image of interest. For example, to attach +a rendering of a SwiftUI view as a PNG file: + +```swift +import Testing +import UIKit +import SwiftUI + +@MainActor @Test func `attaching a SwiftUI view as an image`() throws { + let myView: some View = ... + let image = try #require(ImageRenderer(content: myView).uiImage) + Attachment.record(image, named: "my view", as: .png) + // OR: Attachment.record(image, named: "my view.png") +} +``` + +## Source compatibility + +This change is additive only. + +## Integration with supporting tools + +None needed. + +## Future directions + +- Adding support for [`SwiftUI.Image`](https://developer.apple.com/documentation/swiftui/image) + and/or [`SwiftUI.GraphicsContext.ResolvedImage`](https://developer.apple.com/documentation/swiftui/graphicscontext/resolvedimage). + These types do not directly wrap an instance of `CGImage`. + + Since `SwiftUI.Image` conforms to [`SwiftUI.View`](https://developer.apple.com/documentation/swiftui/view), + it is possible to convert an instance of that type to an instance of `CGImage` + using [`SwiftUI.ImageRenderer`](https://developer.apple.com/documentation/swiftui/imagerenderer). + This approach is generalizable to all `SwiftUI.View`-cnforming types, and the + correct approach here may be to provide an `_AttachableViewWrapper` + type similar to the described `_AttachableImageWrapper` type. + +- Adding support for Windows image types. Windows has several generations of + imaging libraries: + + - Graphics Device Interface (GDI), which shipped with the original Windows in + 1985; + - GDI+, which was introduced with Windows XP in 2001; + - Windows Imaging Component (WIC) with Windows Vista in 2006; and + - Direct2D with Windows 7 in 2008. + + Of these libraries, only the original GDI provides a C interface that can be + directly referenced from Swift. The GDI+ interface is written in C++ and the + WIC and Direct2D interfaces are built on top of COM (a C++ abstraction layer.) + This reliance on C++ poses challenges for Swift Testing. Swift/C++ interop is + still a young technology and is not yet able to provide abstractions for + virtual C++ classes. + + None of these Windows' libraries are source compatible with Apple's Core + Graphics API, so support for any of them will require a different protocol. As + of this writing, [an experimental](https://github.com/swiftlang/swift-testing/pull/1245) + GDI- and (partially) GDI+-compatible protocol is available in Swift Testing + that allows a test author to attach an image represented by an `HBITMAP` or + `HICON` instance. Further work will be needed to make this experimental + Windows support usable with the newer libraries' image types. + +- Adding support for X11-compatible image types such as Qt's [`QImage`](https://doc.qt.io/qt-6/qimage.html) + or GTK's [`GdkPixbuf`](https://docs.gtk.org/gdk-pixbuf/class.Pixbuf.html). + We're also interested in implementing something here, but GUI-level libraries + aren't guaranteed to be present on Linux systems, so we cannot rely on their + headers or modules being accessible while building the Swift toolchain. It may + be appropriate to roll such functionality into a hypothetical `swift-x11`, + `swift-wayland`, `swift-qt`, `swift-gtk`, etc. package if one is ever created. + +- Adding support for Android's [`android.graphics.Bitmap`](https://developer.android.com/reference/android/graphics/Bitmap) + type. The Android NDK includes the [`AndroidBitmap_compress()`](https://developer.android.com/ndk/reference/group/bitmap#androidbitmap_compress) + function, but proper support for attaching an Android `Bitmap` may require a + dependency on [`swift-java`](https://github.com/swiftlang/swift-java) in some + form. Going forward, we hope to work with the new [Android Workgroup](https://www.swift.org/android-workgroup/) + to enhance Swift Testing's Android support. + +- Adding support for rendering to a PDF instead of an image. While technically + feasible using [existing](https://developer.apple.com/documentation/coregraphics/cgcontext/init(consumer:mediabox:_:)) + Core Graphics API, we haven't identified sufficient demand for this + functionality. + +## Alternatives considered + +- Doing nothing. Developers would need to write their own image conversion code. + Since this is a very common operation, it makes sense to incorporate it into + Swift Testing directly. + +- Making `CGImage` etc. conform directly to `Attachable`. Doing so would + prevent us from including sidecar data such as the desired `UTType` or + encoding quality as these types do not provide storage for that information. + As well, `NSImage` does not conform to `Sendable` and would be forced down a + code path that eagerly serializes it, which could pessimize its performance + once we introduce attachment lifetimes in a future proposal. + +- Designing a platform-agnostic solution. This would likely require adding a + dependency on an open-source image package such as [ImageMagick](https://github.com/ImageMagick/ImageMagick). + While we appreciate the value of such libraries and we want Swift Testing to + be as portable as possible, that would be a significant new dependency for the + testing library and the Swift toolchain at large. As well, we expect a typical + use case to involve an instance of `NSImage`, `CGImage`, etc. + +- Designing a solution that does not require `UTType` so as to support earlier + Apple platforms. The implementation is based on Apple's Image I/O framework + which requires a Uniform Type Identifier as input anyway, and the older + `CFString`-based interfaces we would need to use have been deprecated for + several years now. The `AttachableImageFormat` type allows us to abstract away + our platform-specific dependency on `UTType` so that, in the future, other + platforms can reuse `AttachableImageFormat` instead of implementing their own + equivalent solution. (As an example, the experimental Windows support + mentioned previously allows a developer to specify an image codec's `CLSID`.) + +- Designing a solution based around _drawing_ into a `CGContext` rather than + acquiring an instance of `CGImage`. If the proposed protocol looked like: + + ```swift + protocol AttachableByDrawing { + func draw(in context: CGContext, for attachment: Attachment) throws + } + ``` + + It would be easier to support alternative destination contexts (primarily PDF + contexts), but we would need to make a complete copy of an image in memory + before serializing it. If you start with an instance of `CGImage` or an object + that wraps an instance of `CGImage`, you can pass it directly to Image I/O. + +- Including convenience getters for additional image formats in + `AttachableImageFormat`. The set of formats we provide up-front support for is + intentionally small and limited to formats that are universally supported by + the various graphics libraries in use today. If we provided a larger set of + formats that are supported on Apple's platforms, developers may run into + difficulties porting their test code to platforms that _don't_ support those + additional formats. + +## Acknowledgments + +Thanks to Apple's testing teams and to the Testing Workgroup for their support +and advice on this project. From 0c5be06f73384218c7859cc7f0bccfb3bfdf3aeb Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 5 Aug 2025 14:04:43 -0400 Subject: [PATCH 445/505] Update status of ST-0012 Exit Test Value Capturing to Accepted --- proposals/testing/0012-exit-test-value-capturing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/testing/0012-exit-test-value-capturing.md b/proposals/testing/0012-exit-test-value-capturing.md index 43c226b4ae..c31fd772ae 100644 --- a/proposals/testing/0012-exit-test-value-capturing.md +++ b/proposals/testing/0012-exit-test-value-capturing.md @@ -3,10 +3,10 @@ * Proposal: [ST-0012](0012-exit-test-value-capturing.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Paul LeMarquand](https://github.com/plemarquand) -* Status: **Active Review (Jul 7 - July 21, 2025)** +* Status: **Implemented (Swift 6.3)** * Bug: [swiftlang/swift-testing#1157](https://github.com/swiftlang/swift-testing/issues/1157) -* Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040) _et al._ -* Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) ([review](https://forums.swift.org/t/st-0012-capturing-values-in-exit-tests/80963)) +* Implementation: [swiftlang/swift-testing#1040](https://github.com/swiftlang/swift-testing/pull/1040), [swiftlang/swift-testing#1165](https://github.com/swiftlang/swift-testing/pull/1165) _et al._ +* Review: ([pitch](https://forums.swift.org/t/pitch-capturing-values-in-exit-tests/80494)) ([review](https://forums.swift.org/t/st-0012-capturing-values-in-exit-tests/80963)) ([acceptance](https://forums.swift.org/t/accepted-st-0012-capturing-values-in-exit-tests/81250)) ## Introduction From dbc790b53d2359fdc67ecd43ebff72780f002489 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 5 Aug 2025 21:06:19 +0200 Subject: [PATCH 446/505] Update and rename NNNN-cgimage-attachments.md to 0014-image-attachments-in-swift-testing-apple-platforms.md --- ...4-image-attachments-in-swift-testing-apple-platforms.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/testing/{NNNN-cgimage-attachments.md => 0014-image-attachments-in-swift-testing-apple-platforms.md} (98%) diff --git a/proposals/testing/NNNN-cgimage-attachments.md b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md similarity index 98% rename from proposals/testing/NNNN-cgimage-attachments.md rename to proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md index 28d8764372..f9c9414a66 100644 --- a/proposals/testing/NNNN-cgimage-attachments.md +++ b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md @@ -1,9 +1,9 @@ # Image attachments in Swift Testing (Apple platforms) -* Proposal: [ST-NNNN](NNNN-cgimage-attachments.md) +* Proposal: [ST-0014](0014-image-attachments-in-swift-testing-apple-platforms.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [Maarten Engels](https://github.com/maartene/) +* Status: **Active Review (August 8th...August 20th, 2025)** * Bug: rdar://154869058 * Implementation: [swiftlang/swift-testing#827](https://github.com/swiftlang/swift-testing/pull/827), _et al._ * Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) From bcbd3f3f348d8484438ec974664889fdaf96e0b1 Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Tue, 5 Aug 2025 21:14:06 +0200 Subject: [PATCH 447/505] Update 0014-image-attachments-in-swift-testing-apple-platforms.md --- .../0014-image-attachments-in-swift-testing-apple-platforms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md index f9c9414a66..20f050cc0c 100644 --- a/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md +++ b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md @@ -6,7 +6,7 @@ * Status: **Active Review (August 8th...August 20th, 2025)** * Bug: rdar://154869058 * Implementation: [swiftlang/swift-testing#827](https://github.com/swiftlang/swift-testing/pull/827), _et al._ -* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) ([review](https://forums.swift.org/t/st-0014-image-attachments-in-swift-testing-apple-platforms/81507)) ## Introduction From ed69d008575c21f478690f72f2b54c1aa747cc02 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Tue, 5 Aug 2025 12:41:07 -0700 Subject: [PATCH 448/505] Proposal acceptance (#2931) --- proposals/0487-extensible-enums.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index f20b9363cc..0d3f19f5b0 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -1,9 +1,9 @@ -# Extensible enums +# Nonexhuastive enums * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Active Review (July 1 — July 10, 2025)** +* Status: **[Accepted](https://forums.swift.org/t/accepted-se-0487-nonexhaustive-enums/81508)** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` From 9f8e4b209fafcde7032fb11d3809b836ce7f0844 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 5 Aug 2025 17:19:07 -0400 Subject: [PATCH 449/505] Accept SE-0483. (#2932) --- proposals/0483-inline-array-sugar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index fe1be440da..0b6623edeb 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -3,9 +3,9 @@ * Proposal: [SE-0483](0483-inline-array-sugar.md) * Authors: [Hamish Knight](https://github.com/hamishknight), [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Active Review (June 6- June 20, 2025)** +* Status: **Accepted** * Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. -* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ([second review](https://forums.swift.org/t/second-review-se-0483-inlinearray-type-sugar/80337)) +* Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ([second review](https://forums.swift.org/t/second-review-se-0483-inlinearray-type-sugar/80337)) ([acceptance](https://forums.swift.org/t/accepted-se-0483-inlinearray-type-sugar/81509)) ## Introduction From 617ce514899747a9eb462142bdbebfdfa9e604cb Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 6 Aug 2025 06:29:39 +0900 Subject: [PATCH 450/505] Mark SE-0471 as implemented in 6.2 (#2933) This is implemented in 6.2 --- proposals/0471-SerialExecutor-isIsolated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0471-SerialExecutor-isIsolated.md b/proposals/0471-SerialExecutor-isIsolated.md index d5e38f80a8..b91e3693ad 100644 --- a/proposals/0471-SerialExecutor-isIsolated.md +++ b/proposals/0471-SerialExecutor-isIsolated.md @@ -3,7 +3,7 @@ * Proposal: [SE-0471](0471-SerialExecutor-isIsolated.md) * Author: [Konrad 'ktoso' Malawski](https://github.com/ktoso) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: https://github.com/swiftlang/swift/pull/79788 & https://github.com/swiftlang/swift/pull/79946 * Review: [Pitch](https://forums.swift.org/t/pitch-serialexecutor-improved-custom-serialexecutor-isolation-checking/78237/), [Review](https://forums.swift.org/t/se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/78834), [Acceptance](https://forums.swift.org/t/accepted-se-0471-improved-custom-serialexecutor-isolation-checking-for-concurrency-runtime/79894) From 8e7e25e4a486265c1b0b39d834cceca964ff80db Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 5 Aug 2025 17:54:38 -0400 Subject: [PATCH 451/505] Flag that SE-0480 is implemented in Swift 6.2 The implementation was "merged" to the 6.2 branch in https://github.com/swiftlang/swift-package-manager/commit/82119770453c29228d318920cf7fb42463d2e648. --- proposals/0480-swiftpm-warning-control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0480-swiftpm-warning-control.md b/proposals/0480-swiftpm-warning-control.md index 5cdb54c201..c0faff43e7 100644 --- a/proposals/0480-swiftpm-warning-control.md +++ b/proposals/0480-swiftpm-warning-control.md @@ -3,7 +3,7 @@ * Proposal: [SE-0480](0480-swiftpm-warning-control.md) * Authors: [Dmitrii Galimzianov](https://github.com/DmT021) * Review Manager: [John McCall](https://github.com/rjmccall), [Franz Busch](https://github.com/FranzBusch) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift-package-manager#8315](https://github.com/swiftlang/swift-package-manager/pull/8315) * Review: ([pitch](https://forums.swift.org/t/pitch-warning-control-settings-for-swiftpm/78666)) ([review](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475)) ([returned for revision](https://forums.swift.org/t/se-0480-warning-control-settings-for-swiftpm/79475/8)) ([acceptance](https://forums.swift.org/t/accepted-se-0480-warning-control-settings-for-swiftpm/80327)) * Previous Proposal: [SE-0443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md) From 86a3bf655008f48b6f998245f2371c273a02b591 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 5 Aug 2025 18:35:16 -0400 Subject: [PATCH 452/505] Mark SE-0483 as implemented. (#2935) --- proposals/0483-inline-array-sugar.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0483-inline-array-sugar.md b/proposals/0483-inline-array-sugar.md index 0b6623edeb..507605ec34 100644 --- a/proposals/0483-inline-array-sugar.md +++ b/proposals/0483-inline-array-sugar.md @@ -3,8 +3,7 @@ * Proposal: [SE-0483](0483-inline-array-sugar.md) * Authors: [Hamish Knight](https://github.com/hamishknight), [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Accepted** -* Implementation: On `main` under the `InlineArrayTypeSugar` experimental feature flag. +* Status: **Implemented (Swift 6.2)** * Review: ([pitch](https://forums.swift.org/t/pitch-inlinearray-type-sugar/79142)) ([first review](https://forums.swift.org/t/se-0483-inlinearray-literal-syntax/79643)) ([second review](https://forums.swift.org/t/second-review-se-0483-inlinearray-type-sugar/80337)) ([acceptance](https://forums.swift.org/t/accepted-se-0483-inlinearray-type-sugar/81509)) ## Introduction From 4e2a82161fc95b6714398df7a367d7ea2ce3a5ae Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Tue, 5 Aug 2025 21:46:07 -0600 Subject: [PATCH 453/505] Accept SE-0489 (#2927) Updating the text to remove implementation details for which the language steering group would encourage further change separately from the Evolution process. --- proposals/0489-codable-error-printing.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/proposals/0489-codable-error-printing.md b/proposals/0489-codable-error-printing.md index 2d3968aea6..6dd70e71a5 100644 --- a/proposals/0489-codable-error-printing.md +++ b/proposals/0489-codable-error-printing.md @@ -3,9 +3,9 @@ * Proposal: [SE-0489](0489-codable-error-printing.md) * Authors: [Zev Eisenberg](https://github.com/ZevEisenberg) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Active review (July 9...22, 2025)** +* Status: **Accepted** * Implementation: https://github.com/swiftlang/swift/pull/80941 -* Review: ([pitch](https://forums.swift.org/t/pitch-improve-encodingerror-and-decodingerror-s-printed-descriptions/79872)) ([review](https://forums.swift.org/t/se-0489-improve-encodingerror-and-decodingerrors-printed-descriptions/81021)) +* Review: ([pitch](https://forums.swift.org/t/pitch-improve-encodingerror-and-decodingerror-s-printed-descriptions/79872)) ([review](https://forums.swift.org/t/se-0489-improve-encodingerror-and-decodingerrors-printed-descriptions/81021)) ([acceptance](https://forums.swift.org/t/accepted-se-0489-improve-encodingerror-and-decodingerrors-printed-descriptions/81380)) ## Introduction @@ -71,19 +71,13 @@ However, it is not easy or pleasant to read such an error, particularly when dea ## Proposed solution -Conform `EncodingError` and `DecodingError` to `CustomDebugStringConvertible` and provide a clean, readable debug description for each. Here is an example of the proposed change for the same decoding error as above. - -``` -Key 'population' not found in keyed decoding container. -Debug description: No value associated with key CodingKeys(stringValue: "population", intValue: nil) ("population"). -Path: [0]/home/country -``` +Conform `EncodingError` and `DecodingError` to `CustomDebugStringConvertible` and provide a clean, readable debug description for each. Complete examples of the before/after diffs are available in the description of the [implementation pull request](https://github.com/swiftlang/swift/pull/80941) that accompanies this proposal. -**Note 1:** this proposal is _not_ intended to specify an exact output format. The above is provided as an example, and is not a guarantee of current or future behavior. You are still free to inspect the contents of thrown errors directly if you need to detect specific problems. +**Note 1:** This proposal is _not_ intended to specify an exact output format, and any examples are not a guarantee of current or future behavior. You are still free to inspect the contents of thrown errors directly if you need to detect specific problems. -**Note 2:** the output could be further improved by modifying `JSONDecoder` to write a better debug description. See [Future Directions](#future-directions) for more. +**Note 2:** The output could be further improved by modifying `JSONDecoder` to write a better debug description. See [Future Directions](#future-directions) for more. ## Detailed design @@ -127,7 +121,7 @@ It is technically possible to backdeploy the `debugDescription` property, but wi ### Better error generation from Foundation encoders/decoders -The debug descriptions generated in Foundation sometimes contain the same information as the new debug descriptions from this proposal. A future change to the standard JSON and Plist encoders and decoders could provide more compact debug descriptions once they can be sure they have the new standard library descriptions available. They could also use a more compact description when rendering the description of a `CodingKey`. Using part of the example from above: +The debug descriptions generated in Foundation sometimes contain the same information as the new debug descriptions from this proposal. A future change to the standard JSON and Plist encoders and decoders could provide more compact debug descriptions once they can be sure they have the new standard library descriptions available. They could also use a more compact description when rendering the description of a `CodingKey`. Take, for example: ``` Debug description: No value associated with key CodingKeys(stringValue: "population", intValue: nil) ("population"). From 25a4771abe0afae298bb1ab69cb5aa5d3e21df63 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Tue, 5 Aug 2025 21:46:40 -0600 Subject: [PATCH 454/505] SE-0487: fixup typo (#2936) --- proposals/0487-extensible-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index 0d3f19f5b0..0b173fe24b 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -1,4 +1,4 @@ -# Nonexhuastive enums +# Nonexhaustive enums * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) From 5a99e00990bfbe056e1a95deb07cca3536188500 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 7 Aug 2025 12:18:48 -0700 Subject: [PATCH 455/505] Mark some stdlib proposals as implemented (#2937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mark some stdlib proposals as implemented * Mark SE-0477 as implemented * Don’t mark SE-0473 as implemented --- proposals/0459-enumerated-collection.md | 2 +- proposals/0477-default-interpolation-values.md | 2 +- proposals/0485-outputspan.md | 2 +- proposals/0488-extracting.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0459-enumerated-collection.md b/proposals/0459-enumerated-collection.md index e9044be172..14071906cd 100644 --- a/proposals/0459-enumerated-collection.md +++ b/proposals/0459-enumerated-collection.md @@ -3,7 +3,7 @@ * Proposal: [SE-0459](0459-enumerated-collection.md) * Author: [Alejandro Alonso](https://github.com/Azoy) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#78092](https://github.com/swiftlang/swift/pull/78092) * Previous Proposal: [SE-0312](0312-indexed-and-enumerated-zip-collections.md) * Review: ([pitch](https://forums.swift.org/t/pitch-add-collection-conformance-for-enumeratedsequence/76680)) ([review](https://forums.swift.org/t/se-0459-add-collection-conformances-for-enumerated/77509)) ([acceptance](https://forums.swift.org/t/accepted-with-modification-se-0459-add-collection-conformances-for-enumerated/78082)) diff --git a/proposals/0477-default-interpolation-values.md b/proposals/0477-default-interpolation-values.md index c880eba3b3..fc024885c9 100644 --- a/proposals/0477-default-interpolation-values.md +++ b/proposals/0477-default-interpolation-values.md @@ -3,7 +3,7 @@ * Proposal: [SE-0477](0477-default-interpolation-values.md) * Authors: [Nate Cook](https://github.com/natecook1000) * Review Manager: [Xiaodi Wu](https://github.com/xwu) -* Status: **Accepted with modifications** +* Status: **Implemented (Swift 6.2)** * Implementation: [swiftlang/swift#80547](https://github.com/swiftlang/swift/pull/80547) * Review: ([pitch](https://forums.swift.org/t/pitch-default-values-for-string-interpolations/69381)) ([review](https://forums.swift.org/t/se-0477-default-value-in-string-interpolations/79302)) ([acceptance](https://forums.swift.org/t/accepted-with-modification-se-0477-default-value-in-string-interpolations/79609)) diff --git a/proposals/0485-outputspan.md b/proposals/0485-outputspan.md index 8772bdecfb..76f467f6fa 100644 --- a/proposals/0485-outputspan.md +++ b/proposals/0485-outputspan.md @@ -3,7 +3,7 @@ * Proposal: [SE-0485](0485-outputspan.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Doug Gregor](https://github.com/DougGregor) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** ([Extensions to standard library types](#extensions) pending) * Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211) * Implementation: [swiftlang/swift#81637](https://github.com/swiftlang/swift/pull/81637) * Review: [Pitch](https://forums.swift.org/t/pitch-outputspan/79473), [Review](https://forums.swift.org/t/se-0485-outputspan-delegate-initialization-of-contiguous-memory/80032), [Acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0485-outputspan-delegate-initialization-of-contiguous-memory/80435) diff --git a/proposals/0488-extracting.md b/proposals/0488-extracting.md index 351bae8bdd..529b1d7e53 100644 --- a/proposals/0488-extracting.md +++ b/proposals/0488-extracting.md @@ -3,7 +3,7 @@ * Proposal: [SE-0488](0488-extracting.md) * Author: [Guillaume Lessard](https://github.com/glessard) * Review Manager: [Tony Allevato](https://github.com/allevato) -* Status: **Accepted** +* Status: **Implemented (Swift 6.2)** * Implementation: underscored `_extracting()` members of `Span` and `RawSpan`, pending elsewhere. * Review: ([pitch](https://forums.swift.org/t/pitch-apply-the-extracting-slicing-pattern-to-span-and-rawspan/80322)) ([review](https://forums.swift.org/t/se-0488-apply-the-extracting-slicing-pattern-more-widely/80854)) ([acceptance](https://forums.swift.org/t/accepted-se-0488-apply-the-extracting-slicing-pattern-more-widely/81235)) From 82a284da5ae16e23b61c00ee85347c510260d6b5 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Tue, 12 Aug 2025 16:07:55 -0500 Subject: [PATCH 456/505] Fix metadata formatting for SE-0487 I think the linked "Accepted" is the reason this proposal isn't showing up in the list on swift.org. --- proposals/0487-extensible-enums.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0487-extensible-enums.md b/proposals/0487-extensible-enums.md index 0b173fe24b..a8e226c95b 100644 --- a/proposals/0487-extensible-enums.md +++ b/proposals/0487-extensible-enums.md @@ -3,11 +3,11 @@ * Proposal: [SE-0487](0487-extensible-enums.md) * Authors: [Pavel Yaskevich](https://github.com/xedin), [Franz Busch](https://github.com/FranzBusch), [Cory Benfield](https://github.com/lukasa) * Review Manager: [Ben Cohen](https://github.com/airspeedswift) -* Status: **[Accepted](https://forums.swift.org/t/accepted-se-0487-nonexhaustive-enums/81508)** +* Status: **Accepted** * Bug: [apple/swift#55110](https://github.com/swiftlang/swift/issues/55110) * Implementation: [apple/swift#80503](https://github.com/swiftlang/swift/pull/80503) * Upcoming Feature Flag: `ExtensibleAttribute` -* Review: ([pitch](https://forums.swift.org/t/pitch-extensible-enums-for-non-resilient-modules/77649)) +* Review: ([pitch](https://forums.swift.org/t/pitch-extensible-enums-for-non-resilient-modules/77649)) ([first review](https://forums.swift.org/t/se-0487-extensible-enums/80114)) ([second review](https://forums.swift.org/t/second-review-se-0487-extensible-enums/80837)) ([acceptance](https://forums.swift.org/t/accepted-se-0487-nonexhaustive-enums/81508)) Previously pitched in: From 82cb84c0e2439da2ee792c6632634c5064be5474 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 20 Aug 2025 20:40:18 -0700 Subject: [PATCH 457/505] Mark SE-0460 as implemented in Swift Next. (#2941) --- proposals/0460-specialized.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0460-specialized.md b/proposals/0460-specialized.md index e39ffc84c8..8c5ead4bd2 100644 --- a/proposals/0460-specialized.md +++ b/proposals/0460-specialized.md @@ -3,8 +3,7 @@ * Proposal: [SE-0460](0460-specialized.md) * Authors: [Ben Cohen](https://github.com/airspeedswift) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Accepted** -* Implementation: Available in nightly toolchains using the underscored `@_specialize` +* Status: **Implemented (Swift Next)** * Review: ([pitch](https://forums.swift.org/t/pitch-explicit-specialization/76967)) ([review](https://forums.swift.org/t/se-0460-explicit-specialization/77541)) ([acceptance](https://forums.swift.org/t/accepted-se-0460-explicit-specialization/78583)) ## Introduction From 08deb52a8f1516ba477d25589c3e832b47ccaeb1 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 20 Aug 2025 22:17:27 -0700 Subject: [PATCH 458/505] Mark SE-0476 as implemented in Swift 6.2. (#2942) --- proposals/0476-abi-attr.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0476-abi-attr.md b/proposals/0476-abi-attr.md index 6bd6c3efa6..22caeee1a2 100644 --- a/proposals/0476-abi-attr.md +++ b/proposals/0476-abi-attr.md @@ -3,8 +3,7 @@ * Proposal: [SE-0476](0476-abi-attr.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Holly Borla](https://github.com/hborla) -* Status: **Accepted** -* Implementation: behind experimental feature `ABIAttribute` (refinements in [swiftlang/swift#80383](https://github.com/swiftlang/swift/pull/80383)) +* Status: **Implemented (Swift 6.2)** * Review: ([pitch](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)) ([review](https://forums.swift.org/t/se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79233)) ([acceptance](https://forums.swift.org/t/accepted-with-modifications-se-0476-controlling-the-abi-of-a-function-initializer-property-or-subscript/79644)) ## Introduction From e432c48f9a9b8447f118368d12dbf657a34c4029 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 22 Aug 2025 17:06:22 -0500 Subject: [PATCH 459/505] Update header fields --- proposals/testing/0013-issue-severity-warning.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 5c7f0751f7..6acec8a213 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -3,9 +3,10 @@ - Proposal: [ST-0013](0013-issue-severity-warning.md) - Authors: [Suzy Ratcliff](https://github.com/suzannaratcliff) - Review Manager: [Maarten Engels](https://github.com/maartene) -- Status: **Accepted** -- Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075) -- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ([review](https://forums.swift.org/t/st-0013-test-issue-warnings/80991)) ([accepted](https://forums.swift.org/t/accepted-st-0013-test-issue-severity/81385)) +- Status: **Implemented (Swift 6.3)** +- Implementation: [swiftlang/swift-testing#1075](https://github.com/swiftlang/swift-testing/pull/1075), + [swiftlang/swift-testing#1247](https://github.com/swiftlang/swift-testing/pull/1247) +- Review: ([pitch](https://forums.swift.org/t/pitch-test-issue-warnings/79285)) ([review](https://forums.swift.org/t/st-0013-test-issue-warnings/80991)) ([acceptance](https://forums.swift.org/t/accepted-st-0013-test-issue-severity/81385)) ## Introduction From 8c9787aff8b8ffc65867e0e9b2033f4382626bee Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 22 Aug 2025 17:07:23 -0500 Subject: [PATCH 460/505] Fix presentation of the event stream format diff --- proposals/testing/0013-issue-severity-warning.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 6acec8a213..398f0b1ed5 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -159,13 +159,13 @@ Issue severity will be in the event stream output when a `issueRecorded` event o The JSON event stream ABI will be amended correspondingly: -``` - ::= { - "isKnown": , ; is this a known issue or not? -+ "severity": , ; the severity of the issue -+ "isFailure": , ; if the issue is a failing issue - ["sourceLocation": ,] ; where the issue occurred, if known -} +```diff + ::= { + "isKnown": , ; is this a known issue or not? ++ "severity": , ; the severity of the issue ++ "isFailure": , ; if the issue is a failing issue + ["sourceLocation": ,] ; where the issue occurred, if known + } ``` Example of an `issueRecorded` event in the json output: From c7c3942254a1061c1e121a5af75ef5e91f739916 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 22 Aug 2025 17:10:05 -0500 Subject: [PATCH 461/505] Improve formatting of the "Console output" section: fix indentation and use Unicode status symbols instead of SF symbols which don't render on a web page --- proposals/testing/0013-issue-severity-warning.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 398f0b1ed5..5c49209f2e 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -176,17 +176,19 @@ Example of an `issueRecorded` event in the json output: ### Console output -When there is an issue recorded with severity warning the output looks like this: +When there is an issue recorded with severity warning, such as using the following code: ```swift - Issue.record("My comment", severity: .warning) +Issue.record("My comment", severity: .warning) ``` +the console output will look like the following: + ``` -􀟈 Test "All elements of two ranges are equal" started. -􀄣 Test "All elements of two ranges are equal" recorded a warning at ZipTests.swift:32:17: Issue recorded -􀄵 My comment -􁁛 Test "All elements of two ranges are equal" passed after 0.001 seconds with 1 warning. +◇ Test "All elements of two ranges are equal" started. +� Test "All elements of two ranges are equal" recorded a warning at ZipTests.swift:32:17: Issue recorded +↳ My comment +✔ Test "All elements of two ranges are equal" passed after 0.001 seconds with 1 warning. ``` ### Trying this out From 3f6d2582bb133fd87dee51d388d29bf632de006f Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 22 Aug 2025 17:11:14 -0500 Subject: [PATCH 462/505] Improve headers within "Integration with supporting tools" --- proposals/testing/0013-issue-severity-warning.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 5c49209f2e..aace60f793 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -153,7 +153,9 @@ For more details on `Issue`, refer to the [Issue Documentation](https://develope This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. -### Integration with supporting tools +## Integration with supporting tools + +### Event stream Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. `isFailure` is a computed property. From f0717e55b96d978e6b5ac066aed3c4f06194b508 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Sun, 24 Aug 2025 21:37:43 -0500 Subject: [PATCH 463/505] Remove "Trying it out" section of the proposal, since this is typically only included in the proposal review announcement on the forums --- proposals/testing/0013-issue-severity-warning.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index aace60f793..42ee86c3d8 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -193,16 +193,6 @@ the console output will look like the following: ✔ Test "All elements of two ranges are equal" passed after 0.001 seconds with 1 warning. ``` -### Trying this out - -To use severity today, checkout the branch here: https://github.com/swiftlang/swift-testing/pull/1189 - -``` -.package(url: "https://github.com/suzannaratcliff/swift-testing.git", branch: "suzannaratcliff:suzannaratcliff/enable-severity"), -``` - -For more details on how to checkout a branch for a package refer to this: https://developer.apple.com/documentation/packagedescription/package/dependency/package(url:branch:) - ## Alternatives considered - Separate Issue Creation and Recording: We considered providing a mechanism to create issues independently before recording them, rather than passing the issue details directly to the `record` method. This approach was ultimately set aside in favor of simplicity and directness in usage. From eac78275136da2ba7c1e8259d5f636f1bf2a2246 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Sun, 24 Aug 2025 21:42:07 -0500 Subject: [PATCH 464/505] Various stylistic and whitespace fixes --- .../testing/0013-issue-severity-warning.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 42ee86c3d8..ca085886ce 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -49,6 +49,7 @@ The `Severity` enum: ```swift extension Issue { // ... + public enum Severity: Codable, Comparable, CustomStringConvertible, Sendable { /// The severity level for an issue which should be noted but is not /// necessarily an error. @@ -63,7 +64,6 @@ extension Issue { /// marked as a failure. case error } - // ... } ``` @@ -78,6 +78,9 @@ Issue.record("My comment", severity: .warning) Here is the `Issue.record` method definition with severity as a parameter. ```swift +extension Issue { + // ... + /// Record an issue when a running test and an issue occurs. /// /// - Parameters: @@ -96,8 +99,7 @@ Here is the `Issue.record` method definition with severity as a parameter. severity: Severity = .error, sourceLocation: SourceLocation = #_sourceLocation ) -> Self - - // ... +} ``` ### Issue Type Enhancements @@ -107,13 +109,11 @@ The Issue type is enhanced with two new properties to better handle and report i - `severity`: This property allows access to the specific severity level of an issue, enabling more precise handling of test results. ```swift -// ... - extension Issue { + // ... -/// The severity of the issue. -public var severity: Severity { get set } - + /// The severity of the issue. + public var severity: Severity { get set } } ``` @@ -141,11 +141,10 @@ extension Issue { Example usage of `severity` and `isFailure`: ```swift -// ... withKnownIssue { // ... } matching: { issue in - return issue.isFailure || issue.severity > .warning + issue.isFailure || issue.severity > .warning } ``` From 44302dcc27e1f14f2fcd77e06e6c768078424dcf Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Sun, 24 Aug 2025 21:40:28 -0500 Subject: [PATCH 465/505] Add a Source Compatibility section to ST-0013 explaining motivation for keeping and deprecating the prior Issue.record() overload --- .../testing/0013-issue-severity-warning.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/proposals/testing/0013-issue-severity-warning.md b/proposals/testing/0013-issue-severity-warning.md index 5c7f0751f7..03223bb502 100644 --- a/proposals/testing/0013-issue-severity-warning.md +++ b/proposals/testing/0013-issue-severity-warning.md @@ -152,6 +152,36 @@ For more details on `Issue`, refer to the [Issue Documentation](https://develope This revision aims to clarify the functionality and usage of the `Severity` enum and `Issue` properties while maintaining consistency with the existing Swift API standards. +## Source compatibility + +The aspect of this proposal which adds a new `severity:` parameter to the +`Issue.record` function introduces the possibility of a source breakage for any +clients who are capturing a reference to the function. Existing code could break +despite the fact that the new parameter specifies a default value of `.error`. +Here's a contrived example: + +``` +// ❌ Source breakage due to new `Issue.Severity` parameter +let myRecordFunc: (Comment?, SourceLocation) -> Issue = Issue.record +``` + +To avoid source breakage, we will maintain the existing overload and preserve +its signature, but mark it deprecated, disfavored, and hidden from documentation: + +```swift +extension Issue { + // ... + + @available(*, deprecated, message: "Use record(_:severity:sourceLocation:) instead.") + @_disfavoredOverload + @_documentation(visibility: private) + @discardableResult public static func record( + _ comment: Comment? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) -> Self +} +``` + ### Integration with supporting tools Issue severity will be in the event stream output when a `issueRecorded` event occurs. This will be a breaking change because some tools may assume that all `issueRecorded` events are failing. Due to this we will be bumping the event stream version and v1 will maintain it's behavior and not output any events for non failing issues. We will also be adding `isFailure` to the issue so that clients will know if the issue should be treated as a failure. `isFailure` is a computed property. From a623ddca9237b760a988d696ec67c72280cec47d Mon Sep 17 00:00:00 2001 From: Maarten Engels Date: Fri, 29 Aug 2025 13:26:41 +0200 Subject: [PATCH 466/505] Update 0014-image-attachments-in-swift-testing-apple-platforms.md --- ...0014-image-attachments-in-swift-testing-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md index 20f050cc0c..b4c95d641a 100644 --- a/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md +++ b/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md @@ -3,10 +3,10 @@ * Proposal: [ST-0014](0014-image-attachments-in-swift-testing-apple-platforms.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Maarten Engels](https://github.com/maartene/) -* Status: **Active Review (August 8th...August 20th, 2025)** +* Status: **Accepted** * Bug: rdar://154869058 * Implementation: [swiftlang/swift-testing#827](https://github.com/swiftlang/swift-testing/pull/827), _et al._ -* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) ([review](https://forums.swift.org/t/st-0014-image-attachments-in-swift-testing-apple-platforms/81507)) +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing/80867)) ([review](https://forums.swift.org/t/st-0014-image-attachments-in-swift-testing-apple-platforms/81507)) ([acceptance](https://forums.swift.org/t/accepted-st-0014-image-attachments-in-swift-testing-apple-platforms/81868)) ## Introduction From 6bb1157bf84ec8ff64c048e95dbd3dacab939a44 Mon Sep 17 00:00:00 2001 From: Rick van Voorden Date: Tue, 3 Jun 2025 20:11:45 -0700 Subject: [PATCH 467/505] add is identical methods --- proposals/NNNN-add-is-identical-methods.md | 713 +++++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 proposals/NNNN-add-is-identical-methods.md diff --git a/proposals/NNNN-add-is-identical-methods.md b/proposals/NNNN-add-is-identical-methods.md new file mode 100644 index 0000000000..aa6c13db53 --- /dev/null +++ b/proposals/NNNN-add-is-identical-methods.md @@ -0,0 +1,713 @@ +# Add `isIdentical(to:)` Methods for Quick Comparisons to Concrete Types + +* Proposal: [SE-NNNN](NNNN-add-is-identical-methods.md) +* Authors: [Rick van Voorden](https://github.com/vanvoorden), [Karoy Lorentey](https://github.com/lorentey) +* Review Manager: TBD +* Status: **Awaiting review** +* Implementation: ([String, Substring](https://github.com/swiftlang/swift/pull/82055)), ([Array, ArraySlice, ContiguousArray](https://github.com/swiftlang/swift/pull/82438)), ([Dictionary, Set](https://github.com/swiftlang/swift/pull/82439)) +* Review: ([Pre-Pitch](https://forums.swift.org/t/-/78792)), ([Pitch #1](https://forums.swift.org/t/-/79145)), ([Pitch #2](https://forums.swift.org/t/-/80496)) + +### Table of Contents + + * [Introduction](#introduction) + * [Motivation](#motivation) + * [Prior Art](#prior-art) + * [Proposed Solution](#proposed-solution) + * [Detailed Design](#detailed-design) + * [`String`](#string) + * [`Substring`](#substring) + * [`Array`](#array) + * [`ArraySlice`](#arrayslice) + * [`ContiguousArray`](#contiguousarray) + * [`Dictionary`](#dictionary) + * [`Set`](#set) + * [Source Compatibility](#source-compatibility) + * [Impact on ABI](#impact-on-abi) + * [Future Directions](#future-directions) + * [Alternatives Considered](#alternatives-considered) + * [Exposing Identity](#exposing-identity) + * [Different Names](#different-names) + * [Generic Contexts](#generic-contexts) + * [Overload for Reference Comparison](#overload-for-reference-comparison) + * [Support for Optionals](#support-for-optionals) + * [Alternative Semantics](#alternative-semantics) + * [Acknowledgments](#acknowledgments) + +## Introduction + +We propose new `isIdentical(to:)` instance methods to concrete types for quickly determining if two instances must be equal by-value. + +## Motivation + +Suppose we need an algorithm that transforms an `Array` of `Int` values to select only the even numbers: + +```swift +func result(for input: [Int]) -> [Int] { + print("computing new result") + return input.filter { + $0 % 2 == 0 + } +} +``` + +This produces a correct answer… but what about performance? We expect our `result` function to run in `O(n)` time across the size of our `input` value. Suppose we need for this algorithm to be called *many* times over the course of our application. It might also be the case that we sometimes call this algorithm with the same `input` value more than once: + +```swift +let a = [1, 2, 3, 4] +print(result(for: a)) +// Prints "computing new result" +// Prints "[2, 4]" +let b = a +print(result(for: b)) +// Prints "computing new result" +// Prints "[2, 4]" +let c = [1, 2, 3, 4] +print(result(for: c)) +// Prints "computing new result" +// Prints "[2, 4]" +let d = [1, 2, 3, 4, 5, 6] +print(result(for: d)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +let e = d +print(result(for: e)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +let f = [1, 2, 3, 4, 5, 6] +print(result(for: f)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +``` + +If we call our `result` function with an `Array` of values and then pass the same `Array` of values again, we might want to return our previous `result` *without* performing another `O(n)` operation. Because our `result` function is a pure function and free of side-effects, we can check the new `input` value against the last `input` value we used to compute our `result`. If the `input` values have not changed, the `result` value *also* must not have changed. + +Here is an attempt to *memoize* our `result`: + +```swift +final class Memoizer { + private var input: [Int]? + private var result: [Int]? + + func result(for input: [Int]) -> [Int] { + if let result = self.result, + self.input == input { + return result + } else { + print("computing new result") + self.input = input + let result = input.filter { + $0 % 2 == 0 + } + self.result = result + return result + } + } +} +``` + +When we pass `input` values we can see that a new `result` is not computed if we already computed a `result` for those same `input` values: + +```swift +let memoizer = Memoizer() +let a = [1, 2, 3, 4] +print(memoizer.result(for: a)) +// Prints "computing new result" +// Prints "[2, 4]" +let b = a +print(memoizer.result(for: b)) +// Prints "[2, 4]" +let c = [1, 2, 3, 4] +print(memoizer.result(for: c)) +// Prints "[2, 4]" +let d = [1, 2, 3, 4, 5, 6] +print(memoizer.result(for: d)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +let e = d +print(memoizer.result(for: e)) +// Prints "[2, 4, 6]" +let f = [1, 2, 3, 4, 5, 6] +print(memoizer.result(for: f)) +// Prints "[2, 4, 6]" +``` + +This looks like a big improvement… until we begin to investigate a little closer. There’s a subtle performance bottleneck here now from a different direction. Our memoization algorithm depends on the value equality of our `input` values — and this is *also* an `O(n)` operation. So while it is true that we have reduced the amount of `O(n)` operations that take place to compute our `result` values, we have *added* `O(n)` operations to determine value equality. As the amount of time spent computing value equality grows, we might no longer see any performance wins from memoization: it would be cheaper to just go ahead and compute a new `result` every time. + +Let’s see another example. Suppose we are working on our SwiftUI app to display Contacts from [SE-0261](0261-identifiable.md). Let’s begin with our basic data model: + +```swift +struct Contact: Identifiable, Equatable { + let id: Int + var name: String + var isFavorite: Bool +} +``` + +We added an `isFavorite` property to indicate our user added this `Contact` value as one of their favorites. + +Here is a SwiftUI view component that displays our favorite `Contact` values in a `FavoriteContactList`: + +```swift +struct FavoriteContactList: View { + @State private var selection: Contact.ID? + + private let contacts: [Contact] + + init(_ contacts: [Contact]) { + self.contacts = contacts + } + + private var favorites: [Contact] { + self.contacts.filter { + $0.isFavorite + } + } + + var body: some View { + List(self.favorites, selection: self.$selection) { contact in + FavoriteCell(contact) + } + } +} +``` + +When we compute our `body` property we also compute our `favorites` property. The implication is that *every* time our `body` property is computed we perform *another* `O(n)` algorithm across our `contacts`. Because our `FavoriteContactList` supports selection, every time our user selects a `Contact` value we update our `State`. Updating our `State` computes our `body` which computes our `favorites` property. So even though our `contacts` values *have not changed*, we *still* pay the performance penalty of *another* `O(n)` operation just to support cell selection. + +This might look like a good opportunity for another attempt at memoization. Here is an approach using a dynamic property wrapper: + +```swift +@propertyWrapper struct Favorites: DynamicProperty { + @State private var storage: Storage + private let contacts: [Contact] + + init(_ contacts: [Contact]) { + self.storage = Storage(contacts) + self.contacts = contacts + } + + func update() { + self.storage.update(self.contacts) + } + + var wrappedValue: [Contact] { + self.storage.wrappedValue + } +} + +extension Favorites { + private final class Storage { + private var contacts: [Contact] + private var favorites: [Contact]? + + init(_ contacts: [Contact]) { + self.contacts = contacts + self.favorites = nil + } + + func update(_ contacts: [Contact]) { + if self.contacts != contacts { + self.contacts = contacts + self.favorites = nil + } + } + + var wrappedValue: [Contact] { + if let favorites = self.favorites { + return favorites + } + print("computing new result") + let favorites = self.contacts.filter { + $0.isFavorite + } + self.favorites = favorites + return favorites + } + } +} +``` + +Here is what that looks like used from our `FavoriteContactList`: + +```swift +struct FavoriteContactList: View { + @State private var selection: Contact.ID? + + @Favorites private var favorites: [Contact] + + init(_ contacts: [Contact]) { + self._favorites = Favorites(contacts) + } + + var body: some View { + List(self.favorites, selection: self.$selection) { contact in + FavoriteCell(contact) + } + } +} +``` + +When we build and run our app we see that we no longer compute our `favorites` values every time our user selects a new `Contact`. But similar to what we saw in our command line utility, we have traded performance in a different direction. The value equality operation we perform is *also* `O(n)`. As the amount of time we spend computing value equality grows, we can begin to spend more time computing value equality than we would have spent computing our `favorites`: we no longer see the performance benefits of memoization. + +This proposal introduces an advanced performance hook for situations like this: a set of `isIdentical(to:)` methods that are designed to return *faster* than an operation to determine value equality. The `isIdentical(to:)` methods can return `true` in `O(1)` to indicate two values *must* be equal. + +## Prior Art + +We said that the performance of the value equality operator on an `Array` value was `O(n)`. This is true in the *worst case*, but there does exist an important “fast path” that can return `true` in constant time. + +Many types in Standard Library are “copy-on-write” data structures. These types present as value types, but can leverage a reference to some shared state to optimize for performance. When we copy this value we copy a reference to shared storage. If we perform a mutation on a copy we can preserve value semantics by copying the storage reference to a unique value before we write our mutation: we “copy” on “write”. + +This means that many types in Standard Library already have some private reference that can be checked in constant time to determine if two values are identical. Because these types copy before writing, two values that are identical by their shared storage *must* be equal by value. What we propose here is a way to “expose” this fast path operation. + +Product engineers have evolved patterns over the years that can already come close to what we are proposing. Product engineers building on `Array` can use `withUnsafeBufferPointer` or `withContiguousStorageIfAvailable` to compare the “identity” of two `Array` values. One drawback here is that these are only guaranteed to return an identity in constant time if there already exists a contiguous storage. If there does *not* exist a contiguous storage, we might have to perform an `O(n)` algorithm — which defeats the purpose of us choosing this as a fast path. Another option might be `withUnsafeBytes`, but this carries some restrictions on the `Element` of our `Array` and also might require for a contiguous storage to be created: an `O(n)` algorithm. + +Even if we were able to use `withUnsafeBytes` for other data structures, a comparison using `memcmp` might compare “unnecessary” bits that do not affect the identity. This slows down our algorithm and also returns “false negatives”: returning `false` when these instances should be treated as identical. + +A solution for modern operating systems is the support we added from [SE-0456](0456-stdlib-span-properties.md) to bridge an `Array` to `Span`. We can then compare these instances using the `isIdentical(to:)` method on `Span`. One drawback here is that we are blocked on back-deploying support for bridging `Array` to `Span`: it is only available on the most modern operating systems. Another drawback is that if our `Array` does not have a contiguous storage, we have to copy one: an `O(n)` operation. We are also blocked on bringing support for `Span` to collection types like `Dictionary` that do not already implement contiguous storage. + +A new `isIdentical(to:)` method could work around all these restrictions. We could return in constant time *without* needing to copy memory to a contiguous storage. We could adopt this method on many types that might not *ever* have a contiguous storage. We could also work with our library maintainers to discuss a back-deployment strategy that could bring this method to legacy operating systems. + +Our proposal would not be the first example of `isIdentical(to:)` shipping across Swift. `String` already ships a public-but-underscored version of this API.[^1] + +```swift +extension String { + /// Returns a boolean value indicating whether this string is identical to + /// `other`. + /// + /// Two string values are identical if there is no way to distinguish between + /// them. + /// + /// Comparing strings this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// string storage object. Therefore, identical strings are guaranteed to + /// compare equal with `==`, but not all equal strings are considered + /// identical. + /// + /// - Performance: O(1) + @_alwaysEmitIntoClient + public func _isIdentical(to other: Self) -> Bool { + self._guts.rawBits == other._guts.rawBits + } +} +``` + +We don’t see this API currently being used in Standard Library, but it’s possible this API is already being used to optimize performance in private frameworks from Apple. + +Many more examples of `isIdentical(to:)` functions are currently shipping in `Swift-Collections`[^2][^3][^4][^5][^6][^7][^8][^9][^10][^11][^12][^13], `Swift-Markdown`[^14], and `Swift-CowBox`[^15]. We also support `isIdentical(to:)` on the upcoming `Span` and `RawSpan` types from Standard Library.[^16] + +## Proposed Solution + +Before we look at the concrete types in this proposal, let’s begin with some more general principles and ideas we would expect for *all* concrete types to follow when adopting this new method. While this specific proposal is not adding a new protocol to Standard Library, it could be helpful to think of an “informal” protocol that guides us in choosing the types to adopt this new method. This could then serve as a guide for library maintainers that might choose to adopt this method on *new* types in the future. + +Suppose we are proposing an `isIdentical(to:)` method on a type `T`. We propose the following axioms that library maintainers should adopt: +* `a.isIdentical(to: a)` is always `true` (Reflexivity) +* If `T` is `Equatable`: + * `a.isIdentical(to: b)` implies `a == b` (*or else `a` and `b` are exceptional values*) + * `isIdentical(to:)` is *meaningfully* faster than `==` + +Let’s look through these axioms a little closer: + +**`a.isIdentical(to: a)` is always `true` (Reflexivity)** + +* An implementation of `isIdentical(to:)` that always returns `false` would not be an impactful API. We must guarantee that `isIdentical(to:)` *can* return `true` at least *some* of the time. + +**If `T` is `Equatable` then `a.isIdentical(to: b)` implies `a == b`** + +* This is the “fast path” performance optimization that will speed up the memoization examples we saw earlier. One important side effect here is that when `a.isIdentical(to: b)` returns `false` we make *no* guarantees about whether or not `a` is equal to `b`. +* We assume this axiom holds only if `a` and `b` are not “exceptional” values. A example of an exceptional value would be if a container that is generic over `Float` contains `nan`. + +**If `T` is `Equatable` then `isIdentical(to:)` is *meaningfully* faster than `==`** + +* While we could implement `isIdentical(to:)` on types like `Int` or `Bool`, these types are not included in this proposal. Our proposal focuses on types that have the ability to return from `isIdentical(to:)` meaningfully faster than `==`. If a type would perform the same amount of work in `isIdentical(to:)` that takes place in `==`, our advice is that library maintainers should *not* adopt `isIdentical(to:)` on this type. There should exist some legit internal fast-path on this type: like a pointer to a storage buffer that can be compared by reference identity. + +This proposal focuses on concrete types that are `Equatable`, but it might also be the case that a library maintainer would adopt `isIdentical(to:)` on a type that is *not* `Equatable`: like `Span`. Our expectation is that a library maintainer adopting `isIdentical(to:)`on a type that is not `Equatable` has some strong and impactful real-world use-cases ready to make use of this API. Just because a library maintainer *can* adopt this API does not imply they *should*. A library maintainer should also be ready to document for product engineers exactly what is implied from `a.isIdentical(to: b)` returning `true`. What does it *mean* for `a` to be “identical” to `b` if we do not have the implication that `a == b`? We leave this decision to the library maintainers that have the most context on the types they have built. + +Suppose we had an `isIdentical(to:)` method available on `Array`. Let’s go back to our earlier example and see how we can use this as an alternative to checking for value equality from our command line utility: + +```swift +final class Memoizer { + ... + + func result(for input: [Int]) -> [Int] { + if let result = self.result, + self.input.isIdentical(to: input) { + return result + } else { + ... + } + } +} +``` + +We can run our previous example and confirm that we are not computing new results when the input has not changed: + +```swift +let memoizer = Memoizer() +let a = [1, 2, 3, 4] +print(memoizer.result(for: a)) +// Prints "computing new result" +// Prints "[2, 4]" +let b = a +print(memoizer.result(for: b)) +// Prints "[2, 4]" +let c = [1, 2, 3, 4] +print(memoizer.result(for: c)) +// Prints "computing new result" +// Prints "[2, 4]" +let d = [1, 2, 3, 4, 5, 6] +print(memoizer.result(for: d)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +let e = d +print(memoizer.result(for: e)) +// Prints "[2, 4, 6]" +let f = [1, 2, 3, 4, 5, 6] +print(memoizer.result(for: f)) +// Prints "computing new result" +// Prints "[2, 4, 6]" +``` + +When we return `true` from `isIdentical(to:)` we skip computing a new `result`. When `isIdentical(to:)` returns `false` we compute a new `result`. Because `isIdentical(to:)` *can* return `false` when two values are equal, we might be computing the same `result` more than once. The performance tradeoff is that because the operation to compute a new `result` is `O(n)` time, we might not *want* to perform another `O(n)` value equality operation to determine if we should compute a new `result`. Our `isIdentical(to:)` will return in constant time no matter how many elements are in `input` or how expensive this value equality operation would be. + +Let’s go back to our SwiftUI app for displaying `Contact` values. Here is what the change would look like to use `isIdentical(to:)` in place of value equality to memoize `favorites`: + +```swift +extension Favorites { + private final class Storage { + ... + + func update(_ contacts: [Contact]) { + if self.contacts.isIdentical(to: contacts) == false { + self.contacts = contacts + self.favorites = nil + } + } + + ... + } +} +``` + +When we build and run our SwiftUI app we confirm that we are not computing new `favorites` when the user selects new `Contact` values from `FavoriteContactList`. + +## Detailed Design + +We propose adding `isIdentical` methods to the following concrete types from Standard Library: +* `String` +* `Substring` +* `Array` +* `ArraySlice` +* `ContiguousArray` +* `Dictionary` +* `Set` + +For each type being presented we codify important semantics in our header documentation. + +### `String` + +```swift +extension String { + /// Returns a boolean value indicating whether this string is identical to + /// `other`. + /// + /// Two string values are identical if there is no way to distinguish between + /// them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - `a.isIdentical(b)` implies `a == b` + /// + /// Comparing strings this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// string storage object. Therefore, identical strings are guaranteed to + /// compare equal with `==`, but not all equal strings are considered + /// identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `Substring` + +```swift +extension Substring { + /// Returns a boolean value indicating whether this substring is identical to + /// `other`. + /// + /// Two substring values are identical if there is no way to distinguish + /// between them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - `a.isIdentical(b)` implies `a == b` + /// + /// Comparing substrings this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// substring storage object. Therefore, identical substrings are guaranteed + /// to compare equal with `==`, but not all equal substrings are considered + /// identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `Array` + +```swift +extension Array { + /// Returns a boolean value indicating whether this array is identical to + /// `other`. + /// + /// Two array values are identical if there is no way to distinguish between + /// them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// + /// Comparing arrays this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// array storage object. Therefore, identical arrays are guaranteed to + /// compare equal with `==`, but not all equal arrays are considered + /// identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `ArraySlice` + +```swift +extension ArraySlice { + /// Returns a boolean value indicating whether this array is identical to + /// `other`. + /// + /// Two array values are identical if there is no way to distinguish between + /// them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// + /// Comparing arrays this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// array storage object. Therefore, identical arrays are guaranteed to + /// compare equal with `==`, but not all equal arrays are considered + /// identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `ContiguousArray` + +```swift +extension ContiguousArray { + /// Returns a boolean value indicating whether this array is identical to + /// `other`. + /// + /// Two array values are identical if there is no way to distinguish between + /// them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// + /// Comparing arrays this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// array storage object. Therefore, identical arrays are guaranteed to + /// compare equal with `==`, but not all equal arrays are considered + /// identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `Dictionary` + +```swift +extension Dictionary { + /// Returns a boolean value indicating whether this dictionary is identical to + /// `other`. + /// + /// Two dictionary values are identical if there is no way to distinguish + /// between them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// + /// Comparing dictionaries this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying + /// dictionary storage object. Therefore, identical dictionaries are + /// guaranteed to compare equal with `==`, but not all equal dictionaries are + /// considered identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +### `Set` + +```swift +extension Set { + /// Returns a boolean value indicating whether this set is identical to + /// `other`. + /// + /// Two set values are identical if there is no way to distinguish between + /// them. + /// + /// For any values `a`, `b`, and `c`: + /// + /// - `a.isIdentical(to: a)` is always `true`. (Reflexivity) + /// - `a.isIdentical(to: b)` implies `b.isIdentical(to: a)`. (Symmetry) + /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, + /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) + /// - `a.isIdentical(b)` implies `a == b` + /// + /// Comparing sets this way includes comparing (normally) hidden + /// implementation details such as the memory location of any underlying set + /// storage object. Therefore, identical sets are guaranteed to compare equal + /// with `==`, but not all equal sets are considered identical. + /// + /// - Performance: O(1) + public func isIdentical(to other: Self) -> Bool { ... } +} +``` + +## Source Compatibility + +This proposal is additive and source-compatible with existing code. + +## Impact on ABI + +This proposal is additive and ABI-compatible with existing code. + +## Future Directions + +Any Standard Library types that are copy-on-write values could be good candidates to add `isIdentical` functions. Here are some potential types to consider for a future proposal: + +* `Character` +* `Dictionary.Keys` +* `Dictionary.Values` +* `KeyValuePairs` +* `StaticBigInt` +* `StaticString` +* `String.UnicodeScalarView` +* `String.UTF16View` +* `String.UTF8View` +* `Substring.UnicodeScalarView` +* `Substring.UTF16View` +* `Substring.UTF8View` +* `UTF8Span` + +This proposal focuses on what we see as the most high-impact types to support from Standard Library. This proposal *is not* meant to discourage adding `isIdentical(to:)` on any of these types at some point in the future. A follow-up “second-round” proposal could focus on these remaining types. + +## Alternatives Considered + +### Exposing Identity + +Our proposal introduces a new instance method on types that uses some underlying concept of “identity” to perform quick comparisons between two instances. A different approach would be to *return* the underlying identity to product engineers. If a product engineer wanted to test two instances for equality by identity they could perform that check themselves. + +There’s a lot of interesting directions to go with that idea… but we don’t think this is right approach for now. Introducing some concept of an “escapable” identity to value types like `Array` would require *a lot* of design. It’s overthinking the problem and solving for something we don’t need right now. + +### Different Names + +Multiple different names have been suggested for these operations. Including: + +* `hasSameRepresentation(as:)` +* `isKnownIdentical(to:)` + +We prefer `isIdentical(to:)`. This also has the benefit of being consistent with the years of prior art we have accumulated across the Swift ecosystem. + +### Generic Contexts + +We proposed an “informal” protocol for library maintainers adopting `isIdentical(to:)` on new types. Could we just build a new protocol in Standard Library? Maybe. We don’t see a big need for this right now. If product engineers would want for these types to conform to some common protocol to use across generic contexts, those product engineers can define that protocol in their own packages. If these protocols “incubate” in the community and become a common practice, we can consider proposing a new protocol in Standard Library. + +Instead of a new protocol, could we somehow add `isIdentical(to:)` on `Equatable`? Maybe. This would introduce some more tricky questions. If we adopt this on *all* `Equatable` types, what do we do about types like `Int` or `Bool` that do not have an ability to perform a fast check for identity? Similar to our last idea, we prefer to focus just on concrete types for now. If product engineers want to make `isIdentical(to:)` available on generic contexts across `Equatable`, we encourage them to experiment with their own extension for that. If this pattern becomes popular in the community, we can consider a new proposal to add this on `Equatable` in Standard Library. + +### Overload for Reference Comparison + +Could we “overload” the `===` operator from `AnyObject`? This proposal considers that question to be orthogonal to our goal of exposing identity equality with the `isIdentical` methods. We could choose to overload `===`, but this would be a larger “conceptual” and “philosophical” change because the `===` operator is currently meant for `AnyObject` types — not value types like `Array`. + +### Support for Optionals + +We can support `Optional` values with the following extension: + +```swift +extension Optional { + public func isIdentical(to other: Self) -> Bool + where Wrapped == Array { + switch (self, other) { + case let (value?, other?): + return value.isIdentical(to: other) + case (nil, nil): + return true + default: + return false + } + } +} +``` + +Because this extension needs no `private` or `internal` symbols from Standard Library, we can omit this extension from our proposal. Product engineers that want this extension can choose to implement it for themselves. + +### Alternative Semantics + +Instead of publishing an `isIdentical` method which implies two types *must* be equal, could we think of things from the opposite direction? Could we publish a `maybeDifferent` method which implies two types *might not* be equal? This then introduces some potential ambiguity for product engineers: to what extent does “maybe different” imply “probably different”? This ambiguity could be settled with extra documentation on the method, but `isIdentical` solves that ambiguity up-front. The `isIdentical` method is also consistent with the prior art in this space. + +In the same way this proposal exposes a way to quickly check if two values *must* be equal, product engineers might want a way to quickly check if two values *must not* be equal. This is an interesting idea, but this can exist as an independent proposal. We don’t need to block the review of this proposal on a review of `isNotIdentical` semantics. + +## Acknowledgments + +Thanks to [Ben Cohen](https://forums.swift.org/t/-/78792/7) for helping to think through and generalize the original use-case and problem-statement. + +Thanks to [David Nadoba](https://forums.swift.org/t/-/80496/61/) for proposing the formal equivalence relation semantics and axioms on concrete types. + +Thanks to [Xiaodi Wu](https://forums.swift.org/t/-/80496/67) for proposing that our equivalence relation semantics would carve-out for “exceptional” values like `Float.nan`. + +[^1]: https://github.com/swiftlang/swift/blob/swift-6.1.2-RELEASE/stdlib/public/core/String.swift#L397-L415 +[^2]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/DequeModule/Deque._Storage.swift#L223-L225 +[^3]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/HashTreeCollections/HashNode/_HashNode.swift#L78-L80 +[^4]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/HashTreeCollections/HashNode/_RawHashNode.swift#L50-L52 +[^5]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Conformances/BigString%2BEquatable.swift#L14-L16 +[^6]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigString%2BUnicodeScalarView.swift#L77-L79 +[^7]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigString%2BUTF8View.swift#L39-L41 +[^8]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigString%2BUTF16View.swift#L39-L41 +[^9]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigSubstring.swift#L100-L103 +[^10]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigSubstring%2BUnicodeScalarView.swift#L94-L97 +[^11]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigSubstring%2BUTF8View.swift#L64-L67 +[^12]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/BigString/Views/BigSubstring%2BUTF16View.swift#L87-L90 +[^13]: https://github.com/apple/swift-collections/blob/1.2.0/Sources/RopeModule/Rope/Basics/Rope.swift#L68-L70 +[^14]: https://github.com/swiftlang/swift-markdown/blob/swift-6.1.1-RELEASE/Sources/Markdown/Base/Markup.swift#L370-L372 +[^15]: https://github.com/Swift-CowBox/Swift-CowBox/blob/1.1.0/Sources/CowBox/CowBox.swift#L19-L27 +[^16]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md From 53c4b2ddbabb5814a57e49119358abd83e99d7a1 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Wed, 3 Sep 2025 15:27:36 -0700 Subject: [PATCH 468/505] Update Section Control proposal to be independent of @const --- proposals/0nnn-section-control.md | 107 ++++++++++++++---------------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md index 3f0d9e0aca..4d30b0bfc7 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0nnn-section-control.md @@ -62,7 +62,7 @@ This proposal recommends to use sections of the various object file formats as t The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". The `@section` attribute relies heavily on the facilities provided by [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), namely the ability to enforce constantness of an expressions. Using `@section` requires that the initializer expression is a constant expression: ```swift -// Place entry into a section, mark as "do not dead strip". +// Place an entry into a section, mark as "do not dead strip". // Initializer expression must be a constant expression. // The global variable is implicitly made statically initialized. @section("__DATA,mysection") @@ -91,24 +91,14 @@ let myPlugin: PluginData = ( On top of specifying a custom section name with the `@section` attribute, marking a variable as `@used` is needed to prevent otherwise unused symbols from being removed by the compiler. When using section placement to e.g. implement linker sets, such values are typically going to have no usage at compile time, and at the same time they should not be exposed in public interface of libraries (not be made public), therefore we the need the `@used` attribute. -A related new attribute, `@constInitialized` is to be added, which can be used to enforce that a global or static variable is statically initialized, without placing it into a custom section. Using attribute `@section` implies `@constInitialized`. - -```swift -// Static initialization can be requested separately -@constInitialized -var fourPages = 4 * 4096 -``` - -Different object file formats (ELF, Mach-O, COFF) have different restrictions and rules on what are valid section names, and cross-platform code will have to use different names for different file formats. To support that, custom section names can be specified as either a string literal, or by referencing a constant global/static declaration that contains the name. The name will be directly set for the symbol in the resulting object file, without any processing. A new `#if objectFileFormat(...)` conditional compilation directive will be provided to support conditionalizing based on the file format: +Different object file formats (ELF, Mach-O, COFF) have different restrictions and rules on what are valid section names, and cross-platform code will have to use different names for different file formats. To support that, custom section names can be specified as a string literal. The name will be directly set for the symbol in the resulting object file, without any processing. A new `#if objectFileFormat(...)` conditional compilation directive will be provided to support conditionalizing based on the file format: ```swift #if objectFileFormat(ELF) -@const let mySectionName = ".mysection" +@section(".mysection") #elseif objectFileFormat(MachO) -@const let mySectionName = "__DATA,mysection" +@section("__DATA,mysection") #endif - -@section(mySectionName) var global = ... ``` @@ -118,7 +108,7 @@ For the ELF file format specifically, the compiler will also emit a “section i ### Attributes @section and @used on global and static variables -Two new attributes are to be added: `@section`, which has a single argument specifying the section name, and a argument-less `@used` attribute. The section name must be either a string literal, or a reference to a constant string declaration. +Two new attributes are to be added: `@section`, which has a single argument specifying the section name, and a argument-less `@used` attribute. The section name must be a string literal. The attributes can be used either together or independently. ```swift // (1) @@ -127,32 +117,23 @@ Two new attributes are to be added: `@section`, which has a single argument spec let global = ... // ✅ // (2) -@const let mySectionName = "__DATA,mysection" - -@section(mySectionName) +@section("__DATA,mysection") let global = ... // ✅ // (3) -@section(Bool.rand() ? "a" : "b") -let global = ... // ❌ -``` - -The section name must not be one of Swift’s runtime reserved sections (e.g. `__swift5_types`, etc.), such sections would be rejected: - -```swift -@section("__TEXT,__swift5_types") -let global = ... // ❌ +@used +let global = ... // ✅ ``` The new attributes (`@section` and `@used`) can be used on variable declarations under these circumstances: * the variable must be a global variable or a static member variable (no local variables, no non-static member variables) * the variable must not be declared inside a generic context (either directly in generic type or nested in a generic type) -* the variable must be a stored property (not be a computed property) +* the variable must be a stored property (not a computed property) * the variable must not have property observers (didSet, willSet) * the initial expression assigned to the variable must be a constant expression, and it must be eligible for static initilization -*Note: These restrictions limit the `@section` and `@used` attributes to only be allowed on variables that are expected to be represented as exactly one statically-initialized global storage symbol (in the linker sense) for the variable’s content. This is generally true for all global and static variables in C and C++, but in Swift global variables might have zero global storage symbols (e.g. a computed property), or need non-trivial storage (e.g. lazily initialized variables with runtime code in the initializer expression).* +> *Note: These restrictions limit the `@section` and `@used` attributes to only be allowed on variables that are expected to be represented as exactly one statically-initialized global storage symbol (in the linker sense) for the variable’s content. This is generally true for all global and static variables in C and C++, but in Swift global variables might have zero global storage symbols (e.g. a computed property), or need non-trivial storage (e.g. lazily initialized variables with runtime code in the initializer expression).* ```swift @section("__DATA,mysection") @used @@ -201,31 +182,34 @@ The effects described above are applied to the storage symbols and don’t gener ### Guaranteed static initialization -Using attribute `@section` requires the initializer expression of the variable to be a constant expression. The `@const` annotation on the expression is not required (it’s implied). On top of the constant-ness, `@section` on a global or static variable enforces **static initialization** on that variable. The variable can be statically initialized, if the constant expression not only represents a valid compile-time constant, but also is able to be constant-folded into a representation that does not require any runtime initialization (pointer relocations/fixups done automatically by the loader are not considered runtime initialization for this purpose). +Using attribute `@section` requires the initializer expression of the variable to be a **constant expression**. It's not required to separately annotate the expression for being a compile-time expression, instead this is implied from the `@section` attribute. On top of the constant-ness, `@section` on a global or static variable enforces **static initialization** on that variable. + +We consider the variable to be eligible for static initialization when: -This is a property that `@const` alone does not provide, but it’s necessary because we expect the data to be readable without any runtime mechanisms (i.e. reading raw bytes from the section at runtime, or offline binary inspection). +1. the initializer expression represents a valid compile-time constant, and +2. the initializer expression can be constant-folded into a representation that does not require any runtime initialization (pointer relocations/fixups done automatically by the loader are not considered runtime initialization for this purpose). + +Not all constant expressions are necessarily statically initializable. For section placement we require the stronger property (static initialization) because we expect the data to be readable without any runtime mechanisms (i.e. reading raw bytes from the section at runtime, or offline binary inspection). ```swift @section("__DATA,mysection") let a = 42 // ✅ @section("__DATA,mysection") -let b = @const 42 // warning: @const is superfluous +let sectionPlaced = ...expression... // ✅, guaranteed to be statically initialized @section("__DATA,mysection") -let sectionPlaced = ...expression... // guaranteed to be statically initialized - -let justConstant = @const ...expression... // not guaranteed to be statically initialized +let notStaticallyInitializable = ...expression that cannot be statically initialized... // ❌ ``` -*Note: As of this writing, all valid constant values are also eligible to be statically initialized, but we don’t expect that to hold in the future. So it’s important to distinguish between (a) a global variable being initialized with a language-level constant value (`@const`), and (b) a global variable that is guaranteed to be statically initialized. The difference can be subtle, and in some cases immaterial in practice, but future enhancements of constant values in Swift might take advantage of this difference — i.e. not all constant values are going to be statically initializable. Consider the following example: If a future language versions allows dictionary literals to be constant values, such values might not be statically initializable because of randomized hash seeding:* +> *Note: As of this writing, all valid constant values are also eligible to be statically initialized, but we don’t expect that to hold in the future. So it’s important to distinguish between (a) a global variable being initialized with a language-level constant value, and (b) a global variable that is guaranteed to be statically initialized. The difference can be subtle, and in some cases immaterial in practice, but future enhancements of constant values in Swift might take advantage of this difference — i.e. not all constant values are going to be statically initializable. Consider the following example: If a future language versions allows dictionary literals to be constant values, such values might not be statically initializable because of randomized hash seeding:* -```swift -let d1 = @const ["a": 42, "b": 777] // constant, but not statically initializable -let d2 = @const d1.count // statically initializable -``` +> ```swift +> let d1 = ["a": 42, "b": 777] // constant, but not statically initializable +> let d2 = d1.count // statically initializable +> ``` -*However, using a statically non-initializable value in an expression does not preclude the outer expression from being statically initialized either. In this example, `d1` would not be allowed to be placed into a custom section because it’s not statically initializable. But `d2` could still potentially be statically initializable (even though the definition of `d2` uses a sub-expression that is not statically initializable), as it’s simply an integer.* +> *However, using a statically non-initializable value in an expression does not preclude the outer expression from being statically initialized either. In this example, `d1` would not be allowed to be placed into a custom section because it’s not statically initializable. But `d2` could still potentially be statically initializable (even though the definition of `d2` uses a sub-expression that is not statically initializable), as it’s simply an integer.* As described in [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), values of function types are eligible for being compile-time evaluable. Their concrete pointer value is not fully known until link-time or program load-time (depending on type of linking, ASLR, PAC, etc.). For the purposes of guaranteed static initialization, function values are statically initialized into a function pointer. This pointer is still subject to normal linking and loading resolutions and fixups. @@ -237,22 +221,6 @@ let a = (42, foo) // "foo" is statically initialized into a // linkable/relocatable pointer ``` -### Attribute `@constInitialized` - -Static initialization of a global can be useful on its own, without placing data into a custom section. For that, a new attribute `@constInitialized` can be used. This attribute can be only used on variable declarations under the same conditions that `@section` and `@used` require (e.g. only on globals and statics, not in generic contexts, etc.) - -```swift -@constInitialized -var fourPages = 4 * 4096 // ✅ - -struct S { - @constInitialized - var fourPages = 4 * 4096 // ❌ -} -``` - -The effect of this attribute is the same as of the `@section` attribute (static initialization, normal initalization behavior if top-level code) except the symbol is not actually placed into any custom sections. - ### Cross-platform object file format support The custom section name specified in the `@section` attribute is not validated by the compiler, instead it’s passed directly as a string to the linker. Different platforms supported by Swift are using different object and binary file formats (Linux uses ELF, Darwin uses Mach-O, Windows uses COFF), and that implies different restrictions and rules on what are valid section names. Because of that, a multi-platform library code is expected to use `#if os(...)` to use different section names for different platforms. Because of that, it’s expected that the attributes are to be typically only used indirectly via macros that hide the low-level nature of sections and object file formats from higher-level code developers: @@ -305,7 +273,7 @@ The goal of placing metadata into custom section is to make them discoverable bo * In Wasm, dynamic linking is work in progress and not generally available yet. * In ELF, however, section bounds are not guaranteed to be present in the address space at runtime, and in practice they are typically not present. This creates a challenge for retrieving section data in this configuration (ELF + multiple modules with dynamic linking) at runtime. -To solve this problem for the ELF object file format, the Swift compiler is going to emit a “**section index**” into every compilation that uses any symbols placed into a custom section. The index will be emitted only when producing ELF files, and consists of entries added into its own separate well-named section called `swift5_sections`. Each entry will have the following structure: +To solve this problem for the ELF object file format, the Swift compiler is going to emit a “**section index**” into every compilation that uses any symbols placed into a custom section. The index will be emitted only when producing ELF files, and consists of entries added into its own separate well-named section called `swift5_sections`. Each entry will have the following structure: ```c struct SectionIndexEntry { @@ -353,6 +321,25 @@ func firmwareBootEntrypoint() { ... } This will require some design decisions to be made around when should that be allowed, whether the attribute should be automatically inherited, and what exact behavior should we expect from the compiler around thunks, compiler-generated helper functions, getters and setters, etc. +### Standalone attribute for required static initialization + +Static initialization of a global can be useful on its own, without placing data into a custom section, and a separate attribute for that could be added. This way, one can get the same effects as the `@section` attribute (static initialization, normal initalization behavior if top-level code) except the symbol would not be actually placed into any custom section. + +### Allowing a reference to a constant string declaration as a section name + +The requirement to only use string literals as the section names could be lifted in the future, and we might allow referring to a declaration of variable with a compile-time string. This would be useful to avoid repetition when placing multiple values into the same section without needing to use macros. + +```swift +#if objectFileFormat(ELF) +let mySectionName = ".mysection" // required to be a compile-time value +#elseif objectFileFormat(MachO) +let mySectionName = "__DATA,mysection" // required to be a compile-time value +#endif + +@section(mySectionName) +var global = ... +``` + ### Runtime discovery of data in custom sections As described in [ELF section index](#elf-section-index), accessing records in a custom section at runtime is heavily dependent on the object file format (ELF, Mach-O, Wasm, COFF), type of linking (static vs dynamic) and available APIs from the operating system. For a single configuration, users can directly use an appropriate method of accessing the section data, and e.g. in embedded firmwares this might be completely fine as projects are commonly avoiding any attempts to be multi-platform or portable. @@ -445,3 +432,7 @@ In a lot of the list code snippets in this proposal, both `@section` and `@used` * `@section` and `@used` represent separate concepts and all combinations of them can be useful. An example of using `@section` without `@used` is to place for example a large data table from a library into its own section for binary size accounting reasons (so that it shows up separately in per-section binary size listings), but where we’d still expect the data table to be dead-code removed if not used. * It’s already common to have those attributes as separate options in existing popular systems programming languages (C, C++, Rust). + +### Blocking section placement into compiler reserved sections + +In most cases, placing data into one of Swift’s runtime reserved sections (e.g. `__swift5_types`, etc.) without relying on extreme details of the compiler and runtime would result in invalid binaries. It was considered to simply reject using `@section` to target one of these reserved sections, but ultimately that would introduce both false positives (*what if we at some point wanted to write compiler/runtime code in Swift to actually legitimately place data into these sections?*) and false negatives (*there are many other "reserved" sections that the Swift compiler and language cannot know about*), and is thus left out of this proposal. From 5bc18da6ed7886553453dfe26076d9e394b281d4 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 5 Sep 2025 14:31:41 +0100 Subject: [PATCH 469/505] Allocate SE-0490 --- ...ries.md => 0490-environment-constrained-shared-libraries.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{NNNN-environment-constrained-shared-libraries.md => 0490-environment-constrained-shared-libraries.md} (99%) diff --git a/proposals/NNNN-environment-constrained-shared-libraries.md b/proposals/0490-environment-constrained-shared-libraries.md similarity index 99% rename from proposals/NNNN-environment-constrained-shared-libraries.md rename to proposals/0490-environment-constrained-shared-libraries.md index 9a170b0058..c4e97a81a4 100644 --- a/proposals/NNNN-environment-constrained-shared-libraries.md +++ b/proposals/0490-environment-constrained-shared-libraries.md @@ -1,6 +1,6 @@ # Environment Constrained Shared Libraries -* Proposal: [SE-NNNN](NNNN-environment-constrained-shared-libraries.md) +* Proposal: [SE-0490](0490-environment-constrained-shared-libraries.md) * Authors: [tayloraswift](https://github.com/tayloraswift) * Review Manager: TBD * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) From e9dfa0ff5eb9cfc1176740d677e6763a830cf7d8 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 5 Sep 2025 14:54:03 +0100 Subject: [PATCH 470/505] Update status and links for SE-0490 --- proposals/0490-environment-constrained-shared-libraries.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proposals/0490-environment-constrained-shared-libraries.md b/proposals/0490-environment-constrained-shared-libraries.md index c4e97a81a4..d4d9447eb1 100644 --- a/proposals/0490-environment-constrained-shared-libraries.md +++ b/proposals/0490-environment-constrained-shared-libraries.md @@ -2,10 +2,12 @@ * Proposal: [SE-0490](0490-environment-constrained-shared-libraries.md) * Authors: [tayloraswift](https://github.com/tayloraswift) -* Review Manager: TBD +* Review Manager: [Alastair Houghton](https://github.com/al45tair) +* Status: **Active Review (Sep 5 - Sep 18, 2025)** * Implementation: [swiftlang/swift-package-manager#8249](https://github.com/swiftlang/swift-package-manager/pull/8249) -* Documentation: [How to use Environment-Constrained Shared Libraries](https://github.com/swiftlang/swift-package-manager/blob/b586467575580f2365e8f5a29c949379724db795/Documentation/ECSLs.md) +* Documentation: [How to use Environment-Constrained Shared Libraries](https://github.com/swiftlang/swift-package-manager/blob/1eaf59d2facc74c88574f38395aa49983b2badcc/Documentation/ECSLs.md) * Bugs: [SR-5714](https://github.com/swiftlang/swift-package-manager/issues/5714) +* Review: ([pitch](https://forums.swift.org/t/pitch-replaceable-library-plugins/77605)) ([review](https://forums.swift.org/t/se-0490-environment-constrained-shared-libraries/81975)) ## Introduction From 8149f46f4f56bcc9b8a9461b39c4d1be2fdd89b6 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 2 Sep 2025 14:28:43 -0700 Subject: [PATCH 471/505] Inline always proposal --- proposals/NNNN-inline-always.md | 348 ++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 proposals/NNNN-inline-always.md diff --git a/proposals/NNNN-inline-always.md b/proposals/NNNN-inline-always.md new file mode 100644 index 0000000000..3b2cf8dd0f --- /dev/null +++ b/proposals/NNNN-inline-always.md @@ -0,0 +1,348 @@ +# `@inline(always)` attribute + +* Proposal: [SE-NNNN](NNNN-inline-always.md) +* Authors: [Arnold Schwaighofer](https://github.com/aschwaighofer) +* Implementation: [swiftlang/swift#84178](https://github.com/swiftlang/swift/pull/84178) + +## Introduction + +The Swift compiler performs an optimization that expands the body of a function +into the caller called inlining. Inlining exposes the code in the callee to the +code in the caller. After inlining, the Swift compiler has more context to +optimize the code across caller and callee leading to better optimization in +many cases. Inlining can increase code size. To avoid unnecessary code size +increases, the Swift compiler uses heuristics (properties of the code) to +determine whether to perform inlining. Sometimes these heuristics tell the +compiler not to inline a function even though it would be beneficial to do so. +The proposed attribute `@inline(always)` instructs the compiler to always inline +the annotated function into the caller giving the author explicit control over +the optimization. + +## Motivation + +Inlining a function referenced by a function call enables the optimizer to see +across function call boundaries. This can enable further optimization. The +decision whether to inline a function is driven by compiler heuristics that +depend on the shape of the code and can vary between compiler versions. + +In the following example the decision to inline might depend on the number of +instructions in `callee` and on detecting that the call to callee is frequently +executed because it is surrounded by a loop. Inlining this case would be +beneficial because the compiler is able to eliminate a store to a stack slot in +the `caller` after inlining the `callee` because the function's `inout` calling +convention ABI that requires an address no longer applies and further +optimizations are enabled by the caller's function's context. + +```swift +func callee(_ result: inout SomeValue, _ cond: Bool) { + result = SomeValue() + if cond { + // many lines of code ... + } +} + +func caller() { + var cond: Bool = false + var x : SomeValue = SomeValue() + for i in 0 ..< 1 { + callee(&x, cond) + } +} + +func callerAfterInlining(_ cond: Bool { + var x : SomeValue = SomeValue() + var cond: Bool = false + for i in 0 ..< 1 { + // Inlined `callee()`: + // Can keep `SomeValue()` in registers because no longer + // passed as an `inout` argument. + x = SomeValue() // Can hoist `x` out of the loop and perform constant + // propagation. + if cond { // Can remove the code under the conditional because it is + // known not to execute. + // many lines of code ... + } + } +} +``` + +The heuristic might fail to detect that code is frequently executed (surrounding +loop structures might be several calls up in the call chain) or the number of +instructions in the callee might be to large for the heuristic to decide that +inlining is beneficial. +Heuristics might change between compiler versions either directly or indirectly +because some properties of the internal representation of the optimized code +changes. +To give code authors reliable control over the inlining process we propose to +add an `@inline(always)` function attribute. + +This optimization control should instruct the compiler to inline the referenced +function or emit an error when it is not possible to do so. + +```swift +@inline(always) +func callee(_ result: inout SomeValue, _ cond: Bool) { + result = SomeValue() + if cond { + // many lines of code ... + } +} +``` + +## Proposed solution + +We desire for the attribute to function as an optimization control. That means +that the proposed `@inline(always)` attribute should emit an error if inlining +cannot be guaranteed in all optimization modes. The value of the function at a +call site can might determined dynamically at runtime. In such cases the +compiler cannot determine a call site which function is applied without doing +global analysis. In these cases we don't guarantee inlining even if the dynamic +value of the applied function was annotated with `@inline(always)`. +We only guarantee inlining if the annotated function is directly referenced and +not derived by some function value computation such as method lookup or function +value (closure) formation and diagnose errors if this guarantee cannot be +upheld. + +A sufficiently clever optimizer might be able to derive the dynamic value at the +call site, in such cases the optimizer shall respect the optimization control +and perform inlining. + +```swift +protocol SomeProtocol { + func mightBeOverriden() +} + +class C : SomeProtocol{ + @inline(always) + func mightBeOverriden() { + } +} + +@inline(always) +func callee() { +} + +func applyFunctionValues(_ funValue: () -> (), c: C, p: SomeProtocol) { + funValue() // function value, not guaranteed + c.mightBeOverriden() // dynamic method lookup, not guaranteed + p.mightBeOverriden() // dynamic method lookup, not guaranteed + callee() // directly referenced, guaranteed +} + +func caller() { + applyFunctionValue(callee, C()) +} + +caller() +``` + +Code authors shall be able to rely on that if a function is marked with +`@inline(always)` and directly referenced from any context (within or outside of +the defining module) that the function can be inlined or an error is emitted. + + +## Detailed design + +We want to diagnose an error if a directly referenced function is marked with +`@inline(always)` and cannot be inlined. What are the cases where this might not +be possible? + +### Interaction with `@inlinable` + +Function bodies of functions referenceable outside of the defining module are +only available to the outside module if the definition is marked `@inlinable`. + +Therefore, a function marked with `@inline(always)` must be marked `@inlinable` +if it has `open`, `public`, or `package` level access. + +```swift +@inline(always) // error: a public function marked @inline(always) must be marked @inlinable +public func callee() { +} +``` + +### Interaction with `@usableFromInline` + +A `public` `@inlinable` function can reference a function with `internal` access +if it is either `@inlinable` (see above) or `@usableFromInline`. `@usableFromInline` +ensures that there is a public entry point to the `internal` level function but +does not ensure that the body of the function is available to external +modules. Therefore, it is an error to combine `@inline(always)` with a +`@usableFromInline` function as we cannot guaranteed that the function can +always be inlined. + +```swift +@inline(always) // error: an internal function marked with `@inline(always)` and + `@usableFromInline` could be referenced from an + `@inlinable` function and must be marked inlinable +@usableFromInline +internal func callee() {} + +@inlinable +public func caller() { + callee() // could not inline callee into external module +} +``` + +### Module internal access levels + +It is okay to mark `internal`, `private` and `fileprivate` function declarations +with `@inline(always)` in cases other than the ones mention above without the +`@inlinable` attribute as they can only be referenced from within the module. + + +```swift +public func caller() { + callee() +} + +@inline(always) // okay because caller would force either `@inlinable` or + // `@usableFromInline` if it was marked @inlinable itself +internal func callee() { +} + + +@inline(always) // okay can only referenced from within the module +private func callee2() { +} +``` + +#### Infinite recursion during inlining + +We will diagnose if inlining cannot happen due to calls within a +[strongly connected component](https://en.wikipedia.org/wiki/Strongly_connected_component) +marked with `@inline(always)` as errors. + +```swift +@inline(always) +func callee() { + ... + if cond2 { + caller() + } +} + +@inline(always) +func caller() { + ... + if cond { + callee() + } +} +``` + +### Dynamic function values + +As outlined earlier the attribute does not guarantee inlining or diagnose the +failure to inline when the function value is dynamic at a call site: a function +value is applied, or the function value is obtained via class method lookup or +protocol lookup. + +```swift +@inline(always) +func callee() {} +func useFunctionValue() { + let f = callee + ... + f() // function value use, not guaranteed to be inlined +} + +class SomeClass : SomeProto{ + @inline(always) + func nonFinalMethod() {} + + @inline(always) + func method() {} +} + +protocol SomeProto { + func method() +} + + +func dynamicMethodLookup() { + let c = SomeClass() + ... + c.nonFinalMethod() // method lookup, not guaranteed to be inlined + + let p: SomeProto = SomeClass() + p.method() // method lookup, not guaranteed to be inlined +} + +class A { + func finalInSub() {} + final func finalMethod() {} +} +class B : A { + overrided final func finalInSub() {} +} + +func noMethodLookup() { + let a = A() + a.finalMethod() // no method lookup, guaranteed to be inlined + + let b = B() + b.finalInSubClass() // no method lookup, guaranteed to be inlined +} +``` + + +## Source compatibility + +This proposal is additive. Existing code has not used the attribute. It has no +impact on existing code. Existing references to functions in libraries that are +now marked with `@inline(always)` will continue to compile successfully with the +added effect that functions will get inlined (that could have happened with +changes to inlining heuristic). + +## ABI compatibility + +The addition of the attribute has no effect on ABI compatibility. + +## Implications on adoption + +This feature can be freely adopted and un-adopted in source +code with no deployment constraints and without affecting source or ABI +compatibility. + +## Future directions + +`@inline(always)` can be too restrictive in cases where inlining is only +required within a module. For such cases we can introduce an `@inline(module)` +attribute in the future. + + +```swift +@inlinable +public caller() { + if coldPath { + callee() + } +} + +public otherCaller() { + if hotPath { + callee() + } +} + +@inline(module) +@usableFromInline +internal func callee() { +} +``` + +## Alternatives considered + +We could treat `@inline(always)` as an optimization hint that does not need to +be enforced or applied at all optimization levels similar to how the existing +`@inline(__always)` attribute functions and not emit errors if it cannot be +guaranteed to be uphold when the function is directly referenced. +This would deliver less predictable optimization behavior in cases where authors +overlooked requirements for inlining to happen such as not marking a public +function as `@inlinable`. + + +## Acknowledgments + +TODO: .... From 500310ed0d59e46b6fa8e12ea19c7a7d774a2c51 Mon Sep 17 00:00:00 2001 From: Rick van Voorden Date: Wed, 10 Sep 2025 22:28:32 -0700 Subject: [PATCH 472/505] add is identical methods --- proposals/NNNN-add-is-identical-methods.md | 92 ++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/proposals/NNNN-add-is-identical-methods.md b/proposals/NNNN-add-is-identical-methods.md index aa6c13db53..4eb0536cc6 100644 --- a/proposals/NNNN-add-is-identical-methods.md +++ b/proposals/NNNN-add-is-identical-methods.md @@ -393,7 +393,13 @@ When we build and run our SwiftUI app we confirm that we are not computing new ` We propose adding `isIdentical` methods to the following concrete types from Standard Library: * `String` +* `String.UnicodeScalarView` +* `String.UTF16View` +* `String.UTF8View` * `Substring` +* `Substring.UnicodeScalarView` +* `Substring.UTF16View` +* `Substring.UTF8View` * `Array` * `ArraySlice` * `ContiguousArray` @@ -419,6 +425,16 @@ extension String { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing strings this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -431,6 +447,11 @@ extension String { } ``` +The following types will adopt the same semantic guarantees as `String`: +* `String.UnicodeScalarView` +* `String.UTF16View` +* `String.UTF8View` + ### `Substring` ```swift @@ -448,6 +469,16 @@ extension Substring { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing substrings this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -460,6 +491,11 @@ extension Substring { } ``` +The following types will adopt the same semantic guarantees as `Substring`: +* `Substring.UnicodeScalarView` +* `Substring.UTF16View` +* `Substring.UTF8View` + ### `Array` ```swift @@ -477,6 +513,16 @@ extension Array { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing arrays this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -506,6 +552,16 @@ extension ArraySlice { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing arrays this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -535,6 +591,16 @@ extension ContiguousArray { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing arrays this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -564,6 +630,16 @@ extension Dictionary { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - If `a` and `b` are `Equatable`, then `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing dictionaries this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying @@ -593,6 +669,16 @@ extension Set { /// - If `a.isIdentical(to: b)` and `b.isIdentical(to: c)` are both `true`, /// then `a.isIdentical(to: c)` is also `true`. (Transitivity) /// - `a.isIdentical(b)` implies `a == b` + /// - `a == b` does not imply `a.isIdentical(b)` + /// + /// Values produced by copying the same value, with no intervening mutations, + /// will compare identical: + /// + /// ```swift + /// let d = c + /// print(c.isIdentical(to: d)) + /// // Prints true + /// ``` /// /// Comparing sets this way includes comparing (normally) hidden /// implementation details such as the memory location of any underlying set @@ -622,12 +708,6 @@ Any Standard Library types that are copy-on-write values could be good candidate * `KeyValuePairs` * `StaticBigInt` * `StaticString` -* `String.UnicodeScalarView` -* `String.UTF16View` -* `String.UTF8View` -* `Substring.UnicodeScalarView` -* `Substring.UTF16View` -* `Substring.UTF8View` * `UTF8Span` This proposal focuses on what we see as the most high-impact types to support from Standard Library. This proposal *is not* meant to discourage adding `isIdentical(to:)` on any of these types at some point in the future. A follow-up “second-round” proposal could focus on these remaining types. From 94defbe18bb4e3e356561a8fe151a407e0c676bd Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Sat, 13 Sep 2025 16:23:11 -0700 Subject: [PATCH 473/505] Add module selectors proposal (#2914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add module selectors proposal * Minor formatting and wording improvements * Make changes based on parsing code review * Clarify and expand discussions in pitch Particularly future directions and alternatives considered. * Flip-flop on restricting newlines after `::` If reviewers don’t like it, we can revisit the question. * Late edits to module selector proposal * Describe keyword behavior more specifically * Allow module selector in `@available(renamed:)` * Use different Markdown syntax for links * Module selectors is SE-0491 --------- Co-authored-by: Freddy Kellison-Linn From ef78ed4e7628f1991758b360dcf5a2db3a69abbf Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Sat, 13 Sep 2025 19:25:37 -0400 Subject: [PATCH 474/505] Add SE-0491 (#2954) --- proposals/0491-module-selectors.md | 754 +++++++++++++++++++++++++++++ 1 file changed, 754 insertions(+) create mode 100644 proposals/0491-module-selectors.md diff --git a/proposals/0491-module-selectors.md b/proposals/0491-module-selectors.md new file mode 100644 index 0000000000..936c00311c --- /dev/null +++ b/proposals/0491-module-selectors.md @@ -0,0 +1,754 @@ +# Module selectors for name disambiguation + +* Proposal: [SE-0491](0491-module-selectors.md) +* Authors: [Becca Royal-Gordon](https://github.com/beccadax) +* Review Manager: [Freddy Kellison-Linn](https) +* Status: **Awaiting review** +* Bug: [swiftlang/swift#53580](https://github.com/swiftlang/swift/issues/53580) (SR-11183) +* Implementation: [swiftlang/swift#34556](https://github.com/swiftlang/swift/pull/34556) +* Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) + +Previously pitched in: + +* [Pitch: Fully qualified name syntax](https://forums.swift.org/t/pitch-fully-qualified-name-syntax/28482) + +## Introduction + +We propose that Swift's grammar be extended so that, wherever an identifier +is written in source code to reference a declaration, it can be prefixed by +`ModuleName::` to disambiguate which module the declaration is expected to +come from. This syntax will provide a way to resolve several types of name +ambiguities and conflicts. + +## Motivation + +Swift's name lookup rules promote its goal of allowing code to be written in a +very clean, readable style. However, in some circumstances it can be very +difficult to unambiguously reference the declaration you want. + +### Background + +When Swift looks up a name in your source code to find the declaration it +refers to, that lookup can be either *qualified* or *unqualified*. Qualified +lookups are restricted to looking inside a certain declaration, while +unqualified lookups search more broadly. For example, in a chain of names such +as: + +```swift +mission().booster().launch() +``` + +`booster()` can only refer to members of whatever type is returned by +`mission()`, and `launch()` can only refer to members of whatever type is +returned by `booster()`, so Swift will find them using a qualified lookup. +`mission()`, on the other hand, does not have to be a member of some specific +type, so Swift will find that declaration using an unqualified lookup. + +> **Note**: Although the examples given here mostly concern uses in +> expressions, qualified and unqualified lookups are also used for names in +> type syntax, such as `Mission.Booster.Launch`. The exact lookup rules are +> slightly different but the principles are the same. + +Both kinds of lookups are slightly sensitive to context in that, since the +acceptance of [SE-0444 Member Import Visibility][SE-0444], +they are both limited to declarations imported in the current source file; +however, unqualified lookups take *much* more than just that into account. They +search through any enclosing scopes to find the "closest" use of that name. For +example, in code like: + +```swift +import RocketEngine +import IonThruster + +extension Mission { + struct Booster { + func launch(_ crew: Int) { + let attempt = 1 + ignite() + } + } +} +``` + +Swift will look for `ignite` in the following places: + +1. The local declarations inside `launch(_:)` +2. The parameters to `launch(_:)` +3. Instance members and generic parameters of the enclosing type `Booster` + (including its extensions, superclasses, conformances, etc.) +4. Static members and generic parameters of the enclosing type `Mission` +5. Top-level declarations in this module +6. Top-level declarations in other imported modules +7. The names of imported modules + +These rules are a little complicated when written out like this, but their +effect is pretty simple: Swift finds whichever `ignite` is in the "closest" +scope to the use site. If both `Booster` and `Mission` have an `ignite`, for +example, Swift will use the one in `Booster` and ignore the one in `Mission`. + +Of particular note is the last place Swift looks: the names of imported +modules. This is intended to help with situations where two modules have +declarations with the same name. For example, if both `RocketEngine` and +`IonThruster` declare an `ignite()`, `RocketEngine.ignite()` will find `ignite` +using a qualified lookup inside the module `RocketEngine`, filtering out the +one in `IonThruster`. This works in simple cases, but it breaks down in a +number of complicated ones. + +### Unqualified lookups are prone to shadowing + +Swift does not prevent declarations in different scopes from having the same +name. For example, there's nothing preventing you from having both a top-level +type and a nested type with the same name: + +```swift +struct Scrubber { ... } + +struct LifeSupport { + struct Scrubber { ... } +} +``` + +This means that the same name can have different meanings in different places: + +```swift +// This returns the top-level `Scrubber`: +func makeScrubber() -> Scrubber { ... } + +extension LifeSupport { + // This returns `LifeSupport.Scrubber`: + func makeScrubber() -> Scrubber { ... } +} +``` + +Specifically, we say that within the extension, `LifeSupport.Scrubber` +*shadows* the top-level `Scrubber`. + +This poses certain challenges—especially for mechanically-generated code, such +as module interface files—but it's usually not completely insurmountable +because you can qualify a top-level declaration with its module name. However, +it becomes a problem if *the module name itself* is shadowed by a type with the +same name: + +```swift +// Module RocketEngine +public struct RocketEngine { ... } +public struct Fuel { ... } + +// Another module +import RocketEngine + +_ = RocketEngine.Fuel() // Oops, this is looking for a nested type in the + // struct RocketEngine.RocketEngine! +``` + +In this situation, we can no longer qualify top-level declarations with module +names. That makes code generation *really* complicated, because there is no +syntax that works reliably—qualifying will help with some failures but cause +others. + +That may sound like a farfetched edge case, but it's surprisingly common for a +module to contain a type with the same name. For instance, the `XCTest` module +includes an `XCTest` class, which is a base class for `XCTestCase` and +`XCTestSuite`. To avoid this kind of trouble, developers must be careful to +give modules different names from the types inside them—the `Observation` +module, for example, might have been called `Observable` if it didn't have a +type with that name. + +### Qualified lookups can be unresolvably ambiguous + +Extensions create the possibility that a type may have two members with the +same name and similar or even outright conflicting overload signatures, +distinguished only by being in different modules. This is not a problem for +Swift's ABI because the mangled name of an extension member includes the +module it was declared in; however, there is no way to add a module name to +an already-qualified non-top-level lookup, so there's no way to express this +distinction in the surface language. Developers' only option may be to fiddle +with their imports in an attempt to make sure the desired member is the only +one that's visible. + +### Macros don't support module qualification + +Macros cannot have members--the grammar of a macro expansion allows only a +single identifier, and any subsequent `.` is taken to be a member lookup on +the expansion--so there is currently no way to qualify a macro expansion with +a module name. This limitation was discussed during the [second review of SE-0382][SE-0382-review-2] +and the author suggested the only viable solution was to add a new, +grammatically-distinguishable syntax for module qualification. + +### These problems afflict module interfaces, but aren't unique to them + +These issues show up most often in module interfaces because the compiler +needs to generate syntax that reliably resolves to a specific declaration, but +the rules' sensitivity to context and module contents (which might change over +time!) makes that very difficult. In practice, the compiler does not attempt to +fully account for shadowing and name conflicts--by default it qualifies names +as fully as the language allows (which works about 95% of the time) and offers +a number of (undocumented) workaround flags to adjust that which are added by a +maintainer when they discover that their module is in the remaining 5%. These +flags aren't enabled automatically, though, and they don't affect the module +interfaces of downstream modules which need to reference affected declarations. +In short, the situation is a mess. + +It's important to keep in mind, though, that this doesn't *just* affect module +interfaces and generated code. Code written by humans can also run into these +issues; it's just that a person will notice the build error and fiddle with +their code until they get something that works. It therefore makes sense to +introduce a new syntax that can be used by both machines and humans. + +### Separate modules make this uniquely severe + +While problematic conflicts can sometimes occur between two declarations in a +single module, the authors believe that per-module disambiguation is the right +approach because shadowing within a module is much easier to detect and +resolve. The developer will generally notice shadowing problems when they build +or test their code, and since they control both the declaration site and the +use site, they have options to resolve any problems that are not otherwise +available (like renaming declarations or tweaking their overload signatures). +The compiler also detects and prevents outright conflicts within a specific +module, such as two extensions declaring the exact same member, which it would +allow if the declarations were in different modules. + +## Proposed solution + +We propose adding *module selectors* to the language. A module selector is +spelled `::` and can be placed before an identifier to indicate +which module it is expected to come from: + +```swift +_ = RocketEngine::Fuel() // Picks up the `Fuel` in `RocketEngine`, bypassing + // any other `Fuel`s that might be in scope +``` + +On an unqualified lookup, a module selector also indicates that lookup should +start at the top level, skipping over the declarations in contextually-visible +scopes: + +```swift +// In module NASA + +struct Scrubber { ... } + +struct LifeSupport { + struct Scrubber { ... } +} + +extension LifeSupport { + // This returns the top-level `Scrubber` + func makeMissionScrubber() -> NASA::Scrubber { ... } +} +``` + +Module selectors may also be placed on qualified lookups to indicate which +module an extension member should belong to: + +```swift +// In module IonThruster +extension Spacecraft { + public struct Engine { ... } +} + +// In module RocketEngine +extension Spacecraft { + public struct Engine { ... } +} + +// In module NASA +import IonThruster +import RocketEngine + +func makeIonThruster() -> Spacecraft.IonThruster::Engine { ... } +``` + +Module selectors are permitted at locations in the type and expression syntax +where a declaration from elsewhere is referenced by name. However, it is +invalid to use one on the name of a *new* declaration: + +```swift +struct NASA::Scrubber { // Invalid--new declarations are always in the current module + ... +} +``` + +We chose this syntax—module name plus `::` operator prefixing the name they +qualify—because `::` is unused in Swift (it can't even be a custom operator) +and because using `::` in this fashion is highly precedented in other +languages. (C++, PHP, Java, and Rust all use it to indicate that the name on +the right should be looked up inside the scope on the left; Ruby and Perl use +it *specifically* to look up declarations inside modules.) + +## Detailed design + +### Grammar and parsing + +A module selector has the following grammar: + +> *module-selector* → *identifier* `::` + +The following productions may now optionally include a module selector (changes are in bold): + +> *type-identifier* → ***module-selector?*** *type-name* *generic-argument-clause?* | ***module-selector?*** *type-name* *generic-argument-clause?* `.` *type-identifier* +> +> *primary-expression* → ***module-selector?*** *identifier* *generic-argument-clause?* +> +> *implicit-member-expression* → `.` ***module-selector?*** *identifier*
    +> *implicit-member-expression* → `.` ***module-selector?*** *identifier* `.` *postfix-expression* +> +> *macro-expansion-expression* → `#` ***module-selector?*** *identifier* *generic-argument-clause?* *function-call-argument-clause?* *trailing-closures?* +> +> *key-path-component* → ***module-selector?*** *identifier* *key-path-postfixes?* | *key-path-postfixes* +> +> *function-call-argument* → ***module-selector?*** *operator* | *identifier* `:` ***module-selector?*** *operator* +> +> *initializer-expression* → *postfix-expression* `.` ***module-selector?*** `init`
    +> *initializer-expression* → *postfix-expression* `.` ***module-selector?*** `init` `(` *argument-names* `)` +> +> *explicit-member-expression* → *postfix-expression* `.` ***module-selector?*** *identifier* *generic-argument-clause?*
    +> *explicit-member-expression* → *postfix-expression* `.` ***module-selector?*** *identifier* `(` *argument-names* `)` +> +> *attribute-name* → ***module-selector?*** *identifier* +> +> *enum-case-pattern* → *type-identifier?* `.` ***module-selector?*** *enum-case-name* *tuple-pattern?* + +Additionally, a new production allows a scoped `import` declaration to use a +module selector and identifier instead of an import path: + +> *import-declaration* → *attributes?* `import` *import-kind?* *import-path*
    +> ***import-declaration* → *attributes?* `import` *import-kind* *module-selector* *identifier*** + +Note that this new *import-declaration* production does not allow a submodule +to be specified. Use the old `.`-operator-based syntax for submodules. + +#### Token-level behavior + +The `::` operator may be separated from its *identifier* by any whitespace, +including newlines. However, the `::` operator must *not* be separated from the +token after it by a newline: + +```swift +NationalAeronauticsAndSpaceAdministration:: + RocketEngine // Invalid +NationalAeronauticsAndSpaceAdministration + ::RocketEngine // OK +``` + +> **Note**: This restriction aids in recovery when parsing incomplete code; +> the member-lookup `.` operator follows a similar rule. + +If the token after the `::` operator is a keyword, it will be treated as an +ordinary identifier unless it would have special meaning: + +```swift +print(default) // Invalid; 'default' is a keyword and needs backticks +print(NASA.default) // OK under SE-0071 +print(NASA::default) // OK under this proposal +``` + +Depending on context, the following keywords may still be treated as special in +expressions: + +* `deinit` +* `init` +* `subscript` + +> **Note**: This behavior is analogous to [SE-0071 Allow (most) keywords in member references][SE-0071]. + +Similarly, attributes that use a module selector will always be treated as +custom attributes, not built-in attributes. (Put another way, built-in +attributes do not belong to *any* module—not even `Swift`.) Like all custom +attributes, any arguments must be valid expressions. + +```swift +@Swift::available(macOS 15.0.1, *) // Invalid; not parsed as the built-in `@available` +class X {} +``` + +#### Patterns + +Module selectors are allowed in *enum-case-pattern* and in *type* and +*expression* productions nested inside patterns. However, *identifier-pattern* +is unmodified and does *not* permit a module selector, even in shorthand +syntaxes designed to declare a shadow of an existing variable. If a module +selector is needed, you must use an explicit initializer expression. + +```swift +if let NASA::rocket { ... } // Invalid +if let rocket = NASA::rocket { ... } // OK + +Task { [NASA::rocket] in ... } // Invalid +Task { [rocket = NASA::rocket] in ... } // OK +``` + +#### Operator and precedence group declarations + +The *precedence-group-name* production is unmodified and does not permit +a module selector. Precedence group names exist in a separate namespace from +other identifiers and no need for this feature has been demonstrated. + +#### Parsed declaration names + +A parsed declaration name, such as the name in an `@available(renamed:)` +argument, may use module selectors on the declaration's base name and context +names. + +```swift +@available(*, deprecated, renamed: "NASA::launch(_:from:)") // OK +public func launch(_ mission: Mission) { + launch(mission, from: LaunchPad.default) +} +``` + +Module selectors are not valid on base names in clang `swift_name` and +`swift_async_name` attributes, since these specify the name of the current +declaration, rather than referencing a different declaration. + +> **Note**: Clang Importer currently cannot apply import-as-member `swift_name` +> or `swift_async_name` attributes that name a context in a different module, +> but if this limitation is ever lifted, module selectors ought to be supported +> on context names in these clang attributes. + +#### Syntaxes reserved for future directions + +It is never valid to write two module selectors in a row; if you want to access +a declaration which belongs to a clang submodule, you should just write the +top-level module name in the module selector. + +It is never valid to write a keyword, operator, or `_` in place of a module +name; if a module's name would be mistaken for one of these, it must be +wrapped in backticks to form an identifier. + +### Effects on lookup + +When a reference to a declaration is prefixed by a module selector, only +declarations declared in, or re-exported by, the indicated module will be +considered as candidates. All other declarations will be filtered out. + +For example, in the following macOS code: + +```swift +import Foundation + +class NSString {} + +func fn(string: Foundation::NSString) {} +``` + +`string` will be of type `Foundation.NSString`, rather than the `NSString` +class declared in the same file. Because the AppKit module +re-exports Foundation, this example would also behave the same way: + +```swift +import AppKit + +class NSString {} + +func fn(string: AppKit::NSString) {} +``` + +> **Note**: Allowing re-exports ensures that "hoisting" a type from its +> original module up to another module it imports is not a source-breaking +> change. It also helps with situations where developers don't realize where a +> given type is declared; for instance, many developers believe `NSObject` is +> declared in `Foundation`, not `ObjectiveC`. + +Additionally, when a reference to a declaration prefixed by a module selector +is used for an unqualified lookup, the lookup will begin at the module-level +scope, skipping any intervening enclosing scopes. That means a top-level +declaration will not be shadowed by local variables, parameters, generic +parameters, or members of enclosing types: + +```swift +// In module MyModule + +class Shadowed { + struct Shadowed { + let Shadowed = 42 + func Shadowed(Shadowed: () -> Void) { + let Shadowed = "str" + let x = MyModule::Shadowed() // refers to top-level `class Shadowed` + } + } +} +``` + +A module selector can only rule out declarations that might otherwise have been +chosen instead of the desired declaration; it cannot access a declaration which +some other language feature has ruled out. For example, if a declaration is +inaccessible because of access control or hasn't been imported into the current +source file, a module selector will not allow it to be accessed. + +## Source compatibility + +This change is purely additive; it only affects the behavior of code which uses +the new `::` token. In the current language, this sequence can only appear +in valid Swift code in the selector of an `@objc` attribute, and the parser +has been modified to split the token when it is encountered there. + +## ABI compatibility + +This change does not affect the ABI of existing code. The Swift compiler has +always resolved declarations to a specific module and then embedded that +information in the ABI's symbol names; this proposal gives developers new ways +to influence those resolution decisions but doesn't expand the ABI in any way. + +## Implications on adoption + +Older compilers will not be able to parse source code which uses module +selectors. This means package authors may need to increase their tools version +if they want to use the feature, and authors of inlinable code may need to +weigh backwards compatibility concerns. + +Similarly, when a newer compiler emits module selectors into its module +interfaces, older compilers won't be able to understand those files. This isn't +a dealbreaker since Swift does not guarantee backwards compatibility for module +interfaces, but handling it will require careful staging and there may be a +period where ABI-stable module authors must opt in to emitting module +interfaces that use the feature. + +## Future directions + +### Special syntax for the current module + +We could allow a special token, or no token, to be used in place of the module +name to force a lookup to start at the top level, but not restrict it to a +specific module. Candidates include: + +```swift +Self::ignite() +_::ignite() +*::ignite() +::ignite() +``` + +These syntaxes have all been intentionally kept invalid (a module named `Self`, +for instance, would have to be wrapped in backticks: `` `Self`::someName ``), +so one of them can be added later if there's demand for it. + +### Disambiguation for subscripts + +There is currently no way to add a module selector to a use of a subscript. We +could add support for a syntax like: + +```swift +myArray.Swift::[myIndex] +``` + +### Disambiguation for conformances + +Retroactive conformances have a similar problem to extension members—the ABI +distinguishes between otherwise identical conformances in different modules, +but the surface syntax has no way to resolve any ambiguity—so a feature which +addressed them might be nice. However, there is no visible syntax associated +with use of a conformance that can be qualified with a module selector, so it's +difficult to address as part of this proposal. + +It's worth keeping in mind that [SE-0364's introduction of `@retroactive`][SE-0364] +reflects a judgment that retroactive conformances should be used with care. The +absence of such a feature is one of the complications `@retroactive` is meant +to flag. + +### Support selecting conflicting protocol requirements + +Suppose that a single type conforms to two protocols with conflicting protocol +requirements: + +```swift +protocol Employable { + /// Terminate `self`'s employment. + func fire() +} + +protocol Combustible { + /// Immolate `self`. + func fire() +} + +struct Technician: Employable, Combustible { ... } +``` + +It'd be very useful to be able to unambiguously specify which protocol's +requirement you're trying to call: + +```swift +if myTechnician.isGoofingOff { + myTechnician.Employable::fire() +} +if myTechnician.isTooCloseToTheLaunch { + myTechnician.Combustible::fire() +} +``` + +However, allowing a protocol name—rather than a module name—to be written +before the `::` token re-introduces the same ambiguity this proposal seeks +to solve because a protocol name could accidentally shadow a module name. +We'll probably need a different feature with a distinct syntax to resolve +this use case—perhaps something like: + +```swift +if myTechnician.isGoofingOff { + (myTechnician as some Employable).fire() +} +``` + +### Support selecting default implementations + +Similarly, it would be useful to be able to specify that you want to call a +default implementation of a protocol requirement even if the conformance +provides another witness. (This could be used similarly to how `super` is used +in overrides.) However, this runs into similar problems with reintroducing +ambiguity, and it also just doesn't quite fit the shape of the syntax (there's +no name to uniquely identify the default implementation you want). Once again, +this probably requires a different feature with a distinct syntax—perhaps +something a little more like how `super` works. + +## Alternatives considered + +### Change lookup rules in module interfaces + +Some of the problems with module interfaces could be resolved by changing the +rules for qualified lookup *within module interface files specifically*. For +instance, we could decide that in a module interface file, unqualified lookups +can only find module names, and the compiler must always qualify every name +with a module name. + +This would probably be a viable solution with enough effort, but it has a +number of challenges: + +1. There are some declarations—generic parameters, for instance—which are + not accessible through any qualified lookup (they are neither top-level + declarations nor accessible through the member syntax). We would have to + invent some way to reference these. + +2. Existing module interfaces have already been produced which would be broken + by this change, so it would have to somehow be made conditional. + +3. Currently, inlinable function bodies are not comprehensively regenerated + for module interfaces; instead, the original textual source code is + inserted with minor programmatic edits to remove comments and `#if` blocks. + This means we would have to revert to the normal lookup rules within an + inlinable function body. + +It also would not help with ambiguous *qualified* lookups, such as when two +modules use extensions to add identically-named nested types to a top-level +type, and it would not give developers new options for handling ambiguity in +human-written code. + +### Add a fallback lookup rule for module name shadowing + +The issue with shadowing of module names could be addressed by adding a narrow +rule saying that, when a type has the same name as its enclosing module and a +qualified lookup inside it doesn't find any viable candidates, Swift will fall +back to looking in the module it shadowed. + +This would address the `XCTest.XCTestCase` problem, which is the most common +seen in practice, but it wouldn't help with more complicated situations (like +a nested type shadowing a top-level type, or a type in one module having the +same name as a different module). It's also not a very principled rule and +making it work properly in expressions might complicate the type checker. + +### Use a syntax involving a special prefix + +We considered creating a special syntax which would indicate unambiguously that +the next name must be a module name, such as `#Modules.FooKit.bar`. However, +this would only have helped with top-level declarations, not members of +extensions. + +### Use a syntax that avoids `::`'s shortcomings + +Although we have good reasons to propose using the `::` operator (see "Proposed +solution" above), we do not think it's a perfect choice. It appears visually +"heavier" than the `.` operator, which means developers reading the code might +mentally group the identifiers incorrectly: + +```swift +Mission.NASA::Booster.Exhaust // Looks like it means `(Mission.NASA) :: (Booster.Exhaust)` + // but actually means `Mission . (NASA::Booster) . Exhaust` +``` + +This is not unprecedented—in C++, `myObject.MyClass::myMember` means +`(myObject) . (MyClass::myMember)`—but it's awkward for developers without +a background in a language that works like this. + +We rejected a number of alternatives that would avoid this problem. + +#### Make module selectors qualify different names + +One alternative would be to have the module selector qualify the *rightmost* +name in the member chain, rather than the leftmost, so that a module selector +could only appear at the head of a member chain. The previous example would +then be written as: + +```swift +(NASA::Mission.Booster).Exhaust +``` + +We don't favor this design because we believe: + +1. Developers more frequently need to qualify top-level names (which exist in a + very crowded quasi-global namespace) than member names (which are already + limited by the type they're looking inside); a syntax that makes qualifying + the member the default is optimizing for the wrong case. + +2. The distance between the module and the identifier it qualifies increases + the cognitive burden of pairing up modules to the names they apply to. + +3. Subjectively, it's just *weird* that the selector applies to a name that's a + considerable distance from it, rather than the name immediately adjacent. + +A closely related alternative would be to have the module selector qualify +*all* names in the member chain, so that in `(NASA::Mission.Booster).Exhaust`, +both `Mission` and `Booster` must be in module `NASA`. We think point #1 from +the list above applies to this design too: `Mission` is a sparse enough +namespace that developers are more likely to be hindered by `Booster` being +qualified by the `NASA` module than helped by it. + +#### Use a totally different spelling + +We've considered and rejected a number of other spellings for this feature, +such as: + +```swift +Mission.#module(NASA).Booster.Exhaust // Much wordier, not implementable as a macro +Mission.::NASA.Booster.Exhaust // Looks weird in member position +Mission.Booster@NASA.Exhaust // Ignores Swift's left-to-right nesting convention +Mission.'NASA.Booster.Exhaust // Older compilers would mis-lex in inactive `#if` blocks +Mission.NASA'Booster.Exhaust // " +Mission.(NASA)Booster.Exhaust // Arbitrary; little connection to prior art +Mission.'NASA'.Booster.Exhaust // " +``` + +### Don't restrict whitespace to the right of the `::` + +Allowing a newline between `::` and the identifier following it would mean +that, when an incomplete line of code ended with a module selector, Swift might +interpret a keyword on the next line as a variable name, likely causing multiple +confusing syntax errors in the next statement. For instance: + +```swift +let x = NASA:: // Would be interpreted as `let x = NASA::if x { ... }`, +if x { ... } // causing several confusing syntax errors. +``` + +Forbidding it, however, has a cost: it restricts the code styles developers can +use. If a developer wants to put a line break in the middle of a name with a +module selector, they will not be able to format it like this: + +```swift +SuperLongAndComplicatedModuleName:: + superLongAndComplicatedFunctionName() +``` + +And will have to write it like this instead: + +```swift +SuperLongAndComplicatedModuleName + ::superLongAndComplicatedFunctionName() +``` + +The member-lookup `.` operator has a similar restriction, but developers may +not want to style them in exactly the same way, particularly since C++ +developers often split a line after a `::`. + + [SE-0071]: "Allow (most) keywords in member references" + [SE-0364]: "Warning for Retroactive Conformances of External Types" + [SE-0382-review-2]: "SE-0382 (second review): Expression Macros" + [SE-0444]: "SE-0444 Member Import Visibility" From 500dde709a7220b4bf27adb2e379c056376f8f0d Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Sat, 13 Sep 2025 19:35:25 -0400 Subject: [PATCH 475/505] Put SE-0491 into review (#2955) --- proposals/0491-module-selectors.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0491-module-selectors.md b/proposals/0491-module-selectors.md index 936c00311c..7d2c769591 100644 --- a/proposals/0491-module-selectors.md +++ b/proposals/0491-module-selectors.md @@ -3,10 +3,10 @@ * Proposal: [SE-0491](0491-module-selectors.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Freddy Kellison-Linn](https) -* Status: **Awaiting review** +* Status: **Active review (September 13 ... September 26, 2025)** * Bug: [swiftlang/swift#53580](https://github.com/swiftlang/swift/issues/53580) (SR-11183) * Implementation: [swiftlang/swift#34556](https://github.com/swiftlang/swift/pull/34556) -* Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) +* Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) ([review](https://forums.swift.org/t/se-0491-module-selectors-for-name-disambiguation/82124)) Previously pitched in: From ca06ee3cf2805b6553cd16c9aefce6b3d4ffd619 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 16 Sep 2025 12:40:10 -0700 Subject: [PATCH 476/505] Update proposal to state that @inline(always) should imply @inlinable on public'ish declarations --- proposals/NNNN-inline-always.md | 57 +++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/proposals/NNNN-inline-always.md b/proposals/NNNN-inline-always.md index 3b2cf8dd0f..80f5fe2bc1 100644 --- a/proposals/NNNN-inline-always.md +++ b/proposals/NNNN-inline-always.md @@ -3,6 +3,7 @@ * Proposal: [SE-NNNN](NNNN-inline-always.md) * Authors: [Arnold Schwaighofer](https://github.com/aschwaighofer) * Implementation: [swiftlang/swift#84178](https://github.com/swiftlang/swift/pull/84178) +* Pitch thread: https://forums.swift.org/t/pitch-inline-always-attribute/82040 ## Introduction @@ -149,18 +150,55 @@ be possible? ### Interaction with `@inlinable` -Function bodies of functions referenceable outside of the defining module are -only available to the outside module if the definition is marked `@inlinable`. - -Therefore, a function marked with `@inline(always)` must be marked `@inlinable` -if it has `open`, `public`, or `package` level access. +`@inlinable` and `@_alwaysEmitIntoClient` make the function body available to +clients (callers in other modules) in library evolution mode. `@inlinable` makes +the body of the function available to the client and causes an ABI entry point +in the vending module to vended. `@_alwaysEmitIntoClient` makes the body of the +function available for clients but does not cause emission of an ABI entry +point. Functions with `open`, `public`, or `package` level access cause emission +of an ABI entry point for clients to call but in the absence of aforementioned +attributes do not make the body available to the client. + +`@inline(always)` intention is to be able to guarantee that inlining will happen +for any caller inside or outside the defining module therefore it makes sense to +require the use some form of "inline-ability" attribute with them. This +attribute could be required to be explicitly stated. And for it to be an error +when the attribute is omitted. ```swift +@inline(always) +@inlinable // or @_alwaysEmitIntoClient +public func caller() { ... } + @inline(always) // error: a public function marked @inline(always) must be marked @inlinable public func callee() { } ``` +Alternatively, the attribute could be implicitly implied by the usage of +`@inline(always)`. In this proposal, we take the position that it should be +implied to avoid the redundancy of spelling this out. The intention of +`@inline(always)` is for it to inline in all contexts. Instead of an error in the +absence of the attribute we should imply "inline-ability". The question is what +should we default to? + +`@_alwaysEmitIntoClient`'s semantics seems preferable for new functions. We +intend for the function to be always inlined, why should there be an ABI entry +point? + +`@inlinable` semantics allows for annotating existing functions with +`@inline(always)` without breaking ABI compatibility. `@inlinable` keeps an +entry point in the vending module for older code that assumed the existence of +an entry point. + +This proposals takes the position to give `@inline(always)` the semantics of +`@inlineable` and provide an alternative spelling for the case when we desire +`@_alwaysEmitIntoClient` semantics: `@inline(only)`. + +For access levels equal and lower than `internal` `@inlinable` should not be +implied. + + ### Interaction with `@usableFromInline` A `public` `@inlinable` function can reference a function with `internal` access @@ -297,7 +335,9 @@ changes to inlining heuristic). ## ABI compatibility -The addition of the attribute has no effect on ABI compatibility. +The addition of the attribute has no effect on ABI compatibility. We chose to +imply `@inlinable` for `public` (et al.) declarations which will continue to +emit an entry point for existing binary clients. ## Implications on adoption @@ -342,6 +382,11 @@ This would deliver less predictable optimization behavior in cases where authors overlooked requirements for inlining to happen such as not marking a public function as `@inlinable`. +With respect to `@inlinable` an initial draft of the proposal suggested to +require spelling the `@inlinable` attribute on `public` declarations or an error +would be displayed. The argument was that this would ensure that authors would +be aware of the additional semantics implied by the attribute: the body is +exposed. ## Acknowledgments From 0406799a3c47b5245bf0fc1edd7cf25c44087707 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 19 Sep 2025 13:04:23 +0100 Subject: [PATCH 477/505] Mark SE-0482 as implemented in 6.2 The main implementation PR was included in `swift-6.2-RELEASE` tag. --- ...wiftpm-static-library-binary-target-non-apple-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md index 569c018de1..5c7d90c92c 100644 --- a/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md +++ b/proposals/0482-swiftpm-static-library-binary-target-non-apple-platforms.md @@ -3,8 +3,8 @@ * Proposal: [SE-0482](0482-swiftpm-static-library-binary-target-non-apple-platforms.md) * Authors: [Daniel Grumberg](https://github.com/daniel-grumberg), [Max Desiatov](https://github.com/MaxDesiatov), [Franz Busch](https://github.com/FranzBusch) * Review Manager: [Kuba Mracek](https://github.com/kubamracek) -* Status: **Accepted** -* Implementation: [swiftlang/swift-package-manager#6967](https://github.com/swiftlang/swift-package-manager/pull/6967) [swiftlang/swift-package-manager#8605](https://github.com/swiftlang/swift-package-manager/pull/8605) +* Status: **Implemented (Swift 6.2)** +* Implementation: [swiftlang/swift-package-manager#8639](https://github.com/swiftlang/swift-package-manager/pull/8639) [swiftlang/swift-package-manager#8741](https://github.com/swiftlang/swift-package-manager/pull/8741) * Review: ([discussion](https://forums.swift.org/t/se-0482-binary-static-library-dependencies/79634)) ([pitch](https://forums.swift.org/t/pitch-swiftpm-support-for-binary-static-library-dependencies/78619)) ([acceptance](https://forums.swift.org/t/accepted-se-0482-binary-static-library-dependencies/80042)) * Bugs: [Swift Package Manger Issue](https://github.com/swiftlang/swift-package-manager/issues/7035) From a0aa0d49fb7db40df57236381eedd643d22864b1 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 19 Sep 2025 09:07:28 -0700 Subject: [PATCH 478/505] Simplify the introduction section --- proposals/0nnn-section-control.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md index 4d30b0bfc7..344385cf1d 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0nnn-section-control.md @@ -10,11 +10,7 @@ ## Introduction -This proposal builds on top of [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md) and adds two new attributes into the Swift language: `@section` and `@used`. These allow users to directly control which section of the resulting binary should globals variables be emitted into, and give users the ability to disable DCE (dead code elimination) on those. The goal is to enable systems and embedded programming use cases like runtime discovery of test metadata from multiple modules, and also to serve as a low-level building block for higher-level features (e.g. linker sets, plugins). - -The intention is that these attributes are to be used rarely and only by specific use cases; high-level application code should not need to use them directly and instead should rely on libraries, macros and other abstractions over the low-level attributes. - -The scope of this proposal is limited to compile-time behavior and compile-time control. We expect that full user-facing solutions for features like linker sets, test discovery or plugins will also require runtime implementations to discover and iterate the contents of custom sections, possibly from multiple modules. This proposal makes sure to provide the right building blocks and artifacts in binaries for the runtime components, but doesn’t prescribe the shape of those. However, it is providing a significant step towards generalized and safe high-level mechanisms for those use cases. See the discussion of that in the sections [Runtime discovery of data in custom sections](#runtime-discovery-of-data-in-custom-sections) and [Linker sets, plugins as high-level APIs](#linker-sets-plugins-as-high-level-apis) in Future Directions. +This proposal adds `@section` and `@used` attributes which can be applied to global variables. These allow users to directly control which section of the resulting binary should global variables be emitted into, and give users the ability to disable DCE (dead code elimination) on those. The goal is to enable systems and embedded programming use cases like runtime discovery of test metadata from multiple modules, and also to serve as a low-level building block for higher-level features (e.g. linker sets, plugins). ## Motivation @@ -104,6 +100,10 @@ var global = ... For the ELF file format specifically, the compiler will also emit a “section index” into produced object files, containing an entry about each custom section used in the compilation. This is a solution to an ELF specific problem where the behavior of ELF linkers and loaders means that sections are not easily discoverable at runtime. +> Note: The intention is that the `@section` and `@used` attributes are to be used rarely and only by specific use cases; high-level application code should not need to use them directly and instead should rely on libraries, macros and other abstractions over the low-level attributes. + +> The scope of this proposal is limited to compile-time behavior and compile-time control. We expect that full user-facing solutions for features like linker sets, test discovery or plugins will also require runtime implementations to discover and iterate the contents of custom sections, possibly from multiple modules. This proposal makes sure to provide the right building blocks and artifacts in binaries for the runtime components, but doesn’t prescribe the shape of those. However, it is providing a significant step towards generalized and safe high-level mechanisms for those use cases. See the discussion in [Runtime discovery of data in custom sections](#runtime-discovery-of-data-in-custom-sections) and [Linker sets, plugins as high-level APIs](#linker-sets-plugins-as-high-level-apis) in Future Directions. + ## Detailed design ### Attributes @section and @used on global and static variables From 4dd4f53fec73695ffbab43d8051687a4df2b16ac Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 19 Sep 2025 11:00:43 -0700 Subject: [PATCH 479/505] Add definition of constant expressions, add 'lazy' --- proposals/0nnn-section-control.md | 72 ++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md index 344385cf1d..72db9555a7 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0nnn-section-control.md @@ -55,7 +55,7 @@ This proposal recommends to use sections of the various object file formats as t ## Proposed Solution -The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". The `@section` attribute relies heavily on the facilities provided by [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), namely the ability to enforce constantness of an expressions. Using `@section` requires that the initializer expression is a constant expression: +The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". Using `@section` requires that the initializer expression is a constant expression (see Constant Expressions below for the definition of that): ```swift // Place an entry into a section, mark as "do not dead strip". @@ -100,6 +100,13 @@ var global = ... For the ELF file format specifically, the compiler will also emit a “section index” into produced object files, containing an entry about each custom section used in the compilation. This is a solution to an ELF specific problem where the behavior of ELF linkers and loaders means that sections are not easily discoverable at runtime. +When placing variables into a custom section, it's also allowed to use the `lazy` keyword to opt out of the mandatory static initialization and mandatory constant expression behavior, while still achieving section placement of the backing store of the data: + +```swift +@section("__DATA,colocated") lazy let data1: Int = 42 // ✅ +@section("__DATA,colocated") lazy let data2: Int = Int.random(in: 0 ..< 10) // ✅ +``` + > Note: The intention is that the `@section` and `@used` attributes are to be used rarely and only by specific use cases; high-level application code should not need to use them directly and instead should rely on libraries, macros and other abstractions over the low-level attributes. > The scope of this proposal is limited to compile-time behavior and compile-time control. We expect that full user-facing solutions for features like linker sets, test discovery or plugins will also require runtime implementations to discover and iterate the contents of custom sections, possibly from multiple modules. This proposal makes sure to provide the right building blocks and artifacts in binaries for the runtime components, but doesn’t prescribe the shape of those. However, it is providing a significant step towards generalized and safe high-level mechanisms for those use cases. See the discussion in [Runtime discovery of data in custom sections](#runtime-discovery-of-data-in-custom-sections) and [Linker sets, plugins as high-level APIs](#linker-sets-plugins-as-high-level-apis) in Future Directions. @@ -180,6 +187,54 @@ When allowed, the `@used` attribute on a variable declaration has the following The effects described above are applied to the storage symbols and don’t generally affect optimizations and other transformations in the compiler. For example, the compiler is still allowed to propagate and copy a the constant value to code that uses the value, so there’s no guarantee that a value stored into a global with a custom section will not be propagated and “leak” outside of the section. The `@used` annotation, however, does inform the optimizer that such a variable cannot be removed, even when it doesn’t have any observed users or even if it’s inaccessible due to language rules (e.g. if it’s a private static member on an otherwise empty type). +### Constant expressions + +Swift currently does not have a formal notion of a **constant expression**, i.e. an expression with a syntactic form that *guarantees the ability to know it's value at compile-time*. This proposal provides a definition of a "bare minimum" constant expression, with the understanding that this does not cover the language needs in generality, and the expectation that the Swift compiler and language will keep expanding the allowed forms of constant expressions. See [Generalized constant values and expressions](#generalized-constant-values-and-expressions) in Future Directions for further discussion on this. + +This proposal defines a **constant expression** as being one of: + +- an integer literal using any of built-in integer types (Int, UInt, Int8/16/32/64/128, UInt8/16/32/64/128) +- a floating-point literal of type Float or Double +- a boolean literal of type Bool +- a direct reference to a non-generic function using its name (the function itself is not generic, and also it must not be defined in a generic context) +- a direct reference to a non-generic metatype using the type name directly (the type itself is not generic, and also it must not be defined in a generic context), where the type is non-resilient +- a tuple composed of only other constant expressions +- an array literal of type InlineArray composed of only other constant expressions + +Explicitly, this definition currently does **not allow** any operators, using any user-defined named types, any other built-in type (e.g. strings, dictionaries, sets), using closures, or referencing any variables by name. See below for examples of valid and invalid constant expressions: + +```swift +@section("...") let a = 42 // ✅ +@section("...") let b = 3.14 // ✅ +@section("...") let c = 1 + 1 // ❌ operators not allowed +@section("...") let d = Int.max // ❌ not a literal +@section("...") let e: UInt8 = 42 // ✅ +@section("...") let f = UInt8(42) // ❌ not a literal +@section("...") let g: MyCustomExpressibleByIntegerLiteral = 42 // ❌ not a built-in type + +@section("...") let composition1 = (1, 2, 3, 2.718, true) // ✅ +@section("...") let composition2 = (1, 2, Int.max) // ❌ tuple component not constant +@section("...") let composition3: InlineArray = [1, 2, 3] // ✅ +@section("...") let composition4: InlineArray = [1, 2, Int.max] // ❌ array component not constant +@section("...") let composition5: (Int, [1 of Int], [1 of (Int, Int)]) = (1, [1], [(1, 1)]) // ✅ + +func foo() -> Int { return 42 } +@section("...") let func1 = foo // ✅ +@section("...") let func2 = foo() // ❌ not a function reference +@section("...") let func3 = Bool.random // ✅ +@section("...") let func4 = Bool.self.random // ❌ not a direct reference +@section("...") let func5 = (Bool.self as Bool.Type).random // ❌ not a direct reference +@section("...") let func6 = [Int].randomElement // ❌ generic +@section("...") let func7 = { } // ❌ not using name + +struct S { } +@section("...") let metatype1 = S.self // ✅ +@section("...") let metatype2 = Int.self // ✅ +@section("...") let metatype3 = Int.self.self // ❌ not a direct reference +import Foundation +@section("...") let metatype4 = URL.self // ❌ resilient +``` + ### Guaranteed static initialization Using attribute `@section` requires the initializer expression of the variable to be a **constant expression**. It's not required to separately annotate the expression for being a compile-time expression, instead this is implied from the `@section` attribute. On top of the constant-ness, `@section` on a global or static variable enforces **static initialization** on that variable. @@ -221,6 +276,17 @@ let a = (42, foo) // "foo" is statically initialized into a // linkable/relocatable pointer ``` +### Lazy variables with section placement + +On global and static variables that are annotated with `@section`, the compiler will now allow the `lazy` keyword (which is currently disallowed on all global and static variables). Using it will opt such variable out of the "mandatory static initialization" behavior and instead use the at-runtime lazy initialization that traditional global and static variables have. The initializer expression does not need to be a constant expression in this case. This is useful for the uncommon use case of placing variables into a custom section purely for colocation (e.g. to improve performance by increasing page/cacheline locality): + +```swift +@section("__DATA,colocated") lazy let data1: Int = 42 // ✅ +@section("__DATA,colocated") lazy let data2: Int = Int.random(in: 0 ..< 10) // ✅ +``` + +Traditional global and static variables are backed by two symbols: An init-once token and the actual storage for the variable's content. Both of these symbols are going to be placed into the custom section when using `@section` with `lazy`. This also means that any offline or in-process introspection mechanisms cannot assume a specific layout or state of such variables and their storage bytes in the sections, as the exact layout and content of the symbols of lazy variables is an implementation detail of the Swift language runtime. + ### Cross-platform object file format support The custom section name specified in the `@section` attribute is not validated by the compiler, instead it’s passed directly as a string to the linker. Different platforms supported by Swift are using different object and binary file formats (Linux uses ELF, Darwin uses Mach-O, Windows uses COFF), and that implies different restrictions and rules on what are valid section names. Because of that, a multi-platform library code is expected to use `#if os(...)` to use different section names for different platforms. Because of that, it’s expected that the attributes are to be typically only used indirectly via macros that hide the low-level nature of sections and object file formats from higher-level code developers: @@ -325,6 +391,10 @@ This will require some design decisions to be made around when should that be al Static initialization of a global can be useful on its own, without placing data into a custom section, and a separate attribute for that could be added. This way, one can get the same effects as the `@section` attribute (static initialization, normal initalization behavior if top-level code) except the symbol would not be actually placed into any custom section. +### Generalized constant values and expressions + +The notions of constant expressions and constant values is applicable to a much wider set of use cases that just section placement, and the set of allowed types and syntactical forms should be expanded in the future into a full-featured system for compile-time programming. A dedicated proposal, [Swift Compile-Time Values](https://github.com/artemcm/swift-evolution/blob/const-values/proposals/0nnn-const-values.md), is being pitched [on the forums](https://forums.swift.org/t/pitch-3-swift-compile-time-values/77434) and describes in detail the possible future of generalized constants, the relevant motivation and use cases. + ### Allowing a reference to a constant string declaration as a section name The requirement to only use string literals as the section names could be lifted in the future, and we might allow referring to a declaration of variable with a compile-time string. This would be useful to avoid repetition when placing multiple values into the same section without needing to use macros. From 19a0bda2f7b497072e3632f8f1b5437f5b18e6d5 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 19 Sep 2025 11:03:02 -0700 Subject: [PATCH 480/505] Fix inline link --- proposals/0nnn-section-control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0nnn-section-control.md b/proposals/0nnn-section-control.md index 72db9555a7..74af21dbd3 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0nnn-section-control.md @@ -55,7 +55,7 @@ This proposal recommends to use sections of the various object file formats as t ## Proposed Solution -The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". Using `@section` requires that the initializer expression is a constant expression (see Constant Expressions below for the definition of that): +The proposal is to add two new attributes `@section` and `@used` that will allow annotating global and static variables with directives to place the value into a custom section, and to require no-dead-stripping aka "attribute used". Using `@section` requires that the initializer expression is a constant expression (see [Constant expressions](#constant-expressions) below for the definition of that): ```swift // Place an entry into a section, mark as "do not dead strip". From 39a4ec9ecfff9eb4cd4bfc9d3c3e8a172f68e4d4 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 19 Sep 2025 14:34:29 -0400 Subject: [PATCH 481/505] [ST-0015] Swift Testing image attachments (Windows) (#2940) * [WIP] Swift Testing image attachments (Windows) * Update NNNN-image-attachments-in-swift-testing-windows.md Add pitch link * Add another link to ST-0014. * Update tools integration blurb * Assign number (ST-0015) to image attachments on Windows proposal and adjust header fields * Fill in my name as review manager --------- Co-authored-by: Stuart Montgomery --- ...ge-attachments-in-swift-testing-windows.md | 393 ++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 proposals/testing/0015-image-attachments-in-swift-testing-windows.md diff --git a/proposals/testing/0015-image-attachments-in-swift-testing-windows.md b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md new file mode 100644 index 0000000000..954b0f51a9 --- /dev/null +++ b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md @@ -0,0 +1,393 @@ +# Image attachments in Swift Testing (Windows) + +* Proposal: [ST-0015](0015-image-attachments-in-swift-testing-windows.md) +* Authors: [Jonathan Grynspan](https://github.com/grynspan) +* Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) +* Status: **Active Review (September 19…29, 2025)** +* Implementation: [swiftlang/swift-testing#1245](https://github.com/swiftlang/swift-testing/pull/1245), [swiftlang/swift-testing#1254](https://github.com/swiftlang/swift-testing/pull/1254), _et al_. +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing-windows/81871)) + +## Introduction + +In [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md), +we added to Swift Testing the ability to attach images (of types `CGImage`, +`NSImage`, `UIImage`, and `CIImage`) on Apple platforms. This proposal builds on +that one to add support for attaching images on Windows. + +## Motivation + +It is frequently useful to be able to attach images to tests for engineers to +review, e.g. if a UI element is not being drawn correctly. If something doesn't +render correctly in a CI environment, for instance, it is very useful to test +authors to be able to download the failed rendering and examine it at-desk. + +In [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md#integration-with-supporting-tools), +we introduced the ability to attach images to tests on Apple's platforms. Swift +Testing is a cross-platform testing library, so we should extend this +functionality to other platforms too. This proposal covers Windows in +particular. + +## Proposed solution + +We propose adding the ability to automatically encode images to standard +graphics formats such as JPEG or PNG using Windows' built-in Windows Image +Component library, similar to how we added support on Apple platforms using Core +Graphics. + +## Detailed design + +### Some background about Windows' image types + +Windows has several generations of API for representing and encoding images. The +earliest Windows API of interest to this proposal is the Graphics Device +Interface (GDI) which dates back to the earliest versions of Windows. Image +types in GDI that are of interest to us are `HBITMAP` and `HICON`, which are +_handles_ (pointers-to-pointers) and which are not reference-counted. Both types +are projected into Swift as typealiases of `UnsafeMutablePointer`. + +Windows' latest[^direct2d] graphics API is the Windows Imaging Component (WIC) +which uses types based on the Component Object Model (COM). COM types (including +those implemented in WIC) are C++ classes that inherit from `IUnknown`. + +[^direct2d]: There is an even newer API in this area, Direct2D, but it is beyond + the scope of this proposal. A developer who has an instance of e.g. + `ID2D1Bitmap` can use WIC API to convert it to a WIC bitmap source before + attaching it to a test. + +`IUnknown` is conceptually similar to Cocoa's `NSObject` class in that it +provides basic reference-counting and reflection functionality. As of this +proposal, the Swift C/C++ importer is not aware of COM classes and does not +project them into Swift as reference-counted classes. Rather, they are projected +as `UnsafeMutablePointer`, and developers who use them must manually manage +their reference counts and must use `QueryInterface()` to cast them to other COM +classes. + +In short: the types we need to support are all specializations of +`UnsafeMutablePointer`, but we do not need to support all specializations of +`UnsafeMutablePointer` unconditionally. + +### Defining a new protocol for Windows image attachments + +A new protocol is introduced for Windows, similar to the `AttachableAsCGImage` +protocol we introduced for Apple's platforms: + +```swift +/// A protocol describing images that can be converted to instances of +/// [`Attachment`](https://developer.apple.com/documentation/testing/attachment). +/// +/// Instances of types conforming to this protocol do not themselves conform to +/// [`Attachable`](https://developer.apple.com/documentation/testing/attachable). +/// Instead, the testing library provides additional initializers on [`Attachment`](https://developer.apple.com/documentation/testing/attachment) +/// that take instances of such types and handle converting them to image data when needed. +/// +/// You can attach instances of the following system-provided image types to a +/// test: +/// +/// | Platform | Supported Types | +/// |-|-| +/// | macOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) | +/// | iOS, watchOS, tvOS, and visionOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) | +/// | Windows | [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps), [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons), [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) (including its subclasses declared by Windows Imaging Component) | +/// +/// You do not generally need to add your own conformances to this protocol. If +/// you have an image in another format that needs to be attached to a test, +/// first convert it to an instance of one of the types above. +public protocol AttachableAsIWICBitmapSource: SendableMetatype { + /// Create a WIC bitmap source representing an instance of this type. + /// + /// - Returns: A pointer to a new WIC bitmap source representing this image. + /// The caller is responsible for releasing this image when done with it. + /// + /// - Throws: Any error that prevented the creation of the WIC bitmap source. + func copyAttachableIWICBitmapSource() throws -> UnsafeMutablePointer +} +``` + +Conformance to this protocol is added to `UnsafeMutablePointer` when its +`Pointee` type is one of the following types: + +- [`HBITMAP.Pointee`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) +- [`HICON.Pointee`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) +- [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) + (including its subclasses declared by Windows Imaging Component) + +> [!NOTE] +> The list of conforming types may be extended in the future. The Testing +> Workgroup will determine if additional Swift Evolution reviews are needed. + +A type in Swift can only conform to a protocol with **one** set of constraints, +so we need a helper protocol in order to make `UnsafeMutablePointer` +conditionally conform for all of the above types. This protocol must be `public` +so that Swift Testing can refer to it in API, but it is an implementation detail +and not part of this proposal: + +```swift +public protocol _AttachableByAddressAsIWICBitmapSource {} + +extension HBITMAP.Pointee: _AttachableByAddressAsIWICBitmapSource {} +extension HICON.Pointee: _AttachableByAddressAsIWICBitmapSource {} +extension IWICBitmapSource: _AttachableByAddressAsIWICBitmapSource {} + +extension UnsafeMutablePointer: AttachableAsIWICBitmapSource + where Pointee: _AttachableByAddressAsIWICBitmapSource {} +``` + +See the **Future directions** section (specifically the point about COM and C++ +interop) for more information on why the helper protocol is excluded from this +proposal. + +### Attaching a conforming image + +New overloads of `Attachment.init()` and `Attachment.record()` are provided: + +```swift +extension Attachment { + /// Initialize an instance of this type that encloses the given image. + /// + /// - Parameters: + /// - image: A pointer to the value that will be attached to the output of + /// the test run. + /// - preferredName: The preferred name of the attachment when writing it + /// to a test report or to disk. If `nil`, the testing library attempts + /// to derive a reasonable filename for the attached value. + /// - imageFormat: The image format with which to encode `image`. + /// - sourceLocation: The source location of the call to this initializer. + /// This value is used when recording issues associated with the + /// attachment. + /// + /// You can attach instances of the following system-provided image types to a + /// test: + /// + /// | Platform | Supported Types | + /// |-|-| + /// | macOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) | + /// | iOS, watchOS, tvOS, and visionOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) | + /// | Windows | [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps), [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons), [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) (including its subclasses declared by Windows Imaging Component) | + /// + /// The testing library uses the image format specified by `imageFormat`. Pass + /// `nil` to let the testing library decide which image format to use. If you + /// pass `nil`, then the image format that the testing library uses depends on + /// the path extension you specify in `preferredName`, if any. If you do not + /// specify a path extension, or if the path extension you specify doesn't + /// correspond to an image format the operating system knows how to write, the + /// testing library selects an appropriate image format for you. + public init( + _ image: T, + named preferredName: String? = nil, + as imageFormat: AttachableImageFormat? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) where T: AttachableAsIWICBitmapSource, AttachableValue == _AttachableImageWrapper + + /// Attach an image to the current test. + /// + /// - Parameters: + /// - image: The value to attach. + /// - preferredName: The preferred name of the attachment when writing it + /// to a test report or to disk. If `nil`, the testing library attempts + /// to derive a reasonable filename for the attached value. + /// - imageFormat: The image format with which to encode `image`. + /// - sourceLocation: The source location of the call to this initializer. + /// This value is used when recording issues associated with the + /// attachment. + /// + /// This function creates a new instance of ``Attachment`` wrapping `image` + /// and immediately attaches it to the current test. You can attach instances + /// of the following system-provided image types to a test: + /// + /// | Platform | Supported Types | + /// |-|-| + /// | macOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) | + /// | iOS, watchOS, tvOS, and visionOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) | + /// | Windows | [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps), [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons), [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) (including its subclasses declared by Windows Imaging Component) | + /// + /// The testing library uses the image format specified by `imageFormat`. Pass + /// `nil` to let the testing library decide which image format to use. If you + /// pass `nil`, then the image format that the testing library uses depends on + /// the path extension you specify in `preferredName`, if any. If you do not + /// specify a path extension, or if the path extension you specify doesn't + /// correspond to an image format the operating system knows how to write, the + /// testing library selects an appropriate image format for you. + public static func record( + _ image: T, + named preferredName: String? = nil, + as imageFormat: AttachableImageFormat? = nil, + sourceLocation: SourceLocation = #_sourceLocation + ) where T: AttachableAsIWICBitmapSource, AttachableValue == _AttachableImageWrapper +} +``` + +> [!NOTE] +> `_AttachableImageWrapper` was described in [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md#attaching-a-conforming-image). +> The only difference on Windows is that its associated `Image` type is +> constrained to `AttachableAsIWICBitmapSource` instead of `AttachableAsCGImage`. + +### Specifying image formats + +As on Apple platforms, a test author can specify the image format to use with +`AttachableImageFormat`. See [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md#specifying-image-formats) +for more information about that type. + +Windows does not use Uniform Type Identifiers, so those `AttachableImageFormat` +members that use `UTType` are not available here. Instead, Windows uses a +variety of COM classes that implement codecs for different image formats. +Conveniences over those COM classes' `CLSID` values are provided: + +```swift +extension AttachableImageFormat { + /// The `CLSID` value of the Windows Imaging Component (WIC) encoder class + /// that corresponds to this image format. + /// + /// For example, if this image format equals ``png``, the value of this + /// property equals [`CLSID_WICPngEncoder`](https://learn.microsoft.com/en-us/windows/win32/wic/-wic-guids-clsids#wic-guids-and-clsids). + public var encoderCLSID: CLSID { get } + + /// Construct an instance of this type with the `CLSID` value of a Windows + /// Imaging Component (WIC) encoder class and the desired encoding quality. + /// + /// - Parameters: + /// - encoderCLSID: The `CLSID` value of the Windows Imaging Component + /// encoder class to use when encoding images. + /// - encodingQuality: The encoding quality to use when encoding images. For + /// the lowest supported quality, pass `0.0`. For the highest supported + /// quality, pass `1.0`. + /// + /// If the target image encoder does not support variable-quality encoding, + /// the value of the `encodingQuality` argument is ignored. + /// + /// If `clsid` does not represent an image encoder class supported by WIC, the + /// result is undefined. For a list of image encoder classes supported by WIC, + /// see the documentation for the [`IWICBitmapEncoder`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapencoder) + /// class. + public init(encoderCLSID: CLSID, encodingQuality: Float = 1.0) +} +``` + +For convenience, an initializer is provided that takes a path extension and +tries to map it to the appropriate codec's `CLSID` value: + +```swift +extension AttachableImageFormat { + /// Construct an instance of this type with the given path extension and + /// encoding quality. + /// + /// - Parameters: + /// - pathExtension: A path extension corresponding to the image format to + /// use when encoding images. + /// - encodingQuality: The encoding quality to use when encoding images. For + /// the lowest supported quality, pass `0.0`. For the highest supported + /// quality, pass `1.0`. + /// + /// If the target image format does not support variable-quality encoding, + /// the value of the `encodingQuality` argument is ignored. + /// + /// If `pathExtension` does not correspond to a recognized image format, this + /// initializer returns `nil`: + /// + /// - On Apple platforms, the content type corresponding to `pathExtension` + /// must conform to [`UTType.image`](https://developer.apple.com/documentation/uniformtypeidentifiers/uttype-swift.struct/image). + /// - On Windows, there must be a corresponding subclass of [`IWICBitmapEncoder`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapencoder) + /// registered with Windows Imaging Component. + public init?(pathExtension: String, encodingQuality: Float = 1.0) +} +``` + +For consistency, `init(pathExtension:encodingQuality:)` is provided on Apple +platforms too. (This is the only part of this proposal that affects platforms +other than Windows.) + +### Example usage + +A developer may then easily attach an image to a test by calling +`Attachment.record()` and passing the image of interest. For example, to attach +an icon to a test as a PNG file: + +```swift +import Testing +import WinSDK + +@MainActor @Test func `attaching an icon`() throws { + let hIcon: HICON = ... + defer { + DestroyIcon(hIcon) + } + Attachment.record(hIcon, named: "my icon", as: .png) + // OR: Attachment.record(hIcon, named: "my icon.png") +} +``` + +## Source compatibility + +This change is additive only. + +## Integration with supporting tools + +Tools that handle attachments created by Swift Testing will gain support for +this functionality automatically and do not need to make any changes. + +## Future directions + +- Adding support for projecting COM classes as foreign-reference-counted Swift + classes. The C++ interop team is interested in implementing this feature, but + it is beyond the scope of this proposal. **If this feature is implemented in + the future**, it will cause types like `IWICBitmapSource` to be projected + directly into Swift instead of as `UnsafeMutablePointer` specializations. This + would be a source-breaking change for Swift Testing, but it would make COM + classes much easier to use in Swift. + + In the context of this proposal, `IWICBitmapSource` would be able to directly + conform to `AttachableAsIWICBitmapSource` and we would no longer need the + `_AttachableByAddressAsIWICBitmapSource` helper protocol. The + `AttachableAsIWICBitmapSource` protocol's `copyAttachableIWICBitmapSource()` + requirement would likely change to a property (i.e. + `var attachableIWICBitmapSource: IWICBitmapSource { get throws }`) as it would + be able to participate in Swift's automatic reference counting. + + The Swift team is tracking COM interop with [swiftlang/swift#84056](https://github.com/swiftlang/swift/issues/84056). + +- Adding support for managed (.NET or C#) image types. Support for managed types + on Windows would first require a new Swift/.NET or Swift/C# interop feature + and is therefore beyond the scope of this proposal. + +- Adding support for WinRT image types. WinRT is a thin wrapper around COM and + has C++ and .NET projections, neither of which are readily accessible from + Swift. It may be possible to add support for WinRT image types if COM interop + is implemented. + +- Adding support for other platforms. See [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md#future-directions) + for further discussion about supporting additional platforms. + +## Alternatives considered + +- Doing nothing. We have already added support for attaching images on Apple's + platforms, and Swift Testing is meant to be a cross-platform library, so we + should make a best effort to provide the same functionality on Windows and, + eventually, other platforms. + +- Using more Windows-/COM-like terminology and spelling, e.g. + `CloneAttachableBitmapSource()` instead of `copyAttachableIWICBitmapSource()`. + Swift API should follow Swift API guidelines, even when extending types and + calling functions implemented under other standards. + +- Making `IWICBitmapSource` conform directly to `Attachable`. As with `CGImage` + in [ST-0014](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0014-image-attachments-in-swift-testing-apple-platforms.md#alternatives-considered), + this would prevent us from including additional information (i.e. an instance + of `AttachableImageFormat`). Further, it would be difficult to correctly + manage the lifetime of Windows' 'image objects as they do not participate in + automatic reference counting. + +- Using the GDI+ type [`Gdiplus.Image`](https://learn.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nl-gdiplusheaders-image) + as our currency type instead of `IWICBitmapSource`. This type is a C++ class + but is not a COM class, and so it is not projected into Swift except as + `OpaquePointer` which makes it unsafe to extend it with protocol conformances. + As well, GDI+ is a much older API than WIC and is not recommended by Microsoft + for new development. + +- Designing a platform-agnostic solution. This would likely require adding a + dependency on an open-source image package such as [ImageMagick](https://github.com/ImageMagick/ImageMagick). + Such a library would be a significant new dependency for the testing library + and the Swift toolchain at large. + +## Acknowledgments + +Thank you to @compnerd and the C++ interop team for their help with Windows and +the COM API. From 0c208005794b7e18926534f4318c8740e984164d Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Fri, 19 Sep 2025 13:56:44 -0500 Subject: [PATCH 482/505] ST-0015: Add link to forum review topic (#2961) --- .../testing/0015-image-attachments-in-swift-testing-windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/testing/0015-image-attachments-in-swift-testing-windows.md b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md index 954b0f51a9..74549f0ba7 100644 --- a/proposals/testing/0015-image-attachments-in-swift-testing-windows.md +++ b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md @@ -5,7 +5,7 @@ * Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) * Status: **Active Review (September 19…29, 2025)** * Implementation: [swiftlang/swift-testing#1245](https://github.com/swiftlang/swift-testing/pull/1245), [swiftlang/swift-testing#1254](https://github.com/swiftlang/swift-testing/pull/1254), _et al_. -* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing-windows/81871)) +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing-windows/81871)) ([review](https://forums.swift.org/t/st-0015-image-attachments-in-swift-testing-windows/82241)) ## Introduction From 152203aab0e2ab66ff81b84d76cbf772864fce5f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 22 Sep 2025 12:31:21 -0700 Subject: [PATCH 483/505] Initiate review of SE-0492 "Section Placement Control" --- .../{0nnn-section-control.md => 0492-section-control.md} | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename proposals/{0nnn-section-control.md => 0492-section-control.md} (99%) diff --git a/proposals/0nnn-section-control.md b/proposals/0492-section-control.md similarity index 99% rename from proposals/0nnn-section-control.md rename to proposals/0492-section-control.md index 74af21dbd3..1585f96da8 100644 --- a/proposals/0nnn-section-control.md +++ b/proposals/0492-section-control.md @@ -1,8 +1,10 @@ # Section Placement Control -* Proposal: [SE-0NNN](0nnn-section-control.md) +* Proposal: [SE-0492](0492-section-control.md) * Authors: [Kuba Mracek](https://github.com/kubamracek) -* Status: Pitch #3 +* Status: **Active review (September 22 ... October 6, 2025)** +* Implementation: available in recent `main` snapshots under the experimental feature `SymbolLinkageMarkers` and with undercored attribute names `@_section` and `@_used`. +* Review: TBD * Discussion threads: * Pitch #1: https://forums.swift.org/t/pitch-low-level-linkage-control-attributes-used-and-section/65877 * Pitch #2: https://forums.swift.org/t/pitch-2-low-level-linkage-control/69752 From 2666e940998f1639adbdd66ca6f792dfabdcad44 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 22 Sep 2025 12:35:33 -0700 Subject: [PATCH 484/505] Add review link for SE-0492 --- proposals/0492-section-control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0492-section-control.md b/proposals/0492-section-control.md index 1585f96da8..0f84487b38 100644 --- a/proposals/0492-section-control.md +++ b/proposals/0492-section-control.md @@ -4,7 +4,7 @@ * Authors: [Kuba Mracek](https://github.com/kubamracek) * Status: **Active review (September 22 ... October 6, 2025)** * Implementation: available in recent `main` snapshots under the experimental feature `SymbolLinkageMarkers` and with undercored attribute names `@_section` and `@_used`. -* Review: TBD +* Review: [review](https://forums.swift.org/t/se-0492-section-placement-control/82289) * Discussion threads: * Pitch #1: https://forums.swift.org/t/pitch-low-level-linkage-control-attributes-used-and-section/65877 * Pitch #2: https://forums.swift.org/t/pitch-2-low-level-linkage-control/69752 From 10daeacd15e39d02cb24412e3919b0b8101ebd3d Mon Sep 17 00:00:00 2001 From: "Kuba (Brecka) Mracek" Date: Mon, 22 Sep 2025 13:23:30 -0700 Subject: [PATCH 485/505] Update 0492-section-control.md to avoid using a String in the example --- proposals/0492-section-control.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/0492-section-control.md b/proposals/0492-section-control.md index 0f84487b38..8fa1924e75 100644 --- a/proposals/0492-section-control.md +++ b/proposals/0492-section-control.md @@ -75,14 +75,13 @@ let myLinkerSetEntry: Int = Int.random(in: 0 ..< 10) // ❌ error @section("__DATA,mysection") var mutableVariable: Int = 42 // ✅ -// Some complex data types are allowed (static strings, functions) -typealias PluginData = (version: Int, name: String, initializer: @convention(c) ()->()) +// Some complex data types are allowed (tuples, function references) +typealias PluginData = (version: Int, identifier: UInt64, initializer: @convention(c) ()->()) @section("__DATA,plugins") @used let myPlugin: PluginData = ( version: 1, - name: "MyPlugin", initializer: { print("init") } ) ``` From 4467c59bb235b25910cbaccfba69cd10e959a26f Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Mon, 22 Sep 2025 18:33:11 -0400 Subject: [PATCH 486/505] Add defer async proposal (#2943) * Add defer async proposal * Update proposal in response to pitch discussion * Assign SE-0493 to async defer and schedule for review. --------- Co-authored-by: Holly Borla --- proposals/0493-defer-async.md | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 proposals/0493-defer-async.md diff --git a/proposals/0493-defer-async.md b/proposals/0493-defer-async.md new file mode 100644 index 0000000000..619b0a2643 --- /dev/null +++ b/proposals/0493-defer-async.md @@ -0,0 +1,132 @@ +# Support `async` calls in `defer` bodies + +* Proposal: [SE-0493](0493-defer-async.md) +* Authors: [Freddy Kellison-Linn](https://github.com/Jumhyn) +* Review Manager: [Holly Borla](https://github.com/hborla) +* Status: **Active review (September 22 - October 6, 2025)** +* Implementation: [swiftlang/swift#83891](https://github.com/swiftlang/swift/pull/83891) +* Review: ([pitch](https://forums.swift.org/t/support-async-calls-in-defer-bodies/81790)) + +## Introduction + +This is a targeted proposal to introduce support for asynchronous calls within `defer` statements. Such calls must be marked with `await` as any other asynchronous call would be, and `defer` statements which do asynchronous work will be implicitly awaited at any relevant scope exit point. + +## Motivation + +The `defer` statement was introduced in Swift 2 (before Swift was even open source) as the method for performing scope-based cleanup in a reliable way. Whenever a lexical scope is exited, the bodies of prior `defer` statements within that scope are executed (in reverse order, in the case of multiple `defer` statements). + +```swift +func sendLog(_ message: String) async throws { + let localLog = FileHandle("log.txt") + + // Will be executed even if we throw + defer { localLog.close() } + + localLog.appendLine(message) + try await sendNetworkLog(message) +} +``` + +This lets cleanup operations be syntactically colocated with the corresponding setup while also preventing the need to manually insert the cleanup along every possible exit path. + +While this provides a convenient and less-bug-prone way to perform important cleanup, the bodies of `defer` statements are not permitted to do any asynchronous work. If you attempt to `await` something in the body of a `defer` statement, you'll get an error even if the enclosing context is `async`: + +```swift +func f() async { + await setUp() + // error: 'async' call cannot occur in a defer body + defer { await performAsyncTeardown() } + + try doSomething() +} +``` + +If a particular operation *requires* asynchronous cleanup, then there aren't any great options today. An author can either resort to inserting the cleanup on each exit path manually (risking that they or a future editor will miss a path), or else spawn a new top-level `Task` to perform the cleanup: + +```swift +defer { + // We'll clean this up... eventually + Task { await performAsyncTeardown() } +} +``` + +## Proposed solution + +This proposal allows `await` statements to appear in `defer` bodies whenever the enclosing context is already `async`. Whenever a scope is exited, the bodies of all prior `defer` statements will be executed in reverse order of declaration, just as before. The bodies of any `defer` statements containing asynchronous work will be `await`ed, and run to completion before the function returns. + +Thus, the example from **Motivation** above will become valid code: +```swift +func f() async { + await setUp() + defer { await performAsyncTeardown() } // OK + + try doSomething() +} +``` + +## Detailed design + +When a `defer` statement contains asynchronous work, we will generate an implicit `await` when it is called on scope exit. See **Alternatives Considered** for further discussion. + +We always require that the parent context of the `defer` be explicitly or implicitly `async` in order for `defer` to contain an `await`. That is, the following is not valid: + +```swift +func f() { + // error: 'async' call in a function that does not support concurrency + defer { await g() } +} +``` + +In positions where `async` can be inferred, such as for the types of closures, an `await` within the body of a `defer` is sufficient to infer `async`: + +```swift +// 'f' implicitly has type '() async -> ()' +let f = { + defer { await g() } +} +``` + +The body of a `defer` statement will always inherit the isolation of its enclosing scope, so an asynchronous `defer` body will never introduce *additional* suspension points beyond whatever suspension points are introduced by the functions it calls. + +## Source compatibility + +This change is additive and opt-in. Since no `defer` bodies today can do any asynchronous work, the behavior of existing code will not change. + +## ABI compatibility + +This proposal does not have any impact at the ABI level. It is purely an implementation detail. + +## Implications on adoption + +Adoping asynchronous `defer` is an implementation-level detail and does not have any implications on ABI or API stability. + +## Alternatives considered + +### Require some statement-level marking such as `defer async` + +We do not require any more source-level annotation besides the `await` that will appear on the actual line within the `defer` which invokes the asynchronous work. We could go further and require one to write something like: +```swift +defer async { + await fd.close() +} +``` + +This proposal declines to introduce such requirement. Because `defer` bodies are typically small, targeted cleanup work, we do not believe that substantial clarity is gained by requiring another marker which would remain local *to the `defer`* statement itself. Moreover, the enclosing context of such `defer` statements will *already* be required to be `async`. In the case of `func` declarations, this will be explicit. In the case of closures, this may be inferred, but will be no less implicit than the inference that already happens from having an `await` in a closure body. + +### Require some sort of explicit `await` marking on scope exit + +The decision to implicltly await asyncrhonous `defer` bodies has the potential to introduce unexpected suspension points within function bodies. This proposal takes the position that the implicit suspension points introduced by asynchronous `defer` bodies is almost entirely analagous to the [analysis](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0317-async-let.md#requiring-an-awaiton-any-execution-path-that-waits-for-an-async-let) provided by the `async let` proposal. Both of these proposals would require marking every possible control flow edge which exits a scope. + +If anything, the analysis here is even more favorable to `defer`. In the case of `async let` it is possible to have an implicit suspension point without `await` appearing anywhere in the source—with `defer`, any suspension point within the body will be marked with `await`. + +### Suppress task cancellation within `defer` bodies + +During discussion of the behavior expected from asynchronous `defer` bodies, one point raised was whether we ought to remove the ability of code within a `defer` to observe the current task's cancellation state. Under this proposal, no such change is adopted, and if the current task is cancelled then all code called from the `defer` will observe that cancellation (via `Task.isCancelled`, `Task.checkCancellation()`, etc.) just as it would if called from within the main function body. + +The alternative suggestion here noted that because task cancellation can sometimes cause code to be skipped, it is not in the general case appropriate to run necessary cleanup code within an already-cancelled task. For instance, if one wishes to run some cleanup on a timeout (via `Task.sleep`) or via an HTTP request or filesystem operation, these operations could interpret running in a cancelled task as an indication that they _should not perform the requested work_. + +We could, instead, notionally 'un-cancel' the current task if we enter a `defer` body: all code called from within the `defer` would observe `Task.isCancelled == true`, `Task.checkCancellation()` would not throw, etc. This would allow timeouts to continue to function and ensure that any downstream cleanup would not misinterpret task cancellation as an indication that it should early-exit. + +This proposal does not adopt such behavior, for a combination of reasons: +1. Synchronous `defer` bodies already observe cancellation 'normally', i.e., `Task.isCancelled` can be accessed within the body of a synchronous `defer`, and it will reflect the actual cancellation status of the enclosing task. While it is perhaps less likely that existing synchronous code exhibits behavior differences with respect to cancellation status, it would be undesirable if merely adding `await` in one part of a `defer` body could result in behavior changes for other, unrelated code in the same `defer` body. +2. We do not want a difference in behavior that could occur merely from moving existing code into a `defer`. Existing APIs which are sensitive to cancellation must already be used with care even in straight-line code where `defer` may not be used (since cancellation can happen at any time), and this proposal takes the position that such APIs are more appropriately addressed by a general `withCancellationIgnored { ... }` feature (or similar) as discussed in the pitch thread. From 8c5f155660a7b6fd87627528e20c3612a7b9dbcc Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 22 Sep 2025 15:39:07 -0700 Subject: [PATCH 487/505] Link SE-0493 review thread. (#2965) --- proposals/0493-defer-async.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0493-defer-async.md b/proposals/0493-defer-async.md index 619b0a2643..c460b1cbd4 100644 --- a/proposals/0493-defer-async.md +++ b/proposals/0493-defer-async.md @@ -5,7 +5,7 @@ * Review Manager: [Holly Borla](https://github.com/hborla) * Status: **Active review (September 22 - October 6, 2025)** * Implementation: [swiftlang/swift#83891](https://github.com/swiftlang/swift/pull/83891) -* Review: ([pitch](https://forums.swift.org/t/support-async-calls-in-defer-bodies/81790)) +* Review: ([pitch](https://forums.swift.org/t/support-async-calls-in-defer-bodies/81790)) ([review](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293)) ## Introduction From e87f745125c0304be7bbcb3b08647ee34d902801 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 22 Sep 2025 20:09:24 -0400 Subject: [PATCH 488/505] Assign SE-0494 to the `isIdentical(to:)` proposal Also fix some of the header fields --- ...ntical-methods.md => 0494-add-is-identical-methods.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{NNNN-add-is-identical-methods.md => 0494-add-is-identical-methods.md} (99%) diff --git a/proposals/NNNN-add-is-identical-methods.md b/proposals/0494-add-is-identical-methods.md similarity index 99% rename from proposals/NNNN-add-is-identical-methods.md rename to proposals/0494-add-is-identical-methods.md index 4eb0536cc6..b8679fa993 100644 --- a/proposals/NNNN-add-is-identical-methods.md +++ b/proposals/0494-add-is-identical-methods.md @@ -1,11 +1,11 @@ # Add `isIdentical(to:)` Methods for Quick Comparisons to Concrete Types -* Proposal: [SE-NNNN](NNNN-add-is-identical-methods.md) +* Proposal: [SE-0494](0494-add-is-identical-methods.md) * Authors: [Rick van Voorden](https://github.com/vanvoorden), [Karoy Lorentey](https://github.com/lorentey) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [John McCall](https://github.com/rjmccall) +* Status: **Active review (September 22nd...October 6th, 2025)** * Implementation: ([String, Substring](https://github.com/swiftlang/swift/pull/82055)), ([Array, ArraySlice, ContiguousArray](https://github.com/swiftlang/swift/pull/82438)), ([Dictionary, Set](https://github.com/swiftlang/swift/pull/82439)) -* Review: ([Pre-Pitch](https://forums.swift.org/t/-/78792)), ([Pitch #1](https://forums.swift.org/t/-/79145)), ([Pitch #2](https://forums.swift.org/t/-/80496)) +* Review: ([prepitch](https://forums.swift.org/t/-/78792)) ([first pitch](https://forums.swift.org/t/-/79145)) ([second pitch](https://forums.swift.org/t/-/80496)) ### Table of Contents From 8b998ad48d19d43758b90bbfb2248afd5aeda0c5 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 22 Sep 2025 20:14:13 -0400 Subject: [PATCH 489/505] Add review link to SE-0494 --- proposals/0494-add-is-identical-methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0494-add-is-identical-methods.md b/proposals/0494-add-is-identical-methods.md index b8679fa993..076d35f9a5 100644 --- a/proposals/0494-add-is-identical-methods.md +++ b/proposals/0494-add-is-identical-methods.md @@ -5,7 +5,7 @@ * Review Manager: [John McCall](https://github.com/rjmccall) * Status: **Active review (September 22nd...October 6th, 2025)** * Implementation: ([String, Substring](https://github.com/swiftlang/swift/pull/82055)), ([Array, ArraySlice, ContiguousArray](https://github.com/swiftlang/swift/pull/82438)), ([Dictionary, Set](https://github.com/swiftlang/swift/pull/82439)) -* Review: ([prepitch](https://forums.swift.org/t/-/78792)) ([first pitch](https://forums.swift.org/t/-/79145)) ([second pitch](https://forums.swift.org/t/-/80496)) +* Review: ([prepitch](https://forums.swift.org/t/-/78792)) ([first pitch](https://forums.swift.org/t/-/79145)) ([second pitch](https://forums.swift.org/t/-/80496)) ([review](https://forums.swift.org/t/se-0494-add-isidentical-to-methods-for-quick-comparisons-to-concrete-types/82296)) ### Table of Contents From 5c706ee498f6165e17cc327cfd93469f5a199411 Mon Sep 17 00:00:00 2001 From: omochimetaru Date: Tue, 23 Sep 2025 11:55:25 +0900 Subject: [PATCH 490/505] fix trait syntax --- proposals/0450-swiftpm-package-traits.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/0450-swiftpm-package-traits.md b/proposals/0450-swiftpm-package-traits.md index 8670adc75c..70950f32d4 100644 --- a/proposals/0450-swiftpm-package-traits.md +++ b/proposals/0450-swiftpm-package-traits.md @@ -75,7 +75,7 @@ let package = Package( enabledTraits: [ // Other traits that are enabled when this trait is being enabled "Foo", ] - ) + ), .trait( name: "FooBar", enabledTraits: [ @@ -92,7 +92,7 @@ let package = Package( When depending on a package the `default` trait is enabled. However, the enabled traits can be customized by passing a set of enabled traits when declaring the dependency. When specifying the enabled traits of the dependencies the -`.default` trait can be passed which will enable the default trait. The below +`.defaults` trait can be passed which will enable the default trait. The below example enables the default trait and the additional `SomeTrait` of the package. ```swift @@ -101,7 +101,7 @@ dependencies: [ url: "https://github.com/Org/SomePackage.git", from: "1.0.0", traits: [ - .default, + .defaults, "SomeTrait" ] ), @@ -130,7 +130,7 @@ dependencies: [ url: "https://github.com/Org/SomePackage.git", from: "1.0.0", traits:[ - .trait("SomeOtherTrait", condition: .when(traits: ["Foo"])), + .trait(name: "SomeOtherTrait", condition: .when(traits: ["Foo"])), ] ), ] From f52bc4bf8704342aceb1c2397cdd6df05fe9dc16 Mon Sep 17 00:00:00 2001 From: Ali AlSalman Date: Tue, 23 Sep 2025 20:05:39 +0300 Subject: [PATCH 491/505] Update README.md add 6.2 release --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1f5fdb53b..47a172b81a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This repository tracks the ongoing evolution of the Swift programming language, | Version | Announced | Released | | :-------- | :----------------------------------------------------------------------- | :----------------------------------------------------------- | -| Swift 6.2 | [2025-03-08](https://forums.swift.org/t/swift-6-2-release-process/78371) | | +| Swift 6.2 | [2025-03-08](https://forums.swift.org/t/swift-6-2-release-process/78371) | [2025-09-15](https://www.swift.org/blog/swift-6.2-released/) | | Swift 6.1 | [2024-10-17](https://forums.swift.org/t/swift-6-1-release-process/75442) | [2025-03-31](https://www.swift.org/blog/swift-6.1-released/) | | Swift 6.0 | [2024-02-22](https://forums.swift.org/t/swift-6-0-release-process/70220) | [2024-09-17](https://www.swift.org/blog/announcing-swift-6/) | | Swift 5.10 | [2023-08-23](https://forums.swift.org/t/swift-5-10-release-process/66911) | [2024-03-05](https://www.swift.org/blog/swift-5.10-released/) | From bcf0acad5f45b9461d86499817d64d20fd0127b6 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Tue, 23 Sep 2025 12:07:46 -0700 Subject: [PATCH 492/505] SE-0492: Clarify wording (built-in -> standard) and code snippets --- proposals/0492-section-control.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/0492-section-control.md b/proposals/0492-section-control.md index 8fa1924e75..ac8a9d05e8 100644 --- a/proposals/0492-section-control.md +++ b/proposals/0492-section-control.md @@ -92,7 +92,7 @@ Different object file formats (ELF, Mach-O, COFF) have different restrictions an ```swift #if objectFileFormat(ELF) -@section(".mysection") +@section("mysection") #elseif objectFileFormat(MachO) @section("__DATA,mysection") #endif @@ -190,11 +190,11 @@ The effects described above are applied to the storage symbols and don’t gener ### Constant expressions -Swift currently does not have a formal notion of a **constant expression**, i.e. an expression with a syntactic form that *guarantees the ability to know it's value at compile-time*. This proposal provides a definition of a "bare minimum" constant expression, with the understanding that this does not cover the language needs in generality, and the expectation that the Swift compiler and language will keep expanding the allowed forms of constant expressions. See [Generalized constant values and expressions](#generalized-constant-values-and-expressions) in Future Directions for further discussion on this. +Swift currently does not have a formal notion of a **constant expression**, i.e. an expression with a syntactic form that *guarantees the ability to know it's value at compile-time*. This proposal provides a definition of a "bare minimum" constant expression, with the understanding that this does not cover the language needs in generality, and with the expectation that the Swift compiler and language will keep expanding the allowed forms of constant expressions in the future. See [Generalized constant values and expressions](#generalized-constant-values-and-expressions) in Future Directions for further discussion on this. This proposal defines a **constant expression** as being one of: -- an integer literal using any of built-in integer types (Int, UInt, Int8/16/32/64/128, UInt8/16/32/64/128) +- an integer literal using any of standard integer types (Int, UInt, Int8/16/32/64/128, UInt8/16/32/64/128) - a floating-point literal of type Float or Double - a boolean literal of type Bool - a direct reference to a non-generic function using its name (the function itself is not generic, and also it must not be defined in a generic context) @@ -202,7 +202,7 @@ This proposal defines a **constant expression** as being one of: - a tuple composed of only other constant expressions - an array literal of type InlineArray composed of only other constant expressions -Explicitly, this definition currently does **not allow** any operators, using any user-defined named types, any other built-in type (e.g. strings, dictionaries, sets), using closures, or referencing any variables by name. See below for examples of valid and invalid constant expressions: +Explicitly, this definition currently does **not allow** any operators, using any user-defined named types, any other standard type (e.g. strings, dictionaries, sets), using closures, or referencing any variables by name. See below for examples of valid and invalid constant expressions: ```swift @section("...") let a = 42 // ✅ @@ -211,7 +211,7 @@ Explicitly, this definition currently does **not allow** any operators, using an @section("...") let d = Int.max // ❌ not a literal @section("...") let e: UInt8 = 42 // ✅ @section("...") let f = UInt8(42) // ❌ not a literal -@section("...") let g: MyCustomExpressibleByIntegerLiteral = 42 // ❌ not a built-in type +@section("...") let g: MyCustomExpressibleByIntegerLiteral = 42 // ❌ not a standard type @section("...") let composition1 = (1, 2, 3, 2.718, true) // ✅ @section("...") let composition2 = (1, 2, Int.max) // ❌ tuple component not constant @@ -321,7 +321,7 @@ In some cases, it’s not possible to differentiate on the OS to support multipl #if objectFileFormat(MachO) @section("__DATA_CONST,mysection") #elseif objectFileFormat(ELF) -@section(".mysection") +@section("mysection") #endif let value = ... ``` @@ -402,7 +402,7 @@ The requirement to only use string literals as the section names could be lifted ```swift #if objectFileFormat(ELF) -let mySectionName = ".mysection" // required to be a compile-time value +let mySectionName = "mysection" // required to be a compile-time value #elseif objectFileFormat(MachO) let mySectionName = "__DATA,mysection" // required to be a compile-time value #endif From 5949add13f255d3edaba045d7a0525e1fd75694d Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 24 Sep 2025 17:53:59 -0700 Subject: [PATCH 493/505] Revise SE-0491 with carveout for generic params (#2970) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the review, Slava Pestov explained that it didn’t make sense to try to apply a module selector to a member type whose base was a generic parameter, as the member type will always represent the union of all associated types by that name. Edit the proposal to specify that module selectors are not valid in this position. --- proposals/0491-module-selectors.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/proposals/0491-module-selectors.md b/proposals/0491-module-selectors.md index 7d2c769591..60bcd020da 100644 --- a/proposals/0491-module-selectors.md +++ b/proposals/0491-module-selectors.md @@ -476,6 +476,28 @@ some other language feature has ruled out. For example, if a declaration is inaccessible because of access control or hasn't been imported into the current source file, a module selector will not allow it to be accessed. +#### Member types of type parameters + +A member type of a type parameter must not be qualified by a module selector. + +```swift +func fn(_: T) where T.Swift::ID == Int { // not allowed + ... +} +``` + +This is because, when a generic parameter conforms to two protocols that have +associated types with the same name, the member type actually refers to *both* +of those associated types. It doesn't make sense to use a module name to select +one associated type or the other--it will always encompass both of them. + +(In some cases, a type parameter's member type might end up referring to a +concrete type—typically a typealias in a protocol extension–which +theoretically *could* be disambiguated in this way. However, in these +situations you could always use the protocol instead of the generic parameter +as the base (and apply a module selector to it if needed), so we've chosen not +to make an exception for them.) + ## Source compatibility This change is purely additive; it only affects the behavior of code which uses From e8e3cb68ae699e905be224cbf4ca179971d00bb6 Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Wed, 24 Sep 2025 20:56:33 -0400 Subject: [PATCH 494/505] Extend review period (#2971) --- proposals/0491-module-selectors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0491-module-selectors.md b/proposals/0491-module-selectors.md index 60bcd020da..d609228a11 100644 --- a/proposals/0491-module-selectors.md +++ b/proposals/0491-module-selectors.md @@ -3,7 +3,7 @@ * Proposal: [SE-0491](0491-module-selectors.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Freddy Kellison-Linn](https) -* Status: **Active review (September 13 ... September 26, 2025)** +* Status: **Active review (September 13 ... September 30, 2025)** * Bug: [swiftlang/swift#53580](https://github.com/swiftlang/swift/issues/53580) (SR-11183) * Implementation: [swiftlang/swift#34556](https://github.com/swiftlang/swift/pull/34556) * Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) ([review](https://forums.swift.org/t/se-0491-module-selectors-for-name-disambiguation/82124)) From 97cd4b2c511db7e46d04a3f18c7a36051ce63f74 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Wed, 24 Sep 2025 20:54:58 -0700 Subject: [PATCH 495/505] SE-0492: Clarify the intent of using section names verbatim --- proposals/0492-section-control.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/0492-section-control.md b/proposals/0492-section-control.md index ac8a9d05e8..875a9b3ba2 100644 --- a/proposals/0492-section-control.md +++ b/proposals/0492-section-control.md @@ -88,7 +88,7 @@ let myPlugin: PluginData = ( On top of specifying a custom section name with the `@section` attribute, marking a variable as `@used` is needed to prevent otherwise unused symbols from being removed by the compiler. When using section placement to e.g. implement linker sets, such values are typically going to have no usage at compile time, and at the same time they should not be exposed in public interface of libraries (not be made public), therefore we the need the `@used` attribute. -Different object file formats (ELF, Mach-O, COFF) have different restrictions and rules on what are valid section names, and cross-platform code will have to use different names for different file formats. To support that, custom section names can be specified as a string literal. The name will be directly set for the symbol in the resulting object file, without any processing. A new `#if objectFileFormat(...)` conditional compilation directive will be provided to support conditionalizing based on the file format: +Different object file formats (ELF, Mach-O, COFF) have different restrictions and rules on what are valid section names, and cross-platform code will have to use different names for different file formats. To support that, custom section names can be specified as a string literal. The string will be used directly, without any processing, as the section name for the symbol. A new `#if objectFileFormat(...)` conditional compilation directive will be provided to support conditionalizing based on the file format: ```swift #if objectFileFormat(ELF) @@ -180,13 +180,14 @@ When allowed, the `@section` attribute on a variable declaration has the followi 1. The variable’s initializer expression is going to be constant folded at compile-time, and assigned as the initial value to the storage symbol for the variable, i.e. the variable will be **statically initialized**. The variable’s value will not be lazily computed at runtime, and it will not use the one-time initialization helper code and token. If that’s not possible, an error is diagnosed. 2. The storage symbol for the variable will be placed into a custom section with the specified name. + - Concretely, the section name string value will be set verbatim as a section specifier for the storage symbol at the LLVM IR level of the compiler. This means that any special behavior that the optimizer, the backend, the assembler or the linker applies based on known section names (or attributes specified as suffixes on the section name) will apply. 3. If applied to a global that is declared as part of top-level executable code (i.e. main.swift), the usual non-top-level-code initialization behavior is applied to the global. I.e. the variable is not sequentially initialized at startup. When allowed, the `@used` attribute on a variable declaration has the following effect: 1. The storage symbol for the variable will be marked as “do not dead-strip”. -The effects described above are applied to the storage symbols and don’t generally affect optimizations and other transformations in the compiler. For example, the compiler is still allowed to propagate and copy a the constant value to code that uses the value, so there’s no guarantee that a value stored into a global with a custom section will not be propagated and “leak” outside of the section. The `@used` annotation, however, does inform the optimizer that such a variable cannot be removed, even when it doesn’t have any observed users or even if it’s inaccessible due to language rules (e.g. if it’s a private static member on an otherwise empty type). +The effects described above are applied to the storage symbols and don’t generally affect optimizations and other transformations in the compiler. For example, the compiler is still allowed to propagate and copy a constant value of a `let` variable to code that uses the variable, therefore there’s no guarantee that a value stored into a global with a custom section will not be propagated and “leak” outside of the section. The `@used` annotation, however, does inform the optimizer that such a variable cannot be removed, even when it doesn’t have any observed users or even if it’s inaccessible due to language rules (e.g. if it’s a private static member on an otherwise empty type). ### Constant expressions From 40115fa4aae9e849635ec9f7e6ba513ff674b25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Thu, 25 Sep 2025 08:31:57 -0700 Subject: [PATCH 496/505] [Pitch] C compatible functions and enums with `@c` (#2813) * [Pitch] Base proposal to formalize @cdecl * [Pitch] Update @cdecl proposal after pitch and implementation * Mark the @cdecl proposal as ready for review * cdecl: apply early LSG comments * Update and rename NNNN-cdecl.md to 0495-cdecl.md Assign SE-0495 --------- Co-authored-by: Stephen Canon --- proposals/0495-cdecl.md | 228 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 proposals/0495-cdecl.md diff --git a/proposals/0495-cdecl.md b/proposals/0495-cdecl.md new file mode 100644 index 0000000000..1eaa1195cb --- /dev/null +++ b/proposals/0495-cdecl.md @@ -0,0 +1,228 @@ +# C compatible functions and enums + +* Proposal: [SE-0495](0495-cdecl.md) +* Author: [Alexis Laferrière](https://github.com/xymus) +* Review Manager: [Steve Canon](https://github.com/stephentyrone) +* Status: **Ready for Review** +* Implementation: On `main` with the experimental feature flags `CDecl` for `@c`, and `CImplementation` for `@c @implementation`. With the exception of the `@objc` support for global functions which is available under the name `@_cdecl`. +* Review: ([pitch](https://forums.swift.org/t/pitch-formalize-cdecl/79557)) + +## Introduction + +Implementing a C function in Swift eases integration of Swift and C code. This proposal introduces `@c` to mark Swift functions as callable from C, and enums as representable in C. It provides the same behavior under the `@objc` attribute for Objective-C compatible global functions. + +To expose the function to C clients, this proposal adds a new C block to the compatibility header where `@c` functions are printed. As an alternative, this proposal extends `@implementation` support to global functions, allowing users to declare the function in a hand-written C header. + +> Note: This proposal aims to formalize and extend the long experimental `@_cdecl`. While experimental this attribute has been widely in use so we will refer to it as needed for clarity in this document. + +## Motivation + +Swift already offers some integration with C, notably it can import declarations from C headers and call C functions. Swift also already offers a wide integration with Objective-C: import headers, call methods, print the compatibility header, and implement Objective-C classes in Swift with `@implementation`. These language features have proven to be useful for integration with Objective-C. Offering a similar language support for C will further ease integrating Swift and C, and encourage incremental adoption of Swift in existing C code bases. + +Offering a C compatibility type-checking ensures `@c` functions only reference types representable in C. This type-checking helps cross-platform development as one can define a `@c` while working from an Objective-C compatible environment and still see the restrictions from a C only environment. + +Printing the C representation of `@c` functions in a C header will enable a mixed-source software to easily call the functions from C code. The current generated header is limited to Objective-C and C++ content. Adding a section for C compatible clients will extend its usefulness to this language. + +Extending `@implementation` to support global C functions will provide support to developers through type-checking by ensuring the C declaration matches the corresponding definition in Swift. + +## Proposed solution + +We propose to introduce the new `@c` attribute for global functions and enums, extend `@objc` for global functions, and support `@c @implementation`. + +### `@c` global functions + +Introduce the `@c` attribute to mark a global function as a C function implemented in Swift. That function uses the C calling convention and its signature can only reference types representable in C. Its body is implemented in Swift as usual. The signature of that function is printed in the compatibility header using C corresponding types, allowing C source code to import the compatibility header and call the function. + +A `@c` function is declared with an optional C function name, by default the Swift base name is used as C name: +```swift +@c func foo() {} + +@c(mirrorCName) +func mirror(value: CInt) -> CInt { return value } +``` + +### `@objc` global functions + +Extends the `@objc` attribute to be accepted on a global function. It offers the same behavior as `@c` while allowing the signature to reference types representable in Objective-C. The signature of a `@objc` function is printed in the compatibility header using corresponding Objective-C types. + +A `@objc` function is declared with an optional C compatible name without parameter labels: + +```swift +@objc func bar() {} + +@objc(mirrorObjCName) +func objectMirror(value: NSObject) -> NSObject { return value } +``` + +> Note: The attribute `@objc` can be used on a global function to replace `@_cdecl` as it preserves the behavior of the unofficial attribute. + +### `@c` enums + +Accept `@c` on enums to mark them as C compatible. These enums can be referenced from `@c` or `@objc` functions. They are printed in the compatibility header as a C enum or a similar type. + +A `@c` enum may declare a custom C name, and must declare an integer raw type compatible with C: + +```swift +@c +enum CEnum: CInt { + case a + case b +} +``` + +The attribute `@objc` is already accepted on enums. These enums qualify as an Objective-C representable type and are usable from `@objc` global function signatures but not from `@c` functions. + +### `@c @implementation` global functions + +Extend support for the `@implementation` attribute, introduced in [SE-0436](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0436-objc-implementation.md), to global functions marked with either `@c` or `@objc`. These functions are declared in an imported C or Objective-C header, while the Swift function provides their implementation. Type-checking ensures the declaration matches the implementation signature in Swift. Functions marked `@implementation` are not printed in the compatibility header. + +The declaration and implementation are distinct across languages and must have matching names and types: + +```c +// C header +int cImplMirror(int value); +``` + +```swift +// Swift sources +@c @implementation +func cImplMirror(_ value: CInt) -> CInt { return value } +``` + +## Detailed design + +This proposal extends the language syntax, type-checking for both global functions and enums, supporting logic for `@implementation`, and the content printed to the compatibility header. + +### Syntax + +Required syntax changes involve one new attribute and the reuse of two existing attributes. + +* Introduce the attribute `@c` accepted on global functions and enums. It accepts one optional parameter specifying the corresponding C name of the declaration. The C name defaults to the Swift base identifier of the declaration, it doesn't consider parameter names. + +* Extend `@objc` to be accepted on global functions, using the optional parameter to define the C function name instead of the Objective-C symbol. Again here, the C function name defaults to the base identifier of the Swift function. + +* Extend `@implementation` to be accepted on global functions marked with either `@c` or `@objc`. + +### Type-checking of global functions signatures + +Global functions marked with `@c` or `@objc` need type-checking to ensure types used in their signature are representable in the target language. + +The following types are accepted in the signature of `@c` global functions: + +- Primitive types defined in the standard library: Int, UInt, Int8, Float, Double, Bool, etc. +- Pointers defined in the standard library: OpaquePointer and the variants of Unsafe{Mutable}{Raw}Pointer. +- C primitive types defined in the standard library: CChar, CInt, CUnsignedInt, CLong, CLongLong, etc. +- Function references using the C calling convention, marked with `@convention(c)`. +- SIMD types where the scalar is representable in C. +- Enums marked with `@c`. +- Imported C types. + +In addition to the types above, the following types should be accepted in the signature of `@objc` global functions: + +- `@objc` classes, enums and protocols. +- Imported Objective-C types. + +For both `@c` and `@objc` global functions, type-checking should reject: + +- Optional non-pointer types. +- Non-`@objc` classes. +- Swift structs. +- Non-`@c` enums. +- Protocol existentials. + +### Type-checking of `@c` enums + +For `@c` enums to be representable in C, type-checking should ensure the raw type is defined to an integer value that is itself representable in C. This is the same check as already applied to `@objc` enums. + +### `@c @implementation` and `@objc @implementation` + +A global function marked with `@c @implementation` or `@objc @implementation` needs to be associated with the corresponding declaration from imported headers. The compiler should report uses without a corresponding C declaration or inconsistencies in the match. + +### Compatibility header printing + +The compiler should print a single compatibility header for all languages, adding a block specific to C as is currently done for Objective-C and C++. Printing the header is requested using the preexisting compiler flags: `-emit-objc-header`, `-emit-objc-header-path` or `-emit-clang-header-path`. + +This C block declares the `@c` global functions and enums using C types, while `@objc` functions are printed in the Objective-C block with Objective-C types. + +The C block should be printed in a way it's parseable by compilers targeting C, Objective-C and C++. To do so, ensure that only C types are printed, there is no unprotected use of non-standard C features, and the syntax is C compatible. + +### Type mapping to C + +When printing `@c` functions in the compatibility header, Swift types are mapped to their corresponding C representations. Here is a partial mapping: + +- Swift `Bool` maps to C `bool` from `stdbool.h`. +- Swift `Int` maps to `ptrdiff_t`, `UInt` to `size_t`, `Int8` to `int8_t`, `UInt32` to `uint32_t`, etc. +- Swift floating-point types `Float` and `Double` map to C `float` and `double` respectively. +- Swift's version of C primitive types map to their C equivalents: `CInt` to `int`, `CLong` to long, etc. +- Swift SIMD types map to vector types printed as needed in the compatibility header. +- Function references with `@convention(c)` map to C function pointers. + +## Source compatibility + +This proposal preserves all source compatibility as the new features are opt-in. + +Existing adopters of `@_cdecl` can replace the attribute with `@objc` to preserve the same behavior. Alternatively, they can update it to `@c` to get the more restrictive C compatibility check. Using `@c` will however change how the corresponding C function is printed in the compatibility header so it may be necessary to update sources calling into the function. + +## ABI compatibility + +Marking a global function with `@c` or `@objc` makes it use the C calling convention. Adding or removing these attributes on a function is an ABI breaking change. Updating existing `@_cdecl` to `@objc` or `@c` is ABI stable. + +Adding or removing the `@c` attribute on an enum is ABI stable, but changing its raw type is not. + +Moving the implementation of an existing C function to Swift using `@c` or `@objc @implementation` within the same binary is ABI stable. + +## Implications on adoption + +The changes proposed here are backwards compatible with older runtimes. + +## Future directions + +This work opens the door to closer interoperability with the C language. + +### `@c` struct support + +A valuable addition would be supporting C compatible structs declared in Swift. We could consider exposing them to C as opaque data, or produce structs with a memory layout representable in C. Both have different use cases and advantages: + +* Using an opaque data representation would hide Swift details from C. Hiding these details allows the Swift struct to reference any Swift types and language features, without the concern of finding an equivalent C representation. This approach should be enough for the standard references to user data in C APIs. + +* Producing a Swift struct with a C memory layout would give the C code direct access to the data. This struct could be printed in the compatibility header as a normal C struct. This approach would need to be more restrictive on the Swift types and features used in the struct, starting with accepting only C representable types. + +### Custom calling conventions + +Defining a custom calling convention on a function may be a requirement by some API for callback functions and such. + +With this proposal, it should be possible to declare a custom calling convention by using `@c @implementation`. This allows to apply any existing C attribute on the definition in the C header. + +We could allow specifying the C calling conventions from Swift code with further work. Either by extending `@convention` to be accepted on `@c` and `@objc` global functions, and have it accept a wider set of conventions. Or by adding an optional named parameter to the `@c` attribute in the style of `@c(customCName, convention: stdcall)`. + +## Alternatives considered + +### `@c` attribute name + +This proposal uses the `@c` attribute on functions to identify them as C functions implemented in Swift and on enums to identify them as C compatible. This concise attribute clearly references interoperability with the C language. Plus, having an attribute specific to this feature aligns with `@objc` which is already used on some functions, enums, and for `@objc @implementation`. + +We considered some alternatives: + +- An official `@cdecl` may be more practical for discoverability but the terms *cdecl* and *decl* are compiler implementation details we do not wish to surface in the language. + +- An official `@expose(c)`, formalizing the experimental `@_expose(Cxx)`, would align the global function use case with what has been suggested for the C++ interop. However, sharing an attribute for the features described here may add complexity to both compiler implementation and user understanding of the language. + + While `@_expose(Cxx)` supports enums, it doesn't have the same requirement as `@objc` and `@c` for the raw type. The generated representation in the compatibility header for the enums differs too. The attribute `@_expose(Cxx)` also supports structs, while we consider supporting `@c` structs in the future, we have yet to pick the best approach so it would likely differ from the C++ one. + + Although sharing an attribute avoids adding a new one to the language, it also implies a similar behavior between the language interops. However, these behaviors already diverge and we may want to have each feature evolve differently in the future. + +### `@objc` attribute on global functions + +We use the `@objc` attribute on global functions to identify them as C functions implemented in Swift that are callable from Objective-C. This was more of a natural choice as `@objc` is already widely used for interoperability with Objective-C. + +We considered using instead `@c @objc` to make it more explicit that the behavior is similar to `@c`, and extending it to Objective-C is additive. We went against this option as it doesn't add much useful information besides being closer to the compiler implementation. + +### Compatibility header + +We decided to extend the existing compatibility header instead of introducing a new one specific to C compatibility. This allows content printed for Objective-C to reference C types printed earlier in the same header. Plus this follows the current behavior of the C++ interop which prints its own block in the same compatibility header. + +Since we use the same compatibility header, we also use the same compiler flags to request it being emitted. We considered adding a C specific flag as the main one, `-emit-objc-header`, is Objective-C specific. In practice build systems tend to use the `-path` variant, in that case we already have `-emit-clang-header-path` that applies well to the C language. We could add a `-emit-clang-header` flag but the practical use of such a flag would be limited. + +## Acknowledgements + +A special thank you goes to Becca Royal-Gordon, Joe Groff and many others for the past work on `@_cdecl` on which this proposal is built. From 79b68f94c5f7431015363d40e47ea96c89efd456 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Thu, 25 Sep 2025 11:59:24 -0400 Subject: [PATCH 497/505] Update 0495-cdecl.md (#2973) --- proposals/0495-cdecl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0495-cdecl.md b/proposals/0495-cdecl.md index 1eaa1195cb..debdcb3ed4 100644 --- a/proposals/0495-cdecl.md +++ b/proposals/0495-cdecl.md @@ -3,9 +3,9 @@ * Proposal: [SE-0495](0495-cdecl.md) * Author: [Alexis Laferrière](https://github.com/xymus) * Review Manager: [Steve Canon](https://github.com/stephentyrone) -* Status: **Ready for Review** +* Status: **Active Review (Sept 25 ... Oct 9, 2025)** * Implementation: On `main` with the experimental feature flags `CDecl` for `@c`, and `CImplementation` for `@c @implementation`. With the exception of the `@objc` support for global functions which is available under the name `@_cdecl`. -* Review: ([pitch](https://forums.swift.org/t/pitch-formalize-cdecl/79557)) +* Review: ([pitch](https://forums.swift.org/t/pitch-formalize-cdecl/79557))([review](https://forums.swift.org/t/se-0495-c-compatible-functions-and-enums/82365)) ## Introduction From b18ea77cc3feba5d8336d70606fdd31e9c4b12da Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 25 Sep 2025 10:51:05 -0700 Subject: [PATCH 498/505] Address feedback --- proposals/NNNN-inline-always.md | 414 ++++++++++++++++++++------------ 1 file changed, 263 insertions(+), 151 deletions(-) diff --git a/proposals/NNNN-inline-always.md b/proposals/NNNN-inline-always.md index 80f5fe2bc1..97a423ad65 100644 --- a/proposals/NNNN-inline-always.md +++ b/proposals/NNNN-inline-always.md @@ -93,77 +93,271 @@ func callee(_ result: inout SomeValue, _ cond: Bool) { ## Proposed solution We desire for the attribute to function as an optimization control. That means -that the proposed `@inline(always)` attribute should emit an error if inlining -cannot be guaranteed in all optimization modes. The value of the function at a -call site can might determined dynamically at runtime. In such cases the -compiler cannot determine a call site which function is applied without doing -global analysis. In these cases we don't guarantee inlining even if the dynamic -value of the applied function was annotated with `@inline(always)`. -We only guarantee inlining if the annotated function is directly referenced and -not derived by some function value computation such as method lookup or function -value (closure) formation and diagnose errors if this guarantee cannot be -upheld. - -A sufficiently clever optimizer might be able to derive the dynamic value at the -call site, in such cases the optimizer shall respect the optimization control -and perform inlining. +that the proposed `@inline(always)` attribute should emit an error diagnostic if +inlining is not possible in all optimization modes. However, this gets +complicated by the fact that the value of the function at a call site might be +determined dynamically at runtime: + +- Calls through first class function values + ```swift + @inline(always) f() {...} + + func a() { + let fv = f + fv() + } + ``` +- Calls through protocol values and protocol constraint generic types + ```swift + protocol P { + func method() + } + struct S : P { + @inline(always) + func method() {...} + } + func a(_ t: T) { + t.method() + let p : P = S() + p.method() + } + ``` +- Calls through class instance values and the method referenced is not `final` + ```swift + class C { + @inline(always) + func method() {...} + } + func a(c: C) { + c.method() + } + ``` + +In such cases, the compiler cannot determine at a call site which function is +applied without doing non-local analysis: either dataflow, or class hiarchy +analysis. +These cases are in contrast to when the called function can statically be +determined purely by looking at the call site, we refer to this set as direct +function references in the following: + +- Calls to free standing functions +- Calls to methods of `actor`, `struct`, `enum` type +- Calls to final methods of `class` type, and type (`static/class`) methods of + `class` type + +Therefore, in cases where the value of the function at a usage site is +dynamically derived we don't emit an error even if the dynamic value of the +applied function was annotated with `@inline(always)`. We only emit an error if +the annotated function is directly referenced and something would cause it to be +not inlined or if some property at the declaration site of the function would +make it not possible in the common case. + +Listing the different scenarios that can occur for a function marked with +`@inline(always)`: + +1. A function can definitely be inlined at the use site: direct function + references barring recursion cycles +2. A function can never be always inlined at a use site and we diagnose an + error: cycles in `@inline(always)` functions calling each other and all + references are direct. +3. A function can not be inlined reliably and we diagnose an error at the + declaration site: non-final method declaration +4. A function can not be inlined and we don't diagnose an error: calls through + first class function values, protocol values, and protocol constraint generic + types. + +### Direct function references + +Calls to freestanding functions, methods of `enum`, `struct`, `actor` types, +final methods of `class` types, and type methods of `class` types don't +dynamically dispatch to different implementations. Calls to such methods can +always be inlined barring the recursion limitation (see later). (case 1) ```swift -protocol SomeProtocol { - func mightBeOverriden() +struct S { + @inline(always) + final func method() {} } -class C : SomeProtocol{ - @inline(always) - func mightBeOverriden() { - } +func f() { + let s: S = ... + s.method() // can definitely be inlined +} + +class C { + @inline(always) + final func finalMethod() {} + + @inline(always) + class func method() {} +} + +class Sub : C {} + +func f2() { + let c: C = ... + c.finalMethod() // can definitely be inlined + let c2: Sub = .. + c2.finalMethod() // can definitely be inlined + C.method() // can definitely be inlined } @inline(always) -func callee() { +func freestanding() {} + +func f3() { + freestanding() // can definitely be inlined +} + +``` + +### Non final class methods + +Swift performs dynamic dispatch for non-final methods of classes based on the +dynamic receiver type of the class instance value at a use site. Inferring the +value of that dynamic computation at compile time is not possible in many cases +and the success of inlining cannot be ensured. We treat a non-final method +declaration with `@inline(always)` as an declaration site error because we +assume that the intention of the attribute is that the method will be inlined in +most cases and this cannot be guaranteed (case 3). + +```swift +class C { + @inline(always) // error: non-final method marked @inline(always) + func method() {} } -func applyFunctionValues(_ funValue: () -> (), c: C, p: SomeProtocol) { - funValue() // function value, not guaranteed - c.mightBeOverriden() // dynamic method lookup, not guaranteed - p.mightBeOverriden() // dynamic method lookup, not guaranteed - callee() // directly referenced, guaranteed +class C2 : C { + @inline(always) // error: non-final method marked @inline(always) + override func method() {} } +func f(c: C) { + c.method() // dynamic type of c might be C or C2, could not ensure success + // of inlining in general +} +``` + +### Recursion + +Repeatedly inlining `@inline(always)` functions calling each other would lead to +an infinite cycle of inlining. We can never follow the `@inline(always)` +semantics and diagnose an error (case 2). + +```swift +@inline(always) +func callee() { + ... + if cond2 { + caller() // error: caller is marked @inline(always) and would create an + // inlining cycle + } +} + +@inline(always) func caller() { - applyFunctionValue(callee, C()) + ... + if cond { + callee() + } } +``` -caller() +### First class function values + +Swift allows for functions as first class objects. They can be assigned to +variables and passed as arguments. The reference function of a function value +cannot be reliably be determined at the usage and is therefore not diagnosed as +an error (case 4). + +```swift +@inline(always) +func callee() {} + +func use(_ f: () -> ()) { + f() +} +func useFunctionValue() { + let f = callee + ... + f() // function value use, may be inlined but not diagnosed if not + use(callee) // function value use, may be inlined in `use()` but not diagnosed + // if not +} ``` -Code authors shall be able to rely on that if a function is marked with -`@inline(always)` and directly referenced from any context (within or outside of -the defining module) that the function can be inlined or an error is emitted. +### Protocol methods +Protocol constraint or protocol typed values require a dynamic computation to +determine the eventual method called. Inferring the value of the eventual method +called at compile time is not possible in general and the success of inlining +cannot be ensured. We don't diagnose a usage site error if the underlying method +is marked with `@inline(always)` (case 4) -## Detailed design +```swift +protocol P { + func method() +} +struct S : P { + @inline(always) + func method() {} +} +final class C : P { + @inline(always) + func method() {} +} + +@inline(always) +func generic (_ t: T) { + t.method() +} + +func f() { + let p: P = S() + p.method() // might not get inlined, not diagnosed + generic(S()) // might not get inlined, not diagnosed + let p2: P = C() + p2.method() // might not get inlined, not diagnosed + generic(C()) // might not get inlined, not diagnosed +} +``` + +### Optimization control as optimization hint + +A clever optimizer might be able to derive the dynamic value at the +call site, in such cases the optimizer shall respect the optimization control +and perform inlining. + +In the following example the functions will be inlined when build with higher +optimization levels than `-Onone`. + +```swift +@inline(always) +func binaryOp(_ left: T, _ right: T, _ op: (T, T) -> T) -> T { + op(left, right) +} + +@inline(always) +func add(_ left: Int, _ right: Int) -> Int { left + right } + +print(binaryOp(5, 10, add)) +print(binaryOp(5, 10) { add($0, $1) }) +``` -We want to diagnose an error if a directly referenced function is marked with -`@inline(always)` and cannot be inlined. What are the cases where this might not -be possible? ### Interaction with `@inlinable` -`@inlinable` and `@_alwaysEmitIntoClient` make the function body available to -clients (callers in other modules) in library evolution mode. `@inlinable` makes -the body of the function available to the client and causes an ABI entry point -in the vending module to vended. `@_alwaysEmitIntoClient` makes the body of the -function available for clients but does not cause emission of an ABI entry -point. Functions with `open`, `public`, or `package` level access cause emission -of an ABI entry point for clients to call but in the absence of aforementioned -attributes do not make the body available to the client. +`@inlinable` makes the function body available to clients (callers in other +modules) in library evolution mode. Functions with `open`, `public`, or +`package` level access cause emission of an ABI entry point for clients to call +but in the absence of aforementioned attributes do not make the body available +to the client. `@inline(always)` intention is to be able to guarantee that inlining will happen for any caller inside or outside the defining module therefore it makes sense to -require the use some form of "inline-ability" attribute with them. This -attribute could be required to be explicitly stated. And for it to be an error -when the attribute is omitted. +require the use of "@inlinable" attribute with them. This attribute could be +required to be explicitly stated. And for it to be an error when the attribute +is omitted. ```swift @inline(always) @@ -176,28 +370,23 @@ public func callee() { ``` Alternatively, the attribute could be implicitly implied by the usage of -`@inline(always)`. In this proposal, we take the position that it should be -implied to avoid the redundancy of spelling this out. The intention of -`@inline(always)` is for it to inline in all contexts. Instead of an error in the -absence of the attribute we should imply "inline-ability". The question is what -should we default to? - -`@_alwaysEmitIntoClient`'s semantics seems preferable for new functions. We -intend for the function to be always inlined, why should there be an ABI entry -point? +`@inline(always)`. We take the position that it should be implied to avoid the +redundancy of spelling it out. -`@inlinable` semantics allows for annotating existing functions with -`@inline(always)` without breaking ABI compatibility. `@inlinable` keeps an -entry point in the vending module for older code that assumed the existence of -an entry point. +For access levels equal and lower than `internal` `@inlinable` is not implied. -This proposals takes the position to give `@inline(always)` the semantics of -`@inlineable` and provide an alternative spelling for the case when we desire -`@_alwaysEmitIntoClient` semantics: `@inline(only)`. +As a consequence all the rules that apply to `@inlinable` also apply to +`public`/`open`/`package` declarations marked with `@inline(always). -For access levels equal and lower than `internal` `@inlinable` should not be -implied. +```swift +internal func g() { ... } +@inline(always) +public func inlinableImplied() { + g() // error: global function 'g()' is internal and cannot be referenced from an + '@inlinable' function +} +``` ### Interaction with `@usableFromInline` @@ -206,7 +395,7 @@ if it is either `@inlinable` (see above) or `@usableFromInline`. `@usableFromInl ensures that there is a public entry point to the `internal` level function but does not ensure that the body of the function is available to external modules. Therefore, it is an error to combine `@inline(always)` with a -`@usableFromInline` function as we cannot guaranteed that the function can +`@usableFromInline` function as we cannot guarantee that the function can always be inlined. ```swift @@ -224,9 +413,11 @@ public func caller() { ### Module internal access levels -It is okay to mark `internal`, `private` and `fileprivate` function declarations -with `@inline(always)` in cases other than the ones mention above without the -`@inlinable` attribute as they can only be referenced from within the module. +To mark `internal`, `private` and `fileprivate` function declarations +with `@inline(always)` does not imply the `@inlinable` attribute's semantics. +They can only be referenced from within the module. `internal` declarations can +be marked with `@inlinable` if this is required by the presence of other +`@inlinable` (or public `@inline(always)`) functions that reference them. ```swift @@ -245,86 +436,6 @@ private func callee2() { } ``` -#### Infinite recursion during inlining - -We will diagnose if inlining cannot happen due to calls within a -[strongly connected component](https://en.wikipedia.org/wiki/Strongly_connected_component) -marked with `@inline(always)` as errors. - -```swift -@inline(always) -func callee() { - ... - if cond2 { - caller() - } -} - -@inline(always) -func caller() { - ... - if cond { - callee() - } -} -``` - -### Dynamic function values - -As outlined earlier the attribute does not guarantee inlining or diagnose the -failure to inline when the function value is dynamic at a call site: a function -value is applied, or the function value is obtained via class method lookup or -protocol lookup. - -```swift -@inline(always) -func callee() {} -func useFunctionValue() { - let f = callee - ... - f() // function value use, not guaranteed to be inlined -} - -class SomeClass : SomeProto{ - @inline(always) - func nonFinalMethod() {} - - @inline(always) - func method() {} -} - -protocol SomeProto { - func method() -} - - -func dynamicMethodLookup() { - let c = SomeClass() - ... - c.nonFinalMethod() // method lookup, not guaranteed to be inlined - - let p: SomeProto = SomeClass() - p.method() // method lookup, not guaranteed to be inlined -} - -class A { - func finalInSub() {} - final func finalMethod() {} -} -class B : A { - overrided final func finalInSub() {} -} - -func noMethodLookup() { - let a = A() - a.finalMethod() // no method lookup, guaranteed to be inlined - - let b = B() - b.finalInSubClass() // no method lookup, guaranteed to be inlined -} -``` - - ## Source compatibility This proposal is additive. Existing code has not used the attribute. It has no @@ -384,9 +495,10 @@ function as `@inlinable`. With respect to `@inlinable` an initial draft of the proposal suggested to require spelling the `@inlinable` attribute on `public` declarations or an error -would be displayed. The argument was that this would ensure that authors would -be aware of the additional semantics implied by the attribute: the body is -exposed. +would be displayed. The argument was made that this would ensure that authors +would be aware of the additional semantics implied by the attribute: the body is +exposed. This was juxtaposed by the argument that spelling both `@inlinable` and +`@inline(always)` is redundant. ## Acknowledgments From 2dfe5145ca7a8a61b5adb2eb3bc204103ec2b7cc Mon Sep 17 00:00:00 2001 From: Bassam Khouri Date: Tue, 30 Sep 2025 10:20:29 -0400 Subject: [PATCH 499/505] SwiftPM: update organization in template Update the GitHub organization of the Swift Package Manager --- proposal-templates/0000-swiftpm-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposal-templates/0000-swiftpm-template.md b/proposal-templates/0000-swiftpm-template.md index 82898bbc05..bd65132b9e 100644 --- a/proposal-templates/0000-swiftpm-template.md +++ b/proposal-templates/0000-swiftpm-template.md @@ -7,7 +7,7 @@ *During the review process, add the following fields as needed:* -* Implementation: [apple/swift-package-manager#NNNNN](https://github.com/apple/swift-package-manager/pull/NNNNN) +* Implementation: [swiftlang/swift-package-manager#NNNNN](https://github.com/swiftlang/swift-package-manager/pull/NNNNN) * Decision Notes: [Rationale](https://forums.swift.org/), [Additional Commentary](https://forums.swift.org/) * Bugs: [SR-NNNN](https://bugs.swift.org/browse/SR-NNNN), [SR-MMMM](https://bugs.swift.org/browse/SR-MMMM) * Previous Revision: [1](https://github.com/swiftlang/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md) From 122a32e0983966b13c2eec7338d7e88af0d7b2ea Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 1 Oct 2025 08:24:21 -0700 Subject: [PATCH 500/505] Add Acknowledgments --- proposals/NNNN-inline-always.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/proposals/NNNN-inline-always.md b/proposals/NNNN-inline-always.md index 97a423ad65..1c8fa26f58 100644 --- a/proposals/NNNN-inline-always.md +++ b/proposals/NNNN-inline-always.md @@ -502,4 +502,8 @@ exposed. This was juxtaposed by the argument that spelling both `@inlinable` and ## Acknowledgments -TODO: .... +Thanks to [Jordan Rose](https://forums.swift.org/t/optimization-controls-and-optimization-hints/81612/7) for pointing out that inlining can't be always guaranteed, specifically the case of closures. +Thanks to [Xiaodi Wu](https://forums.swift.org/t/pitch-inline-always-attribute/82040/7) for proposing inferring `@inlinable`. +Thanks to [Tony Allevato](https://github.com/swiftlang/swift-evolution/pull/2958#discussion_r2379238582) for suggesting to error on on non-final methods and +providing editing feedback. +Thanks to [Doug Gregor](https://github.com/DougGregor), [Joe Groff](https://github.com/jckarter), [Tim Kientzle](https://github.com/tbkka), and [Allan Shortlidge](https://github.com/tshortli) for discussions related to the feature. From b1ff577c3e36ac4629696b5b9eeabd6d35c37002 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Thu, 2 Oct 2025 09:22:39 -0400 Subject: [PATCH 501/505] Assign SE-0496. --- proposals/{NNNN-inline-always.md => 0496-inline-always.md} | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename proposals/{NNNN-inline-always.md => 0496-inline-always.md} (98%) diff --git a/proposals/NNNN-inline-always.md b/proposals/0496-inline-always.md similarity index 98% rename from proposals/NNNN-inline-always.md rename to proposals/0496-inline-always.md index 1c8fa26f58..94922c087f 100644 --- a/proposals/NNNN-inline-always.md +++ b/proposals/0496-inline-always.md @@ -1,9 +1,11 @@ # `@inline(always)` attribute -* Proposal: [SE-NNNN](NNNN-inline-always.md) +* Proposal: [SE-0496](0496-inline-always.md) * Authors: [Arnold Schwaighofer](https://github.com/aschwaighofer) +* Review Manager: [Tony Allevato](https://github.com/allevato) +* Status: **Active review (October 2–16, 2025)** * Implementation: [swiftlang/swift#84178](https://github.com/swiftlang/swift/pull/84178) -* Pitch thread: https://forums.swift.org/t/pitch-inline-always-attribute/82040 +* Review: ((pitch)[https://forums.swift.org/t/pitch-inline-always-attribute/82040]) ## Introduction From 754d7056d37a0871d7856f4ed6c4e2b689d1892e Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Thu, 2 Oct 2025 09:27:33 -0400 Subject: [PATCH 502/505] Link to review thread. --- proposals/0496-inline-always.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0496-inline-always.md b/proposals/0496-inline-always.md index 94922c087f..eab9725ea1 100644 --- a/proposals/0496-inline-always.md +++ b/proposals/0496-inline-always.md @@ -5,7 +5,7 @@ * Review Manager: [Tony Allevato](https://github.com/allevato) * Status: **Active review (October 2–16, 2025)** * Implementation: [swiftlang/swift#84178](https://github.com/swiftlang/swift/pull/84178) -* Review: ((pitch)[https://forums.swift.org/t/pitch-inline-always-attribute/82040]) +* Review: ([pitch](https://forums.swift.org/t/pitch-inline-always-attribute/82040)) ([review](https://forums.swift.org/t/se-0496-inline-always-attribute/82480)) ## Introduction From 9d0b21074c595206875a3f95af6ba91ba95ff9e8 Mon Sep 17 00:00:00 2001 From: Kenta Kubo <601636+kkebo@users.noreply.github.com> Date: Sun, 5 Oct 2025 00:48:44 +0900 Subject: [PATCH 503/505] [SE-0496] Fix a typo --- proposals/0496-inline-always.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0496-inline-always.md b/proposals/0496-inline-always.md index eab9725ea1..f10d161433 100644 --- a/proposals/0496-inline-always.md +++ b/proposals/0496-inline-always.md @@ -378,7 +378,7 @@ redundancy of spelling it out. For access levels equal and lower than `internal` `@inlinable` is not implied. As a consequence all the rules that apply to `@inlinable` also apply to -`public`/`open`/`package` declarations marked with `@inline(always). +`public`/`open`/`package` declarations marked with `@inline(always)`. ```swift internal func g() { ... } From cc971d980eeb33119d95573fa7244db8515aaa90 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 8 Oct 2025 11:01:35 -0500 Subject: [PATCH 504/505] Update status of ST-0015 to Accepted and link to acceptance announcement (#2987) --- .../0015-image-attachments-in-swift-testing-windows.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/testing/0015-image-attachments-in-swift-testing-windows.md b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md index 74549f0ba7..d23e8793cb 100644 --- a/proposals/testing/0015-image-attachments-in-swift-testing-windows.md +++ b/proposals/testing/0015-image-attachments-in-swift-testing-windows.md @@ -3,9 +3,9 @@ * Proposal: [ST-0015](0015-image-attachments-in-swift-testing-windows.md) * Authors: [Jonathan Grynspan](https://github.com/grynspan) * Review Manager: [Stuart Montgomery](https://github.com/stmontgomery) -* Status: **Active Review (September 19…29, 2025)** +* Status: **Accepted** * Implementation: [swiftlang/swift-testing#1245](https://github.com/swiftlang/swift-testing/pull/1245), [swiftlang/swift-testing#1254](https://github.com/swiftlang/swift-testing/pull/1254), _et al_. -* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing-windows/81871)) ([review](https://forums.swift.org/t/st-0015-image-attachments-in-swift-testing-windows/82241)) +* Review: ([pitch](https://forums.swift.org/t/pitch-image-attachments-in-swift-testing-windows/81871)) ([review](https://forums.swift.org/t/st-0015-image-attachments-in-swift-testing-windows/82241)) ([acceptance](https://forums.swift.org/t/accepted-st-0015-image-attachments-in-swift-testing-windows/82575)) ## Introduction From 99c18ea9c7921874e4428fca3aaeda1f5180e3cf Mon Sep 17 00:00:00 2001 From: Frederick Kellison-Linn Date: Wed, 8 Oct 2025 20:36:14 -0400 Subject: [PATCH 505/505] Update status of SE-0491 to Accepted (#2988) --- proposals/0491-module-selectors.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0491-module-selectors.md b/proposals/0491-module-selectors.md index d609228a11..ad86323f3b 100644 --- a/proposals/0491-module-selectors.md +++ b/proposals/0491-module-selectors.md @@ -3,10 +3,10 @@ * Proposal: [SE-0491](0491-module-selectors.md) * Authors: [Becca Royal-Gordon](https://github.com/beccadax) * Review Manager: [Freddy Kellison-Linn](https) -* Status: **Active review (September 13 ... September 30, 2025)** +* Status: **Accepted** * Bug: [swiftlang/swift#53580](https://github.com/swiftlang/swift/issues/53580) (SR-11183) * Implementation: [swiftlang/swift#34556](https://github.com/swiftlang/swift/pull/34556) -* Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) ([review](https://forums.swift.org/t/se-0491-module-selectors-for-name-disambiguation/82124)) +* Review: ([pitch](https://forums.swift.org/t/pitch-module-selectors/80835)) ([review](https://forums.swift.org/t/se-0491-module-selectors-for-name-disambiguation/82124)) ([acceptance](https://forums.swift.org/t/accepted-se-0491-module-selectors-for-name-disambiguation/82589)) Previously pitched in: