From 722bf9886e92a5afa982cd01859a4ddab3baf03c Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 9 Oct 2026 14:32:07 -0500 Subject: [PATCH 1/4] Enable existential errors in embedded builds When building with a 6.4 compiler, this change allows existential errors to be used in embedded contexts, both within the `ParsingError` type and APIs that take a user-defined throwing closure as a parameter. --- EmbeddedExample/EmbeddedParser.swift | 6 +++++- Sources/BinaryParsing/Parser Types/ParserSource.swift | 2 +- Sources/BinaryParsing/Parser Types/ParsingError.swift | 8 +++++--- Sources/BinaryParsing/Parsers/Array.swift | 2 +- Sources/BinaryParsing/Parsers/InlineArray.swift | 2 +- Sources/BinaryParsing/Parsers/Range.swift | 8 ++++---- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/EmbeddedExample/EmbeddedParser.swift b/EmbeddedExample/EmbeddedParser.swift index 4df6658..de3149e 100644 --- a/EmbeddedExample/EmbeddedParser.swift +++ b/EmbeddedExample/EmbeddedParser.swift @@ -24,6 +24,10 @@ struct EmbeddedTest { precondition(a == 1) precondition(b == 0x203) - print(c) + precondition(c == 0x405) + print("Should print '1 / 515 / 1029' on separate lines") + print(a) // 1 + print(b) // 515 + print(c) // 1029 } } diff --git a/Sources/BinaryParsing/Parser Types/ParserSource.swift b/Sources/BinaryParsing/Parser Types/ParserSource.swift index 4afe91c..27f40f6 100644 --- a/Sources/BinaryParsing/Parser Types/ParserSource.swift +++ b/Sources/BinaryParsing/Parser Types/ParserSource.swift @@ -107,7 +107,7 @@ public protocol ParserSpanProvider { } extension ParserSpanProvider { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Executes the given closure with a `ParserSpan` over the contents of this /// type, consuming the given parser range instead of the full span. @_alwaysEmitIntoClient diff --git a/Sources/BinaryParsing/Parser Types/ParsingError.swift b/Sources/BinaryParsing/Parser Types/ParsingError.swift index 733ac61..bf56d56 100644 --- a/Sources/BinaryParsing/Parser Types/ParsingError.swift +++ b/Sources/BinaryParsing/Parser Types/ParsingError.swift @@ -49,7 +49,7 @@ public struct ParsingError: Error { _location >= 0 ? _location : nil } - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// The user-provided error associated with this parsing error. public var userError: (any Error)? @@ -78,13 +78,15 @@ public struct ParsingError: Error { } } -#if !$Embedded +#if !$Embedded || compiler(>=6.4) extension ParsingError { public init(userError: any Error) { self = .init(status: .userError, userError: userError) } } +#endif +#if !$Embedded extension ParsingError: CustomStringConvertible { public var description: String { if let location { @@ -109,7 +111,7 @@ extension ParsingError.Status: CustomStringConvertible { } #endif -#if !$Embedded +#if !$Embedded || compiler(>=6.4) /// An error thrown by the library user. /// /// In a build for non-embedded Swift, `ThrownParsingError` aliases `any Error`, diff --git a/Sources/BinaryParsing/Parsers/Array.swift b/Sources/BinaryParsing/Parsers/Array.swift index 86d84d0..8aac8ed 100644 --- a/Sources/BinaryParsing/Parsers/Array.swift +++ b/Sources/BinaryParsing/Parsers/Array.swift @@ -44,7 +44,7 @@ extension Array where Element == UInt8 { } extension Array { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Creates a new array by parsing the specified number of elements from the given /// parser span, using the provided closure for parsing. /// diff --git a/Sources/BinaryParsing/Parsers/InlineArray.swift b/Sources/BinaryParsing/Parsers/InlineArray.swift index b87c88a..eec6fc6 100644 --- a/Sources/BinaryParsing/Parsers/InlineArray.swift +++ b/Sources/BinaryParsing/Parsers/InlineArray.swift @@ -28,7 +28,7 @@ extension InlineArray where Element == UInt8 { @available(macOS 26, iOS 26, watchOS 26, tvOS 26, visionOS 26, *) extension InlineArray where Element: ~Copyable { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Creates a new array by parsing the specified number of elements from the given /// parser span, using the provided closure for parsing. /// diff --git a/Sources/BinaryParsing/Parsers/Range.swift b/Sources/BinaryParsing/Parsers/Range.swift index 2c97bfe..b096a84 100644 --- a/Sources/BinaryParsing/Parsers/Range.swift +++ b/Sources/BinaryParsing/Parsers/Range.swift @@ -12,7 +12,7 @@ // MARK: Start & Count extension Range where Bound: FixedWidthInteger { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Creates a new half-open range by parsing the start and count of the range, /// using the given parser closure for each value. /// @@ -68,7 +68,7 @@ extension Range where Bound: FixedWidthInteger { } extension ClosedRange where Bound: FixedWidthInteger { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) @available( *, deprecated, message: @@ -112,7 +112,7 @@ extension ClosedRange where Bound: FixedWidthInteger { // MARK: Start & End extension Range { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Creates a new half-open range by parsing the start and end of the range, /// using the given parser closure for each value. /// @@ -168,7 +168,7 @@ extension Range { } extension ClosedRange { - #if !$Embedded + #if !$Embedded || compiler(>=6.4) /// Creates a new closed range by parsing the start and end of the range, /// using the given parser closure for each value. /// From 799d7027e04fca7ffedde588306e202490fe3ee5 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 9 Oct 2026 14:36:18 -0500 Subject: [PATCH 2/4] Run embedded test on both 6.3 and 6.4 --- .github/workflows/pull_request.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d7e87ad..41417e0 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -35,10 +35,14 @@ jobs: enable_windows_checks: false embedded: - name: Embedded Test (Linux nightly-6.3) + name: Embedded Test (Linux nightly-${{ matrix.swift_version }}) runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + swift_version: ["6.3", "6.4"] container: - image: swiftlang/swift:nightly-6.3-jammy + image: swiftlang/swift:nightly-${{ matrix.swift_version }}-jammy steps: - name: Swift version run: swift --version From 27a0a9c700d5efe021697aeb4c792fcfdfab2834 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 9 Oct 2026 14:43:49 -0500 Subject: [PATCH 3/4] Correct 6.4 container name --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 41417e0..3ec9a4a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -40,7 +40,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ["6.3", "6.4"] + swift_version: ["6.3", "6.4.x"] container: image: swiftlang/swift:nightly-${{ matrix.swift_version }}-jammy steps: From 45ffcc5a6967ab14be0bed3fa9a7ee39ad95e119 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sat, 10 Oct 2026 09:04:09 -0500 Subject: [PATCH 4/4] Update `ParsingError` documentation --- .../Parser Types/ParsingError.swift | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Sources/BinaryParsing/Parser Types/ParsingError.swift b/Sources/BinaryParsing/Parser Types/ParsingError.swift index bf56d56..a39bb2b 100644 --- a/Sources/BinaryParsing/Parser Types/ParsingError.swift +++ b/Sources/BinaryParsing/Parser Types/ParsingError.swift @@ -114,16 +114,17 @@ extension ParsingError.Status: CustomStringConvertible { #if !$Embedded || compiler(>=6.4) /// An error thrown by the library user. /// -/// In a build for non-embedded Swift, `ThrownParsingError` aliases `any Error`, -/// so you can throw an error of any kind from closures passed to methods that -/// are designated as `throws(ThrownParsingError)`. When the method throws an -/// error, it will always be either your error or an instance of -/// `ParsingError`. +/// In a build for non-embedded Swift, or any build using a 6.4 or newer compiler, +/// `ThrownParsingError` aliases `any Error`, so you can throw an error of +/// any kind from closures passed to methods that are designated as +/// `throws(ThrownParsingError)`. When the method throws an error, +/// it will always be either your error or an instance of `ParsingError`. /// -/// In a build for embedded Swift, `ThrownParsingError` instead aliases the -/// specific `ParsingError` type. Because embedded Swift supports only -/// fully-typed throws, and not the existential `any Error`, this allows you to -/// still use error-throwing APIs in an embedded context. +/// In a build for embedded Swift using a pre-6.4 compiler, `ThrownParsingError` +/// instead aliases the specific `ParsingError` type. Because this version of +/// embedded Swift supports only fully-typed throws, and not the existential +/// `any Error`, this allows you to still use error-throwing APIs in an embedded +/// context. public typealias ThrownParsingError = any Error #else // Documentation is built using the non-embedded build.