You didn't look hard enough.
By default, a nested function may access non-dynamic local and static variables of any function which encloses it, but not ByRef parameters
or variables which are created dynamically.
Source: Nested Functions
In AutoHotkey, all non-dynamic variable references are resolved at the moment the script launches, including local variables
. Each function has one set of local variables which exist from the moment the script launches until it exits. The code within the function contains pointers to these variables. Recursion is handled by backing up the local variables when a second layer of the function begins and restoring them after it returns, so at any one time, the local variables belong to the top layer of the function.
Closures may be associated with any layer of a function still running, or a set of variables from a function which has since returned. So obviously, they can't refer to the "top-layer" local variables described above. What they need are "free variables", which are not tied to the top layer of the function, are not freed when the function returns, and are able to exist for as long as a closure refers to them.
Closures are implemented by detecting which variables need to be "free variables", allocating those when the outer
function begins, and turning the top-layer variables in the outer and inner function into aliases of the free variables. ByRef parameters, on the other hand, accept a reference to a variable which may or may not be "free". It is impossible to tell (with certainty) at load time whether a variable is going to be passed to a ByRef parameter, since functions can be called dynamically or via objects. At the time the closure is created, it is impossible to tell which function the variable came from, and too late to convert it into a free variable.
The only feasible solution within the current framework would be to make all
local variables "free", but this would reduce performance for the majority of scripts. ByRef parameters could be allowed within a limited context (when the nested function is called directly, not via a closure), but that requires either greater complexity to detect when it is used incorrectly, or allowing incorrect usages which behave counter-intuitively (the parameter behaving as non-ByRef or referring to the wrong variable).