Type specialisation happens at function calls, which is why the common function-barrier pattern arises.
Speculating a bit: what would be the issue with having some construct that enforces a type-specialisation for a block within the middle of a function? I.e. some statement that, when hit, would pause execution of the function, inspect the types of all variables used in the rest of the function, then specialise the rest of the function on those types.
Perhaps this kind of thing could be achieved quite easily with some macro that generates a closure? Not sure if a closure would have some overhead though - keen to hear from someone who knows this stuff well!
Here’s a simple solution using a macro and do-block syntax to automatically construct a closure which acts as a function barrier:
macro barrier(f, args...)
f.args[1].args = [args...]
esc(:($f($(args...))))
end
function f(x::Int, n::Int)
y = ntuple(_->x, n)
@barrier(y) do
z = zeros(y...)
z .+ n
end
end