[swift-evolution] deinit and failable initializers

davesweeris at mac.com davesweeris at mac.com
Wed Jan 27 13:37:56 CST 2016


I don’t think UnsafeMutablePointer.alloc(capacity) qualifies as “pure”, so you’d have to handle it before failing:
init?(capacity: Int) {
    self.pointer = UnsafeMutablePointer.alloc(capacity)
    if capacity > 100 {
        self.pointer.dealloc(capacity)
        return nil // Ok, because everything that has side effects has been dealt with
    }
    self.capacity = capacity
}
or, as in Kostiantyn’s example, bail out before anything with side effects has been done:
init?(capacity: Int) {
    if capacity > 100 {
        return nil // This is ok, we haven’t actually done anything yet
    }
    self.pointer = UnsafeMutablePointer.alloc(capacity)
    self.capacity = capacity
}

Either way, in this case we don’t really lose anything because current system doesn’t prevent this kind of memory leak in the first place. This doesn’t bother the playground at all:
struct MyArray<T> {
    var pointer: UnsafeMutablePointer<T>
    var capacity: Int
    
    init?(capacity: Int) {
        self.pointer = UnsafeMutablePointer.alloc(capacity)
        self.capacity = capacity
        if capacity > 100 {
            return nil // Oops! Memory leak!
        }
    }
    // Will probably leak anyway, since structs don’t have deinits.
}



What if we allowed functions to have where clauses?
struct MyArray<T> {
    var pointer: UnsafeMutablePointer<T>
    var capacity: Int
    
    init?(capacity: Int where capacity <= 100) { // Immediately returns nil if the where clause evaluates to false
        self.pointer = UnsafeMutablePointer.alloc(capacity)
        self.capacity = capacity
    }
    /* OR (note that the init has become non-failable) */
    init(capacity: Int where capacity <= 100) throws { // Immediately throws an error if the where clause evaluates to false
        self.pointer = UnsafeMutablePointer.alloc(capacity)
        self.capacity = capacity
    }
}

I know guard offers similar functionality, but it can appear anywhere in the function body… where must to be up-front, and would get checked before the function body has a chance to do anything. Plus, since it’s part of the function’s signature, it’d appear in API headers. I can’t remember which thread it was in, but as I’ve said before… Which is more useful: a note buried somewhere in the API docs about preconditions, or being able to see the actual bit of code that’ll validate your data?

- Dave Sweeris

> On Jan 27, 2016, at 10:24, Jean-Daniel Dupas <mailing at xenonium.com> wrote:
> 
> The discussed sample is explicitly about a UnsafeMutablePointer.alloc(capacity) call that must be explicitly freed. That why I said local variable wouldn’t improve much the issue.
> 
> You can’t restrict the operations that can be done before an early return. How would you write a failable init that return nil when a ressource allocation or access fail (which is far more common than having a @pure function failing) ?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160127/816fd033/attachment.html>


More information about the swift-evolution mailing list