Justified concerns about the consequences of ABI stability?

We have seen in SE-0241 that having a stable ABI will commit Swift to good and bad designs. I don't know much about what ABI stability means but from the (mis?)understanding I have, I have concerns I'd like some perspective from the community on.

My worry centres around this: I don't want to wait years to take advantage of new Swift features or bug fixes. For example, if first class language support for concurrency comes in Swift 6, I don't want to have to wait years until the Swift 6 ABI has been distributed to enough of our user's install base.

Can we still bundle Swift with our apps so we can choose to use the system provided Swift or not?

If there is no choice, could (for example) the App Store app on iOS 13 download newer versions of Swift for the system when it's downloading an app built against the corresponding Swift version?

If there would be a delay waiting for Swift versions to be distributed to users, it would obviously have a negative effect on the development of Swift since there would be less opportunity to learn how people use these features.

8 Likes

I expect they would make some kind of shim like with arclite.

These runtime functions are what adds the OS requirement. Luckily, if you target an older OS, Xcode can link in a static library called libarclite that provides implementations of these functions, thus allowing you to use ARC when targeting an older OS (e.g. iOS 4.3).

More info

Shims like that will never be perfect. Although we tried to plan for some forms of backward deployment, it will inevitably be the case that there will be new Swift language or library features that will require a new OS with an updated runtime to use.

1 Like

+1, it would be nice not having Swift version tighted to iOS version and so having a mechanism where iOS devices update Swift version when required. This would remove the need for any shims.

One of the main advantages of Swift reaching a stable ABI isn't just merely that Swift will be distributed with the OS, but that the OS frameworks themselves can be written i Swift, and expose non-bridgable types in the public API. If new iOS SDK frameworks were to be written in Swift, how would this work if there are two different versions of the runtime simultaneously?

3 Likes

The complementary question then arises, how far back can we expect Swift toolchains to be able to deploy? So far backwards-compatibility has been limited to one major version, but it’s not unusual for apps to have three years of backwards compatibility.

The deployment target concern here is OS version, not language compatibility version. Swift toolchains still (at least in theory) support deploying all the way back to OS X 10.9 and iOS 7. The Swift language version setting does not generally affect the ABI or Swift runtime behavior the compiler uses, and I don't think we'd change that going forward. The issue is that new language features may require new runtime or OS functionality that is not available in older OSes. Generally, when we add new language features, we try to add them to all language version settings, unless there are source compatibility problems with doing so. The language version setting is a source compatibility feature, not a runtime compatibility feature.

9 Likes

So, to confirm I've understood correctly:

  1. the consequences of ABI stability concern runtime compatibility and OS functionality as distinct from language not dependent on those?
  2. I should (toolchain provided) still be able to use language features that do not depend on runtime and OS functionality?

How should I understand OS functionality? A scenario like Apple coming up with some awesome hardware, the OS, you know, operating it and, I guess the standard library implements some interface for it? That doesn't sound right. If this was right, I imagine that could quickly turn into a depressing situation for Swift apps on current, non-Apple platforms.

I still feel like I should be able to use improved String API without having to depend on a major OS update and potentially one or more years for our user base to upgrade to it, right? It seems this is a very real problem since Swift 6 very well could provide this.

2 Likes

What make you think you will have to wait the next major OS release. Apple did just proved that they can deploy a new Swift runtime on minor updates (for Swift 5).

Yep, and as I understand it, now I have to wait however long it’ll take the majority of my user base to have that update installed before I can build an app against it.

1 Like

Or have two code paths, just like we actually do for any other API on the platform (which have a stable ABI from the beginning).

That’s ok for trivial features, not so great otherwise. Consider the new string interpolation API in Swift 5. Would you really have time to implement, test and maintain things like this twice knowing how cumbersome it’d be in Swift 4?

1 Like

No more than I had time to reimplement NSCollectionView new behaviour (introduced in 10.11 IIRC), or to backport libdispatch on 10.5. This is not a problem specific to Swift. Any library has this very same issue.

The same apply to languages features, like thread local in C++ which was introduces rather late in macOS and required an updated version of dyld, so a major system upgrade.

It will be frustrating when things like property behaviours or coroutines are introduced in Swift, and it may take some times before we can use them widely.
Fortunately Apple is pretty good at pushing updates on user system, so it will not take too much time before new features are available to enough people in your audience to be able to use them.

2 Likes

Has the core team taken the dev community pulse if ABI stability is something desired at this stage of Swift? I would think most developers would rather be able to use all new language features immediately with a language capable of shedding bad decisions than care about binary compatibility.

I also don't recall any ABI evolution proposal being put forth for the community to discuss and weigh in on.

Yeah developers will always prefer that, but there are multiple points of view to consider.

I think the point mentioned previously about system frameworks being written in Swift is more interesting. We've heard at previous WWDC talks about certain internal components (like the macOS Dock) being partially rewritten in Swift, and the advantages to doing so. I can imagine Apple would like to bring those gains to public frameworks, too.

The more Apple are able to do that, the more they commit to Swift. That's great for the project's health. It's no small thing to be part of a major commercial operating system.

10 Likes

Even though iOS users are generally pretty quick to upgrade looking at the current iOS adoption stats it looks like we’re headed for a 15% tax on users if your app wants to user the latest evolved feature and a lag on when this can be rolled out until sufficient users have loaded the latest OS image. Worse, an application that previously worked will suddenly not work or be un-upgradable or previous versions of the app need to be supported if the user does not/can not upgrade their OS.

https://data.apteligent.com/ios/

I wrote about this in a digression off piste in Prepitch: Character integer literals

The tl;dr; it is the idea of shipping the Swift shared libraries with the operating system image seems to be flawed to me and they are better downloaded on demand by the app store app and installed to a central place in the file system where they can be versioned. This allows for all the advantages of shared distribution including saved resources on the device and allowing Apple to ship system frameworks written in Swift without tying Swift Evolution’s or developer’s hands or somehow hindering Apple’s commitment.

This said, unfortunately the ship has rather sailed on this now with Xcode 10.2 so mentioning this again may not be viewed as being particularly helpful but I have reservations about whether the course we have set is going to pan out - If it doesn’t this idea could always be introduced at a later date.

2 Likes

There was some discussion last year about the possibility of having two components to the standard library: the existing “non-ABI stable” portion that gets bundled with apps, and a new “ABI stable” portion that can be distributed as a system library.

Then over time, as each individual piece of the standard library gets rigorously evaluated, optimized, and ossified, it can be moved from the non-stable component into the stable component.

That way we wouldn’t have this rush where everything gets permanently baked into its current shape all at once, and it would still be possible to modify (and potentially remove) parts that never made the jump to ABI stability.

It also means that newly-proposed features could begin with any implementation that works, without having to worry about getting the exact optimal implementation in the very first attempt. Instead new features would start in the non-stable component, and eventually make their way into the stable component after being optimized.

2 Likes

I remember, but it seemed neither here nor there. Why not just version the whole set of core libraries and Swift system libraries for a particular version of Xcode/Swift in a shared directory managed by the App Store app as the middle road between shipping with the OS and shipping with the app - far simpler to implement and test. Let’s not talk of “ossifying" anything to do with Swift just yet!

1 Like

That does not solve the main problem that ABI stability is supposed to fix: being able to expose Swift API from system framework. If you have 2 incompatibles String types (one used by the main app, one by the frameworks), how is it supposed to work ?

3 Likes

There will be different versions of the system library written in Swift for each Swift version so they run with applications compiled with that Swift version. These would be produced for a version of Xcode then remain static for the future as released applications will not be expecting the API to evolve. If new version of the application are they would use the new version of the Swift framework/core libraries with the version of Xcode they are developed under. The alternative is never being able to change the String implementation in future. If the OS deprecates the underlying C api they use then that’s when you get a problem. It’s a grey area whether frameworks that happen to be written in Swift are part of the OS or part of the Swift version but I’m proposing they are strongly bound to the Swift version people will be coding against when they release their app.

/System
	Library
		Swift
			4_2
				libSwiftCore.dylib
				HealthKit.framework
			5_0
				libSwiftCore.dylib
				HealthKit.framework