Precedence in multiple variable declaration

Can someone help clarify why the first x in let y = f(x), x = 100 seems to default to zero? Also, can you point me towards a source which will help me understand this behavior?

let f = { (x: Int) in x}

// I can understand why
let a = 100, b = f(a)
print(a, b)  // 100 100

// I do not understand how x got an implicit zero
let y = f(x), x = 100
print(x, y)  // 100 0


It seems it always defaults to some implicit value.

let b = a, a = 100
print(a, b)  // 100 0

let y = x, x = true
print(x, y)  // true false

struct Something {var x: Int = 50, y: String = "default value"}
let s2 = s1, s1 = Something(x: 100, y: "some string")
print(s1, s2)  // Something(x: 100, y: "some string") Something(x: 0, y: "")

This is surprising. Reproduced this with String in the REPL.

let i = j, j = "Hello"
i: String = {
  _guts = {
    _object = {
      _countAndFlagsBits = 0
      _object = 0x0000000000000000
j: String = "Hello"

Then I thought, "Ok... so is i equal to an empty string?" and, well, that crashed.

print(i == "") // Runtime trap

I would have expected a diagnostic like...

let i = j, j = "Hello" // error: cannot find 'j' in scope

After all, isn't let i = j, j = "Hello" equivalent to the following?

let i = j
let j = "Hello"
1 Like

This is quite bad and not dissimilar to the comparable issue with global variables.
Even more sinister example:

class C {}
let y = print(x), x = C() // 💣

Better if this gave a compilation error outright.


Is the answer to this Accessing a property of an uninitialized instance results in a Runtime error ? Seems one of my first questions here was also related, if so, my apologies, I seemed to have forgotten and could not relate this.

Edit: I am not really sure :upside_down_face: In this case, as one of the commenter above pointed out, it is in fact defined but fails at a later point.


Issue with global vars is similar but separate, probably hard to fix (or there's not enough pressure).

As for "let x = y, y = 1" this is a regression in Swift 5.2, the code getting (correctly) rejected in earlier Swift versions.


I think it'd require a new language mode to fix. Variables in top level code probably should have been private by default, and not allowed to be used before they were defined.

Yeah, it's more linear than Swift usually is, but top level code is already more linear than normal, so I think it would have been natural in practice.

1 Like