Under Review
over 1 year ago

CIQTOOLS-389

CIQTOOLS-390

Resources seem to be type Number, not Symbol

The documentation says that things like Rez.Strings.name have type Symbol.

But I tried:

        if (Rez.Strings.AppName instanceof Lang.Symbol) {
            System.println("AppName is a Symbol");
        }

and nothing got printed.

So I tried

        if (Rez.Strings.AppName instanceof Lang.Symbol) {
            System.println("AppName is a Symbol");
        }
        if (Rez.Strings.AppName instanceof Lang.Number) {
            System.println("AppName is a Number");
        }

and I got:

ERROR: <device>: bug.mc:4,8: Type '$.Toybox.Lang.Symbol' is not an instance of '$.Toybox.Lang.Number'.

So the type checker definitely seems to think that Rez.Strings.AppName is a Symbol (as an aside, this would be a pretty annoying error, even if it was correct; if it knows that instanceof is false, it could just optimize it away, maybe with a warning, but making it an error seems overkill).

So I turned the type checker off, compiled and ran, and got:

AppName is a Number

making the type checker error look even sillier.

This doesn't seem to matter too much - apparently if you pass a number where a Symbol is expected (eg as the argument to menu.setTitle), it works (provided the number corresponds to an actual symbol), even though the type checker says its an error.

But I noticed it because I was trying to debug a function that took various Rez.Strings.<name> as a symbol argument, and I added some logging to print symbol.toString() - which should show me the name of the symbol in a debug build. But all I got was numbers.

  • ERROR: <device>: bug.mc:4,8: Type '$.Toybox.Lang.Symbol' is not an instance of '$.Toybox.Lang.Number'.

    So the type checker definitely seems to think that Rez.Strings.AppName is a Symbol (as an aside, this would be a pretty annoying error, even if it was correct; if it knows that instanceof is false, it could just optimize it away, maybe with a warning, but making it an error seems overkill).

    Not to state the obvious but I think this is an example of a class of error where the compiler won't let you write a condition that is known to be false. In some languages / configurations this is a warning, but in others, it's a fatal error.

    For example, in typescript the following code would be an error:

    if (0 === 1) {
    // ...
    }

    I think the wording of the Monkey C error message could be improved.

    e.g.

    ERROR: <device>: bug.mc:4,8: This condition will always return 'false' since type '$.Toybox.Lang.Symbol' is not an instance of '$.Toybox.Lang.Number'.

    (Yes, I literally plagiarized TS2367.)

    Then it would be clear that the actual problem is that Monkey C doesn't want you to have a condition that's always false, because it almost always indicates a bug in your code.

    I agree that the other stuff definitely seems like a bug.