The push and pull of Swift’s duality as an open source project that’s intimately tied to closed source products came to a culminating point this week, with the official release of Swift 3.0 🎉, coinciding with Xcode 8, the Swift Playgrounds iPad app, iOS 10, tvOS 10 and watchOS 3. One can’t help but respect the amount of effort it must have taken to coordinate so many moving parts and align all these releases.

The Swift 3.0 release post on swift.org provides a great overview of all the changes that were included, tips to migrate, links to an updated Swift book, and other details about the release.

Apple is the first to share that Swift 3 was made possible by a significant number of community contributions, so all you fine readers deserve a moment to celebrate… ok, break’s over, Swift 4 won’t write itself, so read on!

Starter tasks

The Swift team uses a Python script named cmpcodesize to measure the size of Swift build products. Improving that script is one way to contribute to reducing the size of Swift code. If you know some Python, try these tasks:

  • SR-407: cmpcodesize is capable of analyzing the size and segments of macOS Mach-O build products. Complete this task to allow it to analyze code size on Linux, by supporting the ELF object format.
  • SR-2595: The current output format for cmpcodesize can’t be easily parsed by other programs, making it hard to measure code size improvements and regressions over time. This task tracks adding additional output formats to cmpcodesize, such as CSV.

Submit a task by sending a pull request or a tweet.

Commits and pull requests

Dmitri Gribenko replaced the String hashing algorithm on non-ObjC platforms with an implementation of SipHash-1-3.

Vedant Kumar fixed code coverage not being generated for top-level declarations.

Doug Gregor added support for implicit self in lazy var initializers, fixing SR-2203.

Anders Bertelrud improved the Xcode project generation to use a layered data model instead of print statements. Much nicer!

Michael Ilseman refactored around 3,000 lines of code, reducing the code browsing burden of the ClangImporter.

The one and only Jesse Squires updated the Swift Evolution status site to distinguish between withdrawn and rejected proposals.

Accepted proposals

Joe Groff’s proposal, SE-0139: Bridge Numeric Types to NSNumber and Cocoa Structs to NSValue, was accepted with modifications.

The proposal has been accepted with one modification: numeric values bridged to NSNumber will maintain their type identity (e.g., an Int8 bridged to an NSNumber can be cast via as!/as? to an Int8) while other instances of NSNumber (e.g., those created in Objective-C) can be cast to any numeric type that can represent their value. This matches the existing bridging behavior introduced in id-to-Any bridging (SE-0116). The proposal text has been updated accordingly.

Joe Groff’s other proposal, SE-0140: Warn when Optional converts to Any, and bridge Optional As Its Payload Or NSNull, was accepted with one modification.

The proposal is accepted with one modification (described below).

Reviews on this proposal were mixed, with many expressing significant concerns about the ability to place an optional value into an Any, particularly when the Any comes from a nonnull-annotated Objective-C API:

// Objective-C
@interface MyClass : NSObject
- (void)doSomething:(nonnull id)object;
@end
// Swift
let stringOpt: String? = getSomeString()
MyClass().doSomething(stringOpt) // allowed; likely a programmer error

This behavior was introduced as part of id-as-Any bridging (SE-0116)). As an amendment to SE-0140, Swift will produce a warning when an optional value is converted to a value of type Any, e.g.,

// warning: optional value of type ‘String?’ is converted to an ‘Any’
MyClass().doSomething(stringOpt)

// note: use ‘!’ to force-unwrap the optional
// note: use ‘??’ to provide a default value if the optional is nil
// note: use ‘as Any’ to silence this warning

Such a warning will address most accidental injections of optional values into Any, and the core team felt that this addresses accidental boxing of optional values better than leaving the opaque object types to fail fast in Objective-C code that inspects them (e.g., see this message for a negative review partly on these grounds).

To the main point of this proposal, which is to bridging to either the payload or NSNull, the core team felt that:

  1. Bridging to the payload or NSNull brings to Objective-C code the same behavior that is already present in Swift’s type system, where an optional containing a payload can be dynamically casted to its payload type. For example, this is well-formed in Swift:
let optString: String? = "hello"
let anyValue: Any = optString
let stringValue: String = any as! stringValue // downcast succeeds, produces a String
  1. While NSNull is not widely used in Cocoa APIs, it is better to enable those APIs to work properly when nil optional values do get bridged than to have an opaque-to-Objective-C boxed type that does not work well with any Objective-C APIs.

Proposals in review

Andrew Trick’s proposal (SE-0138) from last week has been renamed to UnsafeRawBufferPointer and its review period was extended by one week.

Mailing lists

Mishal Shah announced that Swift CI is now capable of testing combinations of pull requests. CI can even test pull requests made to two separate repositories! For example, if Swift PR #123 makes a change to the Swift standard library, and swift-corelibs-foundation PR #456 updates Foundation for that change, the two can be tested together by posting the following comment:

<!-- As a comment on apple/swift pull request #123 -->

Please test with following PR:
https://github.com/apple/swift-corelibs-foundation/pull/456

@swift-ci Please test

Pushkar Kulkarni and Philippe Hausler discussed important differences in bridging on Apple versus other platforms.

Pushkar: There’ve been a few bug reports related to the coercion problems between Swift and Foundation types on Linux. For example this one: https://bugs.swift.org/browse/SR-2477 (Double/Int don’t coerce with NSNumber on Linux).

Philippe: From a technical perspective it is not impossible to do however as of current reference type to structural type bridging is conflated with the objective c runtime being present (specifically present on Darwin targets). Personally I think we need a better answer than what we have today but I don’t see the winds changing in the immediate future to support ref type bridges uniformly in a cross platform manner.

Philippe has been advocating for better bridging support on non-Darwin platforms since Swift was open sourced nearly a year ago, and despite portability having been a strong goal for Swift 3, there are still important areas where the behavior varies between platforms, and this is one of them.

Finally

Sightings of the elusive Swift 3.1 have been reported in the wild, so please stay alert! You may have to migrate your apps again soon… 😳