Acknowledged
over 1 year ago

Bug in Simulator 7.2.1 with Float vs Long comparisons

In the following:

    var l = 1L;
    var f = 1.0f;
    System.println(f==l); // false in 7.2.1, true in 7.2.0 and earlier
    System.println(l==f); // false in 7.2.1, true in 7.2.0 and earlier
    System.println(1.0f==1L); // false in 7.2.1 with optimization off, true with optimization on

Essentially, when the 7.2.1 simulator evaluates 1.0f==1L it returns false. All previous simulators return true.

Note that the optimizer also thinks the result is true.

I've not tried on a device yet, but from past experiments I'm pretty sure that all the watches I've used report true.

If this is something that's going to change, or that devices are inconsistent about, the type checker should issue a warning for long vs float comparisons, and the optimizer shouldn't optimize constant comparisons (especially not to the wrong value!). But my guess is that this is just a bug in the simulator.

  • It should obviously do the same thing for the invalid comparisons above even if the types aren't certain. ie, if one argument might be a Float, and the other might be a Long, (and the type checker is in a sufficiently strict mode) it should warn.

    I wish the behavior of Monkey C in this respect was specified. Idek what's supposed to happen here.

    In Java, the following program outputs "true":

    public class MyProgram
    {
        public static void main(String[] args)
        {
            int x = 42;
            double y = 42.0;
            System.out.println(x == y);
        }
    }

    This is because the int is implicitly converted to a float for the purposes of comparison. The same thing happens in C.

    Yes, I realize that it's not a good idea in general to use "==" for float comparison, but that doesn't stop Java and C from making a reasonable attempt.

  • In my example there, I should obviously have included "lng == flt" as returning false...

  • 7.3.0 has the same issue. It's also more extensive than I initially thought. For both 7.2.1 and 7.3.0, it also affects Long vs Char, Float vs Char and Double vs Char.

    ie

    var num as Number = 42;
    var lng as Long = 42L;
    var flt as Float = 42F;
    var dbl as Double = 42D;
    var chr as Char = '*';
    
    ...
    
    lng == chr; // false in 7.2.1 and later, for older devices
    flt == chr; // false in 7.2.1 and later, for older devices
    dbl == chr; // false in 7.2.1 and later, for older devices
    // all other pairwise comparisons are true

    This might be related to the fact, that 7.2.1 has the following line in the release notes

    Yes, I think that's it. For devices like fr955, all the comparisons still return true. But eg fenix5xplus is apparently an "older" device.

    > But ofc that wouldn't help for ... or in situations where the type isn't certain.

    If it followed its existing behavior for such things, it actually would:

      var q as Number | Boolean = false;
      var t as Boolean = q == false;

    Gives me a warning: "Attempting to perform operation 'eq' with invalid types '$.Toybox.Lang.Number' and '$.Toybox.Lang.Boolean'.". And yes, I filed a bug against this particular warning, because it's a perfectly valid thing to check: q is either a Number or a Boolean, and I want to know if it contains the value "false".

    But the point is that here, the type checker doesn't know whether they're both Boolean, so it issues a warning. It should obviously do the same thing for the invalid comparisons above even if the types aren't certain. ie, if one argument might be a Float, and the other might be a Long, (and the type checker is in a sufficiently strict mode) it should warn.

  • This might be related to the fact, that 7.2.1 has the following line in the release notes under general (not simulator) changes section:

    • Fix a behavioral inconsistency for older devices when equality comparing objects of various types.
  • > But my guess is that this is just a bug in the simulator.

    I really hope so

    > If this is something that's going to change, or that devices are inconsistent about, the type checker should issue a warning for long vs float comparisons

    But ofc that wouldn't help for apps which have already been deployed or apps which don't use type checking, or in situations where the type isn't certain. And if it was a warning, devs would feel free to ignore it.