diff --git a/lcode.c b/lcode.c index 8b61d5de..791ec02e 100644 --- a/lcode.c +++ b/lcode.c @@ -1542,15 +1542,19 @@ static void codebinK (FuncState *fs, BinOpr opr, /* Try to code a binary operator negating its second operand. ** For the metamethod, 2nd operand must keep its original value. +** As a special case, avoid the optimization for (exp - 0), because +** (-0.0 - 0) is -0.0, while (-0.0 + 0) is +0.0. */ static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, - OpCode op, int line, TMS event) { + OpCode op, int line, TMS event) { if (!isKint(e2)) return 0; /* not an integer constant */ else { lua_Integer i2 = e2->u.ival; if (!(fitsC(i2) && fitsC(-i2))) return 0; /* not in the proper range */ + if (event == TM_SUB && i2 == 0) + return 0; /* do not optimize (exp - 0) */ else { /* operating a small integer constant */ int v2 = cast_int(i2); finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); diff --git a/testes/math.lua b/testes/math.lua index ab74676a..d09b4202 100644 --- a/testes/math.lua +++ b/testes/math.lua @@ -838,6 +838,11 @@ do local a1, a2, a3, a4, a5 = 0, 0, "\0\0\0\0\0\0\0\0", 0, "\0\0\0\0\0\0\0\0" assert(a1 == a2 and a2 == a4 and a1 ~= a3) assert(a3 == a5) + + -- Bug since 5.4: Results differ for constant 0 versus variable 0; + -- (mz - 0) should be -0.0, but it resulted in +0.0 + local zi = 0 + assert(1/(mz - 0) == 1/(mz - zi)) end