diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-04-16 15:41:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-04-16 15:41:44 -0300 |
commit | 681297187ec45268e872b26753c441586c12bdd8 (patch) | |
tree | 90e62c82146470a4c4931801a36f66de0bc92318 /testes | |
parent | 5148954eed7550dcac587fce0214b470442efa0d (diff) | |
download | lua-681297187ec45268e872b26753c441586c12bdd8.tar.gz lua-681297187ec45268e872b26753c441586c12bdd8.tar.bz2 lua-681297187ec45268e872b26753c441586c12bdd8.zip |
Bug: yielding in '__close' mess up number of returns
Yielding in a __close metamethod called when returning vararg results
changes the top and so messes up the number of returned values.
Diffstat (limited to 'testes')
-rw-r--r-- | testes/locals.lua | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/testes/locals.lua b/testes/locals.lua index 6aad5d25..6151f64d 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
@@ -814,6 +814,65 @@ end | |||
814 | 814 | ||
815 | 815 | ||
816 | do | 816 | do |
817 | -- yielding inside closing metamethods while returning | ||
818 | -- (bug in 5.4.3) | ||
819 | |||
820 | local extrares -- result from extra yield (if any) | ||
821 | |||
822 | local function check (body, extra, ...) | ||
823 | local t = table.pack(...) -- expected returns | ||
824 | local co = coroutine.wrap(body) | ||
825 | if extra then | ||
826 | extrares = co() -- runs until first (extra) yield | ||
827 | end | ||
828 | local res = table.pack(co()) -- runs until yield inside '__close' | ||
829 | assert(res.n == 2 and res[2] == nil) | ||
830 | local res2 = table.pack(co()) -- runs until end of function | ||
831 | assert(res2.n == t.n) | ||
832 | for i = 1, #t do | ||
833 | if t[i] == "x" then | ||
834 | assert(res2[i] == res[1]) -- value that was closed | ||
835 | else | ||
836 | assert(res2[i] == t[i]) | ||
837 | end | ||
838 | end | ||
839 | end | ||
840 | |||
841 | local function foo () | ||
842 | local x <close> = func2close(coroutine.yield) | ||
843 | local extra <close> = func2close(function (self) | ||
844 | assert(self == extrares) | ||
845 | coroutine.yield(100) | ||
846 | end) | ||
847 | extrares = extra | ||
848 | return table.unpack{10, x, 30} | ||
849 | end | ||
850 | check(foo, true, 10, "x", 30) | ||
851 | assert(extrares == 100) | ||
852 | |||
853 | local function foo () | ||
854 | local x <close> = func2close(coroutine.yield) | ||
855 | return | ||
856 | end | ||
857 | check(foo, false) | ||
858 | |||
859 | local function foo () | ||
860 | local x <close> = func2close(coroutine.yield) | ||
861 | local y, z = 20, 30 | ||
862 | return x | ||
863 | end | ||
864 | check(foo, false, "x") | ||
865 | |||
866 | local function foo () | ||
867 | local x <close> = func2close(coroutine.yield) | ||
868 | local extra <close> = func2close(coroutine.yield) | ||
869 | return table.unpack({}, 1, 100) -- 100 nils | ||
870 | end | ||
871 | check(foo, true, table.unpack({}, 1, 100)) | ||
872 | |||
873 | end | ||
874 | |||
875 | do | ||
817 | -- yielding inside closing metamethods after an error | 876 | -- yielding inside closing metamethods after an error |
818 | 877 | ||
819 | local co = coroutine.wrap(function () | 878 | local co = coroutine.wrap(function () |