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.
diff --git a/lstate.h b/lstate.h
index c1283bb..44cf939 100644
--- a/lstate.h
+++ b/lstate.h
@@ -165,7 +165,7 @@
 ** - field 'nyield' is used only while a function is "doing" an
 ** yield (from the yield until the next resume);
 ** - field 'nres' is used only while closing tbc variables when
-** returning from a C function;
+** returning from a function;
 ** - field 'transferinfo' is used only during call/returnhooks,
 ** before the function starts or after it ends.
 */
diff --git a/lvm.c b/lvm.c
index 16e01d6..e4b1903 100644
--- a/lvm.c
+++ b/lvm.c
@@ -847,10 +847,19 @@
       luaV_concat(L, total);  /* concat them (may yield again) */
       break;
     }
-    case OP_CLOSE:  case OP_RETURN: {  /* yielded closing variables */
+    case OP_CLOSE: {  /* yielded closing variables */
       ci->u.l.savedpc--;  /* repeat instruction to close other vars. */
       break;
     }
+    case OP_RETURN: {  /* yielded closing variables */
+      StkId ra = base + GETARG_A(inst);
+      /* adjust top to signal correct number of returns, in case the
+         return is "up to top" ('isIT') */
+      L->top = ra + ci->u2.nres;
+      /* repeat instruction to close other vars. and complete the return */
+      ci->u.l.savedpc--;
+      break;
+    }
     default: {
       /* only these other opcodes can yield */
       lua_assert(op == OP_TFORCALL || op == OP_CALL ||
@@ -1672,6 +1681,7 @@
           n = cast_int(L->top - ra);  /* get what is available */
         savepc(ci);
         if (TESTARG_k(i)) {  /* may there be open upvalues? */
+          ci->u2.nres = n;  /* save number of returns */
           if (L->top < ci->top)
             L->top = ci->top;
           luaF_close(L, base, CLOSEKTOP, 1);
diff --git a/testes/locals.lua b/testes/locals.lua
index 6aad5d2..6151f64 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -814,6 +814,65 @@
 
 
 do
+  -- yielding inside closing metamethods while returning
+  -- (bug in 5.4.3)
+
+  local extrares    -- result from extra yield (if any)
+
+  local function check (body, extra, ...)
+    local t = table.pack(...)   -- expected returns
+    local co = coroutine.wrap(body)
+    if extra then
+      extrares = co()    -- runs until first (extra) yield
+    end
+    local res = table.pack(co())   -- runs until yield inside '__close'
+    assert(res.n == 2 and res[2] == nil)
+    local res2 = table.pack(co())   -- runs until end of function
+    assert(res2.n == t.n)
+    for i = 1, #t do
+      if t[i] == "x" then
+        assert(res2[i] == res[1])    -- value that was closed
+      else
+        assert(res2[i] == t[i])
+      end
+    end
+  end
+
+  local function foo ()
+    local x <close> = func2close(coroutine.yield)
+    local extra <close> = func2close(function (self)
+      assert(self == extrares)
+      coroutine.yield(100)
+    end)
+    extrares = extra
+    return table.unpack{10, x, 30}
+  end
+  check(foo, true, 10, "x", 30)
+  assert(extrares == 100)
+
+  local function foo ()
+    local x <close> = func2close(coroutine.yield)
+    return
+  end
+  check(foo, false)
+
+  local function foo ()
+    local x <close> = func2close(coroutine.yield)
+    local y, z = 20, 30
+    return x
+  end
+  check(foo, false, "x")
+
+  local function foo ()
+    local x <close> = func2close(coroutine.yield)
+    local extra <close> = func2close(coroutine.yield)
+    return table.unpack({}, 1, 100)   -- 100 nils
+  end
+  check(foo, true, table.unpack({}, 1, 100))
+
+end
+
+do
   -- yielding inside closing metamethods after an error
 
   local co = coroutine.wrap(function ()