Inconsistent compiler behavior with `guard let x = x else { }` pattern

I have posted about a similar issue beforehand, where I encountered a compiler error that only popped-up during CI on GitHub using Swift for Linux. Back then, the solution was to replace occurrences of:

guard let x = x else { }

with

guard let x = self.x else { }

In other words: introducing scope was a workaround. But even then, guard let x = x else { } would work most of the time and it only would fail sometimes.

The New Problem

Now I am facing this problem again in this context:

        let (x, y) = myMethod(z)
        guard let x = x else { return self }

which results in the following error:

... error: definition conflicts with previous value
        guard let x = x else { return self }
                  ^
... note: previous definition of 'x' is here
        let (x, y) = myMethod(z)

This works fine in Xcode 13.1 with Swift 5.5.1, but fails again in the GitHub CI workflow where Linux is running. Obviously, in this context I cannot fall back to use scope to tell the compiler which symbol I am talking about and I am forced to use a different name for x in the first line. If I have time, then I might be able to get around to try to replicate this using Docker on my laptop where I could play around with different Linux-versions of the Swift compiler.

The main issue (for me) is not that I have to provide scope and/or rename a symbol, but that the compiler behavior differs across platforms and that it sometimes works fine and fails seemingly randomly.

Not sure if it's useful in your context, but you could also do the assignment and the test at the same time:

guard case let (x?, y) = myMethod(z) else { return self }
1 Like

Well that is alarming that code which is valid will apparently non-deterministically fail to compile on one platform…

I should clarify: if it fails, then it fails deterministically. But you do not know if an assignment will/will not work before actually running the compiler.

Apologies for the confusion.