Any closure that is not explicitly marked as @escaping is non-escaping. Why would the @escaping attribute exist if non-escaping closures didn't exist? What would be the point?
The reason why the above code compiles is because the closure does not escape the test function.
That only applies to function/method/closure parameters. All struct/class members are (necessarily) escaping by default, and so are the enum's associated values. For local variables, non-contexted closures are escaping by default.
What I do not know is the existence of non-escaping local closure variables. It is theoretically possible, but I don't recall any formal proposal (and feel like it might be needed, given the code below could cause confusion), hence the question.
We have non-escaping closure parameters, which is the default. But, unfortunately, that is irrelevant since my question is about local variables.
That is not exactly an ideal explanation, given the compiler fails to realize that y below never escapes the test function:
func x(y: () -> ()) {
// Error: Passing non-escaping parameter 'y' to
// function expecting an @escaping closure
let z = y ?? {}
}
Thanks for the link. It is indeed the case that my code may be using an optional promotion or casting to a generic type, either of which may escape. However, it is just a contrived example of why "intuitively" looking at the code behaviour isn't the perfect way to figure out what the compiler is doing.
when compiled with -Ounchecked compiles down to return true (and you can also run it to see the same result), meaning that at some level the compiler considers the escaping and non-escaping types to be equivalent (caveats about withoutActuallyEscaping potentially causing weird behaviour aside). That might not be telling us much, though – it could just be that e.g. @escaping doesn't get encoded into the mangled type name.