Confusion about Swift 5.1 on <= iOS 12.4 deployment targets

Reading https://docs.swift.org/swift-book/GuidedTour/Compatibility.html it sounds like I'm allowed to update my app to Swift 5.1 even though my deployment target is iOS 10.0 - which includes iOS 12.4 which ships with the Swift 5.0 runtime - as long as I don't use opaque result types and other bullet points listed.

However, this behavior seems inconsistent with previous behavior "The try? expression doesn’t introduce an extra level of optionality to expressions that already return optionals."

So how can I know my code will operate the same on Swift 5.0 and Swift 5.1? Or will my code type check/compile in a way that forces me to use Swift 5.0 syntax/semantics even with the Swift 5.1 runtime?

The compiler will let you know if you're using a runtime-dependent feature without the right deployment target. Things like try? only change compile-time behavior, so aren't dependent on what OS the compiled app runs on.

5 Likes

What’s the behavior on OSes before ABI stability? If you deploy back to iOS 10, does the app include the Swift runtime that has the 5.1 features?

When deploying to older OSes, a copy of the Swift 5.0 runtime will be bundled. Swift 5.1's runtime is integrated with and depends on the new OSes.

5 Likes

Thanks!

Wait, but that does mean that older OSs don‘t get any runtime bug fixes as they don‘t get 5.1 runtime bundled? That feels like a sneaky trick to force upgrades. :face_with_monocle:

I expected 5.1 runtime on older OSs but the IDE would prevent me from using new runtime dependent features like opaque types because of the minimum deployment traget which crosses with ABI locked OSs that lack 5.1 runtime.

To be clear, I don‘t flame or anything, I‘m just super surprised right now.

Would you expect a situation like this?

New OS (runtime included in OS): 5.1 runtime
Previous OS (runtime included in OS): 5.0 runtime
Older OSs (runtime in app): 5.1 runtime

Because that's what would happen if newer runtimes were back-deployed. Not to mention it would effectively be a different 5.1 runtime because some of the OS functionality it depends on didn't used to exist (e.g. the function 5.2 calls to do availability checking is a relatively recent addition to libsystem).

It does sound odd but the consequences of doing it the other way are even odder.

1 Like

How did it worked before? The Swift runtime depends on OS functionality?

The runtime couldn't use any new OS functionality, basically*. Meant a lot of stuff was slower than it could be (runtime type checks, bridging, and availability checking, at the very least).

*or at least had to be very careful in how it did it. dlsym() came in handy!

And yeah, the runtime and standard library call into the OS in quite a few places. In particular Foundation/CF (for bridging), libobjc (for object deinitialization, bridging, some dynamic casts, and probably a few other things), ICU (for unicode handling), and libsystem (allocation, OS version checking, a bunch of other stuff).

3 Likes

And it was decided to drop that kind of support for older OS's after Swift 5? :thinking:

There wasn't really a good way around that since the new/old/new situation I described above would have been incredibly confusing. Imagine trying to explain to your users that your app supports iOS 13 and 11 but not 12.

And since there's no good alternative, there's no reason not to take advantage of it to improve the language :) (for example, one change I've been tinkering with on and off speeds up most object deallocations, even non-objc ones, by ~2x by coordinating better with libobjc)

2 Likes

That wasn't my point. I get that this whole ABI situation creates a hole in between when considering the bundled runtime, but I was expecting this:

  • iOS 11 gets 5.1 runtime bundled
  • iOS 12 has 5.0 runtime
  • iOS 13 has 5.1 runtime

Since we set the minimal deployment target to iOS 11, the compiler tells us what we're allowed to use from the runtime dependent features and what not.

That way iOS 11 gets bug fixes that are runtime related, iOS 12 won't, and iOS 13 gets them again because well it contains the right runtime.

That's how I imagined the whole situation up until now. :see_no_evil:


Thank you both for clarification. :+1:

If the Swift runtime had been part of the OS all along, then older OSes wouldn't have gotten new Swift runtime updates regardless.

I get that part. That's why I preferred the bundled approach over the ABI as it allowed to target older OS's but use the full power of Swift and stdlib.

Not bundling it has the advantage of making the apps much smaller. And afaict @David_Smith‘s response will actually make it more performant, as it can rely on some things of the OS.

Sure, it’s a trade-off, and you can argue that you would have preferred a different way, but I don’t think there is any evidence for nefarious motives/trying to get users to update or similar here.

1 Like

I also get the advantages of having ABI, otherwise frameworks like SwiftUI or Combine wouldn't be possible.

I was just surprised that older OS's aren't getting the newer runtime anymore even though Swift will be bundled with the app there.

Since this is clear now we can move on I guess. :smiley: Thank you everyone.

1 Like
Terms of Service

Privacy Policy

Cookie Policy