Bug 9668 – Disallow (dis)equality with FP.nan/FP.init literals

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-08T11:50:05Z
Last change time
2024-12-13T18:04:37Z
Assigned to
No Owner
Creator
bearophile_hugs
Moved to GitHub: dmd#18531 →

Comments

Comment #0 by bearophile_hugs — 2013-03-08T11:50:05Z
Since a lot of time D statically refuses the use of "classReference == null": // Program #1 class Foo {} void main() { Foo f; assert(f == null); assert(f != null); } test.d(4): Error: use 'is' instead of '==' when comparing with null test.d(5): Error: use '!is' instead of '!=' when comparing with null Not expert D programmers sometime compare a double with double.nan in a wrong way: http://forum.dlang.org/thread/[email protected]#post-jmlhfr:2428cv:241:40digitalmars.com because someDouble == double.nan is always false: // Program #2 import std.math: isNaN; void main() { double x = double.init; assert(x != double.nan); assert(x != double.init); assert(isNaN(x)); assert(x is double.init); assert(x !is double.nan); double y = double.nan; assert(y != double.nan); assert(y != double.init); assert(isNaN(y)); assert(y !is double.init); assert(y is double.nan); } I think there are three common wrong usage patterns of NaNs testing: 1) Test that x is equal to/different from nan using x==FP.nan/x!=FP.nan 2) Test that x is equal to/different from all NaNs using x==FP.nan/x!=FP.nan 3) Test that x is equal to/different from FP.init using x==FP.init/x!=FP.init The case 3 is a bit less important because the programmer already knows something about FP init, but it's wrong still. There are other wrong usages of NaNs but they are by more expert programmers, to I don't want to catch them (example: using "is" to test if x is equal to/different from all NaNs is a bug, because there are many bitwise-different NaNs. But if the programmer uses "is" I assume he/she/shi knows enough about NaNs, so this is not flagged by the compiler). Currently this program compiles with no errors: // Program #3 void main() { float x1 = float.nan; assert(x1 == float.nan); float x2 = 0.0; assert(x2 != float.nan); float x3 = float.init; assert(x3 == float.init); float x4 = 0.0; assert(x4 != float.init); double x5 = double.nan; assert(x5 == double.nan); double x6 = 0.0; assert(x6 != double.nan); double x7 = double.init; assert(x7 == double.init); double x8 = 0.0; assert(x8 != double.init); real x9 = real.nan; assert(x9 == real.nan); real x10 = 0.0; assert(x10 != real.nan); real x11 = real.init; assert(x11 == real.init); real x12 = 0.0; assert(x12 != real.init); enum double myNaN = double.nan; assert(myNaN == double.nan); } So I propose to statically disallow comparisons of Program #3, so it generates errors similar to: test.d(4): Error: comparison is always false. Use 'std.math.isNaN' to test for every kind of NaN or 'is float.nan' for this specific NaN test.d(6): Error: comparison is always true. Use '!std.math.isNaN' to test for every kind of NaN or '!is float.nan' for this specific NaN test.d(8): Error: comparison is always false. Use 'std.math.isNaN' to test for every kind of NaN or 'is float.init' for this specicif NaN ... Opinions, improvements, votes or critics are welcome. See discussion thread, this idea was generally liked: http://forum.dlang.org/thread/[email protected]
Comment #1 by robert.schadek — 2024-12-13T18:04:37Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18531 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB