Does module stability offer backwards compatibility?

The examples I've seen of module stability always present a scenario where you compile a swift library with a version of Swift, and then the consumer of that library is free to use a later version of the Swift compiler than what your library was compiled with. For example: You compile a framework with Xcode 11.7 (Swift 5.2.4) w/ ABI and module stability, and then give it to another developer who is using Xcode 12.4 (Swift 5.3.2) and they can use it because module stability provides compatibility with future swift compilers.

I'm interested in backwards compatibility of libraries built with module stability. If I build my library in Xcode 12.4 (Swift 5.3.2), can I guarantee that it will work in an app compiled with Xcode 11.7 (Swift 5.2.4)? Or will I, as the library author, always need to build with a <= version of the Swift compiler than my consumers?

I can't seem to find documentation on this, but if there is any I'd appreciate a link to it.

Notes:

Compatible across compiler versions

Which makes it seem like you could, but in the talk he says

And since they behave like source code, then future versions of the Swift Compiler will be able to import module interfaces created with older versions

Because of these I think the answer is that there are no backwards-compatibility guarantees, but I wasn't completely sure.

There was a great deal of ABI and module stability on these forums, the upshot is that modules stability only marches forward, not back. You might want to do a search on module stability on these forums.

1 Like

There's no guarantee of backwards compatibility with older compilers – there may be new syntax features used in the swiftinterface that an older compiler doesn't understand. However, if none of those features are used or exposed in a library (e.g. if you don't use actors once those land), there's a chance the interface file from a newer compiler might still work with the older one. But it's not supported.

2 Likes

Thank you both for your help!

I forgot to mention this, there's a feature that's being worked on in the compiler that (while not guaranteeing backwards compatibility) seeks to reduce the surface area for backwards compatibility issues.

New syntax should introduce a new "compiler feature" flag, which causes the compiler to automatically surround code that uses that feature with:

#if $SpacefaringFunctions
func goToMoon() spacefaring {
}
#endif

Again, not to guarantee backwards compatibility, but to make it more likely that a given compiler update produces swift interfaces that can at least be partially used by slightly older clients.

1 Like

Nice one. Would this be some internals in the swift compiler, or as we write swift code we can make use of this?

We have a case where the SDK was built with 5.7.2 and the app with 5.5. Error message below:

(the SDK is built with 'Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)', while this compiler is 'Apple Swift version 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)'). Please select a toolchain which matches the SDK.

Is there a place where we can check which interface features have appeared in each version, to deduce how likely it is for backwards compatibility to break between 2 specific versions?

Btw, can you tell whether the above error is related to backwards compatibility? Because I have a vague feeling it implies that the SDK was not built for distribution, although we pass BUILD_LIBRARY_FOR_DISTRUBUTION to xcodebuild.

This backwards compatibility feature is not intended to support this configuration. Either you’ll need to recompile the SDK with the 5.5 compiler or update Xcode and recompile the app with a newer Swift.