I'm trying to write a library that uses templated/generic type dispatch, but I can't figure out how overload resolution works in Swift. (Is there a more technical reference than The Swift Programming Language?)
The following works exactly as I'd hope:
func f(_ v: String) { print(v) }
func f(_ v: String?) { f(v!) }
func f(_ v: Int) { print(v) }
func f(_ v: Int?) { f(v!) }
f("foo")
f(Optional("bar"))
f(2)
f(Optional(3))
And this code also works the same way:
func g<T>(_ v: T) { print(v) }
func g<T>(_ v: T?) { g(v!) }
g("foo")
g(Optional("bar"))
g(2)
g(Optional(3))
But when I compile this:
func h(_ v: String) { print(v) }
func h(_ v: Int) { print(v) }
func h<T>(_ v: T?) { h(v!) }
h("foo")
h(Optional("bar"))
h(2)
h(Optional(3))
I get the warning
all paths through this function will call itself
func h<T>(_ v: T?) { h(v!) }
And sure enough executing it with an optional parameter blows the stack.
My first zany theory was that maybe generics don't participate in overload resolution with non-generics, but this:
func i<T: StringProtocol>(_ v: T) { print(v) }
func i<T>(_ v: T?) { i(v!) }
i("foo")
i(Optional("bar"))
gives me the same warning, and the second invocation blows the stack.
If v
is of type Optional(String)
, I don't even understand how v!
can be passed to a generic expecting a T?
.