[swift-users] inout generic struct parameter error

Georgios Moschovitis george.moschovitis at icloud.com
Sun Jan 1 12:48:53 CST 2017


While getting my feet wet with Swift, I am still surprised with type-system ‘quirks’ here and there.

I tried to implement a simple array of weak references:

public struct WeakArrayIterator<T: AnyObject>: IteratorProtocol {
    var array: [Weak<T>]
    var index = 0
    
    init(_ array: [Weak<T>]) {
        self.array = array
    }
    
    mutating public func next() -> T? {
        while index < array.count && array[index].value == nil {
            // Remove weak references invalidated by ARC.
            array.remove(at: index)
        }
        
        if index < array.count {
            let value = array[index].value
            index += 1
            return value
        } else {
            return nil
        }
    }
}

public struct WeakArray<T: AnyObject>: Sequence {
    var weakRefs: [Weak<T>]
    
    init() {
        weakRefs = []
    }
    
    public var count: Int {
        return weakRefs.count
    }

    public subscript(index: Int) -> T? {
        get {
            return weakRefs[index].value
        }
        
        set(value) {
            weakRefs[index] = Weak(value!)
        }
    }
    
    mutating public func append(_ value: T) {
        weakRefs.append(Weak(value))
    }
    
    @discardableResult
    mutating func remove(at index: Int) -> T? {
        return weakRefs.remove(at: index).value
    }
    
    public func makeIterator() -> WeakArrayIterator<T> {
        return WeakArrayIterator(weakRefs)
    }
}

This kinda works but because we pass a struct at:

        return WeakArrayIterator(weakRefs)

the ‘garbage collection’ at:

            // Remove weak references invalidated by ARC.
            array.remove(at: index)

doesn’t affect the original array.

I tried changing to this:

public struct WeakArrayIterator<T: AnyObject>: IteratorProtocol {
    ...    
    init(_ array: inout [Weak<T>]) {
        self.array = array
    }        return WeakArrayIterator(&weakRefs)
…

public struct WeakArray<T: AnyObject>: Sequence {
    return WeakArrayIterator(&weakRefs)

but I get this strange (to me) error:

Cannot convert value of type ‘[Weak<T>]’ to expected argument type ‘[Weak<_>]’

I even get the fix-it suggestion:

Fix-it Insert “as [Weak<_>]”

which does not even compile!

I would appreciate it if someone could explain me this cryptic error and maybe provide some pointers about how to properly/efficiently implement a WeakArray.

thanks,
-g.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170101/053b5e5e/attachment.html>


More information about the swift-users mailing list