Does it mean it counts as a noescape closure?
No, certainly not. It escapes the lifetime of the function that it's passed to (init(c:)
in this case) – thus by definition, it is escaping. You just don't have to mark it as @escaping
because only closure function arguments (i.e function arguments that are typed as functions themselves) are non-escaping by default (as per SE-0103).
Therefore, because the closure is escaping, it will need any state that it captures to be heap-allocated. There's no possibility that this state can be stack-allocated, as its lifetime is not limited to the current stack frame.
However in your case, you're just passing in a simple global function, test
. No additional heap allocation need take place here as global functions are stored statically, thus only a simple pointer needs to be passed about.
Although it's worth noting that because that you're working with generics, in order to type a function as a given generic placeholder T
, Swift will use a reabstraction thunk in order to unify the calling convention. To do this, a heap-allocated box will be used in order to store the function value (I go into this in more detail in this Q&A).
However, in an optimised build, it appears the thunk is able to be specialised in some cases (such as with direct usage of a top-level function), therefore meaning no additional heap-allocation need occur.