Swift Regret: Implicit Optional Initialization

Part of the Swift Regrets series.

In Swift, stored properties and local variables aren’t initialized by default; the compiler makes you do it. …Unless it’s Optional and mutable (var, not let).

I don’t think I’d have bothered to elevate this to the list if it didn’t manage to cause performance problems, somehow. (The fact that a stored property is initialized to nil shouldn’t necessarily be exposed to clients.)

But how did we get here? Well, in early Swift, we knew we weren’t going to follow C’s performance-over-safety choice of allowing variables to be totally uninitialized. (Turn on ‑Wuninitialized, everybody!) So at the very least the compiler was going to check. But we didn’t know how often people were doing this deliberately, or relying on Objective-C zero-initializing instance fields. ARC already zero-initialized local object pointers, so it wasn’t unprecedented to say that we’d do some kind of default initialization for simple types. That is, zero for integers and floats, nil for Optionals, and false for Bools.

Of course, this wouldn’t work on let, because you can’t reassign a let. But we didn’t know if we could convince people to use let when C’s default is non-const. Fortunately, it turned out people didn’t mind initializing things explicitly, and they loved let…and 0 wasn’t always a good default, and it only worked for a few types anyway. So we took out all the defaults…except for nil. Because that really is a sensible default.

(Aside: I argued for a long time that false-for-Bool was a step too far; it’s not obviously a better choice than true. @Gankra_ finally convinced me years later, but just barely.)

The thing is…if Optional is the only type that behaves like this, it’s weird. And it’s not an important thing for a learner to learn, so I bet plenty of people don’t know. Which is valid because it’s not that useful: = nil isn’t that hard to type. (Though I’ll admit leaving it out seems appropriate for calling C functions with pointer out-parameters.) To add insult to injury, the compiler checked syntactically for the sugared form of Optional, Int?. If you write out Optional<Int>, you don’t get this behavior. (I think this was originally a layering problem in the compiler and now it’s a compatibility issue in edge cases.)

So now there’s behavior in the compiler to save five characters = nil, which can cause performance problems in weird situations. (Specifically: types with inlinable initializers and Optional stored properties.) Hopefully the compiler folks can fix that part, at least.

P.S. Maybe we can fix this one in a language mode?