Print a GDScript warning when comparing floating-point numbers directly
`is_equal_approx()` or `is_zero_approx()` should be used instead to ensure consistent results.
This commit is contained in:
parent
a4f2ea91a1
commit
e6254946d4
4 changed files with 22 additions and 0 deletions
|
@ -495,6 +495,9 @@
|
|||
<member name="debug/gdscript/warnings/exclude_addons" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], scripts in the [code]res://addons[/code] folder will not generate warnings.
|
||||
</member>
|
||||
<member name="debug/gdscript/warnings/float_comparison" type="int" setter="" getter="" default="1">
|
||||
If [code]true[/code], enables warnings when comparing a floating-point value with another floating-point value or an integer value. Due to the limitations of floating-point math, such comparisons may not always evaluate to [code]true[/code] as you expect. Instead, [method @GlobalScope.is_equal_approx] or [method @GlobalScope.is_zero_approx] should be used to perform reliable floating-point number comparisons.
|
||||
</member>
|
||||
<member name="debug/gdscript/warnings/function_used_as_property" type="int" setter="" getter="" default="1" deprecated="This warning is never produced. When a function is used as a property, a [Callable] is returned.">
|
||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when using a function as if it is a property.
|
||||
</member>
|
||||
|
|
|
@ -2865,6 +2865,20 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o
|
|||
if (p_binary_op->variant_op == Variant::OP_DIVIDE && left_type.builtin_type == Variant::INT && right_type.builtin_type == Variant::INT) {
|
||||
parser->push_warning(p_binary_op, GDScriptWarning::INTEGER_DIVISION);
|
||||
}
|
||||
|
||||
const bool number_to_float_direct_comparison =
|
||||
(p_binary_op->variant_op == Variant::OP_EQUAL || p_binary_op->variant_op == Variant::OP_NOT_EQUAL) &&
|
||||
(left_type.builtin_type == Variant::INT || left_type.builtin_type == Variant::FLOAT) &&
|
||||
right_type.builtin_type == Variant::FLOAT;
|
||||
const bool float_to_number_direct_comparison =
|
||||
(p_binary_op->variant_op == Variant::OP_EQUAL || p_binary_op->variant_op == Variant::OP_NOT_EQUAL) &&
|
||||
left_type.builtin_type == Variant::FLOAT &&
|
||||
(right_type.builtin_type == Variant::INT || right_type.builtin_type == Variant::FLOAT);
|
||||
|
||||
if (number_to_float_direct_comparison || float_to_number_direct_comparison) {
|
||||
// GDScript allows comparing floats with integers with implicit conversion, but the precision issue remains nonetheless.
|
||||
parser->push_warning(p_binary_op, GDScriptWarning::FLOAT_COMPARISON);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_binary_op->left_operand->is_constant && p_binary_op->right_operand->is_constant) {
|
||||
|
|
|
@ -119,6 +119,8 @@ String GDScriptWarning::get_message() const {
|
|||
return "Assert statement will raise an error because the expression is always false.";
|
||||
case INTEGER_DIVISION:
|
||||
return "Integer division, decimal part will be discarded.";
|
||||
case FLOAT_COMPARISON:
|
||||
return "Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `is_equal_approx()` or `is_zero_approx()` for an approximate but predictable comparison.";
|
||||
case NARROWING_CONVERSION:
|
||||
return "Narrowing conversion (float is converted to int and loses precision).";
|
||||
case INT_AS_ENUM_WITHOUT_CAST:
|
||||
|
@ -221,6 +223,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
|
|||
"ASSERT_ALWAYS_TRUE",
|
||||
"ASSERT_ALWAYS_FALSE",
|
||||
"INTEGER_DIVISION",
|
||||
"FLOAT_COMPARISON",
|
||||
"NARROWING_CONVERSION",
|
||||
"INT_AS_ENUM_WITHOUT_CAST",
|
||||
"INT_AS_ENUM_WITHOUT_MATCH",
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
ASSERT_ALWAYS_TRUE, // Expression for assert argument is always true.
|
||||
ASSERT_ALWAYS_FALSE, // Expression for assert argument is always false.
|
||||
INTEGER_DIVISION, // Integer divide by integer, decimal part is discarded.
|
||||
FLOAT_COMPARISON, // Floating-point number is compared with another number using `==` or `!=`, leading to inconsistent results.
|
||||
NARROWING_CONVERSION, // Float value into an integer slot, precision is lost.
|
||||
INT_AS_ENUM_WITHOUT_CAST, // An integer value was used as an enum value without casting.
|
||||
INT_AS_ENUM_WITHOUT_MATCH, // An integer value was used as an enum value without matching enum member.
|
||||
|
@ -127,6 +128,7 @@ public:
|
|||
WARN, // ASSERT_ALWAYS_TRUE
|
||||
WARN, // ASSERT_ALWAYS_FALSE
|
||||
WARN, // INTEGER_DIVISION
|
||||
WARN, // FLOAT_COMPARISON
|
||||
WARN, // NARROWING_CONVERSION
|
||||
WARN, // INT_AS_ENUM_WITHOUT_CAST
|
||||
WARN, // INT_AS_ENUM_WITHOUT_MATCH
|
||||
|
|
Loading…
Reference in a new issue