I've run into a somewhat weird (compile time) error that I cannot make any sense out of. The error is given for the following snippet:
/* error: type 'Int1' does not conform to protocol 'BooleanType' */
let closure1 : (inout foo: Int) -> () = {
foo -> () in
(foo<0 ? (foo = -1) : (foo = 1))
}
Error: type 'Int1' does not conform to protocol 'BooleanType'
Note that Int1 is not a typo here.
Question 1: Why am I not allowed to use a single inline if statement (with result '()') as the implicit return type of a void return closure?
Question 2: Out of curiosity, what is the Int1 type? (Curiously enough the same error message, Int1 ... is given even if modifying the closure above to operate on different types in a similar manner).
Why is this of interest for me? I have a few closures that I would like to use in the anonymous form similar of closure1Anon below, but due to this error I can't.
Details and my own (non-fruitful) investigation into the matter follow below.
As described above, the error is prompted when---within a void return closure---using a single inline if statement which includes assignments to an inout parameter.
We can verify that result of an inline statement is the empty tuple value, (), consider e.g.:
var foo = -4
print((foo<0 ? (foo = -1) : (foo = 1)).dynamicType) // ()
print(foo) // -1
... so it should be OK to use as return statement for a void return closure (see e.g. the assignment-followed-by-return example closure4 below).
Below follows the erroneous closure (closure1, closure1Explicit, closure1Anon) as well as five very similar/associated closures that work fine (closure2 through closure7).
/* error: type 'Int1' does not conform to protocol 'BooleanType' */
let closure1 : (inout foo: Int) -> () = {
foo -> () in
(foo<0 ? (foo = -1) : (foo = 1))
}
/* same error */
let closure1Explicit : (inout foo: Int) -> () = {
foo -> () in
return (foo<0 ? (foo = -1) : (foo = 1))
}
let closure1Anon : (inout foo: Int) -> () = { ($0<0 ? ($0 = -1) : ($0 = 1)) }
Ok:
/* The following are all OK */
let closure2 : (inout foo: Int) -> () = {
(inout foo: Int) -> () in
(foo<0 ? (foo = -1) : (foo = 1))
} // thanks @MartinR
let closure3 : (inout foo: Int) -> () = {
foo -> () in
let _ = (foo<3 ? (foo = 1) : (foo = 2))
}
let closure4 : (inout foo: Int) -> () = {
foo -> () in
(foo<3 ? (foo = 1) : (foo = 2))
return ()
}
let closure5 : (inout foo: Int) -> () = {
foo -> () in
let bar = (foo<3 ? (foo = 1) : (foo = 2))
return bar
}
/* Error must be related to inout as the two
following closures works fine */
let closure6 : () -> () = {
() -> () in
var a = 0
return (a<0 ? (a = -1) : (a = 1))
}
var globalVar = 1
let closure7 : () -> () = {
() -> () in
(globalVar<0 ? (globalVar = -1) : (globalVar = 1))
}
I can't for the world figure out why closure1/closure1Explicit/closure1Anon above yields this error. Possibly someone can shed some light on this for me?
Final note: the following seemingly similar SO thread seems non-relevant in this case:
I'm using Swift 2.1.1 and Xcode 7.2.1.
Int1is actuallyBuiltin.Int1and comes from the Swift internal type representations linked to LLVM. (I accidentally deleted my previous similar comment, sorry for the double notification...)closure1compiles if you replacefoo -> () ininside the closure by(inout foo: Int) -> () in. I don't why that is necessary in closure1 but not in closure2, 3, ...