Pre-pitch: remove the implicit initialization of Optional variables

I'm prolly in favour of this but I expect it would get a lot of pushback from the wider developer community as being 'pedantic', 'visual noise'. The issues that implicit initialisation brings aren't very clear unless you get into the weeds of the Swift initialisation rules, etcetera.


+1 - I was really puzzled about those 'variable initialization expression' things, and I don't think I would have ever discovered that this was the cause had I not asked. So thanks again to @lukasa and everyone else.

I'm happy my issue was able to be resolved, but I don't think it's a good situation for future developers who encounter this. It's hard to write fast, efficient code, and IMO the language should do its best to support you with that; not make it harder.

I think it's also important to remember that not only would this change make the language model simpler, but also the performance improvements and binary size reductions that I observed with my project could also apply to other applications.

I'll post some numbers later, but I'd also encourage others to profile their code, look for 'variable intialization expression' to identify problem areas, and try it out on their own code.

I actually really don't like implicit initialization for locals. Personally, I'm a big fan of Swift's definite initialization feature, which I often use with let variables:

let x: SomeType // not initialized

if someCondition {
  x = ...
} else {
  x = ...

foo(x) // Will not compile if 'x' is not initialized along all code paths.

But this language feature gets broken by implicit initialization - if SomeType is an optional (written with sugar, because that's the idiomatic/most obvious way to write it), x will implicitly be set to nil, meaning it now needs to become a var so that I can actually initialize it.

It's a minor issue compared to the inlining/performance problems, but still. It bugs me.


Eliminating implicit initializations would lead to behavioral alignment, which is what we need for the design of Swift. With major version bump, we’re allowed to displease some developers — because it would make a lot more newcomers less confused.

+1 for this (with Swift 6)


Thankfully, they changed how optional let bindings work a while ago so that they don't implicitly initialize to nil. Your code now works for optional no problem.


+1 I don't think requiring the addition of = nil is a burden to the writer and it makes the intent clearer to a maintainer/reader.


Same, It should work like any other initialization


"variable initialization expression" / double initialisation has nothing to do with implicit initialisation of T? variables... these are two completely separate issues!


struct S {
    let int: Int
    init(_ int: Int) {
        print("S init with \(int)") = int

struct MyStruct {
    var s: S = S(1)
    init(s: S) {
        print("setting s to \(")
        self.s = s

func foo(_ s: S) {
    print("foo start")
    let s = MyStruct(s: s)


foo start
S init with 1 // ** BUG **
setting s to 2

here that the "s" is initialised twice is the bug, and it has nothing to do with implicit initialisation of T? variables. the latter is just a manifestation of this bug in var v: T? case... but the same bug will happen in the var v: T? = nil case.

Double initialization is not a bug, it’s a feature. :-) That is, the behavior you’re describing was deliberate, if not always what people want. The problem is for Optional variables there’s no way to turn it off, which usually doesn’t matter but sometimes does.


The acceptance notes for SE–0242 might suggest otherwise:


I think we should get rid of the implicit initialisation of optional values. Making the language more consistent overall is more valuable than saving a few chars IMO. Aside from consistency, this "forced initialisation" thing:

var thing: Int?

if thePlanetsAreAligned() {
    thing = 4

// And if they are not aligned, what then? In cases where `thing` is _not_ optional I really value the compiler error Swift throws here.

is to me the most compelling reason to change it.

I don't really understand why ! should be treated any differently. In this thread it has been brought up as an "oh damn! yeah.. that ol' chestnut." case. But to me it should be treated exactly the same: var myView: UIView! = nil – isn't that just reflecting reality?

The consensus in the older thread @Slava_Pestov linked to seemed to be "Yeah, we're using that but we wouldn't be mad if it was gone", which is about the same as I feel about it. I know about it and I use it because I can, but I'm more for consistency than brevity (which seems to fit Swift's overall philosophy too).

I agree with this sentiment. It also helps demystify IUO's for newcomers by removing one layer of (IMO) excessive "magic".


The problem with an argument from "consistency" is that it's circular. The argument is that it's good to be consistent, because consistency is good.

Why is consistency good?

(I'm not actually inviting answers to that unanswerable question, but rather pointing out that there's no answer that doesn't take the use-case into account.)

Also, I don't think the argument for omitting the initializer is brevity, but rather in eliminating redundancy. Why tell the compiler something that it already knows? By far the most common use case is = nil, because if you know the value from the start you likely don't need an optional. (The opposite case, where you start with a non-nil value but need to be able to set a nil value later exists, of course, but it doesn't seem typical to me.)

The other un-addressed issue here (well, it was sort of addressed at the end of this post) is that the declaration of an optional has a unique syntactic form (because of the ? after the type). That means it should be easy for the compiler to recognize the difference between this and a non-optional declaration, so nothing is forcing the compiler to add a boilerplate = nil initializer (along with the performance implications that has) to the optional form just to make it consistent (hmm, see above) with the non-optional form.

IOW, the compiler could set the storage to nil cheaply without an initializer expression, if someone chose to put that behavior into the compiler.

The only downside here (and the only inconsistency that matters, I think) is the ambiguity of this local variable construct:

var myOptional: Int?
if (myBool) {
    myOptional = 4

Should this produce an error (that myOptional isn't initialized on all paths) or not? It's unclear which choice would be the most beneficial.


Consistency is good because it means fewer things to remember, and that code is less likely to break when one piece is swapped out for another. It's not circular at all. I don't think consistency is the most important goal for designing something, but it's a goal.

Anyway, the case where this matters most is stored properties, not locals, but I wouldn't want to change the behavior for stored properties and not locals, because that makes the special case even smaller.


also do not forget the "let" case here.

let myOptional: Int? // fine without "= nil", won't compile with it.
if myBool {
    myOptional = 4

i agree. why not have this one consistent?

var v = true
func foo(v = true) {} // error?

Yes, but mostly no. :lying_face:
It's semantically incorrect. We don't actually have a truthful mechanism for properties that cannot be initialized during initialization.*

final class ViewController: UIViewController {
  @IBOutlet private unowned var label: UILabel! = uninitializedImplicitlyUnwrappedOptional()
/// The "value" of an implicitly unwrapped `Optional` that has not yet been assigned a real value.
/// This is technically `.none` / `nil`, but it should never be used directly.
/// If it is *ever* valid for getting an `Optional`'s value to result in `nil`,
/// then it should not be implicitly unwrapped.
func uninitializedImplicitlyUnwrappedOptional<Wrapped>() -> Wrapped! {

* There are proposed property wrappers that could help, but don't, for the most common use case, because IBOutlets are required to be optional.

1 Like

just recently we introduced implicit returns from single-expression closures... now the new comers have to remember that this is good:


and this is not

    print("inside closure")

if we want to be consistent we need to either always require return or never, right? i wouldn't mind the latter.

implicit returns from single-expression closures optimisation breaks consistency and reduces visual clutter by removing some noise characters. var v: Int? is exactly the same thing.

if we do consistency in one place but not another - we are ... inconsistent.


@jrose isn’t saying that consistency is the most important goal — in fact, he says that it isn’t the most important goal. Rather, he’s saying that we should be consistent unless there’s a good reason to be inconsistent (unless I’ve misunderstood what he said). It would be theoretically nice if Swift were a totally consistent language, but in practice it would be verbose, take a long time to compile, and/or cause bugs.

Implicit returns for single-expression functions helps make code more readable by removing useless return statements. Furthermore, single-expression closures were already inconsistent with multiple-expression closures before this feature was implemented since type inference only applies to single-expression closures, not multiple-expression closures. And I think the rule is simple enough that its complexity cost is justified.


yep, that's how i understood him as well. looks like the decision whether to prefer "more noise plus more consistency" vs "less noise plus less consistency" is taken on a case by case basis.

1 Like

I think every exception should have a rationale. I don't think there is a good one for implicitly initialized Optionals.

By the way, I’m not sure how practical this would actually be, but I’d love some form of “multi-stage” initialization that allows you to call instance functions to set properties. I suspect that’s infeasible, since you’d need some way of confirming at compile-time that the relevant instance methods don’t depend on uninitialized properties, but I can dream.

Implicitly-unwrapped Optionals are meant to solve this problem, of course, but they remain dangerous (if not unsafe in the sense of undefined behavior) forever.

1 Like

listing the previous attempts:

nov 2017 Pitch: Remove default initialization of optional bindings
jan 2019 Remove implicit initialization of Optionals?
jun 2019 PrePitch: Optional variables should require explicit initialization

the other radical way of solving this inconsistency is to introduce some DefaultValueInitializable (?) protocol. Optionals would confirm to it, so could user types.