Search code examples
swiftoptional-chaining

Swift: compile-time error with optional chaining and nil-coalescing


I have a strange problem with optional chaining and nil-coalescing in Swift. Can anyone explain why the following code won't compile:

class A<T> {
    var val: T
    var x: A<T>?
    var y: A<T>?
    init(t:T){
        val = t
    }
    func test() -> [T] {
        return (self.x?.test() ?? []) + [val] + (self.y?.test() ?? [])
    }
}

But when writing

func test() -> [T] {
    return (self.x?.test() ?? []) + ([val] + (self.y?.test() ?? []))
}

It does? The error says:

Cannot convert value of type '[T]?' to expected argument type '[_]?'

For me it looks a lot like a compiler bug.


Solution

  • Type inferring is hard with complicated expressions. That [_] usually means that type is unknown - could not be inferred. Simplifying the expression solves the problem in 99% of the time:

    class A<T> {
        var val: T
        var x: A<T>?
        var y: A<T>?
        init(t:T){
            val = t
        }
        func test() -> [T] {
            let xResult = self.x?.test() ?? []
            let yResult = self.y?.test() ?? []
    
            return xResult + [val] + yResult
        }
    }
    

    Another 99% of the time, type inferring problems can be solved by specifying a type explicitly:

    return (self.x?.test() as [T]? ?? []) + [val] + (self.y?.test() ?? [])
    

    You have found a workaround yourself. That workaround with parenthesis removes certain number of type inferring paths.

    Reported as SR-4309