Adding autoclosure breaks the function's usage?

My understanding is that the intent of @autoclosure was to let the callee delay the execution of its parameters without a breaking change for the caller.

So, if I changed a function from:

func isEven(_ n: Int) -> Bool { 
   n % 2 == 0 
}

to

func isEven(_ n: @autoclosure () -> Int) -> Bool { 
   n() % 2 == 0 
}

the caller is not impacted:

let result = isEven(Int.random(1...100))

This, however, breaks when the function is passed as a parameter:

// error, if implemented with autoclosure
let results = [1,2,3].filter(isEven)

The error is:
Cannot convert value of type 'Int' to expected element type '() -> Int'

Is this a design decision or a known limitation?

1 Like

This seems like a limitation, not an intentional feature. There could be a subtype relationship between the corresponding function types, since an autoclosure argument is more general than a strict argument.

2 Likes

Thanks. Makes sense.

Looks like SR-1793 is the earliest reported instance of this. I wonder if the cleanups in the type checker over the past year make this easier to deal with, or if it's still a Problematic Implicit Conversion.

1 Like