-
Notifications
You must be signed in to change notification settings - Fork 415
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 it be possible to use
modules with conflicting symbols?
#21157
Comments
I don't have a problem with making errors occur at |
My opinion on this (which I think David knows already): I think it makes good sense to have the errors at the import/use for all imports and I'm pretty convinced that we need conflicting symbols from multiple |
I agree with Michael here. Is this what we already have implemented? (I'd guess so, especially after recent improvements) If not, what remains? If so, can we close this? |
AFAIK, the production compiler only considers this class of error an ambiguity (when the symbol is used). David made the issue here because we were talking about how the dyno scope resolver should do this checking. We are thinking that the dyno scope resolver should emit "multiple declaration" errors even if there is no mention of the conflicting variable -- with the exception of Note that this could be viewed as a language change. For example, here are two programs that compile today but won't compile with the proposed direction here: module A {
var x: int;
}
module B {
var x: real;
}
module Main {
import A.x;
import B.x;
// but, x never used
proc main() {
}
} module A {
var x: int;
}
module B {
var x: real;
}
module Main {
public use A;
public use B;
// but, x never used
proc main() {
}
} I do not think it is by any means a big language change, however. Perhaps we can argue that the change here represents a bug fix. |
OK, thanks. For some reason, I was thinking after your recent changes to |
@dlongnecke-cray - would you be able to check the language specification in this area and make a PR to improve it, if it is unclear about what would happen in these cases? Thanks |
I have been implementing this for the dyno scope resolver (i.e. Tests that have a helper file that
These tests were using a
The modules primer had an example describing a multiple definition error with
The AMR tests followed the Python pattern of having a little test function per module in
|
) Addresses #18177 and #21157 but only with `--dyno` Resolves Cray/chapel-private#4409 This PR improves the multiply-defined symbol error in the dyno scope resolver (currently available with `--dyno`). The improvements are: * do the multiply-defined symbol checking in a query to avoid redundant errors (e.g. for `proc f(x: int, x)`). * include symbols `public use` and `public` or `private` `import` in the checking * add checking for symbols of a different category in the same scope #### Details This PR: * adds `parsing::idIsFunction` * updates the Redefinition error to take in a trace indicating the source of the symbols (relevant for errors with `public use`) * adds `emitMultipleDefinedSymbolErrors` which invokes a query that emits the error if necessary and can be called in multiple places without worry of emitting redundant errors * adds to `IdAndVis::SymbolTypeFlags` `PARENFUL_FUNCTION` and `NOT_PARENFUL_FUNCTION` which is useful for the Redefinition and may be important in the future for other errors / behavior adjustments for parenless functions. Adjusts the code creating OwnedIdsWithName to pass this information & added `isParenfulFunction` in `scope-queries.cpp` to help compute it. * adds `BorrowedIdsWithNameIter::curIdAndFlags` so that it is possible to extract the `IdAndFlags::Flags` when iterating over the matches in a `BorrowedIdsWithName` * added a new `LookupConfig` setting: `LOOKUP_SKIP_SHADOW_SCOPES`. This is needed so that the redefinition error can focus on `public use` / `import` but ignore redefinitions from `private use`, per discussion in #21157. * adds `Scope::collectNames` and `Scope::names` to help with the redefinition error. Moved `lookupName` out of the header file since it has a loop so might not be inline-able. * adds calls to `emitMultipleDefinedSymbolErrors` in `Resolver::enter(const NamedDecl* decl)`, `Resolver::enter(const Use* node)`, and `Resolver::enter(const Import* node)` and also in `resolveModule` and `scopeResolveModule`. * Replaces `describeSymbolSource` with `describeSymbolTrace` and creates per-error functions for the remaining logic (e.g. `describeAmbiguousMatch`). This way, it is easier to use the trace reporting code while customizing the description of the found symbols. Updated `ErrorRedefinition::write` to use the new trace information and print out something reasonable for conflicts just from `import` or `public use`. * Added `collectAllNames` to gather all names defined in a scope (not counting shadow scopes). Used this to implement `emitMultipleDefinedSymbolErrors`. * Added tests to `test/errors` for a variety of redefinition error patterns; as well as for the shadowed formal warning (follow-up to PR #21614). * Renames `OwnedIdsWithName::appendIdAndVis` to `OwnedIdsWithName::appendIdAndFlags` (I missed this when doing the broader rename in PR #21779). * Fixes a GCC warning when compiling a test after PR #21764. #### Updated tests There were a number of test changes to keep everything working with the additional checking for conflicts with public use and import. Tests that have a helper file that `public use BlockDist, CyclicDist` run into a conflict because the `config param testFastFollowerOptimization` is defined in each of them. * test/distributions/robust/arithmetic/driver.chpl * test/optimizations/autoLocalAccess/common.chpl These tests were using a `public use` within `main`. I don't think that is relevant to what is being tested here & I think PR #14353 just migrated all of the `use` statements in these tests to `public use`. * test/modules/diten/test_use_chain_resolution.chpl * test/modules/diten/test_use_chain_resolution2.chpl The modules primer had an example describing a multiple definition error with `import` where the use of the variable was commented out (since it doesn't compile) but now that still results in an error. So my PR just comments out the conflicting declaration. * test/release/examples/primers/modules.chpl The AMR tests followed the Python pattern of having a little test function per module in `proc main`. These AMR tests also do a lot of `public use` (and I don't think there is a fundamental reason it has to work that way; it is just what these tests were doing when they were written). The result is that we get symbol conflicts for `proc main` being defined multiple times. The fix for these is just to use `private proc main` instead (and using `public use Bla except main` would also work, but involves changing more lines). * test/studies/amr/ (many files) #### Tests with different error messages Tests now needing .good updates for `--dyno` after this PR: ``` functions/bradc/queryClassArgGenerics-bad2.chpl functions/bradc/resolution/arrayVsFn modules/shadowing/issue-19167-1-f.chpl modules/shadowing/issue-19167-1-x.chpl modules/shadowing/issue-19167-2-f.chpl modules/shadowing/issue-19167-2-x.chpl modules/shadowing/issue-19167-3-f.chpl modules/shadowing/issue-19167-3-x.chpl modules/shadowing/issue-19167-4-f.chpl modules/shadowing/issue-19167-4-x.chpl modules/shadowing/issue-19167-5-f.chpl modules/shadowing/issue-19167-5-x.chpl modules/shadowing/var-shadows-private-import.chpl modules/shadowing/var-shadows-public-import.chpl modules/shadowing/var-shadows-public-use.chpl visibility/import/edgeCases/anotherMultipleDef2 visibility/import/edgeCases/multipleDef2.chpl visibility/import/edgeCases/multipleDef3.chpl visibility/import/rename/same_name_in_mod.chpl visibility/import/rename/same_name_in_mod2.chpl ``` #### Future Work * Adjust the error checking according to the resolution of #20509. #### Testing and Review Reviewed by @riftEmber - thanks! - [x] full local testing - [x] no unexpected failures in `--dyno` testing
Should it be possible to
use
modules with conflicting symbols?Context: While bug-fixing the dyno scope resolver, I encountered a
semantic conundrum.
Specifically, if I define the symbol
x
in moduleA
and thenuse
the moduleB
which also definesx
, what should happen?When should an error occur, and when is the code OK? If an error
should occur, then where should it occur? At the point of
use
orimport
? At the point of definition forx
(which one)? At thepoint of mention for
x
(e.g.,writeln(x)
)?Here's the code:
And here's what happens today for any flavor:
Note that the behavior for plain-old
use B
is correct, and printsA
(no concern aboutprivate use
). For documentation, see:https://chapel-lang.org/docs/language/spec/modules.html#conflicts
Errors will not occur if an ambiguous symbol is not mentioned
Looking at production compiler code - errors are triggered at the
point-of-mention. For every
writeln(x)
I add to the code, I getanother error and note.
Point-of-mention has an interesting semantic consequence. Today, if I
remove the
writeln(x)
, I will no longer see an error, and theprogram will compile, regardless of if any (or ALL) visibility
statements are used!
Erroring at point-of-mention vs
import
/use
If errors are at
import
/use
then users will get the errorsas early as possible. This is useful if you are a library author,
because any conflicts between library components become evident
immediately.
If errors are at point-of-mention then an error will only occur
if an ambiguous symbol is actually used. This seems more useful
for a developer who is authoring an end-program.
Key difference between
import
anduse
In any
import
statement, the set of symbols imported are eitherknown (e.g.,
import B.x
introduces one symbol namedx
), or ifthe entire module is imported, it is prefixed so as not to be
ambiguous (have to write
B.x
).When a
use
occurs, the entire contents of the used module aredumped into a shadow-scope.
In other words, in an
import
, the set of possible conflicts areknown and usually small in number. In a
use
, they cannot be knownwithout first collecting all the symbols introduced by the
use
.This number of symbols can grow quite large.
Should errors be at point-of-mention or at
import
/use
?Since the set of symbols in an import are known, it seems reasonable
to emit redefinition errors for
import
at theimport
statementitself, regardless of whether or not the
import
ispublic
orprivate
.This leaves only
public use
. Because the intention ofpublic
isto make the symbols available for outside use (e.g, as a library
author), it also seems reasonable to emit redefinition errors at
the point of
public use
rather than the point-of-mention.The text was updated successfully, but these errors were encountered: