Demo code:
import Toybox.Test; import Toybox.Lang; module ImportWeirdness { module Strange { import ImportWeirdness.ImportedOutOfScope; } module NotImported { const K = 0; } module ImportedInScope { const K = 1; } module ImportedOutOfScope { const K = 2; } module Nest { import ImportWeirdness.ImportedInScope; module NotImported { const K = 3; } module ImportedInScope { const K = 4; } module ImportedOutOfScope { const K = 5; } (:test) function test(logger as Logger) as Boolean { var ok = true; if (NotImported.K != 3) { logger.debug( "NotImported.K was " + NotImported.K.toString() + " not 3" ); ok = false; } if (ImportedInScope.K != 1) { logger.debug( "ImportedInScope.K was " + ImportedInScope.K.toString() + " not 1" ); ok = false; } if (ImportedOutOfScope.K != 5) { logger.debug( "ImportedOutOfScope.K was " + ImportedOutOfScope.K.toString() + " not 5" ); ok = false; } return ok; } } }
The issue here relates to how import/using prioritizes the imported module.
- When there are no imports, the search for a name goes strictly from inner scopes to outer scopes, so when looking up NotImported.K it finds the nearest one, namely $.ImportWeirdness.Nest.NotImported.K. This works with the old and new compilers.
- When a module is imported, and the import is in scope, the import takes priority, so ImportedInScope.K resolves to $.ImportWeirdness.ImportedInScope.K, rather than $.ImportWeirdness.Nest.ImportedInScope.K. Again, this works with both the old and new compilers.
- When a module is imported, but the import is *not* in scope, the import should have no effect. So ImportedOutOfScope.K should resolve to $.ImportWeirdness.Nest.ImportedOutOfScope.K, and it does in the old compiler, but in the new compiler it behaves as if the import was in scope, and resolves to $.ImportWeirdness.ImportedOutOfScope.K
The result is that the test passes on the old compiler, and fails on the new.