What’s New in Swift, where they describe the (currently unimplemented) indirect keyword for use in recursive enums.

In the optimization video, Michael Gottesman points out that Swift’s copy-on-write semantics for structs can cause performance problems if the struct contains many reference-counted properties. (14:12) The ﬁrst time a struct is modiﬁed it must be copied, which means that the reference counts of all reference properties must be incremented. His solution is to group the reference properties into a wrapper class and store an instance of the wrapper class in the struct. That way only one reference count needs to be incremented when the struct is copied. In the value types talk, Bill Dudney shows how to implement this workaround eﬃciently for Swift types using the isUniquelyReferencedNonObjC function. (32:25)

This solves the performance problem, but at a cost in legibility and maintenance. For example, take this simple struct with three reference properties:

This is a lot of code to write and maintain for a simple (and presumably common) optimization. And although Swift can catch some common errors in this code, there are many that it can’t catch. For instance, while the compiler will complain if you use pathForWriting in a get method, it won’t say a word if you use pathForReading in a set method, which is arguably a much bigger problem. And of course it will have no idea if you make a copy/paste error and return pathForReading.ﬁrstName from the accessor for middleName.

A Proposed Improvement

If these wrapper classes are going to be common in production Swift code, then perhaps it would be better for Swift to provide built-in support for them. I was trying to ﬁgure out what keyword might be used to request this optimization when I remembered Chris Lattner’s talk where he reveals the (currently unimplemented) indirect keyword for creating recursive cases in enums.

To me, this seems like the right keyword for requesting indirect properties in structs as well.

From a certain point of view, enums and structs in Swift aren’t that diﬀerent from one another. They are both value types that can contain sub-values. (The sub-values are known as associated values for enums, and properties for structs.) The main diﬀerence is that while an enum contains one of the sub-values, a struct contains all of the sub-values.

The indirect keyword being added to enums in Swift 2.0 solves a practical, rather than a conceptual, problem. Conceptually, there is no issue with an enum containing itself as an associated value, since a program can only create a ﬁnite number of enums and eventually the recursion must end. But in practice, associated values are stored directly in the enum and so indirection is needed to avoid allocating an inﬁnitely large object.

The use of the indirect keyword that I’m proposing for structs is also to solve a practical problem — in this case, a performance problem. But the eﬀect is essentially the same as with enums:the sub-values are moved out to a separate object and referenced indirectly.

If the indirect keyword were allowed in structs as well as enums, then the above code could simply become:

The Swift compiler could gather all of the indirect properties into a wrapper class and take care of creating the hidden wrapper class, the hidden value property, and rewriting the getters and setters to indirect through the hidden property.

I’d love to hear what others think of this proposal. If you’d like make a comment, get in touch @samalone64 and I’ll update this post with the best feedback.