-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Fix typed arrays not working with concatenation operator +
#73540
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like these need to be guarded with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also it compares the value with itself... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See #78478 |
||
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; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
GDTEST_OK | ||
2 | ||
4 | ||
0 | ||
2 | ||
Object | ||
true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check
array_b.is_typed()
?Apologies for the drive by comment... :^) Testing a github action PR review bot and was using your PR as an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically I don't even think
array_a.is_typed()
needs to be checked.is_same_typed
might just be enough because if they are both untyped thenset_typed
pretty much acts like a no-op. I guess it can be a bit expensive to callset_typed
just to set no type though so it helps optimize that use-case.To answer your question, checking if
array_b.is_typed()
would be redundant. Ifarray_a.is_typed()
andarray_a.is_same_typed(array_b)
then it can be safe to assumearray_b.is_typed()
.