Skip to content

Conversation

@jflan-dd
Copy link
Contributor

I ran into a compiler error when compiling this package using the Swift 6.1 compiler in Swift 5 language mode.

The specific error I hit was caused by the mismatch between #if swift(>=6.1) check on _DependencyTrait and the if compiler(<6.1) check around testValuesByTestID.

That resulted in not being able to compile the following code with the Swift 6.1 compiler in Swift 5 language mode because testValuesByTestID wasn't defined.

    extension _DependenciesTrait: SuiteTrait, TestTrait {
      public var isRecursive: Bool { true }

      public func prepare(for test: Test) async throws {
        try testValuesByTestID.withValue {
          try self.updateValues(&$0[test.id, default: DependencyValues(context: .test)])
        }
      }
    }

We're using Bazel to depend on this package, which is how we're hitting this issue, but you can replicate it with SPM by running swift test -Xswiftc -swift-version -Xswiftc 5 in this repo.

I updated every instance of #if swift to #if compiler in this PR and had passing tests with both swift test and swift test -Xswiftc -swift-version -Xswiftc 5

@stephencelis
Copy link
Member

@jflan-dd Thanks for looking into this!

Did you change every #if swift to #if compiler, or are these all compiler features being bracketed, and not language mode features?

If the former, my worry is that this may introduce unintended changes where #if swift was the appropriate thing to do. Do you think you could update this PR to simply make the required change(s) for your app to build successfully?

If you do believe all of these changes are appropriate, could you comment on each #if changed with your reasoning? We just want to understand things better.

}

#if swift(>=6)
#if compiler(>=6)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

#isolation default argument.
https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md

Swift 6 compiler feature without upcoming feature flag

import Testing

#if swift(>=6.1)
#if compiler(>=6.1)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TestScoping ships with Swift Testing in Swift 6.1 compiler

@@ -1,4 +1,4 @@
#if swift(<6)
#if compiler(<6)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one is for the sendability of key paths and should probably go back to swift or enable the specific upcoming feature flag: https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/sourcecompatibility#Inferring-Sendable-for-methods-and-key-path-literals

@jflan-dd
Copy link
Contributor Author

@stephencelis I commented on the changes in Sources. I reverted one change that depends on a Swift 6 language mode feature, but I believe the remaining two are valid changes.

I built and ran tests after deleting the [email protected] file to force using Swift 5 language mode and didn't have any new warnings after reverting the check related to KeyPath sendability.

The instances in Tests looked like they were all about TestScoping.

}

#if swift(>=6)
#if compiler(>=6)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

also #isolation

@jflan-dd
Copy link
Contributor Author

jflan-dd commented Aug 5, 2025

@stephencelis Do the updated comments make sense?

@stephencelis
Copy link
Member

@jflan-dd Yup! Just lost track of this, sorry 😄

For the key path sendability, want to add the feature flag to the Swift 5 package.swift and see if that helps things?

@jflan-dd
Copy link
Contributor Author

jflan-dd commented Aug 6, 2025

@stephencelis I spent a while experimenting with this and I think the current PR implementation is the most correct, although in the vanilla all-SPM case it's all moot.

When using SPM natively the existence of the [email protected] with swift-tools-version: 6.0 makes is so this package is always compiled with Swift 6 language mode with the 6.0+ compiler even if the package/project depending on it is using Swift 5 language mode. Therefore the compiler and swift directive's are functionally equivalent when using SPM end-to-end in this case.

It's only through using something like Bazel that this package could be compiled with the Swift 6 compiler in Swift 5 language mode. I've raised an issue on rules_swift_package_manager to correctly set the language mode it cases like this, and I should have some time to fix it in a few weeks.

In this specific case updating the Swift 5 Package.swift file to add the extra flag wouldn't matter because the Bazel build definition files are created using the Swift 6 compiler to extract the package descriptions, so the [email protected] will always be used.

@jflan-dd
Copy link
Contributor Author

@stephencelis I still believe this change is the more correct way to declare these conditionals, but also merged a change to the Bazel rules that we're using to import SPM packages to correctly honor Swift language mode based on Package.swift tools versions, so it's not actually causing an issue for us anymore.

cgrindel/rules_swift_package_manager#1770

@stephencelis stephencelis merged commit a501eeb into pointfreeco:main Aug 19, 2025
7 checks passed
@jflan-dd jflan-dd deleted the jflan/compiler-directive branch August 19, 2025 18:56
@stephencelis
Copy link
Member

@jflan-dd Thanks for this! All good to go!

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.

2 participants