Skip to content

Replace platforms: block with per-API @available annotations#11

Open
rnro wants to merge 6 commits into
apple:mainfrom
rnro:availability
Open

Replace platforms: block with per-API @available annotations#11
rnro wants to merge 6 commits into
apple:mainfrom
rnro:availability

Conversation

@rnro

@rnro rnro commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

The platforms: block in Package.swift sets an OS 26 deployment-target floor for the package and transitively for any downstream package. Requiring this of every adopter is an onerous constraint, especially for libraries that want to offer QUIC / HTTP/3 as one transport option among several. We should avoid it where possible.

This PR drops the platforms: [.macOS("26.0"), ...] block from Package.swift and annotates availability per-declaration instead.

The first commit applies per-declaration @available annotations across the source tree, in tiers chosen as the lowest that suffices:

  • Mark with @available(Network 0.1.0, *) (= macOS 26 / iOS 26 / tvOS 26 / watchOS 26 / visionOS 26) every top-level declaration in Sources/, Tests/, the benchmark target, and the executable tools whose body uses an OS-26+ feature (Span / RawSpan / MutableRawSpan / OutputRawSpan, InlineArray, ~Escapable types, @_lifetime, the package's own SwiftTLSQUICInstance etc.) or another @available(Network 0.1.0, *) / @available(SwiftTLS 0.1.0, *) symbol.
  • Use @available(macOS 11, iOS 14, tvOS 14, watchOS 7, *) on os.Logger(subsystem:category:) initializers in Darwin branches and on the Logger-using UInt64+VLE helpers, where the actual binding constraint is os.Logger.
  • Use @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) on extensions of SymmetricKey / AES.GCM / ChaChaPoly / HMAC in CryptoWrappers.swift, where the binding constraint is the underlying CryptoKit type.
  • Split Logging.swift's extension Logger into Darwin and non-Darwin halves so only the os.Logger-using half carries the macOS 11 floor.
  • Wrap each tool's main.swift runtime body in if #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) { ... } else { fatalError(...) }. Tool helper types and free functions live at module scope with @available(Network 0.1.0, *); in SocketTransfer, NSEC_PER_MSEC becomes a static let on the class because script-mode top-level lets cannot carry @available.
  • Wire availabilityMacros into the benchmark, test, and executable tool targets' swiftSettings so the Network 0.1.0 macro is defined when building those targets.

The second commit replaces every @available(Network 0.1.0, *) with the equivalent @available(anyAppleOS 26, *). anyAppleOS is a meta-platform covering the Apple platforms with unified versioning starting at 26.0, which expands to the same macOS 26 / iOS 26 / tvOS 26 / watchOS 26 / visionOS 26 tuple the custom macro produced.

This lets us drop the package-level macro plumbing: the AvailabilityMacro=Network 0.1.0:macOS 26, ... enableExperimentalFeature setting, the _OSAvailability / _Availability helpers, and the per-target availabilityMacros + prefix on swiftSettings. Adopters no longer need to know the macro name to read the source.

Future-gated declarations can use @available(anyAppleOS 10000, *) directly if this pattern is ever needed.

The two commits are kept separate so the anyAppleOS change can be reverted independently if reviewers prefer to keep the named macro.

rnro added 2 commits June 11, 2026 11:26
The `platforms:` block in `Package.swift` sets an OS 26 deployment-target
floor for the package and transitively for any downstream package.
Requiring this of every adopter is an onerous constraint, especially for
libraries that want to offer QUIC / HTTP/3 as one transport option among
several. We should avoid it where possible.

This change drops the `platforms: [.macOS("26.0"), ...]` block from
`Package.swift` and annotates availability per-declaration instead.

The annotation changes broadly fall into these categories:
* Mark with `@available(Network 0.1.0, *)` (= macOS 26 / iOS 26 / tvOS 26
  / watchOS 26 / visionOS 26) every top-level declaration in `Sources/`,
`Tests/`, the benchmark target, and the executable tools whose body uses
an OS-26+ feature (Span / RawSpan / MutableRawSpan / OutputRawSpan,
InlineArray, ~Escapable types, @_lifetime, the package's own
`SwiftTLSQUICInstance` etc.) or another `@available(Network 0.1.0, *)` /
`@available(SwiftTLS 0.1.0, *)` symbol.
* Use `@available(macOS 11, iOS 14, tvOS 14, watchOS 7, *)` on
  `os.Logger(subsystem:category:)` initializers in Darwin branches and on
the `Logger`-using `UInt64+VLE` helpers, where the actual binding
constraint is `os.Logger`.
* Use `@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)` on
  extensions of `SymmetricKey` / `AES.GCM` / `ChaChaPoly` / `HMAC` in
`CryptoWrappers.swift`, where the binding constraint is the underlying
CryptoKit type.
* Split `Logging.swift`'s `extension Logger` into Darwin and non-Darwin
  halves so only the os.Logger-using half carries the macOS 11 floor.
* Wrap each tool's `main.swift` runtime body in `if
  #available(macOS 26, iOS 26, tvOS 26, watchOS 26, visionOS 26, *) { ... }
else { fatalError(...) }`. Tool helper types and free functions live at
module scope with `@available(Network 0.1.0, *)`; in `SocketTransfer`,
`NSEC_PER_MSEC` becomes a `static let` on the class because script-mode
top-level `let`s cannot carry `@available`.
* Wire `availabilityMacros` into the benchmark, test, and executable tool
  targets' `swiftSettings` so the `Network 0.1.0` macro is defined when
building those targets.
Replace every `@available(Network 0.1.0, *)` annotation across `Sources/`,
`Tests/`, the benchmark target, and the executable tools with the equivalent
`@available(anyAppleOS 26, *)`. `anyAppleOS` is a meta-platform covering the
Apple platforms with unified versioning starting at 26.0, which expands to
the same `macOS 26 / iOS 26 / tvOS 26 / watchOS 26 / visionOS 26` tuple the
custom macro produced.

Drop the package-level macro plumbing this enables: the
`AvailabilityMacro=Network 0.1.0:macOS 26, ...` `enableExperimentalFeature`
setting, the `_OSAvailability` / `_Availability` helpers, and the per-target
`availabilityMacros + ` prefix on `swiftSettings`. Adopters no longer need
to know the macro name to read the source.

Future-gated declarations can use `@available(anyAppleOS 10000, *)` directly
if this pattern is ever needed.

@agnosticdev agnosticdev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On piece of feedback. Also just confirming that the plan is to synchronize on anyAppleOS across SwiftTLS and SwiftNetwork, correct?

#endif

#if !(os(Linux) || (NETWORK_EMBEDDED && !NETWORK_DRIVERKIT))
#if canImport(os) || NETWORK_DRIVERKIT

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the second branch of this statement make sense? (NETWORK_EMBEDDED && !NETWORK_DRIVERKIT) when we check for #if canImport(os) || NETWORK_DRIVERKIT on the next line?
Should we consolidate on #if canImport(os) || NETWORK_DRIVERKIT or do Linux still pickup the os module?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it doesn't

@rnro

rnro commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

On piece of feedback. Also just confirming that the plan is to synchronize on anyAppleOS across SwiftTLS and SwiftNetwork, correct?

That is definitely my plan, I intend to open a follow-up PR to SwiftTLS

@rnro

rnro commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

On piece of feedback. Also just confirming that the plan is to synchronize on anyAppleOS across SwiftTLS and SwiftNetwork, correct?

That is definitely my plan, I intend to open a follow-up PR to SwiftTLS

I have since opened and backed out that PR. Upon further reflection it might not give us all the flexibility we would like. I'll back that change out here.

///
/// See `NetworkPOSIXError` and `HTTP2Error` as two examples of `NetworkDomainSpecificError`.
@_spi(ProtocolProvider)
@available(Network 0.1.0, *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing all availability here seems wrong. Why was this changed?

@preconcurrency internal import Crypto
#endif

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason these can't also just be@available(Network 0.1.0, *)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason, I was just trying to express the minimum requirement wherever relevant. This is what’s required because of upstream requirements. You can always put more stringent requirements on. I personally think the granularity and matching the code we’re using makes it easier to reason about and it’ll match the numbers in things like build errors.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. It just seems a bit odd to have bits of code that we define that are unused and unusable on those older platforms, but still marked available. I don't care strongly though.

} else {
print("Error running all (\(iterations)) transfers, something failed")
}
fatalError("This tool requires macOS 26 or newer")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to make the entire test tool products have a minimum platform?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants