diff --git a/godot-core/src/builtin/callable.rs b/godot-core/src/builtin/callable.rs index a88ff657d..af482163b 100644 --- a/godot-core/src/builtin/callable.rs +++ b/godot-core/src/builtin/callable.rs @@ -205,8 +205,8 @@ impl Callable { /// Returns the object on which this callable is called. /// - /// Returns `None` when this callable doesn't have any target object to call a method on, regardless of - /// if the method exists for that target or not. + /// Returns `None` when this callable doesn't have any target object to call a method on (regardless of whether the method exists for that + /// target or not). Also returns `None` if the object is dead. You can differentiate these two cases using [`object_id()`][Self::object_id]. /// /// _Godot equivalent: `get_object`_ pub fn object(&self) -> Option> { @@ -222,6 +222,8 @@ impl Callable { /// /// Returns `None` when this callable doesn't have any target to call a method on. /// + /// If the pointed-to object is dead, the ID will still be returned. Use [`object()`][Self::object] to check for liveness. + /// /// _Godot equivalent: `get_object_id`_ pub fn object_id(&self) -> Option { let id = self.as_inner().get_object_id(); diff --git a/godot-core/src/builtin/signal.rs b/godot-core/src/builtin/signal.rs index 1e6393a11..4184a214a 100644 --- a/godot-core/src/builtin/signal.rs +++ b/godot-core/src/builtin/signal.rs @@ -121,7 +121,8 @@ impl Signal { /// Returns the object to which this signal belongs. /// - /// Returns [`None`] when this signal doesn't have any object. + /// Returns [`None`] when this signal doesn't have any object, or the object is dead. You can differentiate these two situations using + /// [`object_id()`][Self::object_id]. /// /// _Godot equivalent: `get_object`_ pub fn object(&self) -> Option> { @@ -135,6 +136,8 @@ impl Signal { /// /// Returns [`None`] when this signal doesn't have any object. /// + /// If the pointed-to object is dead, the ID will still be returned. Use [`object()`][Self::object] to check for liveness. + /// /// _Godot equivalent: `get_object_id`_ pub fn object_id(&self) -> Option { let id = self.as_inner().get_object_id(); diff --git a/itest/rust/src/builtin_tests/containers/callable_test.rs b/itest/rust/src/builtin_tests/containers/callable_test.rs index c5e6bded9..504391d91 100644 --- a/itest/rust/src/builtin_tests/containers/callable_test.rs +++ b/itest/rust/src/builtin_tests/containers/callable_test.rs @@ -67,13 +67,19 @@ fn callable_hash() { #[itest] fn callable_object_method() { - let obj = CallableTestObj::new_gd(); - let callable = obj.callable("foo"); + let object = CallableTestObj::new_gd(); + let object_id = object.instance_id(); + let callable = object.callable("foo"); - assert_eq!(callable.object(), Some(obj.clone().upcast::())); - assert_eq!(callable.object_id(), Some(obj.instance_id())); + assert_eq!(callable.object(), Some(object.clone().upcast::())); + assert_eq!(callable.object_id(), Some(object_id)); assert_eq!(callable.method_name(), Some("foo".into())); + // Invalidating the object still returns the old ID, however not the object. + drop(object); + assert_eq!(callable.object_id(), Some(object_id)); + assert_eq!(callable.object(), None); + assert_eq!(Callable::invalid().object(), None); assert_eq!(Callable::invalid().object_id(), None); assert_eq!(Callable::invalid().method_name(), None); diff --git a/itest/rust/src/builtin_tests/containers/signal_test.rs b/itest/rust/src/builtin_tests/containers/signal_test.rs index 19dcb8440..d7c860747 100644 --- a/itest/rust/src/builtin_tests/containers/signal_test.rs +++ b/itest/rust/src/builtin_tests/containers/signal_test.rs @@ -95,6 +95,7 @@ fn signals() { #[itest] fn instantiate_signal() { let mut object = RefCounted::new_gd(); + let object_id = object.instance_id(); object.add_user_signal("test_signal".into()); @@ -102,8 +103,13 @@ fn instantiate_signal() { assert!(!signal.is_null()); assert_eq!(signal.name(), StringName::from("test_signal")); - assert_eq!(signal.object().unwrap(), object.clone().upcast()); - assert_eq!(signal.object_id().unwrap(), object.instance_id()); + assert_eq!(signal.object(), Some(object.clone().upcast())); + assert_eq!(signal.object_id(), Some(object_id)); + + // Invalidating the object still returns the old ID, however not the object. + drop(object); + assert_eq!(signal.object_id(), Some(object_id)); + assert_eq!(signal.object(), None); } #[itest]