[swift-evolution] Proposal: allow delegating from a throwing initializer to a failable initializer

Chris Lattner clattner at apple.com
Mon Dec 14 14:29:34 CST 2015


> On Dec 14, 2015, at 11:43 AM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> On Dec 12, 2015, at 7:55 PM, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
>> It is not currently possible to call a failable (optional) initializer from a throwing initializer.  This is unfortunate as many Cocoa initializers are failable and it is desirable to be able to extend Cocoa types with throwing convenience initializers that call a failable (optional) designated initializer.
>> 
>> For example, something similar to the following should be possible:
>> 
>> enum CustomError: ErrorType { case E }
>> 
>> struct S {
>>   let urlString: String
>> }
>> 
>> extension NSURL {
>>   convenience init(s: S) throws {
>>       guard self.init(string: s.urlString)
>>           else { throw CustomError.E }
>>   }
>> }
>> 
>> In the current language, even if the compiler preventing us from calling the failable initializer we would not be able to access the return value in the guard expression. Furthermore, even if we could an Optional expression would not be valid in a guard condition.  I am interested in ideas for how this should be handled.  Would there be a special case of the guard statement to allow this?  Or should some other mechanism be used to guarantee that we either successfully complete initialization or throw?
> 
> Definitive initialization already ensures things like this; it should be straightforward to check the additional control-flow rules here if we can decide on how to write the check syntactically.
> 
> One constraint is that subobject initializers cannot allow “retries” after the delegating call, since user code can't distinguish semantically between failures that occurred before the instance was fully initialized (which can in principle be retried) and failures which occurred afterwards (which cannot, because the object may have escaped).

Right, the compiler would need to prove that the failure path from self.init returning nil could never lead to a normal return (it has to throw, abort, infinite loop, whatever).

Personally, I consider this an implementation limitation that doesn’t need an evolution proposal.  Someone with a good patch to implement this would be welcome to submit a PR.

-Chris


More information about the swift-evolution mailing list