Standard initializer fulfilling prototype requirement for failable initializer

I didn't think this would work, but I tried it anyway. And it works. I am glad it does, but am curious as to "why"? Is this documented anywhere?

import Foundation                                                   
                                                                    
protocol Somethingable {                                            
    init?(something: Data)                                          
}                                                                   
                                                                    
extension String: Somethingable {                                   
    init?(something: Data) {                                        
        if let myself = String(data: something, encoding: .ascii) { 
            self = myself                                           
        }                                                           
        else {                                                      
            return nil                                              
        }                                                           
    }                                                               
}                                                                   
                                                                    
extension FixedWidthInteger {                                       
    init(something: Data) {                                         
        self = something.withUnsafeBytes { $0.pointee }             
    }                                                               
}                                                                   
                                                                    
extension UInt32 : Somethingable {}                                 
                                                                    
let data = Data([0x31, 0x32, 0x33, 0x34])                           
let ui32 = UInt32(something: data)                                  
print(ui32)                                                         
if let str = String(something: data) {                              
    print(str)                                                      
}                                                                   
else {                                                              
    print("not convertable to string")                              
}

I've haven't been in a situation to satisfy a failable initializer requirement with a non-failable one, but it makes sense: it can be interpreted as a failable initializer that never throws. Similarly to how we can write

func foo() throws -> Int {
    return 0
}

Vice-versa, however, would be of course incorrect. To satisfy a non-failable requirement with a failable one, that is.

BTW we can't do this.

protocol Somethingable {
    func foo() -> Int?
}

extension String: Somethingable {
    func foo() -> Int {
        return 0
    }
}

It looks inconsistent.

1 Like

That can be fixed; someone needs to complete the work though:

3 Likes

Oh that would be nice!