diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index d2163cf92dd..387210d9e62 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -824,6 +824,11 @@ public: _FORCE_INLINE_ static void _add_arrays(Array &sum, const Array &array_a, const Array &array_b) { int asize = array_a.size(); int bsize = array_b.size(); + + if (array_a.is_typed() && array_a.is_same_typed(array_b)) { + sum.set_typed(array_a.get_typed_builtin(), array_a.get_typed_class_name(), array_a.get_typed_script()); + } + sum.resize(asize + bsize); for (int i = 0; i < asize; i++) { sum[i] = array_a[i]; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index c8dfdbdd685..bf9b4ae40c5 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -4306,7 +4306,16 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va result.builtin_type = p_value.get_type(); result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; // Constant has explicit type. - if (p_value.get_type() == Variant::OBJECT) { + if (p_value.get_type() == Variant::ARRAY) { + const Array &array = p_value; + if (array.get_typed_script()) { + result.set_container_element_type(type_from_metatype(make_script_meta_type(array.get_typed_script()))); + } else if (array.get_typed_class_name()) { + result.set_container_element_type(type_from_metatype(make_native_meta_type(array.get_typed_class_name()))); + } else if (array.get_typed_builtin() != Variant::NIL) { + result.set_container_element_type(type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin()))); + } + } else if (p_value.get_type() == Variant::OBJECT) { // Object is treated as a native type, not a builtin type. result.kind = GDScriptParser::DataType::NATIVE; @@ -4741,11 +4750,21 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator } } - Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type); + GDScriptParser::DataType result; bool hard_operation = p_a.is_hard_type() && p_b.is_hard_type(); + + if (p_operation == Variant::OP_ADD && a_type == Variant::ARRAY && b_type == Variant::ARRAY) { + if (p_a.get_container_element_type() == p_a.get_container_element_type()) { + r_valid = true; + result = p_a; + result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED; + return result; + } + } + + Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type); bool validated = op_eval != nullptr; - GDScriptParser::DataType result; if (validated) { r_valid = true; result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED; diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.gd b/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.gd new file mode 100644 index 00000000000..ef3ee8d2550 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.gd @@ -0,0 +1,28 @@ +# https://github.com/godotengine/godot/issues/72948 + +class Example: + extends RefCounted + +const const_ints : Array[int] = [1, 2, 3] + +func test(): + var ints: Array[int] = [1, 2, 3] + var strings: Array[String] = ["4", "5", "6"] + + var ints_concatenated: Array[int] = ints + ints + var strings_concatenated: Array[String] = strings + strings + var untyped_concatenated: Array = ints + strings + var const_ints_concatenated: Array[int] = const_ints + const_ints + + print(ints_concatenated.get_typed_builtin()) + print(strings_concatenated.get_typed_builtin()) + print(untyped_concatenated.get_typed_builtin()) + print(const_ints_concatenated.get_typed_builtin()) + + var objects: Array[Object] = [] + var objects_concatenated: Array[Object] = objects + objects + print(objects_concatenated.get_typed_class_name()) + + var examples: Array[Example] = [] + var examples_concatenated: Array[Example] = examples + examples + print(examples_concatenated.get_typed_script() == Example) diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.out b/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.out new file mode 100644 index 00000000000..34f1221a78b --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_concatenation.out @@ -0,0 +1,7 @@ +GDTEST_OK +2 +4 +0 +2 +Object +true