diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 6fb1abaf844..0b0eb4170f8 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1514,7 +1514,6 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi GDScriptParser::DataType type; type.kind = GDScriptParser::DataType::VARIANT; - bool is_variable = p_assignable->type == GDScriptParser::Node::VARIABLE; bool is_constant = p_assignable->type == GDScriptParser::Node::CONSTANT; GDScriptParser::DataType specified_type; @@ -1576,13 +1575,11 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi } else if (!specified_type.is_variant()) { if (initializer_type.is_variant() || !initializer_type.is_hard_type()) { mark_node_unsafe(p_assignable->initializer); - if (is_variable) { - static_cast(p_assignable)->use_conversion_assign = true; - } + p_assignable->use_conversion_assign = true; } else if (!is_type_compatible(specified_type, initializer_type, true, p_assignable->initializer)) { - if (is_variable && is_type_compatible(initializer_type, specified_type, true, p_assignable->initializer)) { + if (!is_constant && is_type_compatible(initializer_type, specified_type, true, p_assignable->initializer)) { mark_node_unsafe(p_assignable->initializer); - static_cast(p_assignable)->use_conversion_assign = true; + p_assignable->use_conversion_assign = true; } else { push_error(vformat(R"(Cannot assign a value of type %s to %s "%s" with specified type %s.)", initializer_type.to_string(), p_kind, p_assignable->identifier->name, specified_type.to_string()), p_assignable->initializer); } diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 57ee41e34e2..6c80fb76656 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -872,8 +872,12 @@ void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) { append(p_target); } -void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_dst, const Address &p_src) { - write_assign(p_dst, p_src); +void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_dst, const Address &p_src, bool p_use_conversion) { + if (p_use_conversion) { + write_assign_with_conversion(p_dst, p_src); + } else { + write_assign(p_dst, p_src); + } function->default_arguments.push_back(opcodes.size()); } diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index ac9c4c8fb59..171c5051160 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -460,7 +460,7 @@ public: virtual void write_assign_with_conversion(const Address &p_target, const Address &p_source) override; virtual void write_assign_true(const Address &p_target) override; virtual void write_assign_false(const Address &p_target) override; - virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override; + virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src, bool p_use_conversion) override; virtual void write_store_global(const Address &p_dst, int p_global_index) override; virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override; virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index c7a1bcb9e99..e885938ebac 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -113,7 +113,7 @@ public: virtual void write_assign_with_conversion(const Address &p_target, const Address &p_source) = 0; virtual void write_assign_true(const Address &p_target) = 0; virtual void write_assign_false(const Address &p_target) = 0; - virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0; + virtual void write_assign_default_parameter(const Address &dst, const Address &src, bool p_use_conversion) = 0; virtual void write_store_global(const Address &p_dst, int p_global_index) = 0; virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0; virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index beed6e90d2e..77c6690d200 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2116,7 +2116,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ } } - codegen.generator->write_assign_default_parameter(dst_addr, src_addr); + codegen.generator->write_assign_default_parameter(dst_addr, src_addr, parameter->use_conversion_assign); if (src_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 4bb02c4ea3b..0903f62061d 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -360,6 +360,7 @@ public: ExpressionNode *initializer = nullptr; TypeNode *datatype_specifier = nullptr; bool infer_datatype = false; + bool use_conversion_assign = false; int usages = 0; virtual ~AssignableNode() {} @@ -1182,7 +1183,6 @@ public: bool onready = false; PropertyInfo export_info; int assignments = 0; - bool use_conversion_assign = false; #ifdef TOOLS_ENABLED String doc_description; #endif // TOOLS_ENABLED diff --git a/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd new file mode 100644 index 00000000000..a72ac9b5ee3 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd @@ -0,0 +1,8 @@ +var weakling = 'not float' +func weak(x: float = weakling): + print(x) + print('typeof x is', typeof(x)) + +func test(): + print(typeof(weak())) + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out new file mode 100644 index 00000000000..8543cf976e6 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out @@ -0,0 +1,8 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: weak() +>> runtime/errors/bad_conversion_for_default_parameter.gd +>> 2 +>> Trying to assign value of type 'String' to a variable of type 'float'. +0 +not ok diff --git a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd new file mode 100644 index 00000000000..9d0c6317b3c --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd @@ -0,0 +1,19 @@ +func literal(x: float = 1): + print('x is ', x) + print('typeof x is ', typeof(x)) + +var inferring := 2 +func inferred(x: float = inferring): + print('x is ', x) + print('typeof x is ', typeof(x)) + +var weakling = 3 +func weak(x: float = weakling): + print('x is ', x) + print('typeof x is ', typeof(x)) + +func test(): + literal() + inferred() + weak() + print('ok') diff --git a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out new file mode 100644 index 00000000000..a9ef4919cf1 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out @@ -0,0 +1,8 @@ +GDTEST_OK +x is 1 +typeof x is 3 +x is 2 +typeof x is 3 +x is 3 +typeof x is 3 +ok