Browse Source

GDScript: Fix implicit conversions for function returns

Dmitrii Maganov 2 years ago
parent
commit
6194a7e0fa

+ 15 - 20
modules/gdscript/gdscript_analyzer.cpp

@@ -1958,11 +1958,9 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {
 	GDScriptParser::DataType result;
 	GDScriptParser::DataType result;
 
 
 	GDScriptParser::DataType expected_type;
 	GDScriptParser::DataType expected_type;
-	bool has_expected_type = false;
-
-	if (parser->current_function != nullptr) {
+	bool has_expected_type = parser->current_function != nullptr;
+	if (has_expected_type) {
 		expected_type = parser->current_function->get_datatype();
 		expected_type = parser->current_function->get_datatype();
-		has_expected_type = true;
 	}
 	}
 
 
 	if (p_return->return_value != nullptr) {
 	if (p_return->return_value != nullptr) {
@@ -1985,24 +1983,21 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {
 		result.is_constant = true;
 		result.is_constant = true;
 	}
 	}
 
 
-	if (has_expected_type) {
-		expected_type.is_meta_type = false;
-		if (expected_type.is_hard_type()) {
-			if (!is_type_compatible(expected_type, result)) {
-				// Try other way. Okay but not safe.
-				if (!is_type_compatible(result, expected_type)) {
-					push_error(vformat(R"(Cannot return value of type "%s" because the function return type is "%s".)", result.to_string(), expected_type.to_string()), p_return);
-				} else {
-					// TODO: Add warning.
-					mark_node_unsafe(p_return);
-				}
+	if (has_expected_type && !expected_type.is_variant()) {
+		if (result.is_variant() || !result.is_hard_type()) {
+			mark_node_unsafe(p_return);
+			if (!is_type_compatible(expected_type, result, true, p_return)) {
+				downgrade_node_type_source(p_return);
+			}
+		} else if (!is_type_compatible(expected_type, result, true, p_return)) {
+			mark_node_unsafe(p_return);
+			if (!is_type_compatible(result, expected_type)) {
+				push_error(vformat(R"(Cannot return value of type "%s" because the function return type is "%s".)", result.to_string(), expected_type.to_string()), p_return);
+			}
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-			} else if (expected_type.builtin_type == Variant::INT && result.builtin_type == Variant::FLOAT) {
-				parser->push_warning(p_return, GDScriptWarning::NARROWING_CONVERSION);
-			} else if (result.is_variant() && !expected_type.is_variant()) {
-				mark_node_unsafe(p_return);
+		} else if (expected_type.builtin_type == Variant::INT && result.builtin_type == Variant::FLOAT) {
+			parser->push_warning(p_return, GDScriptWarning::NARROWING_CONVERSION);
 #endif
 #endif
-			}
 		}
 		}
 	}
 	}
 
 

+ 34 - 0
modules/gdscript/tests/scripts/analyzer/features/return_conversions.gd

@@ -0,0 +1,34 @@
+func convert_literal_int_to_float() -> float: return 76
+func convert_arg_int_to_float(arg: int) -> float: return arg
+func convert_var_int_to_float() -> float: var number := 59; return number
+
+func convert_literal_array_to_packed() -> PackedStringArray: return ['46']
+func convert_arg_array_to_packed(arg: Array) -> PackedStringArray: return arg
+func convert_var_array_to_packed() -> PackedStringArray: var array := ['79']; return array
+
+func test():
+	var converted_literal_int := convert_literal_int_to_float()
+	assert(typeof(converted_literal_int) == TYPE_FLOAT)
+	assert(converted_literal_int == 76.0)
+
+	var converted_arg_int := convert_arg_int_to_float(36)
+	assert(typeof(converted_arg_int) == TYPE_FLOAT)
+	assert(converted_arg_int == 36.0)
+
+	var converted_var_int := convert_var_int_to_float()
+	assert(typeof(converted_var_int) == TYPE_FLOAT)
+	assert(converted_var_int == 59.0)
+
+	var converted_literal_array := convert_literal_array_to_packed()
+	assert(typeof(converted_literal_array) == TYPE_PACKED_STRING_ARRAY)
+	assert(str(converted_literal_array) == '["46"]')
+
+	var converted_arg_array := convert_arg_array_to_packed(['91'])
+	assert(typeof(converted_arg_array) == TYPE_PACKED_STRING_ARRAY)
+	assert(str(converted_arg_array) == '["91"]')
+
+	var converted_var_array := convert_var_array_to_packed()
+	assert(typeof(converted_var_array) == TYPE_PACKED_STRING_ARRAY)
+	assert(str(converted_var_array) == '["79"]')
+
+	print('ok')

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/features/return_conversions.out

@@ -0,0 +1,2 @@
+GDTEST_OK
+ok