www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9668] New: Disallow (dis)equality with FP.nan/FP.init literals

http://d.puremagic.com/issues/show_bug.cgi?id=9668

           Summary: Disallow (dis)equality with FP.nan/FP.init literals
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc


--- Comment #0 from bearophile_hugs eml.cc 2013-03-08 11:50:05 PST ---
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/mailman.1845.1334694574.4860.digitalmars-d-learn puremagic.com#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/undjpdewiqmghmhndedw forum.dlang.org

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 08 2013