Output changes depending on optimization level

--!optimize 0

local function create(secret)
	local o = { secret = secret }
	setmetatable(o, {
		__eq = function(a, b)
			return a.secret == b.secret
		end
	})
	return o
end

print(create("abc") == create("abc")) -- false
--!optimize 1

local function create(secret)
	local o = { secret = secret }
	setmetatable(o, {
		__eq = function(a, b)
			return a.secret == b.secret
		end
	})
	return o
end

print(create("abc") == create("abc")) -- true
--!optimize 2

local function create(secret)
	local o = { secret = secret }
	setmetatable(o, {
		__eq = function(a, b)
			return a.secret == b.secret
		end
	})
	return o
end

print(create("abc") == create("abc")) -- true

Expected behavior

All optimization levels should produce the same output.

Thank you for the report.

This behavior is by design.

All optimization levels should produce the same output.

Luau does not provide this guarantee.

Can there be at least a warning or have this behavior documented?

Can you elaborate why that is the case?

1 Like

The requirements for the equality are already explained in that link, in particular the footnote about the equality of the metamethods.

To improve performance Luau compiler is allowed to make additional optimizations even if they affect how program is being executed.

In this particular case, Luau does not provide a guarantee that each closure will be unique as it is generally wasteful and also a bad fit to use as unique tokens How we make Luau fast | Luau

Since object equality is defined to rely on metamethods being the same, the closure identity being undefined has this visible behavior difference.

2 Likes