GDScript: Make using return of void function an error

Remove the `VOID_ASSIGNMENT` warning since those cases will be errors
now.
This commit is contained in:
George Marques 2022-12-30 11:57:25 -03:00
parent 0c15844551
commit bc739a4687
No known key found for this signature in database
GPG Key ID: 046BD46A3201E43D
16 changed files with 38 additions and 35 deletions

View File

@ -464,9 +464,6 @@
<member name="debug/gdscript/warnings/unused_variable" type="int" setter="" getter="" default="1"> <member name="debug/gdscript/warnings/unused_variable" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable is unused. When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable is unused.
</member> </member>
<member name="debug/gdscript/warnings/void_assignment" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when assigning the result of a function that returns [code]void[/code] to a variable.
</member>
<member name="debug/settings/crash_handler/message" type="String" setter="" getter="" default="&quot;Please include this when reporting the bug to the project developer.&quot;"> <member name="debug/settings/crash_handler/message" type="String" setter="" getter="" default="&quot;Please include this when reporting the bug to the project developer.&quot;">
Message to be displayed before the backtrace when the engine crashes. By default, this message is only used in exported projects due to the editor-only override applied to this setting. Message to be displayed before the backtrace when the engine crashes. By default, this message is only used in exported projects due to the editor-only override applied to this setting.
</member> </member>

View File

@ -1748,12 +1748,6 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
type = p_variable->initializer->get_datatype(); type = p_variable->initializer->get_datatype();
#ifdef DEBUG_ENABLED
if (p_variable->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
parser->push_warning(p_variable->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_variable->initializer)->function_name);
}
#endif
if (p_variable->infer_datatype) { if (p_variable->infer_datatype) {
type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
@ -1843,12 +1837,6 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
} }
type = p_constant->initializer->get_datatype(); type = p_constant->initializer->get_datatype();
#ifdef DEBUG_ENABLED
if (p_constant->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
parser->push_warning(p_constant->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_constant->initializer)->function_name);
}
#endif
} }
if (p_constant->datatype_specifier != nullptr) { if (p_constant->datatype_specifier != nullptr) {
@ -2333,9 +2321,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
} }
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_value_type.is_hard_type() && assigned_value_type.kind == GDScriptParser::DataType::BUILTIN && assigned_value_type.builtin_type == Variant::NIL) { if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_assignment->assigned_value)->function_name);
} else if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION); parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
} }
#endif #endif
@ -2650,6 +2636,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
} else if (GDScriptUtilityFunctions::function_exists(function_name)) { } else if (GDScriptUtilityFunctions::function_exists(function_name)) {
MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name); MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name);
if (!p_is_root && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
}
if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) { if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) {
// Can call on compilation. // Can call on compilation.
Vector<const Variant *> args; Vector<const Variant *> args;
@ -2693,6 +2683,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
} else if (Variant::has_utility_function(function_name)) { } else if (Variant::has_utility_function(function_name)) {
MethodInfo function_info = info_from_utility_func(function_name); MethodInfo function_info = info_from_utility_func(function_name);
if (!p_is_root && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
}
if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) { if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) {
// Can call on compilation. // Can call on compilation.
Vector<const Variant *> args; Vector<const Variant *> args;
@ -2835,6 +2829,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
mark_lambda_use_self(); mark_lambda_use_self();
} }
if (!p_is_root && return_type.is_hard_type() && return_type.kind == GDScriptParser::DataType::BUILTIN && return_type.builtin_type == Variant::NIL) {
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", p_call->function_name), p_call);
}
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) { if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) {
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name); parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);

View File

@ -80,10 +80,6 @@ String GDScriptWarning::get_message() const {
case STANDALONE_EXPRESSION: { case STANDALONE_EXPRESSION: {
return "Standalone expression (the line has no effect)."; return "Standalone expression (the line has no effect).";
} break; } break;
case VOID_ASSIGNMENT: {
CHECK_SYMBOLS(1);
return "Assignment operation, but the function '" + symbols[0] + "()' returns void.";
} break;
case NARROWING_CONVERSION: { case NARROWING_CONVERSION: {
return "Narrowing conversion (float is converted to int and loses precision)."; return "Narrowing conversion (float is converted to int and loses precision).";
} break; } break;
@ -202,7 +198,6 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"UNREACHABLE_CODE", "UNREACHABLE_CODE",
"UNREACHABLE_PATTERN", "UNREACHABLE_PATTERN",
"STANDALONE_EXPRESSION", "STANDALONE_EXPRESSION",
"VOID_ASSIGNMENT",
"NARROWING_CONVERSION", "NARROWING_CONVERSION",
"INCOMPATIBLE_TERNARY", "INCOMPATIBLE_TERNARY",
"UNUSED_SIGNAL", "UNUSED_SIGNAL",

View File

@ -57,7 +57,6 @@ public:
UNREACHABLE_CODE, // Code after a return statement. UNREACHABLE_CODE, // Code after a return statement.
UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind). UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind).
STANDALONE_EXPRESSION, // Expression not assigned to a variable. STANDALONE_EXPRESSION, // Expression not assigned to a variable.
VOID_ASSIGNMENT, // Function returns void but it's assigned to a variable.
NARROWING_CONVERSION, // Float value into an integer slot, precision is lost. NARROWING_CONVERSION, // Float value into an integer slot, precision is lost.
INCOMPATIBLE_TERNARY, // Possible values of a ternary if are not mutually compatible. INCOMPATIBLE_TERNARY, // Possible values of a ternary if are not mutually compatible.
UNUSED_SIGNAL, // Signal is defined but never emitted. UNUSED_SIGNAL, // Signal is defined but never emitted.

View File

@ -0,0 +1,3 @@
func test():
var builtin := []
print(builtin.reverse()) # Built-in type method.

View File

@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot get return value of call to "reverse()" because it returns "void".

View File

@ -0,0 +1,5 @@
func foo() -> void:
pass
func test():
print(foo()) # Custom method.

View File

@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot get return value of call to "foo()" because it returns "void".

View File

@ -0,0 +1,2 @@
func test():
print(print_debug()) # GDScript utility function.

View File

@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot get return value of call to "print_debug()" because it returns "void".

View File

@ -0,0 +1,3 @@
func test():
var obj := Node.new()
print(obj.free()) # Native type method.

View File

@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot get return value of call to "free()" because it returns "void".

View File

@ -0,0 +1,2 @@
func test():
print(print()) # Built-in utility function.

View File

@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot get return value of call to "print()" because it returns "void".

View File

@ -1,6 +0,0 @@
func i_return_void() -> void:
return
func test():
var __ = i_return_void()

View File

@ -1,5 +0,0 @@
GDTEST_OK
>> WARNING
>> Line: 6
>> VOID_ASSIGNMENT
>> Assignment operation, but the function 'i_return_void()' returns void.