Static access to inherited constants behaves differently than instance access

I recently noticed some unexpected behavior and would appreciate your thoughts on whether this is intended or a bug.

In my app, I use classes that define constants to control various device-specific aspects. There is a base class that provides default values, and derived classes can override selected constants as needed.

This works fine when accessing the constants from instance methods. However, when I try to access them from a static method, I can only access constants that are explicitly defined in the concrete class. Inherited constants are not accessible.

Here is a simplified example:

import Toybox.Lang;

class ConstantsA {
    public static const X as Number = 1;
    public static const Y as Number = 2;
    public static const Z as Number = 3;
}

class ConstantsB extends ConstantsA {
    public static const Y as Number = 2;
    public static const Z as Number = ConstantsA.Z;
}

class ConstantsC extends ConstantsA {
    public static const Y as Number = 2;
    public static const Z as Number = ConstantsB.Z;
}

class ConstantsTest {
    public function test() as Void {
        Toybox.System.println( ConstantsC.X ); // Works
        Toybox.System.println( ConstantsC.Y ); // Works
        Toybox.System.println( ConstantsC.Z ); // Works
    }
    public static function testStatic() as Void {
        Toybox.System.println( ConstantsC.X ); // Does not work
        Toybox.System.println( ConstantsC.Y ); // Works
        Toybox.System.println( ConstantsC.Z ); // Works
    }
}

In this example, ConstantsC.X is accessible from the instance method but not from the static method, even though it is defined in the base class.

In the static method, I receive the following error:

ERROR: edge840: D:\GitHub\ohg\source\test.mc:26,8: Cannot find symbol ':X' on class definition '$.ConstantsC'.

Is there a logical explanation for this behavior? Or does this appear to be a bug in the language or compiler?

Any insight would be greatly appreciated.

  • The fact that the non-static funtion can access X seems logical, because the non static funtion is an instance method (it requires an instance of ConstantsC) to call it, and static constants are shared by all instances of a class. The static function is not an instamce method, and by calling it you do not access an instance.

    But as written, test() is an instance method of ConstantsTest, not ConstantsC.

    Both test() (instance method of ConstantsTest) and testStatic() (static method of ConstantsTest) are accessing ConstantsC in exactly the same way (without an instance of ConstantsC).

    I'm not saying you're not on the right track, but some of the details you've provided here don't seem to be quite right, unless I am missing something.

  • BTW I think that you can add static before the const. I don't have the computer here, but you could try if that changes anything

    I’m not sure what you mean. All constants are already declared as public static const. If they weren’t, I wouldn’t be able to access them the way I currently do. While one could argue that constants are inherently static, that is not the case. Constants that are not explicitly declared as static require an instance to be accessed.

  • If you disable type checking, building (of course) and running will work as you expect.

    I think this is a type checker bug since compile-time lookup is different from runtime lookup.