Given this code:
import Toybox.Test; import Toybox.Lang; module nesting { module MB { const MBK = 1; class Base { const BaseK = 2; } } module MC { const MCK = 3; class X extends MB.Base { function initialize() { Base.initialize(); } const XK = 4; function getXK() as Number { return XK; } function getMCK() as Number { return MCK; } function getBaseK() as Number { return BaseK; } function getMBK() as Number { return MBK; } class Y { function getXK() as Number { return XK; } function getMCK() as Number { return MCK; } function getBaseK() as Number { return BaseK; } function getMBK() as Number { return MBK; } } } } } // all these getXK functions work, and return the // expected values. (:test) function testClassLookup(logger as Logger) as Boolean { var x = new nesting.MC.X(); logger.debug(x.getXK()); logger.debug(x.getMCK()); logger.debug(x.getBaseK()); logger.debug(x.getMBK()); return true; } // all the testNestedLookup* function crash inside the // corresponding Y.get* method (:test) function testNestedLookupXK(logger as Logger) as Boolean { var x = new nesting.MC.X.Y(); logger.debug(x.getXK()); return true; } (:test) function testNestedLookupMCK(logger as Logger) as Boolean { var x = new nesting.MC.X.Y(); logger.debug(x.getMCK()); return true; } (:test) function testNestedLookupBaseK(logger as Logger) as Boolean { var x = new nesting.MC.X.Y(); logger.debug(x.getBaseK()); return true; } (:test) function testNestedLookupMBK(logger as Logger) as Boolean { var x = new nesting.MC.X.Y(); logger.debug(x.getMBK()); return true; }
I get this output:
Executing test testClassLookup... DEBUG (13:19): 4 DEBUG (13:19): 3 DEBUG (13:19): 2 DEBUG (13:19): 1 PASS ------------------------------------------------------------------------------ Executing test testNestedLookupXK... Error: Symbol Not Found Error Details: Could not find symbol 'XK' Stack: - getXK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:362 0x10001d2f - testNestedLookupXK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:390 0x10000a50 - evaluate_test_entries_0_to_11() at UnitTests.mc:72 0x100007d2 - runTest() at UnitTests.mc:93 0x100009d8 ERROR ------------------------------------------------------------------------------ Executing test testNestedLookupMCK... Error: Symbol Not Found Error Details: Could not find symbol 'MCK' Stack: - getMCK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:365 0x10001d45 - testNestedLookupMCK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:396 0x10000e3c - evaluate_test_entries_0_to_11() at UnitTests.mc:75 0x100007f3 - runTest() at UnitTests.mc:93 0x100009d8 ERROR ------------------------------------------------------------------------------ Executing test testNestedLookupBaseK... Error: Symbol Not Found Error Details: Could not find symbol 'BaseK' Stack: - getBaseK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:368 0x10001d3a - testNestedLookupBaseK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:402 0x10000faa - evaluate_test_entries_0_to_11() at UnitTests.mc:78 0x10000814 - runTest() at UnitTests.mc:93 0x100009d8 ERROR ------------------------------------------------------------------------------ Executing test testNestedLookupMBK... Error: Symbol Not Found Error Details: Could not find symbol 'MBK' Stack: - getMBK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:371 0x10001d50 - testNestedLookupMBK() at /Users/mwilliams/www/git/monkeyc-optimizer/test/OptimizerTests/source/OptimizerTestsTest.mc:408 0x100017ec - evaluate_test_entries_0_to_11() at UnitTests.mc:81 0x10000835 - runTest() at UnitTests.mc:93 0x100009d8 ERROR
I had to put one failing test per test function because there's no way to recover when symbol lookup fails, but the test runner runs each test function as a separate invocation of the program.
But basically, the X.get* functions all work (as expected, and as predicted by the type checker), but the corresponding Y.get* functions (for the inner class) all fail, even though the type checker thinks everything is ok.
It appears that a nested class behaves as if it were defined in the global scope, so it doesn't get access to the context of the containing class. There's a hint at this on the monkeyc reference page: "Nested classes in Monkey C do not have access to the members of the enclosing class", but its not entirely clear what that means. I had initially assumed it was talking about not having privileged access to private/protected members. But it seems to mean no access at all, even to the enclosing modules (except for the global module, of course).
I've confirmed that this behavior is the same in both the latest full release, and the 4.1.4 compiler 2 beta.
Edit: Its actually much worse. At -O2, because the new compiler thinks it knows the values for these consts, it replaces the them with their values so that the tests stop crashing. This is not a good thing...