Odd behaviour when passing Callables as parameters

Godot Version

4.6.3

Question

I was trying to clean up the animation queue for my game and ran into the following behaviour that I cannot for the life of me explain. I made a very simple class to wrap queueable methods and be able to wait for multiple concurrent things (which may, but need not, be animations) to finish.

class_name Action extends Node

var callback: Callable
var arguments: Array

signal finished

func _init(
	cb: Callable,
	...args
) -> void:
	self.callback = cb
	self.arguments = args


func do() -> void:
	await callback.callv(arguments)
	finished.emit()

Consider now the following two scripts. Script A:

var function = func(): print("hi")
var a = Action.new(function, [])
a.do()

Script B:

var function = func(): print("hi")
var a = Action.new(func(): function.callv([]))
a.do()

These should be equivalent, no? However, script B prints “hi”, while script A has no output.

How can this be? Why would I have to wrap my callback into an anonymous lambda that does literally nothing except make my code harder to read?

Wouldn’t that be because you’re passing an empty array [ ] in scipt A. If you also pass an empty array [ ] in scipt B, what happens?

Should leaving the variadic part of the function call empty not automatically assign an empty array?

Never mind, I am dumb. Obviously I was making a nested “empty” array, and then due to the outstanding bug with callv, the callback silently failed. I wish that would get resolved so the engine would check me for stupid things like this.

(Issue #69237 if you are interested.)

For anyone stumbling over this in their searches: always use bindv instead of callv until the mentioned bug is resolved.