New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should use statements have two shadow scopes? #19219
Comments
I'm divided. On the one hand, option 1 means less breaking changes and it feels like we've done a lot of reshuffling of the rules in scope resolution, so I have some change fatigue there. I also suspect some users will dislike having the symbols conflict in that case. On the other hand, 2 does sound like an intriguing simplification and would be both easier to explain and implement/maintain. |
@lydia-duncan - I also added a more aggressive Option 3 - what do you think about that? |
I think use and import statements should continue to add at least one shadow scope. I don't think implicitly included symbols (which could be at an arbitrary distance, depending on if the module author has been too incautious with public uses or imports) should conflict with explicitly defined symbols. |
Say that we did Option 3. I think that might present a problem when we want to add functionality to the set of included-by-default operations. Here is a scenario. Start with this Program: // Program
// implicitly has a 'use ChapelStandardLibrary' (whatever that is)
proc foo() { }
foo(); Now imagine that in a new version, the standard library adds a // ChapelStandardLibrary
proc foo() { } Now when Program is compiled, with Option 3, it would fail with an ambiguity error. That is not desirable because we would like to be able to add functions to the standard library without considering that a backwards-breaking change. (Interestingly, there are reasons why even with the other options, it would still be a problem. In particular, if the program wanted to pass |
I have been exploring a combination of Option 2 and Option 4. However I am running into a pattern that we have discussed before in #13925 : module MyDist {
class MyDist {
}
}
module Program {
use MyDist;
...MyDist... // does this refer to the module or the class?
} Some cases in our standard library where I am seeing this are:
It seems not ideal to use this pattern because if there are symbol conflicts that come up, it won't be possible to resolve them with qualified naming. However, on #13925 there was some rationale for continuing with the current behavior, which will require two shadow scopes (effectively) for |
Even if we continue with the two shadow scopes though, a |
@mppf: A couple of quick thoughts on your latest comments:
|
@bradcray - thanks for your thoughts.
Yes I think it is nice if we can avoid banning it outright. IIRC it is a common pattern in Python.
Yes, it is my understanding that working with
This is an interesting proposal and I think of it as bringing up #13978 again. In the past I was in favor of a design that all Anyway, not bringing in the symbol So, I would lean towards doing that, because I think it makes |
Oh, and another possible direction here is this from #13978 (comment)
It seems weird to me that the |
In testing with the "public use does not bring in the module name" change, one interesting case that failed is this test -- https://github.com/chapel-lang/chapel/blob/main/test/visibility/rename/renameUsedMod/renamePublicUse2.chpl . It is interesting because it raises the question of what
Any thoughts on which way to go here? I am slightly inclined to do 1. |
At this moment, I'd be fine with either approach. One minor argument in favor of approach 2 is that it can be changed later without breaking existing code (and if users found they wanted it, they could request it). |
I'm in favor of continuing to support using |
simplify use/import shadowing This PR describes and implements some candidate language adjustments to shadowing behavior for use and import statements. We need to do something in this area because the definition of shadowing is currently inconsistent between variables and functions (#19167). This PR attempts to simplify the language design in this area. The adjustments to the language design in this PR are as follows: * isMoreVisible in function disambiguation as well as scope resolution use the same rules for determining shadowing with use/import statements * isMoreVisible starts it search from the POI where the candidates were discovered (see issue #19198 -- not discussed further here) * private use statements still have two shadow scopes * public and private import statements now do not introduce a shadow scope * public use statements now do not introduce a shadow scope * `public use M` does not bring in `M` (but `public use M as M` does) * methods are no longer subject to shadowing Note that the above design leads to less shadowing of symbols from the automatic library (see the section "Less Shadowing of Symbols from the Automatic Standard Library" in #19306 (comment)) ## Discussion Elements of the language design direction are discussed in these issues: * #19167 * #19160 * #19219 and #13925 * #19312 * #19352 Please see also #19306 (comment) which discusses pros and cons of these language design choices. ### Testing and Review Reviewed by @lydia-duncan - thanks! This PR passes full local futures testing. Resolves the future `test/modules/vass/use-depth.chpl`. Also fixes #19198 and adds a test based on the case in that issue. - [x] full local futures testing - [x] gasnet testing ### Future Work There are two areas of future work that we would like to address soon: * #19313 which relates to changes in this PR to the test `modules/bradc/userInsteadOfStandard/foo2`. The behavior for trying to replace a standard module has changed (presumably due to minor changes in how the usual standard modules are now available). I think that changing the compiler to separately list each standard module would bring the behavior back the way it was. (Or we could look for other implementation changes to support it). * #19780 to add warnings for cases where the difference between `public use M` and `private use M` might be surprising
I feel as though through the discussion around #19306, we got pretty comfortable with the notion of private use continuing to have two shadow scopes, one for the symbols, and a slightly outer one for the module name itself. That makes me think we could close this issue unless I'm missing some thread that's unresolved. |
Yes I consider this issue resolved after PR #19306. Closing. |
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 moduleM
also defines a symbol namedM
. After theuse M
, what shouldM
refer to?Currently, this program compiles and runs, printing 0, which shows that after the
use M
,M
refers toM.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 #14014 (comment) where it describes the use statement adding two hidden/implicit/shadow scopes. However, the language specification only says this on the matter ( https://chapel-lang.org/docs/language/spec/modules.html#using-and-importing ):What should we do here?
use
statements to only work with one shadow scope. The program discussed above would result in an ambiguity error becausemodule M
andvar M
would be considered to be in the same scope (namely, the new/hidden/shadow scope of symbols brought in by theuse
statement). This would mean that it's not possible touse
a module defining a symbol with the same name as the module name (see also issue Should modules be able to define symbols that share their name? #13925). It would be possible toimport
such a module, though.use
/import
to not use a shadow scope at all. This would mean one could no longer shadow something brought in with theuse
with a function/variable declaration. This is the same as Option C. in definition of shadowing is inconsistent between variables and functions #19167 and:public use
/public import
to not use a shadow scope at all. This is the same as Option C'. in definition of shadowing is inconsistent between variables and functions #19167. We would still have to choose one of the other options for the behavior of private use/import.The text was updated successfully, but these errors were encountered: