godotengine / godotengine/godot
"Already connected" error when trying to connect signal to objects that are different but with same content
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
- Reproducible in v4.6.stable.official [89cea1439] and v4.5.1.stable.official [f62fdbde1]
### System information
Godot v4.6.stable - Windows 10 (build 19045) - Multi-window, 2 monitors - OpenGL 3 (Compatibility) - NVIDIA GeForce RTX 2060 (NVIDIA; 32.0.15.7242) - AMD Ryzen 5 3600X 6-Core Processor (12 threads) - 31.93 GiB memory
### Issue description
When connecting a signal to a callable on an object, I would expect that any two objects that are different objects can both be connected to the signal. However if the equality operator evaluates to true for two objects that aren't the same (e.g. arrays that have the same contents), it results in the following error: `Signal 'something' is already connected to given callable 'Array::erase' in that object.`
This issue was already raised in: https://github.com/godotengine/godot/issues/97044 but dismissed there with "you can't connect the same method of the same object to the same signal" which is not relevant here as these are clearly two different arrays, as testcase 0 and 5 in the script below thoroughly highlight.
There is no issue when two arrays that are already connected happen to contain the same elements at a later point. The only thing that doesn't work is connecting the signal while their contents are the same.
### Steps to reproduce
See here a script with testcases, highlighting the issue:
```
extends Node
signal something(args)
signal otherthing(args)
func _ready() -> void:
# testcase 0 (baseline)
var a = ["foo"]
var b = ["bar"]
something.connect(a.erase)
something.connect(b.erase)
# expectation: no error
# result: no error
# testcase 1
var empty1 = []
var empty2 = []
something.connect(empty1.erase)
something.connect(empty2.erase)
# expectation: no error
# result: already connected error
# testcase 3
var c = ["blub"]
var d = ["blub"]
something.connect(c.erase)
something.connect(d.erase)
# expectation: no error
# result: already connected error
# testcase 4
var e = ["floop"]
var f = []
f.append("floop")
something.connect(e.erase)
something.connect(f.erase)
# expectation: no error
# result: already connected error
# testcase 5
var first = ["this"]
var second = ["fine"]
something.connect(first.erase)
something.connect(second.erase)
first.erase("this")
first.append("fine")
something.emit("fine")
print("first:", first)
print("second:", second)
# expectation: no error, and both have "first" and "second" are empty in the end
# result: as expected
# testcase 6
var third = ["why"]
var fourth = ["why"]
something.connect(third.erase)
something.connect(fourth.erase)
something.emit("why")
print("third:", third)
print("fourth:", fourth)
# expectation: it let's me connect both with no error, and "third" and "fourth" are empty in the end
# result: error on the second connect, so when the signal is emitted, the element is only deleted from "third" but not "fourth"
#testcase 7
var v1 = Vector2(0, 0)
var v2 = Vector2(1, 0)
otherthing.connect(v1.angle_to)
otherthing.connect(v2.angle_to)
# expectation: no error
# result: no error
#testcase 8
var v3 = Vector2(0, 1)
var v4 = Vector2(0, 1)
otherthing.connect(v3.angle_to)
otherthing.connect(v4.angle_to)
# expectation: no error
# result: already connected error
#testcase 9
var m1 = {}
var m2 = {}
something.connect(Callable.create(m1, "erase"))
something.connect(Callable.create(m2, "erase"))
# expectation: no error
# result: already connected error
```
notably testcase 0, 5 and 7 are currently successful and well supported
### Minimal reproduction project (MRP)
attach the above script to a node and run the project
Contributor guide
Assessment
This issue has not been assessed yet.