Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to make ResilientDecoding work with Swift Concurrency #53

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

bdbergeron
Copy link

Starting a conversation about updating this library to support Swift Concurrency, namely Sendable values, so consumers don't have to use @preconcurrecny import ResilientDecoding. This simple "build and fix" approach may not be the most ideal, as it requires the wrapped property to no longer simply be a Decodable but also a Sendable value. However, it's worth having the conversation of what the future of this library looks like in a modern Swift world, so here I'm proposing the first steps to getting us to a more modern Swift syntax.

Copy link
Collaborator

@dfed dfed left a comment

Choose a reason for hiding this comment

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

this seems like a reasonable approach to me. I'm curious how hard this change would be to adopt for consumers, though I'm not sure that should stop y'all from rolling a breaking change like this.

@@ -0,0 +1,31 @@
// swift-tools-version:5.8
Copy link
Collaborator

@dfed dfed Nov 9, 2023

Choose a reason for hiding this comment

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

this swift tools version does not align with the name of this package file.

Comment on lines 18 to 31
.target(
name: "ResilientDecoding",
dependencies: []),
.testTarget(
name: "ResilientDecodingTests",
dependencies: ["ResilientDecoding"]),
]
)

for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(.enableExperimentalFeature("StrictConcurrency"))
target.swiftSettings = settings
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you're intending this file to be swift tools version 5.8, I'd recommend writing this as:

Suggested change
.target(
name: "ResilientDecoding",
dependencies: []),
.testTarget(
name: "ResilientDecodingTests",
dependencies: ["ResilientDecoding"]),
]
)
for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(.enableExperimentalFeature("StrictConcurrency"))
target.swiftSettings = settings
}
.target(
name: "ResilientDecoding",
dependencies: [],
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency")
]),
.testTarget(
name: "ResilientDecodingTests",
dependencies: ["ResilientDecoding"],
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency")
])
]
)

Note that this is an upcoming rather than experimental feature. In tools version 5.7, you indeed do need to call this experimental IIRC.

Copy link
Author

Choose a reason for hiding this comment

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

With 5.8, this is still considered an experimental feature, so we need to keep it as . enableExperimentalFeature. I will inline it to the targets, however, as you suggest.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Welp I may have some code in my own projects to update then

@@ -234,12 +234,12 @@ public struct UnknownNovelValueError: Error {
/**
The raw value for which `init(rawValue:)` returned `nil`.
*/
public let novelValue: Any
public let novelValue: Sendable
Copy link
Collaborator

@dfed dfed Nov 9, 2023

Choose a reason for hiding this comment

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

Worth noting that this is a breaking change, and we should update the sample dependency management code in the README to match. Podspec needs bumping too.

Copy link
Author

Choose a reason for hiding this comment

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

For sure, I see this being a minor version bump at a minimum.

@bdbergeron
Copy link
Author

bdbergeron commented Nov 9, 2023

I had a thought earlier this morning about trying to make this work via conditional conformance instead of requiring all values to be Sendable, thus reducing the breaking API surfaces. Going to take a stab at that approach and see if we like it better.

Edit: Not feasible due to all the internal generic objects used in DEBUG builds. Might be possible for RELEASE but I think enforcing Sendable on all @Resilient properties does make sense.

Comment on lines +45 to +54
onlyGenerateCoverageForSpecifiedTargets = "YES">
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ResilientDecoding"
BuildableName = "ResilientDecoding"
BlueprintName = "ResilientDecoding"
ReferencedContainer = "container:">
</BuildableReference>
</CodeCoverageTargets>
Copy link
Author

Choose a reason for hiding this comment

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

Ensures code coverage numbers are accurate - previously was including the test target coverage too.

@@ -234,12 +234,12 @@ public struct UnknownNovelValueError: Error {
/**
The raw value for which `init(rawValue:)` returned `nil`.
*/
public let novelValue: Any
public let novelValue: Sendable
Copy link
Author

Choose a reason for hiding this comment

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

For sure, I see this being a minor version bump at a minimum.

@MatyasKrizN
Copy link

Hey, major bump is technically correct since the version would contain breaking changes, but since this library is perfect as it is and hasn't needed any releases in a quite a long time a minor one is fine as well IMO, though that's up to @dfed.

@bdbergeron could you please update the version in ResilientDecoding.podspec?

Also, @dfed what changes do you envision for the README, info about the new version requiring Sendable conformance (with the possibility to fall back to 1.1.0 if that's not possible) or is there something else?

By the way, since I'm already writing this, I want to thank you @dfed for this wonderful utility and @bdbergeron for the preparation for strict Swift concurrency. ❤️

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