godot icon indicating copy to clipboard operation
godot copied to clipboard

GDScript 2.0: Static typing on signals isn't enforced

Open AaronRecord opened this issue 3 years ago • 12 comments

Godot version

v4.0.dev.custom_build [a851012b1]

System information

Windows 10

Issue description

The following code:

signal test(a: Node2D, b: Camera3D)

func _ready():
	test.connect(func(a, b): print(a + b))
	test.emit(Vector2.UP, Vector2.RIGHT)

compiles without any errors, and prints (1, -1).


It should produce an error, something like:

Invalid argument for "emit()" function: argument 1 should be Node2D but is Vector2.
Invalid argument for "emit()" function: argument 2 should be Camera3D but is Vector2.

Steps to reproduce

See above.

Minimal reproduction project

No response

AaronRecord avatar Oct 28 '21 02:10 AaronRecord

Duplicate of https://github.com/godotengine/godot-proposals/issues/2557.

akien-mga avatar Oct 28 '21 07:10 akien-mga

Duplicate of godotengine/godot-proposals#2557.

I was aware of that issue, the weird part is that is accepts type arguments without complaint, it just doesn't use them. On 3.x you get an error if you try to add types to signal arguments. So if this won't be supported for 4.0 then the ability to add types to signal arguments should be removed.

AaronRecord avatar Oct 28 '21 13:10 AaronRecord

See also https://github.com/godotengine/godot/pull/52083#issuecomment-934350865.

Calinou avatar Oct 28 '21 14:10 Calinou

See also https://github.com/godotengine/godot-proposals/issues/2557#issuecomment-815645240.

dalexeev avatar Nov 20 '21 15:11 dalexeev

See also godotengine/godot-proposals#2557 (comment).

Okay, but at the very least this limitation should be documented before this issue is closed, otherwise it's quite counterintuitive as many users will expect the types to be enforced.

AaronRecord avatar Nov 20 '21 16:11 AaronRecord

@vnen I would push this issue to 4.x or 4.1

adamscott avatar Feb 24 '23 17:02 adamscott

Bumping this as relatively important for the following reason:

When checking the types for the argument list of a signal against those of the parameter list for a potential method that will connect.

In this instance, for every built-in signal there are types, for custom signals the types are all '0'. This is inconsistent behaviour as custom signals should have the same functionality as built in signals.

qaptoR avatar Apr 11 '23 01:04 qaptoR

This is inconsistent behaviour as custom signals should have the same functionality as built in signals.

There is no protection for built-in signals either, you can emit a signal with any arguments. The only "protection" is callback type hints. The difference from built-in signals is that the editor does not currently use this information when generating a custom signal callback. But this can be considered a bug that we need to fix.

extends Node

func _ready() -> void:
    child_entered_tree.connect(_on_child_entered_tree)
    child_entered_tree.emit(42, [], NAN) # No error.

#func _on_child_entered_tree(node: Node) -> void:
#    pass

func _on_child_entered_tree(a, b, c) -> void:
    prints(a, b, c)

dalexeev avatar Apr 11 '23 08:04 dalexeev

In this instance, for every built-in signal there are types, for custom signals the types are all '0'. This is inconsistent behaviour as custom signals should have the same functionality as built in signals.

BTW this isn't related to enforcing types on signals, this is only because script info is not being populated properly for all the get_*() functions. It's the same problem as #67544

vnen avatar Apr 11 '23 12:04 vnen

Wanted to chime in with an example as to why this feature is important. I had the following code:

# event_bus.gd
signal on_update_letters(word: String, letters: Array[bool])

# level.gd
func _ready():
	var word = "ICY"
	var letters = [false, false, false]
	EventBus.on_update_letters.emit(word, letters)

# level_ui.gd
func _ready():
	EventBus.connect("on_update_letters", on_update_letters)

func on_update_letters(word: String, letters: Array[bool]):
	print("This should get printed, but it never gets invoked")

Can you spot the bug?

on_update_letters in level_ui.gd never gets called because letters in level.gd is NOT an Array[bool]. Don't know why, honestly, but changing that line to var letters: Array[bool] = [false, false, false] resolves the issue.

It's way too easy for minor type mistakes to lead to silent failures, and they're extremely annoying to debug. I haven't had to do any refactoring work around signals yet, but I'd bet my bottom dollar that it can be a similarly frustrating debugging experience.

Calling emit on a signal with params that do not match the types in its declaration shouldn't fail silently.

FabriceCastel avatar Jan 29 '24 18:01 FabriceCastel

So, this is not really a bug. It could be changed but it is like so by design because the core never enforced types either. The types you can set are only for documentation purposes, at least for now, the same as they are in core.

vnen avatar Feb 08 '24 13:02 vnen

The difference from built-in signals is that the editor does not currently use this information when generating a custom signal callback. But this can be considered a bug that we need to fix.

Fixed in #79366 and others.

  • See also godotengine/godot-proposals#2557.

dalexeev avatar Feb 08 '24 13:02 dalexeev