New Issue: Should use statements have two shadow scopes?

19219, "mppf", "Should use statements have two shadow scopes?", "2022-02-08T16:48:30Z"

This is a follow-up to #11262 (and other related issues are #14013 #14014 and #19167).

I am writing this issue because in #19167 I am proposing simplifying the visibility rules and this issue discusses a related simplification.

Consider this program which has a use M where the module M also defines a symbol named M. After the use M, what should M refer to?

module M {
  var M: int;
}

module N {
  use M;

  proc main() {
    writeln(M);
  }
}

Currently, this program compiles and runs, printing 0, which shows that after the use M, M refers to M.M. It has done so since at least 1.19 (although PR #13930 changed how it was implemented). The explanation for the current behavior is in multiple-defined module symbol has shadowing instead of error · Issue #14014 · chapel-lang/chapel · GitHub where it describes the use statement adding two hidden/implicit/shadow scopes. However, the language specification only says this on the matter ( Modules — Chapel Documentation 1.32 ):

The names that are made visible by a use or import statement are inserted in to a new scope that immediately encloses the scope within which the statement appears.

What should we do here?

  1. Keep the current behavior and document in the language specification that use statements work with two shadow scopes. The program discussed above would continue to compile.
  2. Simplify the rules for use statements to only work with one shadow scope. The program discussed above would result in an ambiguity error because module M and var M would be considered to be in the same scope (namely, the new/hidden/shadow scope of symbols brought in by the use statement). This would mean that it's not possible to use a module defining a symbol with the same name as the module name (see also issue #13925). It would be possible to import such a module, though.
  3. Change the rules for use / import to not use a shadow scope at all. This would mean one could no longer shadow something brought in with the use with a function/variable declaration.