-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
Description
When using the left hand side of an assignment, inside a closure, on the right hand side, compiler fails to detect this illegal use and compiles the code.
It seems it unexpectedly uses unsafeBitCast(0.0, to: TheType.self)
to default the value and it has different behavior on different types. For example:
String -> returns nil -> Crashes at runtime -> EXC-BAD-ACCESS
Date -> returns reference date -> 2001-01-01 00:00:00 +0000
Int -> returns 0
Double -> returns 0.0
Custom enum without rawValue -> returns the first case of the enum
Also discussed Here
Reproduction
func foo(date: Date, action: () -> Void) -> Date {
action()
return date
}
var actionDate: Date!
let resultDate = foo(date: Date.now) {
actionDate = resultDate
print("Assigned")
}
print(actionDate == resultDate) // 👈 false
print(actionDate) // 👈 Optional(2001-01-01 00:00:00 +0000)
Expected behavior
It should prevent the use of variable in the first place or at least throws some warnings or errors like one of these:
Environment
swift-driver version: 1.127.14.1 Apple Swift version 6.2 (swiftlang-6.2.0.19.9 clang-1700.3.19.1)
Target: arm64-apple-macosx26.0
Tested in DEBUG
and RELEASE
mode
Also tested on an online compiler
Additional information
It seems like if we put the variable declaration in a do { }
block, the compiler starts to throws a meaningful error and refuses compiling:
enum Bar {
case a
case b
}
func foo(bar: Bar, action: () -> Void) -> Bar {
action()
return bar
}
do {
var actionBar: Bar!
let resultBar = foo(bar: Bar.b) {
actionBar = resultBar // 👈 🛑 Closure captures 'resultBar' before it is declared
print("Assigned")
}
print(actionBar == resultBar)
print(actionBar)
}
Some folks suggested that it is because of the single file top-level code or main.swift file but you can reproduce it in a iOS project using a SPM without these conditions. Explained here