Lua 5.5 - for loop variables
In the current version of Teal this is valid:
local t: {integer: integer} = { [2] = 4}
for k, v in pairs(t) do
k = k * 2
assert(k == v)
end
This will warn:
local t: {integer: integer} = { [2] = 4}
for k, v in pairs(t) do
local k = k * 2
assert(k == v)
end
foo.tl:3:9: variable shadows previous declaration of 'k' (originally declared at 2:5)
In Lua 5.5 the first snippet is invalid and the second one will become a common idiom as it has been suggested by Roberto.
For an example of a code base needing this kind of change see https://github.com/luarocks/luarocks/pull/1844
How should Teal deal with this change?
I wonder if Teal should have a <shadow> annotation to allow variable shadowing, they're useful sometimes.
(Also, multi annotation, like <const, shadow>)
Good questions. In Rust, for example, variable shadowing is super common, when extracting values from Options, etc. Given a statically-typed language, shadowing a variable is less often a mistake (because when it's a mistake they often have different types and the compiler catches misuses). Unlike Rust, Teal does (a little bit of) flow typing, so there ought to be less of that if let Some(foo) = foo shadowing that you see in Rust.
One simple option would be to lift Lua 5.5's restriction, and just translate for k, v in exp do block end to for k, v in exp do local k = k; block end (and we could do that efficiently, i.e., only when needed). That would produce Lua 5.3 semantics, if I'm not mistaken. In the 5.3 manual, the semantics of generic for state that writing to the control variable doesn't modify the loop:
https://www.lua.org/manual/5.3/manual.html#3.3.5
A for statement likefor var_1, ···, var_n in explist do block endis equivalent to the code:
do local f, s, var = explist while true do local var_1, ···, var_n = f(s, var) if var_1 == nil then break end var = var_1 block end end
The Lua 5.4 mysteriously says "You should not change the value of the control variable during the loop" but doesn't specify what happens. The 5.3 manual specification above seems to show that assigning to var_1 will not affect the internal variable var which actually controls the loop.