浏览代码

Merge pull request #70702 from vnen/gdscript-error-on-assign-void

GDScript: Error when assigning return value of void function
Rémi Verschelde 2 年之前
父节点
当前提交
4e360ac612
共有 26 个文件被更改,包括 108 次插入53 次删除
  1. 2 0
      core/variant/variant_call.cpp
  2. 0 3
      doc/classes/ProjectSettings.xml
  3. 13 15
      modules/gdscript/gdscript_analyzer.cpp
  4. 14 14
      modules/gdscript/gdscript_compiler.cpp
  5. 20 0
      modules/gdscript/gdscript_vm.cpp
  6. 0 5
      modules/gdscript/gdscript_warning.cpp
  7. 0 1
      modules/gdscript/gdscript_warning.h
  8. 3 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd
  9. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out
  10. 5 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd
  11. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out
  12. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd
  13. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out
  14. 3 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd
  15. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out
  16. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd
  17. 2 0
      modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out
  18. 0 6
      modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd
  19. 0 5
      modules/gdscript/tests/scripts/parser/warnings/void_assignment.out
  20. 4 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd
  21. 6 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out
  22. 4 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd
  23. 6 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out
  24. 4 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd
  25. 6 0
      modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out
  26. 4 4
      modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd

+ 2 - 0
core/variant/variant_call.cpp

@@ -65,11 +65,13 @@ static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...) const, Variant *b
 
 
 template <class T, class... P>
 template <class T, class... P>
 static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
 static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+	VariantInternal::clear(&r_ret);
 	call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
 	call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
 }
 }
 
 
 template <class T, class... P>
 template <class T, class... P>
 static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
 static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+	VariantInternal::clear(&r_ret);
 	call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
 	call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
 }
 }
 
 

+ 0 - 3
doc/classes/ProjectSettings.xml

@@ -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>

+ 13 - 15
modules/gdscript/gdscript_analyzer.cpp

@@ -1751,12 +1751,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;
 
 
@@ -1846,12 +1840,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) {
@@ -2335,9 +2323,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) {
-		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) {
+	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
@@ -2652,6 +2638,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;
@@ -2695,6 +2685,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;
@@ -2837,6 +2831,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);

+ 14 - 14
modules/gdscript/gdscript_compiler.cpp

@@ -538,20 +538,20 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 				// Construct a built-in type.
 				// Construct a built-in type.
 				Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(call->callee)->name);
 				Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(call->callee)->name);
 
 
-				gen->write_construct(result, vtype, arguments);
+				gen->write_construct(return_addr, vtype, arguments);
 			} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
 			} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
 				// Variant utility function.
 				// Variant utility function.
-				gen->write_call_utility(result, call->function_name, arguments);
+				gen->write_call_utility(return_addr, call->function_name, arguments);
 			} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) {
 			} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) {
 				// GDScript utility function.
 				// GDScript utility function.
-				gen->write_call_gdscript_utility(result, GDScriptUtilityFunctions::get_function(call->function_name), arguments);
+				gen->write_call_gdscript_utility(return_addr, GDScriptUtilityFunctions::get_function(call->function_name), arguments);
 			} else {
 			} else {
 				// Regular function.
 				// Regular function.
 				const GDScriptParser::ExpressionNode *callee = call->callee;
 				const GDScriptParser::ExpressionNode *callee = call->callee;
 
 
 				if (call->is_super) {
 				if (call->is_super) {
 					// Super call.
 					// Super call.
-					gen->write_super_call(result, call->function_name, arguments);
+					gen->write_super_call(return_addr, call->function_name, arguments);
 				} else {
 				} else {
 					if (callee->type == GDScriptParser::Node::IDENTIFIER) {
 					if (callee->type == GDScriptParser::Node::IDENTIFIER) {
 						// Self function call.
 						// Self function call.
@@ -563,22 +563,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 
 
 							if (_have_exact_arguments(method, arguments)) {
 							if (_have_exact_arguments(method, arguments)) {
 								// Exact arguments, use ptrcall.
 								// Exact arguments, use ptrcall.
-								gen->write_call_ptrcall(result, self, method, arguments);
+								gen->write_call_ptrcall(return_addr, self, method, arguments);
 							} else {
 							} else {
 								// Not exact arguments, but still can use method bind call.
 								// Not exact arguments, but still can use method bind call.
-								gen->write_call_method_bind(result, self, method, arguments);
+								gen->write_call_method_bind(return_addr, self, method, arguments);
 							}
 							}
 						} else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
 						} else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
 							GDScriptCodeGenerator::Address self;
 							GDScriptCodeGenerator::Address self;
 							self.mode = GDScriptCodeGenerator::Address::CLASS;
 							self.mode = GDScriptCodeGenerator::Address::CLASS;
 							if (within_await) {
 							if (within_await) {
-								gen->write_call_async(result, self, call->function_name, arguments);
+								gen->write_call_async(return_addr, self, call->function_name, arguments);
 							} else {
 							} else {
 								gen->write_call(return_addr, self, call->function_name, arguments);
 								gen->write_call(return_addr, self, call->function_name, arguments);
 							}
 							}
 						} else {
 						} else {
 							if (within_await) {
 							if (within_await) {
-								gen->write_call_self_async(result, call->function_name, arguments);
+								gen->write_call_self_async(return_addr, call->function_name, arguments);
 							} else {
 							} else {
 								gen->write_call_self(return_addr, call->function_name, arguments);
 								gen->write_call_self(return_addr, call->function_name, arguments);
 							}
 							}
@@ -589,18 +589,18 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 						if (subscript->is_attribute) {
 						if (subscript->is_attribute) {
 							// May be static built-in method call.
 							// May be static built-in method call.
 							if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
 							if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
-								gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
+								gen->write_call_builtin_type_static(return_addr, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
 							} else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
 							} else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
 									ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
 									ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
 								// It's a static native method call.
 								// It's a static native method call.
-								gen->write_call_native_static(result, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
+								gen->write_call_native_static(return_addr, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
 							} else {
 							} else {
 								GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
 								GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
 								if (r_error) {
 								if (r_error) {
 									return GDScriptCodeGenerator::Address();
 									return GDScriptCodeGenerator::Address();
 								}
 								}
 								if (within_await) {
 								if (within_await) {
-									gen->write_call_async(result, base, call->function_name, arguments);
+									gen->write_call_async(return_addr, base, call->function_name, arguments);
 								} else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
 								} else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
 									// Native method, use faster path.
 									// Native method, use faster path.
 									StringName class_name;
 									StringName class_name;
@@ -613,16 +613,16 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 										MethodBind *method = ClassDB::get_method(class_name, call->function_name);
 										MethodBind *method = ClassDB::get_method(class_name, call->function_name);
 										if (_have_exact_arguments(method, arguments)) {
 										if (_have_exact_arguments(method, arguments)) {
 											// Exact arguments, use ptrcall.
 											// Exact arguments, use ptrcall.
-											gen->write_call_ptrcall(result, base, method, arguments);
+											gen->write_call_ptrcall(return_addr, base, method, arguments);
 										} else {
 										} else {
 											// Not exact arguments, but still can use method bind call.
 											// Not exact arguments, but still can use method bind call.
-											gen->write_call_method_bind(result, base, method, arguments);
+											gen->write_call_method_bind(return_addr, base, method, arguments);
 										}
 										}
 									} else {
 									} else {
 										gen->write_call(return_addr, base, call->function_name, arguments);
 										gen->write_call(return_addr, base, call->function_name, arguments);
 									}
 									}
 								} else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
 								} else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
-									gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments);
+									gen->write_call_builtin_type(return_addr, base, base.type.builtin_type, call->function_name, arguments);
 								} else {
 								} else {
 									gen->write_call(return_addr, base, call->function_name, arguments);
 									gen->write_call(return_addr, base, call->function_name, arguments);
 								}
 								}

+ 20 - 0
modules/gdscript/gdscript_vm.cpp

@@ -1533,8 +1533,28 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				Callable::CallError err;
 				Callable::CallError err;
 				if (call_ret) {
 				if (call_ret) {
 					GET_INSTRUCTION_ARG(ret, argc + 1);
 					GET_INSTRUCTION_ARG(ret, argc + 1);
+#ifdef DEBUG_ENABLED
+					Variant::Type base_type = base->get_type();
+					Object *base_obj = base->get_validated_object();
+					StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
+#endif
 					base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
 					base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
+					if (ret->get_type() == Variant::NIL) {
+						if (base_type == Variant::OBJECT) {
+							if (base_obj) {
+								MethodBind *method = ClassDB::get_method(base_class, *methodname);
+								if (*methodname == CoreStringNames::get_singleton()->_free || (method && !method->has_return())) {
+									err_text = R"(Trying to get a return value of a method that returns "void")";
+									OPCODE_BREAK;
+								}
+							}
+						} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
+							err_text = R"(Trying to get a return value of a method that returns "void")";
+							OPCODE_BREAK;
+						}
+					}
+
 					if (!call_async && ret->get_type() == Variant::OBJECT) {
 					if (!call_async && ret->get_type() == Variant::OBJECT) {
 						// Check if getting a function state without await.
 						// Check if getting a function state without await.
 						bool was_freed = false;
 						bool was_freed = false;

+ 0 - 5
modules/gdscript/gdscript_warning.cpp

@@ -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",

+ 0 - 1
modules/gdscript/gdscript_warning.h

@@ -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.

+ 3 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out

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

+ 5 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out

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

+ 3 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd

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

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out

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

+ 0 - 6
modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd

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

+ 0 - 5
modules/gdscript/tests/scripts/parser/warnings/void_assignment.out

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

+ 4 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd

@@ -0,0 +1,4 @@
+func test():
+	var obj
+	obj = Node.new()
+	print(obj.free())

+ 6 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out

@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_free_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"

+ 4 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd

@@ -0,0 +1,4 @@
+func test():
+	var value
+	value = []
+	print(value.reverse())

+ 6 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out

@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_void_builtin_method_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"

+ 4 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd

@@ -0,0 +1,4 @@
+func test():
+	var obj
+	obj = RefCounted.new()
+	print(obj.notify_property_list_changed())

+ 6 - 0
modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out

@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_void_native_method_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"

+ 4 - 4
modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd

@@ -15,10 +15,10 @@ func test():
 	var string_array: Array[String] = []
 	var string_array: Array[String] = []
 	var stringname_array: Array[StringName] = []
 	var stringname_array: Array[StringName] = []
 
 
-	assert(!string_array.push_back(&"abc"))
+	string_array.push_back(&"abc")
 	print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
 	print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
 
 
-	assert(!stringname_array.push_back("abc"))
+	stringname_array.push_back("abc")
 	print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
 	print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
 
 
 	print("StringName in Array[String]: ", &"abc" in string_array)
 	print("StringName in Array[String]: ", &"abc" in string_array)
@@ -28,8 +28,8 @@ func test():
 	assert(!packed_string_array.push_back("abc"))
 	assert(!packed_string_array.push_back("abc"))
 	print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
 	print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
 
 
-	assert(!string_array.push_back("abc"))
+	string_array.push_back("abc")
 	print("StringName finds String in Array: ", string_array.find(&"abc"))
 	print("StringName finds String in Array: ", string_array.find(&"abc"))
 
 
-	assert(!stringname_array.push_back(&"abc"))
+	stringname_array.push_back(&"abc")
 	print("String finds StringName in Array: ", stringname_array.find("abc"))
 	print("String finds StringName in Array: ", stringname_array.find("abc"))