diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 7b9aa70686a..69615994c3c 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1505,14 +1505,15 @@ GDScript::UpdatableFuncPtr::~UpdatableFuncPtr() { } void GDScript::_recurse_replace_function_ptrs(const HashMap &p_replacements) const { - MutexLock lock(func_ptrs_to_update_mutex); - for (UpdatableFuncPtr *updatable : func_ptrs_to_update) { - HashMap::ConstIterator replacement = p_replacements.find(updatable->ptr); - if (replacement) { - updatable->ptr = replacement->value; - } else { - // Probably a lambda from another reload, ignore. - updatable->ptr = nullptr; + { + MutexLock lock(func_ptrs_to_update_mutex); + for (UpdatableFuncPtr *updatable : func_ptrs_to_update) { + HashMap::ConstIterator replacement = p_replacements.find(updatable->ptr); + if (replacement) { + updatable->ptr = replacement->value; + } else { + updatable->ptr = nullptr; + } } } diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 965bbe65e9b..cec361372ea 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -3110,129 +3110,113 @@ void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::Cl } } -GDScriptCompiler::FunctionLambdaInfo GDScriptCompiler::_get_function_replacement_info(GDScriptFunction *p_func, int p_index, int p_depth, GDScriptFunction *p_parent_func) { - FunctionLambdaInfo info; - info.function = p_func; - info.parent = p_parent_func; - info.script = p_func->get_script(); - info.name = p_func->get_name(); - info.line = p_func->_initial_line; - info.index = p_index; - info.depth = p_depth; - info.capture_count = 0; - info.use_self = false; - info.arg_count = p_func->_argument_count; - info.default_arg_count = p_func->_default_arg_count; - info.sublambdas = _get_function_lambda_replacement_info(p_func, p_depth, p_parent_func); - - ERR_FAIL_NULL_V(info.script, info); - GDScript::LambdaInfo *extra_info = info.script->lambda_info.getptr(p_func); - if (extra_info != nullptr) { - info.capture_count = extra_info->capture_count; - info.use_self = extra_info->use_self; - } else { - info.capture_count = 0; - info.use_self = false; - } - - return info; -} - -Vector GDScriptCompiler::_get_function_lambda_replacement_info(GDScriptFunction *p_func, int p_depth, GDScriptFunction *p_parent_func) { - Vector result; - // Only scrape the lambdas inside p_func. +void GDScriptCompiler::LambdaSourceInfoList::collect_function_lambda_replacement_info(GDScriptFunction *p_func) { + // Only collect the lambdas inside. for (int i = 0; i < p_func->lambdas.size(); ++i) { - result.push_back(_get_function_replacement_info(p_func->lambdas[i], i, p_depth + 1, p_func)); + GDScriptFunction *lambda = p_func->lambdas[i]; + LambdaSourceInfo &info = infos[lambda->get_name()].push_back({})->get(); + + info.function = lambda; + info.parent = p_func; + info.script = lambda->get_script(); + info.name = lambda->get_name(); + info.is_static = lambda->is_static(); + info.use_self = false; + info.capture_count = 0; + info.arg_count = lambda->get_argument_count(); + info.default_arg_count = lambda->get_default_argument_count(); + info.sublambdas.collect_function_lambda_replacement_info(lambda); + + if (info.script) { + GDScript::LambdaInfo *extra_info = info.script->lambda_info.getptr(lambda); + if (extra_info != nullptr) { + info.capture_count = extra_info->capture_count; + info.use_self = extra_info->use_self; + } else { + info.capture_count = 0; + info.use_self = false; + } + } } - return result; } -GDScriptCompiler::ScriptLambdaInfo GDScriptCompiler::_get_script_lambda_replacement_info(GDScript *p_script) { - ScriptLambdaInfo info; - +void GDScriptCompiler::ScriptLambdaInfo::collect_script_lambda_replacement_info(GDScript *p_script) { if (p_script->implicit_initializer) { - info.implicit_initializer_info = _get_function_lambda_replacement_info(p_script->implicit_initializer); + initializers.collect_function_lambda_replacement_info(p_script->implicit_initializer); } if (p_script->implicit_ready) { - info.implicit_ready_info = _get_function_lambda_replacement_info(p_script->implicit_ready); + initializers.collect_function_lambda_replacement_info(p_script->implicit_ready); } if (p_script->static_initializer) { - info.static_initializer_info = _get_function_lambda_replacement_info(p_script->static_initializer); + initializers.collect_function_lambda_replacement_info(p_script->static_initializer); } for (const KeyValue &E : p_script->member_functions) { - info.member_function_infos.insert(E.key, _get_function_lambda_replacement_info(E.value)); + member_functions[E.key].collect_function_lambda_replacement_info(E.value); } for (const KeyValue> &KV : p_script->get_subclasses()) { - info.subclass_info.insert(KV.key, _get_script_lambda_replacement_info(KV.value.ptr())); + subclasses[KV.key].collect_script_lambda_replacement_info(KV.value.ptr()); } - - return info; } -bool GDScriptCompiler::_do_function_infos_match(const FunctionLambdaInfo &p_old_info, const FunctionLambdaInfo *p_new_info) { - if (p_new_info == nullptr) { +bool GDScriptCompiler::LambdaSourceInfo::can_be_replaced_by(const LambdaSourceInfo &p_new_info) const { + if (p_new_info.capture_count != capture_count || p_new_info.use_self != use_self) { return false; } - if (p_new_info->capture_count != p_old_info.capture_count || p_new_info->use_self != p_old_info.use_self) { + if (p_new_info.script != script) { return false; } - int old_required_arg_count = p_old_info.arg_count - p_old_info.default_arg_count; - int new_required_arg_count = p_new_info->arg_count - p_new_info->default_arg_count; - if (new_required_arg_count > old_required_arg_count || p_new_info->arg_count < old_required_arg_count) { + int old_required_arg_count = arg_count - default_arg_count; + int new_required_arg_count = p_new_info.arg_count - p_new_info.default_arg_count; + if (new_required_arg_count > old_required_arg_count || p_new_info.arg_count < old_required_arg_count) { return false; } return true; } -void GDScriptCompiler::_get_function_ptr_replacements(HashMap &r_replacements, const FunctionLambdaInfo &p_old_info, const FunctionLambdaInfo *p_new_info) { - ERR_FAIL_COND(r_replacements.has(p_old_info.function)); - if (!_do_function_infos_match(p_old_info, p_new_info)) { - p_new_info = nullptr; - } +void GDScriptCompiler::_collect_function_ptr_replacements(HashMap &r_replacements, LambdaSourceInfoList &p_old, LambdaSourceInfoList *p_new) { + for (KeyValue> &old_named_infos : p_old.infos) { + HashMap>::Iterator new_named_infos_it = p_new->infos.find(old_named_infos.key); + bool sizes_equal = new_named_infos_it && new_named_infos_it->value.size() == old_named_infos.value.size(); - r_replacements.insert(p_old_info.function, p_new_info != nullptr ? p_new_info->function : nullptr); - _get_function_ptr_replacements(r_replacements, p_old_info.sublambdas, p_new_info != nullptr ? &p_new_info->sublambdas : nullptr); -} + List::Element *old_info_E = old_named_infos.value.front(); + List::Element *new_info_E = new_named_infos_it ? new_named_infos_it->value.front() : nullptr; -void GDScriptCompiler::_get_function_ptr_replacements(HashMap &r_replacements, const Vector &p_old_infos, const Vector *p_new_infos) { - for (int i = 0; i < p_old_infos.size(); ++i) { - const FunctionLambdaInfo &old_info = p_old_infos[i]; - const FunctionLambdaInfo *new_info = nullptr; - if (p_new_infos != nullptr && p_new_infos->size() == p_old_infos.size()) { - // For now only attempt if the size is the same. - new_info = &p_new_infos->get(i); + while (old_info_E) { + LambdaSourceInfo &old_info = old_info_E->get(); + LambdaSourceInfo *new_info = nullptr; + if (new_info_E && sizes_equal) { + new_info = &new_info_E->get(); + } + + if (new_info && old_info.can_be_replaced_by(*new_info)) { + r_replacements[old_info.function] = new_info->function; + } + + // This must be run on every `old_info.sublambdas` whether or not we have new info. + _collect_function_ptr_replacements(r_replacements, old_info.sublambdas, new_info ? &new_info->sublambdas : nullptr); + old_info_E = old_info_E->next(); + if (new_info_E) { + new_info_E = new_info_E->next(); + } } - _get_function_ptr_replacements(r_replacements, old_info, new_info); } } -void GDScriptCompiler::_get_function_ptr_replacements(HashMap &r_replacements, const ScriptLambdaInfo &p_old_info, const ScriptLambdaInfo *p_new_info) { - _get_function_ptr_replacements(r_replacements, p_old_info.implicit_initializer_info, p_new_info != nullptr ? &p_new_info->implicit_initializer_info : nullptr); - _get_function_ptr_replacements(r_replacements, p_old_info.implicit_ready_info, p_new_info != nullptr ? &p_new_info->implicit_ready_info : nullptr); - _get_function_ptr_replacements(r_replacements, p_old_info.static_initializer_info, p_new_info != nullptr ? &p_new_info->static_initializer_info : nullptr); +void GDScriptCompiler::_collect_function_ptr_replacements(HashMap &r_replacements, ScriptLambdaInfo &p_old_info, ScriptLambdaInfo *p_new_info) { + _collect_function_ptr_replacements(r_replacements, p_old_info.initializers, p_new_info ? &p_new_info->initializers : nullptr); - for (const KeyValue> &old_kv : p_old_info.member_function_infos) { - _get_function_ptr_replacements(r_replacements, old_kv.value, p_new_info != nullptr ? p_new_info->member_function_infos.getptr(old_kv.key) : nullptr); + for (KeyValue &old_kv : p_old_info.member_functions) { + _collect_function_ptr_replacements(r_replacements, old_kv.value, p_new_info ? p_new_info->member_functions.getptr(old_kv.key) : nullptr); } - for (int i = 0; i < p_old_info.other_function_infos.size(); ++i) { - const FunctionLambdaInfo &old_other_info = p_old_info.other_function_infos[i]; - const FunctionLambdaInfo *new_other_info = nullptr; - if (p_new_info != nullptr && p_new_info->other_function_infos.size() == p_old_info.other_function_infos.size()) { - // For now only attempt if the size is the same. - new_other_info = &p_new_info->other_function_infos[i]; - } - // Needs to be called on all old lambdas, even if there's no replacement. - _get_function_ptr_replacements(r_replacements, old_other_info, new_other_info); - } - for (const KeyValue &old_kv : p_old_info.subclass_info) { - const ScriptLambdaInfo &old_subinfo = old_kv.value; - const ScriptLambdaInfo *new_subinfo = p_new_info != nullptr ? p_new_info->subclass_info.getptr(old_kv.key) : nullptr; - _get_function_ptr_replacements(r_replacements, old_subinfo, new_subinfo); + for (KeyValue &old_kv : p_old_info.subclasses) { + ScriptLambdaInfo &old_subinfo = old_kv.value; + ScriptLambdaInfo *new_subinfo = p_new_info ? p_new_info->subclasses.getptr(old_kv.key) : nullptr; + _collect_function_ptr_replacements(r_replacements, old_subinfo, new_subinfo); } } @@ -3246,7 +3230,8 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri source = p_script->get_path(); - ScriptLambdaInfo old_lambda_info = _get_script_lambda_replacement_info(p_script); + ScriptLambdaInfo old_lambda_info; + old_lambda_info.collect_script_lambda_replacement_info(p_script); // Create scripts for subclasses beforehand so they can be referenced make_scripts(p_script, root, p_keep_state); @@ -3263,10 +3248,11 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri return err; } - ScriptLambdaInfo new_lambda_info = _get_script_lambda_replacement_info(p_script); + ScriptLambdaInfo new_lambda_info; + new_lambda_info.collect_script_lambda_replacement_info(p_script); HashMap func_ptr_replacements; - _get_function_ptr_replacements(func_ptr_replacements, old_lambda_info, &new_lambda_info); + _collect_function_ptr_replacements(func_ptr_replacements, old_lambda_info, &new_lambda_info); main_script->_recurse_replace_function_ptrs(func_ptr_replacements); if (has_static_data && !root->annotated_static_unload) { diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 45f0f9e19b9..91d62015a81 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -36,6 +36,7 @@ #include "gdscript_function.h" #include "gdscript_parser.h" +#include "core/templates/hash_map.h" #include "core/templates/hash_set.h" class GDScriptCompiler { @@ -44,34 +45,41 @@ class GDScriptCompiler { HashSet parsing_classes; GDScript *main_script = nullptr; - struct FunctionLambdaInfo { +public: + struct LambdaSourceInfo; + + struct LambdaSourceInfoList { + HashMap> infos; + + void collect_function_lambda_replacement_info(GDScriptFunction *p_func); + }; + + struct LambdaSourceInfo { GDScriptFunction *function = nullptr; GDScriptFunction *parent = nullptr; GDScript *script = nullptr; StringName name; - int line = 0; - int index = 0; - int depth = 0; //uint64_t code_hash; //int code_size; - int capture_count = 0; + bool is_static = false; bool use_self = false; + int capture_count = 0; int arg_count = 0; int default_arg_count = 0; - //Vector argument_types; - //GDScriptDataType return_type; - Vector sublambdas; + LambdaSourceInfoList sublambdas; + + bool can_be_replaced_by(const LambdaSourceInfo &p_new_info) const; }; struct ScriptLambdaInfo { - Vector implicit_initializer_info; - Vector implicit_ready_info; - Vector static_initializer_info; - HashMap> member_function_infos; - Vector other_function_infos; - HashMap subclass_info; + LambdaSourceInfoList initializers; + HashMap member_functions; + HashMap subclasses; + + void collect_script_lambda_replacement_info(GDScript *p_script); }; +private: struct CodeGen { GDScript *script = nullptr; const GDScriptParser::ClassNode *class_node = nullptr; @@ -161,13 +169,10 @@ class GDScriptCompiler { Error _parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter); Error _prepare_compilation(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); Error _compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); - FunctionLambdaInfo _get_function_replacement_info(GDScriptFunction *p_func, int p_index = -1, int p_depth = 0, GDScriptFunction *p_parent_func = nullptr); - Vector _get_function_lambda_replacement_info(GDScriptFunction *p_func, int p_depth = 0, GDScriptFunction *p_parent_func = nullptr); - ScriptLambdaInfo _get_script_lambda_replacement_info(GDScript *p_script); - bool _do_function_infos_match(const FunctionLambdaInfo &p_old_info, const FunctionLambdaInfo *p_new_info); - void _get_function_ptr_replacements(HashMap &r_replacements, const FunctionLambdaInfo &p_old_info, const FunctionLambdaInfo *p_new_info); - void _get_function_ptr_replacements(HashMap &r_replacements, const Vector &p_old_infos, const Vector *p_new_infos); - void _get_function_ptr_replacements(HashMap &r_replacements, const ScriptLambdaInfo &p_old_info, const ScriptLambdaInfo *p_new_info); + + static void _collect_function_ptr_replacements(HashMap &r_replacements, LambdaSourceInfoList &p_old, LambdaSourceInfoList *p_new); + static void _collect_function_ptr_replacements(HashMap &r_replacements, ScriptLambdaInfo &p_old_info, ScriptLambdaInfo *p_new_info); + int err_line = 0; int err_column = 0; StringName source; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 6433072b556..f40effe789e 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -580,6 +580,7 @@ public: _FORCE_INLINE_ bool is_static() const { return _static; } _FORCE_INLINE_ MethodInfo get_method_info() const { return method_info; } _FORCE_INLINE_ int get_argument_count() const { return _argument_count; } + _FORCE_INLINE_ int get_default_argument_count() const { return _default_arg_count; } _FORCE_INLINE_ Variant get_rpc_config() const { return rpc_config; } _FORCE_INLINE_ int get_max_stack_size() const { return _stack_size; } diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 28f594619b9..096bdf2eb72 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -203,13 +203,11 @@ int GDScriptTestRunner::run_tests() { print_line(test.get_source_relative_filepath()); } for (GDScriptTest::TestResult &result : test.run_test()) { - String source_file = result.source_test->get_source_file(); - String output_file = result.source_test->get_output_file(); - String expected = FileAccess::get_file_as_string(output_file); + String expected = FileAccess::get_file_as_string(result.source_test->get_output_file()); #ifndef DEBUG_ENABLED expected = strip_warnings(expected); #endif - INFO(source_file); + INFO(result.source_test->get_source_file()); if (!result.passed) { INFO(expected); failed++; diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.gd b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.gd new file mode 100644 index 00000000000..bda3d9e7347 --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.gd @@ -0,0 +1,30 @@ +var member1 := func(): + return "Member 1" + +var local1: Callable + +var param1: Callable + +var anon1: Callable +var anon2: Callable + +func test(): + var _v1 = func(): return "Local 1" + local1 = _v1 + + print(local1.call()) + + print(member1.call()) + + test_parameters() + + print(param1.call()) + + anon1 = func(): return "Anonymous 1" + anon2 = func(): return "Anonymous 2" + + print(anon1.call()) + print(anon2.call()) + +func test_parameters(_v1 = func(): return "Param 1"): + param1 = _v1 diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.out b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.out new file mode 100644 index 00000000000..6bcd449c78d --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.out @@ -0,0 +1,6 @@ +GDTEST_OK +Local 1 +Member 1 +Param 1 +Anonymous 1 +Anonymous 2 diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1 b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1 new file mode 100644 index 00000000000..532e70b4087 --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1 @@ -0,0 +1,49 @@ +var member1 := func(): + return "Member 1 Hotswap 1" + +var member2 := func(): + return "Member 2 Hotswap 1" + +var local1: Callable +var local2: Callable + +var param1: Callable +var param2: Callable + +var anon1: Callable +var anon2: Callable + +func test(): + var _v1 = func(): return "Local 1 Hotswap 1" + var _v2 = func(): return "Local 2 Hotswap 1" + # Only set local2 here, local1 has already been set. + local2 = _v2 + + print(local1.call()) + print(local2.call()) + + + print(member1.call()) + if member2: + print(member2.call()) + else: + print(member2) + + test_parameters() + + print(param1.call()) + print(param2.call()) + + # Only set anon2 here, anon1 has already been set. + sink(func(): return "Anonymous 1 Hotswap 1") + sink(func(): return "Anonymous 2 Hotswap 1") + + print(anon1.call()) + print(anon2.call()) + +func test_parameters(_v1 = func(): return "Param 1 Hotswap 1", _v2 = func(): return "Param 2 Hotswap 1"): + # Only set param2 here, param1 has already been set. + param2 = _v2 + +func sink(_v): + pass diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1.out b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1.out new file mode 100644 index 00000000000..a0618bf4356 --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap1.out @@ -0,0 +1,9 @@ +GDTEST_OK +Local 1 Hotswap 1 +Local 2 Hotswap 1 +Member 1 Hotswap 1 + +Param 1 Hotswap 1 +Param 2 Hotswap 1 +Anonymous 1 Hotswap 1 +Anonymous 2 Hotswap 1 diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2 b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2 new file mode 100644 index 00000000000..c5ece17984e --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2 @@ -0,0 +1,48 @@ +var member2 := func(): + return "Member 2 Hotswap 2" + +var member1 := func(): + return "Member 1 Hotswap 2" + +var local1: Callable +var local2: Callable + +var param1: Callable +var param2: Callable + +var anon1: Callable +var anon2: Callable + +func test(): + var _v2 = func(): return "Local 2 Hotswap 2" + var _v1 = func(): return "Local 1 Hotswap 2" + # local1 and local2 have already been set. + + print(local1.call()) + print(local2.call()) + + print(member1.call()) + if member2: + print(member2.call()) + else: + print(member2) + + test_parameters() + + print(param1.call()) + print(param2.call()) + + # Only set anon2 here, anon1 has already been set. + # No way for compiler to tell that theyve been swapped, so anon1 and anon2's output will be swapped. + sink(func(): return "Anonymous 2 Hotswap 2") + sink(func(): return "Anonymous 1 Hotswap 2") + + print(anon1.call()) + print(anon2.call()) + +func test_parameters(_v2 = func(): return "Param 2 Hotswap 2", _v1 = func(): return "Param 1 Hotswap 2"): + # param1 and param2 have already been set. + pass + +func sink(_v): + pass diff --git a/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2.out b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2.out new file mode 100644 index 00000000000..51a1bbb27ca --- /dev/null +++ b/modules/gdscript/tests/scripts/hotswap/hotswap_lambda.swap2.out @@ -0,0 +1,9 @@ +GDTEST_OK +Local 1 Hotswap 2 +Local 2 Hotswap 2 +Member 1 Hotswap 2 + +Param 1 Hotswap 2 +Param 2 Hotswap 2 +Anonymous 2 Hotswap 2 +Anonymous 1 Hotswap 2 diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd index 160e43a797e..3efc948e65e 100644 --- a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd +++ b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd @@ -10,7 +10,7 @@ func test(): foo() print(lambda_self.get_method()) # Should print "test". - print(anon_lambda_self.get_method()) # Should print "". + print(anon_lambda_self.get_method()) # Should print "". var lambda_non_self := func test() -> void: pass @@ -18,4 +18,4 @@ func test(): pass print(lambda_non_self.get_method()) # Should print "test". - print(anon_lambda_non_self.get_method()) # Should print "". + print(anon_lambda_non_self.get_method()) # Should print "". diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out index 17ee47fca28..30b558c08c3 100644 --- a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out +++ b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out @@ -1,5 +1,5 @@ GDTEST_OK test - + test - +