How to call a generic, non-throwing function, over a specialized, throwing function?

i have an extension on String that is generic:

extension String
    @inlinable public
    init(bson:BSON.UTF8View<some BidirectionalCollection<UInt8>>)

it witnesses a non-generic protocol requirement that throws:

protocol BSONStringDecodable:BSONDecodable
    /// Initializes an instance of this type from the given UTF8-8 string.
    init(bson:BSON.UTF8View<ArraySlice<UInt8>>) throws

extension String:BSONStringDecodable

but i cannot actually seem to call this witness. instead, when i call it, it tries to dispatch through the throwing protocol requirement:

let bson:BSON.UTF8View<ArraySlice<UInt8>>
let string:String = .init(bson: bson)
//  call can throw but is not marked with 'try'

i do not want to add a concrete overload to String because it will be impossible to reference it from documentation without a DocC overload hash. and i also do not want to name it with a different argument label, because it is the same function.

You have to bounce through a context that doesn't know the concrete argument type. Throws-ness isn't taken into account in overload resolution. (I realize there's no way to know this because the rules aren't written down anywhere, but not being able to overload on just throws is a hint.)


i ended up making the String.init(bson:) witness non-generic and manually inlining the generic call sites. this was needed because i had a default implementation

extension BSONStringDecodable where Self:LosslessStringConvertible

that would have caused infinite recursion because String itself is LosslessStringConvertible.

1 Like