Swift: EXC_BAD_ACCESS when using nil-coalescing on optional closures [Xcode 3.3 (13E113)]

Hi,

We are getting crashes in code that has worked fine for the last 1.5 years and which by all means looks legal to us.

Since Upgrading to Xcode 13.3 the following two code examples crash on iPhone & Simulator and MacOS.
They work fine when compiling with Xcode 13.2.1:  

fileprivate typealias Closure = () -> Void

func crash1() {
    let closure1: Closure? = nil
    let closure2: Closure? = nil
    let closure3: Closure? = nil
    print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")
   
    let closure = closure1 ?? closure2 ?? closure3

    print("\(#line): \(String(describing: closure))")
    closure?() // <- EXC_BAD_ACCESS
    assert(closure == nil)
}

func crash2() {
    let closure1: Closure? = nil
    let closure2: Closure? = nil
    let closure3: Closure? = { }
    print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")

    let closure = closure1 ?? closure2 ?? closure3

    print("\(#line): \(String(describing: closure))")
    closure?() // <- EXC_BAD_ACCESS
    assert(closure != nil)
}

 

The resulting closure has a value of Optional((Function)) in both cases, but it is corrupted, i.e. crashes on use. Please not the it should be nil in the first example, after all.  

Note: The Code apparently works in a playground (albeit sometimes the playground simply hangs), but not in an iOS (UIKit/SwiftUI) or MacOS (SwiftUI or command line tool) project.

No crashes when:
a) using only two optionals in a row:

let closure = closure1 ?? closure2

or b) when using parentheses:

let closure = (closure1 ?? closure2) ?? closure3

 

Known issue?
Radar?
Any ideas?

Thanks,
Lars

No crashes on Xcode 13.3 playground - it just locks the IDE up after a few runs.

Effectively, I see the same different behaviour between Xcode 13.2.1 and 13.3.1 Crash only on 13.3

With all declared as nil:

let closure = closure1 ?? closure2 ?? closure3

which should be equivalent to

let closure = closure1 ?? (closure2 ?? closure3)

Gives (with no crash as you noticed)

  • 13.3: Optional((Function))
  • 13.2.1: nil

.

and

let closure = (closure1 ?? closure2) ?? closure3

Gives

  • 13.3: nil
  • 13.2.1: nil

I also tested:

let closure4 = closure2 ?? closure3
let newClosure = closure1 ?? closure4
newClosure??()

Here, in 13.3,

  • closure4 is logically nil
  • newClosure is nil
  • no crash

So there is something in the associativity rule for ?? that has apparently changed (in compiler).

So it worth a bug report because of the difference between Xcode 13.2.1 and 13.3.

Note: If that can help, I found this old thread which reports a similar issue with chaining, showing that compiler has issues inferring the type:

https://stackoverflow.com/questions/42936281/swift-compile-time-error-with-optional-chaining-and-nil-coalescing

I filed a bug report at https://bugs.swift.org/browse/SR-16062

Swift: EXC_BAD_ACCESS when using nil-coalescing on optional closures [Xcode 3.3 (13E113)]
 
 
Q