[swift-evolution] deinit and failable initializers

Chris Eidhof chris at eidhof.nl
Tue Jan 26 11:15:46 CST 2016


Now that we can return nil from a failable initializer without having initialized all the properties, it’s easier to make a mistake. For example, consider the following (artificial) code:

class MyArray<T> {
    var pointer: UnsafeMutablePointer<T>
    var capacity: Int
    
    init?(capacity: Int) {
        pointer = UnsafeMutablePointer.alloc(capacity)
        if capacity > 100 {
            // Here we should also free the memory. In other words, duplicate the code from deinit.
            return nil
        }
        self.capacity = capacity
        
    }
    
    deinit {
        pointer.destroy(capacity)
    }
}

In the `return nil` case, we should really free the memory allocated by the pointer. Or in other words, we need to duplicate the behavior from the deinit.

Before Swift 2.2, this mistake wasn’t possible, because we knew that we could count on deinit being called, *always*. With the current behavior, return `nil` is easier, but it does come at the cost of accidentally introducing bugs. As Joe Groff pointed out, a solution would be to have something like “deferOnError” (or in this case, “deferOnNil”), but that feels a bit heavy-weight to me (and you still have to duplicate code).

In any case, I think it’s nice that we can now return nil earlier. I don’t like that it goes at the cost of safety, but I realize it’s probably only making things less safe in a small amount of edge cases.

Chris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160126/cfbde381/attachment.html>


More information about the swift-evolution mailing list