summaryrefslogtreecommitdiff
path: root/testes/locals.lua
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-25 12:50:20 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-25 12:50:20 -0300
commit41c800b352149e037bdebd5f20d2f25ed2a0e2a5 (patch)
tree740a459fd69d687dfe200fc91762208079e0c25b /testes/locals.lua
parent0a9aca56caa925c42aaa683b43560357ab736ea4 (diff)
downloadlua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.tar.gz
lua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.tar.bz2
lua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.zip
Closing methods should not interfere with returning values
A closing method cannot be called in its own stack slot, as there may be returning values in the stack after that slot, and the call would corrupt those values. Instead, the closing method must be copied to the top of the stack to be called. Moreover, even when a function returns no value, its return istruction still has to have its position (which will set the stack top) after the local variables, otherwise a closing method might corrupt another not-yet-called closing method.
Diffstat (limited to 'testes/locals.lua')
-rw-r--r--testes/locals.lua55
1 files changed, 54 insertions, 1 deletions
diff --git a/testes/locals.lua b/testes/locals.lua
index f21fa2ec..65b145db 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -175,6 +175,9 @@ assert(x==20)
175 175
176print"testing to-be-closed variables" 176print"testing to-be-closed variables"
177 177
178local function stack(n) n = ((n == 0) or stack(n - 1)) end
179
180
178do 181do
179 local a = {} 182 local a = {}
180 do 183 do
@@ -187,6 +190,57 @@ do
187 assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out") 190 assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out")
188end 191end
189 192
193do
194 local X = false
195
196 local function closescope () stack(10); X = true end
197
198 -- closing functions do not corrupt returning values
199 local function foo (x)
200 local scoped _ = closescope
201 return x, X, 23
202 end
203
204 local a, b, c = foo(1.5)
205 assert(a == 1.5 and b == false and c == 23 and X == true)
206
207 X = false
208 foo = function (x)
209 local scoped _ = closescope
210 local y = 15
211 return y
212 end
213
214 assert(foo() == 15 and X == true)
215
216 X = false
217 foo = function ()
218 local scoped x = closescope
219 return x
220 end
221
222 assert(foo() == closescope and X == true)
223
224end
225
226
227do
228 -- to-be-closed variables must be closed in tail calls
229 local X, Y
230 local function foo ()
231 local scoped _ = function () Y = 10 end
232 assert(X == 20 and Y == nil)
233 return 1,2,3
234 end
235
236 local function bar ()
237 local scoped _ = function () X = 20 end
238 return foo()
239 end
240
241 local a, b, c, d = bar()
242 assert(a == 1 and b == 2 and c == 3 and X == 20 and Y == 10 and d == nil)
243end
190 244
191do -- errors in __close 245do -- errors in __close
192 local log = {} 246 local log = {}
@@ -211,7 +265,6 @@ do -- errors in __close
211end 265end
212 266
213if rawget(_G, "T") then 267if rawget(_G, "T") then
214 local function stack(n) n = (n == 0) or stack(n - 1); end;
215 -- memory error inside closing function 268 -- memory error inside closing function
216 local function foo () 269 local function foo ()
217 local scoped y = function () T.alloccount() end 270 local scoped y = function () T.alloccount() end