luau-lang / luau

A fast, small, safe, gradually typed embeddable scripting language derived from Lua
https://luau.org
MIT License
4.06k stars 381 forks source link

__eq metamethod does not work #1051

Closed DimitarBogdanov closed 1 year ago

DimitarBogdanov commented 1 year ago

Hello! The __eq metamethod does not work, at all.

Sample code:

local t = setmetatable({}, {
    __eq = function()
        return true
    end,
})

print(t == {}) -- should print true, but prints false

The official Lua demo page correctly runs this code and outputs true, but Luau seems to be struggling with it. (tested on Luau 0.596-windows, latest at the time of writing) image

Also the case with Roblox (on a completely blank workspace): image

DimitarBogdanov commented 1 year ago

For completeness, the following two code samples do not work too:

local t = {}
setmetatable(t, {
    __eq = function()
        return true
    end,
})

print(t == {}) -- should print true, but prints false
local t = {}
t.__eq = function()
    return true
end

print(t == {}) -- should print true, but prints false
DimitarBogdanov commented 1 year ago

luau-compile output: https://gist.github.com/DimitarBogdanov/2c72dd31ef5ea465a50e8aca3ee15715 Edit: this is the output from the first code sample

DimitarBogdanov commented 1 year ago

I'm speculating here, but it seems that this would be the reason for the issue: Referenced in compileExprBinary, the compileCompareJump function doesn't seem to check if the type is a table when emitting.

Linked code:

// this is in an if statement which checks if the left value is a constant, which it isn't here
        else 
        {
            LuauOpcode opc = getJumpOpCompare(expr->op, not_);

            uint8_t rr = compileExprAuto(right, rs);

            size_t jumpLabel = bytecode.emitLabel();

            if (expr->op == AstExprBinary::CompareGt || expr->op == AstExprBinary::CompareGe)
            {
                bytecode.emitAD(opc, rr, 0);
                bytecode.emitAux(rl);
            }
            else
            {
                bytecode.emitAD(opc, rl, 0);
                bytecode.emitAux(rr);
            }

            return jumpLabel;
        }
    }
Someon1e commented 1 year ago

Screenshot_20230924-225908.png

DimitarBogdanov commented 1 year ago

Why is this the behavior? It's non-compliant to Lua - and not documented in the compatibility docs.

vegorov-rbx commented 1 year ago

Luau is based on Lua 5.1 and doesn't include all the changes from later versions. Luau is compliant to Lua 5.1 and 5.2 here.

image

We will update the compatibility document to note that this change from 5.3 is not supported.

DimitarBogdanov commented 1 year ago

This makes sense. Thank you.