I've started putting real effort into migrating packages of mine to make better use of Swift 6 language features. I'm finding it incredibly hard to live without them. The thing is, a lot of these changes affect my public API.
Occationally, I can pull of what I want with a typealias:
This does not compile, and this forces me to duplicate the function declaration in a way that is typically quite hard to factor into a single common shared internal implementation.
Does anyone have any tips/tricks on how to best deal with this kind of stuff? I think I'm just going to abandon Swift < 6.0, but I thought I'd ask just in case.
In the latter case, iirc, you can wrap the entire method signature in the conditional, but not the method body. And barring that, you can create two methods that call a shared private implementation. I have not tested this in a playground yet, but I recall seeing this pattern before.
If you can wrap the whole signature, I cannot figure out how. All permutations I can think of fail to compile...
But, worse, these changes can have profound semantic differences which can, sometimes, make that common shared private implication really hard to actually implement.
It’s certainly not ideal and rather cumbersome, but theoretically it should work just fine. I think the trickier part will be finding a signature for the implementation function that works for both compiler versions
Right, this totally is a feasible approach if the type differences for that closure argument do not matter. But that's exactly what I'm talking about.
The difference between a sending, @Sendable, and plain closure are significant and will almost certainly make _doThing unimplementable without unsafe casting.
Hey Mattie, I know its a bit off-topic but in your first snippet you replace @Sendable with @isolated(any), does this generally apply when using Swift 6 (I haven't looked into @isolated(any) yet) or it applies for your own solution in particular?
In fact, that's a weird artifact of my particular solution.
@isolated(any) and @Sendable are type attributes, and are not interchangable. sendingis often a great replacement for @Sendable, but is not a type attribute.
So, this is why these interfaces are so hard to build for two compilers. They have fundamentally different types and signatures, and will affect all code that interacts with them.
(this compiles, but I'm not sure how safe this assumption on @Sendable for inner implementation when going from sending, in theory this should be fine?)
Sort of! This is more of an evolution of an existing API. It is 100% source-compatible with both Swift 5 and Swift 6 mode, but requires a Swift 6 compiler.
You are making me wonder how overloads might work in this situation. But at the end of the day, the internal implemenation still gets quite messy, at best, because of the different meanings of the types being used.
Oh! This is something I have not thought of. You're right though, you have to be quite careful to make sure the runtime behavior is compatible. But this is something that would at least help specifically for the @Sendable -> sending transition, and possibly in other situations as well. It's less-unsafe than a bitcast.
At the end of the day, though, I'm just not sure it's worth it. Even if I do decide this is something I do, I'm still expecting a rapid transition to the Swift 6 compiler across the community...