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

John McCall rjmccall at apple.com
Mon Dec 14 13:43:24 CST 2015


> 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).

John.


More information about the swift-evolution mailing list