In those cases it compiles - it’s only possible because you are not actually using escaped closure, which is useless as once you try to actually use it - it won’t compile. Swift could have prohibited it in all instances to make it less “promising”, but it is what it is. The rule is basically “don’t escape non escaping closure, and if you managed to create an escaping closure from non escaping - don’t actually use it (it won’t be allowed)”.
func bar(_ closure: () -> Void) {
let f = { closure() }
f()
}
as in both cases the closure is not actually "escaped"; in the ideal world the "permissive" approach should have resulted in both fragmented being allowed whilst the "prohibitive" approach should have prohibited both fragments, and what we have here is an inconsistency and not ideal. Is that a big deal? No.
Edit: Interestingly changing let to var in this app affects it compile-ability:
func foo(_ closure: () -> Void) {
let f = { closure() } // âś…
var g = { closure() } // 🛑
}
According to my own experience, there is no "explicit rule" about escaping checking.
Correct me if I'm wrong, I think they must be using some heuristics in the compiler. And I believe that's part of the reason why withoutActuallyEscaping is provided.
A variation of your case 2:
func someFunc( _ clsr: ()->Void) {
withoutActuallyEscaping(clsr) { clsr in
let clsr2 = {
clsr()
}
clsr2()
}
}
FYI, in some cases, if you change a local closure value to a local function, things will compile.