Howdy,
I have an API that looks like this
protocol Base {}
enum BaseOption {
case base
}
extension Base {
func foo(_ option: BaseOption) {
print("Base")
}
}
protocol Refined: Base {}
// Basically an extension to BaseOption
enum RefinedOption {
case base, refined
}
extension Refined {
func foo(_ option: RefinedOption) {
switch option {
case .base:
// Call into base impl
(self as Base).foo(.base)
case .refined:
print("Refined")
}
}
}
struct Thing: Refined {}
let x = Thing()
x.foo(.base) // > Base
x.foo(.refined) // > Refined
(x as Base).foo(.base) // > Base
(x as Base).foo(.refined) // > error: type 'BaseOption' has no member 'refined'
So far everything is working as I desire. A Refined is just Base with some extra options for foo. Where this falls apart however is when I introduce a second refinement on Base...
protocol Refined2: Base {}
enum Refined2Option {
case base, refined2
}
extension Refined2 {
func foo(_ option: Refined2Option) {
switch option {
case .base:
// Call into base impl
(self as Base).foo(.base)
case .refined2:
print("Refined2")
}
}
}
extension Thing: Refined2 {}
x.foo(.refined) // > Refined
x.foo(.refined2) // > Refined2
x.foo(.base) // > error: ambiguous use of 'foo'
Now, I'm aware that the underscored attribute @_disfavoredOverload
can "solve" this issue, but I am unsure if this is really a good idea. And the following quote from the linked documentation doesn't exactly inspire confidence...
Use
@_disfavoredOverload
to work around known bugs in the overload resolution rules that cannot be immediately fixed without a source break. Don't use it to adjust overload resolution rules that are otherwise sensible but happen to produce undesirable results for your particular API; it will likely be removed or made into a no-op eventually, and then you will be stuck with an overload set that cannot be made to function in the way you intend.
Since the ambiguity on foo seems reasonable to me, this leads me to believe that I should not be using @_disfavoredOverload
here, but I would like that confirmed.
Also, as a follow-up question if I should not be using @_disfavoredOverload
, how could I design an API that has a similar shape?
Thanks,
smkuehnhold