[swift-evolution] Closure identity (was Re: Compiler directive for current closure reference)
brent at architechies.com
Mon Feb 22 22:00:46 CST 2016
> Closures don't have identity (i.e. you can't use === on them). ObjC blocks do, so if you really need it you can pass things around as @convention(objc_block), but closures don't. So I think you'd have to start there if you want to do anything like this.
Actually, I've wondered about this for a while.
Closures are pretty weird in that they're a reference type, but they don't have a stable identity. I asked about this once before Swift was open sourced (I think on Twitter), and I believe I was told that it was due to certain optimizations. What are these optimizations, and can we give closures stable identities despite them?
In a few minutes of research, my guess is that it has to do with thick vs. thin closures: thick closures carry a context object, while thin ones don't. <https://github.com/apple/swift/blob/master/docs/CallingConvention.rst#closures> Is that the issue here? If so…
- Leaving aside thin closures for the moment, is a thick closure's context object unique enough to be used as its identity? Is function pointer + context unique enough, or does the function pointer change too?
- Now, for thin closures, obviously we don't want to allocate an entire unnecessary object to carry an empty context around. But what would the costs be if, instead of omitting the context pointer, we replaced it with a unique integer (presumably with the low bit set to avoid colliding with valid context pointers)? Perhaps keep a thread-local counter and combine it with the thread ID so we don't need any locking?
(As for motivation: besides just being kind of a weird asymmetry, there are certain classes of APIs which are made more convoluted by the lack of closure identity. Basically any API where you can register and unregister multiple handlers with a single object is affected: the "add" operation has to return some kind of token to be used for the "remove" operation, which may now have a different lifetime from the registration itself. It seems simpler to add and remove the closure itself, but the lack of identity prevents that.)
More information about the swift-evolution