Type-specific function selection in method default value

Given the following example:

func identify<I: Identifiable>(value: I) -> AnyHashable { value.id }
func identify<H: Hashable>(value: H) -> AnyHashable { value }
func identify(value: Any) -> AnyHashable { 1 }

func foo<V>(
    value: V,
    identity: (V) -> AnyHashable = { identify(value: $0) }
) -> AnyHashable {

print(foo(value: 5))

Is there a way to make Swift select the specialized identify function most appropriate to type V, rather than using only the Any variant, without duplicating the foo function with specialized overloads for every type case?

1 Like

A nit: swift is selecting the identify function most appropriate to type V. That selection happens at compile time, in the context of the generic caller, so the most specialized identify function for V (which is a totally unconstrained generic type, and so does not conform to either Hashable or Identifiable) is the last one.

1 Like

I would counter that at compile time, there is sufficient type information available to resolve V as Int. And while I'm certain that your explanation does indeed indicate what is happening in the compiler, I believe it is lacking some details.
Note that it might not be entirely unreasonable for a user to expect that the default value of a function parameter be evaluated in the context of the caller, where the compiler has all the freedom to substitute a pointer to the identify function which is type-specific in the caller context - a freedom that it certainly does not have when identify were to be used in the function body (note, for instance, that moving the default value inline changes the result).
Regardless, I believe the intent of the example is clear and I'm curious if anyone has had any experience with this type of situation and has found a workable solution.

(Curiously, even though default argument values in this context appear to behave internal to the function itself, we cannot refer to private global functions from default values on public functions, suggesting that the caller context needs access to any global functions referenced from the default value - I'm really not sure how to square these two facts)

Does SE-0347 solve this?