Notes from Swift core team 2016-01-04 design discussion


(Alex Martini) #1

Happy New Year!

To help keep proposals moving forward, the Swift core team has set aside some time specifically for design discussions of upcoming proposals. Below are some rough notes from the discussion this week.

These are informal comments, intended to guide the proposals in directions that draw constructive feedback. You are welcome to ignore the feedback, agree with it, or disagree with it. As always, the formal decision doesn't happen until after the review period ends.

Limiting @objc inference <file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2017-01-04.html#limiting-objc-inference>
https://github.com/DougGregor/swift-evolution/blob/objc-inference/proposals/NNNN-objc-inference.md
As discussed before the break, this pares back the inference of @objc. Keep doing it for NSManaged and IBOutlet because those things are tightly tied to the Obj-C runtime.

Stop inferring it for dynamic which lets us, in the future, do dynamic properly in a pure-Swift world. Also stop inferring @objc on subclasses of NSObject. The rules for when it’s inferred are too complex; there are a lot of selector collisions and the default selectors are usually poor because of the differences between Swift and Obj-C naming conventions; and it causes code bloat. All of these issues would go away.

We know that 6-8% of the binary size are thunks, but we don’t know how many of them are used, so we can’t assume that this change will cause 6-8% of the binary size to go away.

People use dynamic for Core Data and KVO and providing your own property implementation. We can grep for dynamic to see how much it’s used quantitatively. You can write @objc dynamic in Swift 3, it’s allowed — in Swift 4 it will be required. We can add a fix-it or warning to add the expanded version; the user impact is pretty small.

The source compatibility story for NSObject subclasses is complicated. Recompiling Swift 3 code under Swift 4 causes a bunch of selectors to go away. If you’re lucky, you’re using them from Obj-C code in your project and get compile-time errors. If you’re unlucky, you’re doing something dynamic, and you’ll get runtime errors.

One recommended approach is, in Swift 3 mode, to put deprecation notes on the Obj-C headers where @objc is being inferred. We could have Swift 4 keep generating these declarations with an “unavailable” message, but even if you do that you still get unrecognized selector errors. On the other hand, marking them unavailable would give you a compile error instead of a compile warning.

This seems like a form of refactoring. The indexer knows what symbols are being used. Could we use that as part of the migrator?

An alternative approach is to make the migrator add @objc everywhere. In many places, the @objc is junk code that you don’t need, but the migrator doesn’t know which you need — adding it everywhere means we can be sure that your code is correct. There is some concern about people cargo-culting the correction.

You can’t have two declarations in Obj-C for the same selector, even if they’re both unavailable. So it becomes really hard to generate these from code after it has been migrated to Swift 4 — only the generated header printer is keeping track of what is a duplicate.

We could provide Clang a side table, via structured comments, to describe the unavailable selectors. That would let us at least give a better runtime error.

We could make @objc on a class give you the Swift 3 behavior, where it is implied on all of that class’s members. Sort of like how public extension makes all of the members inside the extension be public. That would make the splat-@objc-everywhere migration story less painful because of a much smaller “everywhere”. You would want this behavior in two major cases: When you’re migrating code from Obj-C to Swift and you want everything to be exposed to Obj-C, and when you’re migrating Swift 3 to Swift 4.

Requiring an explicit selector name if you write @objc would be too much boilerplate. Sometimes the default is ok, and sometimes you just don’t care.

Is there a problem that people know what is being exposed to Obj-C, but don’t know what needs to be exposed?

Argument labels <file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2017-01-04.html#argument-labels>
A bunch of changes in Swift 3 made argument labels not part of the tuple, which leaves a bunch of annoying special cases.

Let’s fix it. This seems like a starter proposal. We have a JIRA keyword for starter proposals, and a number of other starter proposals that we can let folks in the community pick up — although we do need to decide on a timeline, likely a month or two.

  https://bugs.swift.org/issues/?jql=labels%20%3D%20StarterProposal <https://bugs.swift.org/issues/?jql=labels%20=%20StarterProposal>