When designing result builders which consume and product generic types, I often find myself needing to spell out types in an annoyingly explicit way. Consider this toy example:
@resultBuilder enum SomeBuilder {
static func buildBlock(_ v: Result<Int,Error>) -> Result<Int,Error> { v }
}
struct SomeStruct {
init(@SomeBuilder _ v: () -> Result<Int,Error>) {}
}
let x = SomeStruct {
Result.success(0)
}
SomeBuilder is almost the simplest possible @resultBuilder: it takes in single values of type Result<Int,Error> and returns them as-is. SomeStruct is a simple struct with an initializer that takes a single @SomeBuilder closure which produces Result<Int,Error>. Consequently, it makes sense to me that this code should compile. Swift should be able to figure out that Result.success(0) refers to Result<Int,Error>.success(0) because this is the only type that could make sense in this context. However, this example fails to compile with
_:9:5: error: cannot convert value of type 'Result<Int, _>' to expected argument type 'Result<Int, Error>'
Result.success(0)
^
_:9:5: note: arguments to generic parameter 'Failure' ('_' and 'Error') are expected to be equal
Result.success(0)
^
_:9:5: error: generic parameter 'Failure' could not be inferred
Result.success(0)
^
_:9:5: note: explicitly specify the generic arguments to fix this issue
Result.success(0)
^
<Int, <#Failure: Error#>>
On the same line, Swift claims that it cannot infer the Failure type of Result.success(0) and then claims that it knows the failure must be Error. I can get this code to compile by using
let x = SomeStruct {
Result<Int,Error>.success(0)
}
but in real examples, being this verbose with the types is extremely inhibitive to the DSLs I want to design.
Is this a bug in the compiler? How can I get Swift to infer generic types in result builders such as this one?