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.