Seemingly incorrect error about wrong type (number expected, got playdate.geometry.point), when completely unrelated variable changes

I'm getting this error from both my physical Playdate running 1.12.2 and the 1.12.2 PlaydateSimulator, and I cannot figure out why. Changes to a vector2d cause a call to math.floor, a call which doesn't involve the vector2d at all, directly or indirectly, to fail with this error:

Update error: main.lua:12: bad argument #1 to '(temp)' (number expected, got playdate.geometry.point)
stack traceback:
	[C]: in function 'math.floor'
	main.lua:12: in function <main.lua:6>

I'm using pdc 1.12.2 and PlaydateSimular 1.12.2 on Ubuntu 20.04.4 running on an Intel x86-64 system. I build my project with "pdc src Oddbehavior.pdx". I run it with "PlaydateSimulator Oddbehavior.pdx". The entire contents of src are pdxinfo and main.lua.

src/pdxinfo:

name=Odd behavior
author=Alan De Smet
description=Testing odd behavior
bundleID=com.highprogrammer.test-program
version=0.1
buildNumber=100

This version of the program works; the Playdate Console fills with "(0.0, 0.0)" 30 times or so per second:

src/main.lua: (working version)

local Point <const> = playdate.geometry.point
local Vector <const> = playdate.geometry.vector2D

TEST_SIZE = Point.new(0, 0)

function playdate.update()
	local max_cells = Vector.new(0,0)
	max_cells.dx -= 0
	max_cells.dy -= 0
	local second_point = Point.new(0, 0)
	second_point.x -= math.floor(TEST_SIZE.x)
	second_point.y -= math.floor(TEST_SIZE.y)
	print(second_point)
end

But a bunch of inexplicable things break it, generating this error. When things go wrong, they generate this error:

stack traceback:
	[C]: in function 'math.floor'
	main.lua:12: in function <main.lua:6>
Update error: main.lua:12: bad argument #1 to '(temp)' (number expected, got playdate.geometry.point)

Error case: Comment out both "max_cells.SOMETHING -= 0" lines. That should do nothing. And even if it did something, max_cells is never referenced again after yet. But it fails.

src/main.lua: (broken version)

local Point <const> = playdate.geometry.point
local Vector <const> = playdate.geometry.vector2D

TEST_SIZE = Point.new(0, 0)

function playdate.update()
	local max_cells = Vector.new(0,0)
	--max_cells.dx -= 0
	--max_cells.dy -= 0
	local second_point = Point.new(0, 0)
	second_point.x -= math.floor(TEST_SIZE.x)
	second_point.y -= math.floor(TEST_SIZE.y)
	print(second_point)
end

Alternatively, initialize max_cells using the full namespace to vector2D instead of the local alias and it fails:

src/main.lua: (broken version)

local Point <const> = playdate.geometry.point
local Vector <const> = playdate.geometry.vector2D

TEST_SIZE = Point.new(0, 0)

function playdate.update()
	local max_cells = playdate.geometry.vector2D.new(0,0)
	max_cells.dx -= 0
	max_cells.dy -= 0
	local second_point = Point.new(0, 0)
	second_point.x -= math.floor(TEST_SIZE.x)
	second_point.y -= math.floor(TEST_SIZE.y)
	print(second_point)
end

I have a feeling this has to do with our -= assignment operator, which is a Lua language extension.

If you replace all occurrences of x -= y with x = x - y, does the crash go away?

Indeed, that seems to work:

local Point <const> = playdate.geometry.point
local Vector <const> = playdate.geometry.vector2D

TEST_SIZE = Point.new(0, 0)

function playdate.update()
	local max_cells = Vector.new(0,0)
	--max_cells.dx -= 0
	--max_cells.dy -= 0
	local second_point = Point.new(0, 0)
	second_point.x = second_point.x - math.floor(TEST_SIZE.x)
	second_point.y = second_point.y - math.floor(TEST_SIZE.y)
	print(second_point)
end

Oddly, my original "working" version... no longer works. I'm pretty sure it was working. I tested that over-and-over as I was worked to create a minimal example. To take a very wild guess, perhaps there is use of uninitialized or corrupted memory going on in the interpreter or compiler.

Yeah, looks like a compiler bug. We'll fix it, but for now I guess just avoid using -= in this particular situation. Thanks for letting us know!

3 Likes

Found it! It's a side effect of a "fix" I added January 2021 in 1.0.3. :flushed: The problem is it thinks it needs to preserve more stack slots than it really does (the previous bug was because it wasn't saving enough) so the floor() call winds up as math.floor(TEST_SIZE, TEST_SIZE.x) when it's in the compound operator.

MR is filed, should be fixed in 1.13 I expect?

1 Like