aboutsummaryrefslogtreecommitdiff
path: root/testes/locals.lua
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-31 10:43:51 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-31 10:43:51 -0300
commitf645d3157372c73573dff221c5b26691cb0e7d56 (patch)
tree61adb1f332bbd8c0c0365b81cef8de47fa2ea06a /testes/locals.lua
parent35b4efc270db2418bc2cac6671575a45028061c3 (diff)
downloadlua-f645d3157372c73573dff221c5b26691cb0e7d56.tar.gz
lua-f645d3157372c73573dff221c5b26691cb0e7d56.tar.bz2
lua-f645d3157372c73573dff221c5b26691cb0e7d56.zip
To-be-closed variables must be closed on initialization
When initializing a to-be-closed variable, check whether it has a '__close' metamethod (or is a false value) and raise an error if if it hasn't. This produces more accurate error messages. (The check before closing still need to be done: in the C API, the value is not constant; and the object may lose its '__close' metamethod during the block.)
Diffstat (limited to '')
-rw-r--r--testes/locals.lua23
1 files changed, 12 insertions, 11 deletions
diff --git a/testes/locals.lua b/testes/locals.lua
index 3b145ca3..6eb1ba0e 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -215,11 +215,13 @@ end
215do 215do
216 local a = {} 216 local a = {}
217 do 217 do
218 local b <close> = false -- not to be closed
218 local x <close> = setmetatable({"x"}, {__close = function (self) 219 local x <close> = setmetatable({"x"}, {__close = function (self)
219 a[#a + 1] = self[1] end}) 220 a[#a + 1] = self[1] end})
220 local w, y <close>, z = func2close(function (self, err) 221 local w, y <close>, z = func2close(function (self, err)
221 assert(err == nil); a[#a + 1] = "y" 222 assert(err == nil); a[#a + 1] = "y"
222 end, 10, 20) 223 end, 10, 20)
224 local c <close> = nil -- not to be closed
223 a[#a + 1] = "in" 225 a[#a + 1] = "in"
224 assert(w == 10 and z == 20) 226 assert(w == 10 and z == 20)
225 end 227 end
@@ -325,24 +327,22 @@ do -- errors in __close
325end 327end
326 328
327 329
328do 330do -- errors due to non-closable values
329
330 -- errors due to non-closable values
331 local function foo () 331 local function foo ()
332 local x <close> = {} 332 local x <close> = {}
333 os.exit(false) -- should not run
333 end 334 end
334 local stat, msg = pcall(foo) 335 local stat, msg = pcall(foo)
335 assert(not stat and string.find(msg, "variable 'x'")) 336 assert(not stat and
337 string.find(msg, "variable 'x' got a non%-closable value"))
336 338
337
338 -- with other errors, non-closable values are ignored
339 local function foo () 339 local function foo ()
340 local x <close> = 34 340 local xyz <close> = setmetatable({}, {__close = print})
341 local y <close> = func2close(function () error(32) end) 341 getmetatable(xyz).__close = nil -- remove metamethod
342 end 342 end
343 local stat, msg = pcall(foo) 343 local stat, msg = pcall(foo)
344 assert(not stat and msg == 32) 344 assert(not stat and
345 345 string.find(msg, "attempt to close non%-closable variable 'xyz'"))
346end 346end
347 347
348 348
@@ -519,7 +519,8 @@ end
519-- a suspended coroutine should not close its variables when collected 519-- a suspended coroutine should not close its variables when collected
520local co 520local co
521co = coroutine.wrap(function() 521co = coroutine.wrap(function()
522 local x <close> = function () os.exit(false) end -- should not run 522 -- should not run
523 local x <close> = func2close(function () os.exit(false) end)
523 co = nil 524 co = nil
524 coroutine.yield() 525 coroutine.yield()
525end) 526end)