Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callables of static methods are not valid if accessed via the class's name #79521

Closed
jtnicholl opened this issue Jul 15, 2023 · 1 comment · Fixed by #82767
Closed

Callables of static methods are not valid if accessed via the class's name #79521

jtnicholl opened this issue Jul 15, 2023 · 1 comment · Fixed by #82767

Comments

@jtnicholl
Copy link
Contributor

Godot version

v4.1.stable.official [9704596], v4.1.1.rc1.official [e709ad4]

System information

Ubuntu 23.04

Issue description

4.1 introduced support for using static methods as callables. However, if the callable is accessed via the class's name, it is considered invalid. This makes using static methods from other classes as callables very difficult.

Steps to reproduce

class_name Test extends Node

static func static_func() -> void:
	pass

func _ready() -> void:
	print(Test.static_func.is_valid()) # prints false
	print(static_func.is_valid()) # prints true

Minimal reproduction project

ClassNameCallables.zip

@dalexeev
Copy link
Member

dalexeev commented Jul 16, 2023

class_name Test extends Node

static func static_func() -> String:
    return "static_func()"

func test_callable(c: Callable) -> void:
    print("object=%-32s is_standard=%-5s is_valid=%-5s result=%s" % [
            c.get_object(), c.is_standard(), c.is_valid(), c.call()])

func _ready() -> void:
    test_callable(Test.static_func)
    test_callable(Test.new().static_func)
    test_callable(static_func)
object=<GDScript#-9223372010329996131>  is_standard=true  is_valid=false result=static_func()
object=<Node#26843546782>               is_standard=true  is_valid=true  result=static_func()
object=Node:<Node#26776437914>          is_standard=true  is_valid=true  result=static_func()

In the case of a static method call on a class, the base object is the script. The problem is here:

bool Callable::is_valid() const {
if (is_custom()) {
return get_custom()->is_valid();
} else {
return get_object() && get_object()->has_method(get_method());
}
}

bool Object::has_method(const StringName &p_method) const {
if (p_method == CoreStringNames::get_singleton()->_free) {
return true;
}
if (script_instance && script_instance->has_method(p_method)) {
return true;
}
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
return method != nullptr;
}

These methods cannot be overridden:

godot/core/object/object.h

Lines 817 to 818 in a758388

bool has_method(const StringName &p_method) const;
void get_method_list(List<MethodInfo> *p_list) const;

I'm not sure if we should add the ability to override/customize the methods. We don't have _get_method_list() like _get_property_list(). This is a question for @godotengine/core. Probably the easiest way to solve this is to add a CallableCustom wrapper.

EDIT. I changed my mind. Having static methods in the script's method list would be useful and consistent with static variables (that are in the script's property list).

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment