TLDR: Should we just always import C/ObjC types under their Swift 4 names, and
use typealiases in Swift 3 mode?
---
Hi, swift-dev. As my recent PRs have probably indicated, I've been working on
the problems that can come up when mixing Swift 3 and Swift 4 code. Most of
these problems have to do with C/ObjC APIs that might present themselves
differently in Swift 3 and Swift 4, using the "API notes" feature in our
downstream branch of Clang, and a good subset of these problems have to do with
types getting renamed. (This includes being "renamed" into a member, such as
NSNotificationName becoming (NS)Notification.Name in Swift.)
What's the problem? Well, there are a few. First of all, an API defined in
terms of the Swift 3 name should still be callable in Swift 4. As an example,
let's pretend NSNotification.Name was going to be renamed
NSNotification.Identifier in Swift 4.
// Swift 3 library
public func postTestNotification(named name: NSNotification.Name) { … }
// Swift 4 app
let id: Notification.Identifier = …
postTestNotification(named: id) // should work
This means the reference to "NSNotification.Name" in the library's swiftmodule
needs to still be resolvable. This isn't too bad if we leave behind a typealias
for 'NSNotification.Name'. I have a reasonable (but too broad) implementation
at https://github.com/apple/swift/pull/8737
<https://github.com/apple/swift/pull/8737>.
That just leads us to another problem, though: because Swift functions can be
overloaded, the symbol name includes the type, and the type has changed. The
Swift 3 library exposes a symbol
'_T03Lib20postTestNotificationySo14NSNotificationC4NameV5named_tF', but the
Swift 4 client expects
'_T03Lib20postTestNotificationySo14NSNotificationC10IdentifierV5named_tF'.
My planned approach to combat this was to use the C name of the type in the
mangling, producing
'_T03Lib20postTestNotificationySo18NSNotificationNamea5named_tF'. This is
prototyped in https://github.com/apple/swift/pull/8871
<https://github.com/apple/swift/pull/8871>.
At this point Slava pointed out I was chasing down a lot of issues when there's
a much simpler solution for Swift 4: when importing types, always use the Swift
4 name, and use typealiases to handle Swift 3 compatibility. This defines both
of the previous issues away, as well as any more that I just haven't thought of
yet.
There are some downsides:
- We currently keep people from using Swift 4 names in Swift 3 code, and we
wouldn't be able to do that, since the actual declaration of the type always
needs to be available.
- We'd probably want to tweak the "aka" printing in diagnostics to not look
through these typealiases. That's not hard, though.
- We can't keep doing this once we have ABI stability. Hopefully framework
owners aren't going to continue changing Swift names of types, but we'll
probably need to implement my "C name in the mangling" plan anyway, just in
case.
What do people think?
Jordan
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev