Hello everyone
I came across a real mind-twist in Swift, and Iβd love to hear your thoughts.
Take a look at this code (no escaping, no concurrency involved):
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)
Where did the reference date come from? Even if Swift wrongly uses the free init of the Date()
, it should be equal to .now
or at least with a fraction of a second difference, right?
I've tested with different types and observed the last print:
Int -> passing 1234 -> prints 0
Bool -> passing true -> prints false
Double -> passing 12.34 -> prints 0.0
String -> passing "Hi" -> prints nil
Why does using String
return nil
then? The foo
function's return type is not even an Optional
.
Also checked with a custom enum which does not have an initializer or rawValue, and the result was that it returns the first case as the value:
enum Bar {
case a
case b
}
func foo(bar: Bar, action: () -> Void) -> Bar {
action()
return bar
}
var actionBar: Bar!
let resultBar = foo(bar: Bar.b) {
actionBar = resultBar
print("Assigned")
}
print(actionBar == resultBar) // π false
print(actionBar) // π Optional(DemoProject.Bar.a)
I was expecting some compile time error like this:
or like this:

or at least like this:

It seems like Swift is defaulting types to some unpredicted real values with unknown and inconsistent behaviour, which is unexpected from Swift (IMO).
So what is happening?
Is it by design or is it a bug?
I think it should be prevented by the compiler, such an inconsistency at the first place.
Thank you
Tested in:
Both DEBUG
and RELEASE
mode
Tested in:
- a command line project -> in the main.swift file
- an iOS app with a SPM package -> inside a SwiftUI button action closure
- an online Swift compiler