Deprecating a function with a similar overload

I made a mistake in a published API that I want to deprecate.

It looks a bit like this (the generic aspect of these may not be important to the example - but the functions in question are generic in this way):

func foo<T>(_: T.Type) -> T?

being refactored to

func foo<T>(_: T.Type) throws -> T

But the problem is that the following brand of code cannot be successfully refactored to use the updated method:

guard let x = foo(T.self) else { ... } // Deprecated warning
guard let x = try? foo(T.self) else { ... } // No calls to throwing functions occur within 'try' expression

I tried something sneaky and used @_disfavoredOverload on the deprecated method, but that put me in the opposite situation where the existing API is unreachable and instead creates a compile error to the tune of Call can throw but is not marked with 'try'

Suggestions?
Is there another way I can hint to the compiler which overload of a function I want to use. I tried adding type hints but none of my attempts have worked so far.

2 Likes

As far as I know there’s no way to achieve what you’re after short of giving the new overload a different name (or argument label, etc), because the semantic checks for throwing errors are performed after the type checker has resolved all overloads.

4 Likes

Nobody want to actually supply a metatype, so I think you fortunately have an opportunity for this special case, by improving the API more. Yes?

guard let x2 = try? foo() as T else { }
guard let x2: T = try? foo() else { }
func foo<T>(_: T.Type = T.self) throws -> T {

In my actual implementation I do have the default T.self that you suggest. I didn't include it in my approximation here because it didn't seem relevant.

You're right about the default being more convenient in certain situations.

Yeah that's what it is seeming like. Thanks for the confirmation. :slight_smile: