@ -685,10 +685,10 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
result . builtin_type = GDScriptParser : : get_builtin_type ( first ) ;
if ( result . builtin_type = = Variant : : ARRAY ) {
GDScriptParser : : DataType container_type = type_from_metatype ( resolve_datatype ( p_type - > container_type) ) ;
GDScriptParser : : DataType container_type = type_from_metatype ( resolve_datatype ( p_type - > get_ container_type_or_null( 0 ) ) ) ;
if ( container_type . kind ! = GDScriptParser : : DataType : : VARIANT ) {
container_type . is_constant = false ;
result . set_container_element_type ( container_type ) ;
result . set_container_element_type ( 0 , container_type ) ;
}
}
} else if ( class_exists ( first ) ) {
@ -829,8 +829,16 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
}
}
if ( result . builtin_type ! = Variant : : ARRAY & & p_type - > container_type ! = nullptr ) {
push_error ( " Only arrays can specify the collection element type. " , p_type ) ;
if ( ! p_type - > container_types . is_empty ( ) ) {
if ( result . builtin_type = = Variant : : ARRAY ) {
if ( p_type - > container_types . size ( ) ! = 1 ) {
push_error ( " Arrays require exactly one collection element type. " , p_type ) ;
return bad_type ;
}
} else {
push_error ( " Only arrays can specify collection element types. " , p_type ) ;
return bad_type ;
}
}
p_type - > set_datatype ( result ) ;
@ -1891,8 +1899,8 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
if ( p_assignable - > initializer - > type = = GDScriptParser : : Node : : ARRAY ) {
GDScriptParser : : ArrayNode * array = static_cast < GDScriptParser : : ArrayNode * > ( p_assignable - > initializer ) ;
if ( has_specified_type & & specified_type . has_container_element_type ( ) ) {
update_array_literal_element_type ( array , specified_type . get_container_element_type ( ) ) ;
if ( has_specified_type & & specified_type . has_container_element_type ( 0 ) ) {
update_array_literal_element_type ( array , specified_type . get_container_element_type ( 0 ) ) ;
}
}
@ -1955,7 +1963,7 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
} 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 ) ;
}
} else if ( specified_type . has_container_element_type ( ) & & ! initializer_type . has_container_element_type ( ) ) {
} else if ( specified_type . has_container_element_type ( 0 ) & & ! initializer_type . has_container_element_type ( 0 ) ) {
mark_node_unsafe ( p_assignable - > initializer ) ;
# ifdef DEBUG_ENABLED
} else if ( specified_type . builtin_type = = Variant : : INT & & initializer_type . builtin_type = = Variant : : FLOAT ) {
@ -2127,8 +2135,8 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
if ( list_type . is_variant ( ) ) {
variable_type . kind = GDScriptParser : : DataType : : VARIANT ;
mark_node_unsafe ( p_for - > list ) ;
} else if ( list_type . has_container_element_type ( ) ) {
variable_type = list_type . get_container_element_type ( ) ;
} else if ( list_type . has_container_element_type ( 0 ) ) {
variable_type = list_type . get_container_element_type ( 0 ) ;
variable_type . type_source = list_type . type_source ;
} else if ( list_type . is_typed_container_type ( ) ) {
variable_type = list_type . get_typed_container_type ( ) ;
@ -2377,8 +2385,8 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {
result . builtin_type = Variant : : NIL ;
result . is_constant = true ;
} else {
if ( p_return - > return_value - > type = = GDScriptParser : : Node : : ARRAY & & has_expected_type & & expected_type . has_container_element_type ( ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_return - > return_value ) , expected_type . get_container_element_type ( ) ) ;
if ( p_return - > return_value - > type = = GDScriptParser : : Node : : ARRAY & & has_expected_type & & expected_type . has_container_element_type ( 0 ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_return - > return_value ) , expected_type . get_container_element_type ( 0 ) ) ;
}
if ( has_expected_type & & expected_type . is_hard_type ( ) & & p_return - > return_value - > is_constant ) {
update_const_expression_builtin_type ( p_return - > return_value , expected_type , " return " ) ;
@ -2598,7 +2606,7 @@ void GDScriptAnalyzer::update_const_expression_builtin_type(GDScriptParser::Expr
// This function determines which type is that (if any).
void GDScriptAnalyzer : : update_array_literal_element_type ( GDScriptParser : : ArrayNode * p_array , const GDScriptParser : : DataType & p_element_type ) {
GDScriptParser : : DataType expected_type = p_element_type ;
expected_type . unset_ container_element_type( ) ; // Nested types (like `Array[Array[int]]`) are not currently supported.
expected_type . container_element_types. clear ( ) ; // Nested types (like `Array[Array[int]]`) are not currently supported.
for ( int i = 0 ; i < p_array - > elements . size ( ) ; i + + ) {
GDScriptParser : : ExpressionNode * element_node = p_array - > elements [ i ] ;
@ -2621,7 +2629,7 @@ void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNo
}
GDScriptParser : : DataType array_type = p_array - > get_datatype ( ) ;
array_type . set_container_element_type ( expected_type ) ;
array_type . set_container_element_type ( 0 , expected_type ) ;
p_array - > set_datatype ( array_type ) ;
}
@ -2668,8 +2676,8 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
}
// Check if assigned value is an array literal, so we can make it a typed array too if appropriate.
if ( p_assignment - > assigned_value - > type = = GDScriptParser : : Node : : ARRAY & & assignee_type . is_hard_type ( ) & & assignee_type . has_container_element_type ( ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_assignment - > assigned_value ) , assignee_type . get_container_element_type ( ) ) ;
if ( p_assignment - > assigned_value - > type = = GDScriptParser : : Node : : ARRAY & & assignee_type . is_hard_type ( ) & & assignee_type . has_container_element_type ( 0 ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_assignment - > assigned_value ) , assignee_type . get_container_element_type ( 0 ) ) ;
}
if ( p_assignment - > operation = = GDScriptParser : : AssignmentNode : : OP_NONE & & assignee_type . is_hard_type ( ) & & p_assignment - > assigned_value - > is_constant ) {
@ -2747,7 +2755,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
// weak non-variant assignee and incompatible result
downgrades_assignee = true ;
}
} else if ( assignee_type . has_container_element_type ( ) & & ! op_type . has_container_element_type ( ) ) {
} else if ( assignee_type . has_container_element_type ( 0 ) & & ! op_type . has_container_element_type ( 0 ) ) {
// typed array assignee and untyped array result
mark_node_unsafe ( p_assignment ) ;
}
@ -3311,8 +3319,8 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
// If the function requires typed arrays we must make literals be typed.
for ( const KeyValue < int , GDScriptParser : : ArrayNode * > & E : arrays ) {
int index = E . key ;
if ( index < par_types . size ( ) & & par_types [ index ] . is_hard_type ( ) & & par_types [ index ] . has_container_element_type ( ) ) {
update_array_literal_element_type ( E . value , par_types [ index ] . get_container_element_type ( ) ) ;
if ( index < par_types . size ( ) & & par_types [ index ] . is_hard_type ( ) & & par_types [ index ] . has_container_element_type ( 0 ) ) {
update_array_literal_element_type ( E . value , par_types [ index ] . get_container_element_type ( 0 ) ) ;
}
}
validate_call_arg ( par_types , default_arg_count , method_flags . has_flag ( METHOD_FLAG_VARARG ) , p_call ) ;
@ -3444,8 +3452,8 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
}
}
if ( p_cast - > operand - > type = = GDScriptParser : : Node : : ARRAY & & cast_type . has_container_element_type ( ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_cast - > operand ) , cast_type . get_container_element_type ( ) ) ;
if ( p_cast - > operand - > type = = GDScriptParser : : Node : : ARRAY & & cast_type . has_container_element_type ( 0 ) ) {
update_array_literal_element_type ( static_cast < GDScriptParser : : ArrayNode * > ( p_cast - > operand ) , cast_type . get_container_element_type ( 0 ) ) ;
}
if ( ! cast_type . is_variant ( ) ) {
@ -4432,8 +4440,8 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
break ;
// Can have an element type.
case Variant : : ARRAY :
if ( base_type . has_container_element_type ( ) ) {
result_type = base_type . get_container_element_type ( ) ;
if ( base_type . has_container_element_type ( 0 ) ) {
result_type = base_type . get_container_element_type ( 0 ) ;
result_type . type_source = base_type . type_source ;
} else {
result_type . kind = GDScriptParser : : DataType : : VARIANT ;
@ -4597,7 +4605,7 @@ Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::Expressi
}
Variant GDScriptAnalyzer : : make_array_reduced_value ( GDScriptParser : : ArrayNode * p_array , bool & is_reduced ) {
Array array = p_array - > get_datatype ( ) . has_container_element_type ( ) ? make_array_from_element_datatype ( p_array - > get_datatype ( ) . get_container_element_type ( ) ) : Array ( ) ;
Array array = p_array - > get_datatype ( ) . has_container_element_type ( 0 ) ? make_array_from_element_datatype ( p_array - > get_datatype ( ) . get_container_element_type ( 0 ) ) : Array ( ) ;
array . resize ( p_array - > elements . size ( ) ) ;
for ( int i = 0 ; i < p_array - > elements . size ( ) ; i + + ) {
@ -4719,8 +4727,8 @@ Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNo
GDScriptParser : : DataType datatype = p_variable - > get_datatype ( ) ;
if ( datatype . is_hard_type ( ) ) {
if ( datatype . kind = = GDScriptParser : : DataType : : BUILTIN & & datatype . builtin_type ! = Variant : : OBJECT ) {
if ( datatype . builtin_type = = Variant : : ARRAY & & datatype . has_container_element_type ( ) ) {
result = make_array_from_element_datatype ( datatype . get_container_element_type ( ) ) ;
if ( datatype . builtin_type = = Variant : : ARRAY & & datatype . has_container_element_type ( 0 ) ) {
result = make_array_from_element_datatype ( datatype . get_container_element_type ( 0 ) ) ;
} else {
VariantInternal : : initialize ( & result , datatype . builtin_type ) ;
}
@ -4747,11 +4755,11 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
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 ( ) ) ) ) ;
result . set_container_element_type ( 0 , 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 ( ) ) ) ) ;
result . set_container_element_type ( 0 , 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 ( ) ) ) ) ;
result . set_container_element_type ( 0 , 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.
@ -4873,7 +4881,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo
ERR_FAIL_V_MSG ( result , " Could not find element type from property hint of a typed array. " ) ;
}
elem_type . is_constant = false ;
result . set_container_element_type ( elem_type ) ;
result . set_container_element_type ( 0 , elem_type ) ;
} else if ( p_property . type = = Variant : : INT ) {
// Check if it's enum.
if ( ( p_property . usage & PROPERTY_USAGE_CLASS_IS_ENUM ) & & p_property . class_name ! = StringName ( ) ) {
@ -5225,7 +5233,7 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
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 . has_container_element_type ( ) & & p_b . has_container_element_type ( ) & & p_a . get_container_element_type ( ) = = p_b . get_container_element_type ( ) ) {
if ( p_a . has_container_element_type ( 0 ) & & p_b . has_container_element_type ( 0 ) & & p_a . get_container_element_type ( 0 ) = = p_b . get_container_element_type ( 0 ) ) {
r_valid = true ;
result = p_a ;
result . type_source = hard_operation ? GDScriptParser : : DataType : : ANNOTATED_INFERRED : GDScriptParser : : DataType : : INFERRED ;
@ -5276,8 +5284,8 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
}
if ( valid & & p_target . builtin_type = = Variant : : ARRAY & & p_source . builtin_type = = Variant : : ARRAY ) {
// Check the element type.
if ( p_target . has_container_element_type ( ) & & p_source . has_container_element_type ( ) ) {
valid = p_target . get_container_element_type ( ) = = p_source . get_container_element_type ( ) ;
if ( p_target . has_container_element_type ( 0 ) & & p_source . has_container_element_type ( 0 ) ) {
valid = p_target . get_container_element_type ( 0 ) = = p_source . get_container_element_type ( 0 ) ;
}
}
return valid ;