"Removing implicit `nil` initial value for Optional-typed variables"

A while ago I read this line of this post by Slava Pestov and it stuck with me.

Today I felt motivated to follow-up on this idea, and I found this thread started by Jordan Rose:

which I see ended with @tera's unanswered question to those with the power to make this decision.

I made this new thread because I'm aware of the existence of some cultural norms about bumping old threads, but I'm not really sure what they are. Otherwise, I might have simply voiced my support in Jordan's thread, since that's really all I'm doing.

I don't currently have any insight to add, other than to strengthen the specific subset of the choir that's saying, "I can't speak to the implementation, but the change to the surface language seems like an obvious improvement to me."


Wholeheartedly agree. Not only is this behaviour weird and surprising, it disrupts the otherwise very useful help you get from the compiler when you e.g. forget to initialise all properties in an init.

struct Person {
    let name: String
    let number: Int?
    var score: Int?

    init(name: String) {
        self.name = name
        // Compiler will remind me to set `self.number` but not `self.score`

I also agree with this sentiment. While it is seemingly helpful at times, the "magic" behind this feature also only working with the ?-style syntax is also confusing. For example, this works:

struct SomeStruct {
  let a: Int
  var b: Int?

  init(a: Int) {
    self.a = a
    // b is implicitly set to `nil`...

But this doesn't work:

struct SomeStruct {
  let a: Int
  var b: Optional<Int>

  init(a: Int) {
    self.a = a
    // ERROR: Return from initializer without initializing all stored properties

I would accept it as a breaking change for Swift 6 and I believe that the pitch is in the correct direction, especially when we’re now focusing on lifetime and ownership👍


I like omitting "= nil" whenever I can, but I agree this is subpar for memberwise initializers. So I would be less opposed to such a change than I was in the past.

The place I'd like the most to keep implicit nil is for @IBOutlet properties:

@IBOutlet var nameField: NSTextField!
@IBOutlet var continueButton: NSButton!

I suppose the @IBOutlet attribute could be an exception that allows implicit nil, mirroring how property wrappers should also continue to be able to provide their own default value.


When this has been discussed in the past it has also been suggested that it might make sense to maintain the behavior for all implicitly unwrapped optionals.


I'll just point out that it's not uncommon to use regular optionals for @IBOutlet too (at least in my code). So I'd rather have it linked to @IBOutlet than whether the optional is implicitly unwrapped or not.

1 Like

It’s been a very long time since I’ve thought about @IBOutlet. Can you clarify for me (and for anyone else with the same confusion) - what is it about the nature of IBOutlet that would make it more onerous to write out = nil than in all of the other places that this proposed change would affect?

I don't think that having "= nil" would be of any harm in case of IBOutlets:

@IBOutlet var someView: UIView! = nil

So long as IBOutlet variable is properly set to whatever value it needs too be set to (like a view, etc).

It may be perceived as it gets set to nil first, then to a non-nil value, but I don't think that's a problem (whether this double set actually happens or not).

IMHO, implicitly unwrapped optionals could follow the same rules as normal optionals, without being treated specially. In particular, I'd expect this member wise initialiser to be done:

struct S {
    var x: Int!
    var y: Int! = nil
// automatic memberwise  init:
    init(x: Int!, y: Int! = nil) {

While we are on this we could also finally take the opportunity of introducing the real type, "!" is a syntax sugar for:

var x: ImplicitlyUnwrappedOptional<T> // same as:
var x: T!

Agree. This would seem to fit with our treatment of IUOs in general.

We won’t be doing that, since we actively removed it: