src/Data/Ord.lua defines a single comparison helper and reuses it for every type:
local unsafeCoerceImpl = function(lt)
return function(eq)
return function(gt)
return function(x)
return function(y)
if x < y then
return lt
elseif x == y then
return eq
else
return gt
end
end
end
end
end
end
return {
ordBooleanImpl = (unsafeCoerceImpl),
...
}
For Int, Number, String and Char the < operator is well defined in Lua, so reusing the helper is fine. For Boolean it is not. Lua 5.1 (the pslua target) raises a runtime error on relational operators between booleans:
$ lua -e 'print(pcall(function() return false < true end))'
false (command line):1: attempt to compare two boolean values
So any use of Ord Boolean (compare, <, <=, min, max, clamp) crashes at runtime instead of returning an ordering. The bug stays silent until a program actually compares two booleans.
Fix
Give ordBooleanImpl its own implementation that orders false < true without relying on <:
ordBooleanImpl = (function(lt)
return function(eq)
return function(gt)
return function(x)
return function(y)
if not x and y then
return lt
elseif x == y then
return eq
else
return gt
end
end
end
end
end
end),
A working implementation already exists in @UnrelatedString's #3. It will be carried over from there with credit as part of the upstream-sync pass. The other ord*Impl aliases are correct and should stay on the shared helper.
Test coverage
The fix must ship with a regression test that fails on the current alias and passes after the fix: assert compare false true == LT, compare true false == GT, compare true true == EQ, and that min/max on Boolean do not error. This belongs in the prelude test suite being revived during upstream-sync. Without it the crash can regress unnoticed, since luacheck does not exercise the comparison.
src/Data/Ord.luadefines a single comparison helper and reuses it for every type:For Int, Number, String and Char the
<operator is well defined in Lua, so reusing the helper is fine. For Boolean it is not. Lua 5.1 (the pslua target) raises a runtime error on relational operators between booleans:So any use of
Ord Boolean(compare,<,<=,min,max,clamp) crashes at runtime instead of returning an ordering. The bug stays silent until a program actually compares two booleans.Fix
Give
ordBooleanImplits own implementation that ordersfalse < truewithout relying on<:A working implementation already exists in @UnrelatedString's #3. It will be carried over from there with credit as part of the upstream-sync pass. The other
ord*Implaliases are correct and should stay on the shared helper.Test coverage
The fix must ship with a regression test that fails on the current alias and passes after the fix: assert
compare false true == LT,compare true false == GT,compare true true == EQ, and thatmin/maxon Boolean do not error. This belongs in the prelude test suite being revived during upstream-sync. Without it the crash can regress unnoticed, since luacheck does not exercise the comparison.