Inconsistency in `Generic parameter 'T' could not be inferred `

Is shorthand the preferred way to write ifelse statements in Swift when working with generics?

protocol SomeExample {
    var id: String { get }
    init(id: String)
}

struct Object: SomeExample {
    var id: String
}

class Source {
    func get<T: SomeExample>(completion: ([T]) -> Void) {
        completion([T(id: "")])
    }
}
var outside: Object?
let source = Source()

// Error: Generic parameter 'T' could not be inferred
source.get(completion: {
    if let first: Object = $0.first {
        outside = first
    } else {
        fatalError()
    }
})

// I understand this is easier to infer
source.get(completion: {
    outside = $0.first
})

// But this should definitely be harder than the if
// statement that literally states the type but it
// runs fine
source.get(completion: { objects in
    objects.first != nil ? {
        outside = objects.first
    }() : {
        fatalError()
    }()
})

Swift's rule for type inference in closures is that if the closure contains multiple statements, the body is not used to determine its type. This matches the behavior outside of a closure, where later statements in a function do not affect the types of earlier statements in the function, but it does produce a discontinuity when you go from one statement to two.

This is a good motivation for expanding what can be done with expressions.

It's a motivation. I'm not sure it's a good one because (as frequently complained) massive expressions result in worse type-checker performance (something that may be possible to improve) and more opaque diagnostics (something that's probably inherent, at least to some degree).

Yes, it would require judicious use for sure. But I run across code regularly that would be improved by it. Simple closures with verbose return types that could be inferred are a relatively common example. I could be wrong, but I don’t think the cases I have in mind would run into significant type checker performance issues.

Terms of Service

Privacy Policy

Cookie Policy