-
-
Notifications
You must be signed in to change notification settings - Fork 693
Deprecate import/module name mismatch (ALL CASES) #7778
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| Deprecate import module name mismatch | ||
|
|
||
| Some instances of module name/import name mismatches were deprecated while others are now considered errors. | ||
|
|
||
| Case 1: DEPRECATED: import a module name with a qualified name but the module being imported has no module declaration. | ||
| --- | ||
| // main.d | ||
| import foo.bar; | ||
|
|
||
| // foo/bar.d | ||
| // this file is empty, it has no module declaration | ||
| --- | ||
| The above code will now print: | ||
|
|
||
| $(CONSOLE Deprecated: module bar from file foo/bar.d should be imported with 'import bar;' ) | ||
|
|
||
| Case 2: DEPRECATED: import a module with a qualified name that partially matches the name of the module being imported. | ||
| --- | ||
| // main.d | ||
| import foo.bar; | ||
| import foo.baz.buz; | ||
|
|
||
| // foo/bar.d | ||
| module bar; | ||
|
|
||
| // foo/baz/buz.d | ||
| module baz.buz; | ||
| --- | ||
| The above code will now print: | ||
|
|
||
| $(CONSOLE Deprecated: module bar from file foo/bar.d should be imported with 'import bar;' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively: replace module declaration with We need to show advantages of this as well. For example show how the current rules lead to a breach in modularity. My current mental model goes like this: import takezat = foo.bar;We'd need a good argument that the above is a bad thing.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. That's not how I originally understood the module system to work, but your description matches the implementation that I found. One disadvantage of the current mechanism is that this causes the compiler to load the same module multiple times. Each unique path used to import the module will result in another instance of the module being instantiated. I think there's more to say but I'll leave it at that for now. |
||
| Deprecated: module baz.buz from file foo/baz/buz.d should be imported with 'import baz.buz;' ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A similar line of reasoning would apply here. We need to build a case on why that's bad. |
||
|
|
||
| Note that for this rule to apply, the shorter name must completely match the end of the longer name. | ||
|
|
||
| Case 3: ERROR: import a module that matches the filename but does not match the module name. | ||
| --- | ||
| // main.d | ||
| import foo; | ||
|
|
||
| // foo.d | ||
| module bar; | ||
| --- | ||
| The above code will now fail and print: | ||
|
|
||
| $(CONSOLE Error: module bar from file foo.d must be imported with 'import bar;') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand how the file would ever be found. So the compiler is supposed to compile
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The file is give on the command line. Note that module names not matching file names is a technique already used (see #7778 (comment)) , however, this PR does enforce that the import name matches the actual module name. |
||
|
|
||
| Note that importing a module whose module name does not match its filename is still supported. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -313,3 +313,22 @@ unittest | |
| array[2] = 910; | ||
| assert([123, 421, 910, 123, 1, 2, 8, 20, 4, 3] == array.asDArray); | ||
| } | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why isn't it called opEqual ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allows you to compare to pointers to array and handles the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, changed it to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would have to be |
||
| /** | ||
| * Returns true if every element of $(D left) and $(D right) are equal. | ||
| * Note that an array of size 0 is considered equivalent to a `null` pointer. | ||
| * Params: | ||
| * left = pointer to array to compare | ||
| * right = pointer to array to compare | ||
| */ | ||
| bool opEquals(T)(const(Array!T)* left, const(Array!T)* right) | ||
| { | ||
| if (left is null || left.dim == 0) | ||
| return right is null || right.dim == 0; | ||
| if (right is null || left.dim != right.dim) | ||
| return false; | ||
| foreach (i; 0 .. left.dim) | ||
| if ((*left)[i] != (*right)[i]) | ||
| return false; | ||
| return true; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| module imports.test14894a; | ||
| module test14894a; | ||
|
|
||
| mixin template Protocol() | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.a313templatemixin1; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this necessary? We should continue to work if the module declaration is not present.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's one way to go. You could also add the then no module declaration is required.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @marler8997 can't we just penalize people who enter wrong module information? It seems this PR does that but also adds another restriction, which is more difficult to justify.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I'm not sure exactly what you're trying to say. There's 2 cases listed in the original PR message that have been deprecated, and 1 that has been declared to be an error. Do those use cases categorize the cases you are thinking of? If so, which ones do you think should not be deprecated/made errors?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @marler8997 yah let me discuss exactly on the cases you present in the changelog. Thanks for the neat organization. |
||
| void bug() | ||
| { | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.a313templatemixin2; | ||
| void bug() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.checkimports3a; | ||
| void foo() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.checkimports3b; | ||
| private void foo(int) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.checkimports3c; | ||
| void foo(string) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.fwdref12201a; | ||
| alias int FILE; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,9 @@ | ||
| module fwdref2_test17548; | ||
| module imports.fwdref2_test17548; | ||
|
|
||
| import test17548; | ||
|
|
||
| struct S2 { | ||
| void bar(int arg = .test17548.cnst) {} | ||
| S1 s; | ||
| import fwdref2_test17548; | ||
| import imports.fwdref2_test17548; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.fwdref9514; | ||
| bool find9514(alias pred, R)(R range) | ||
| { | ||
| return true; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.g313public; | ||
| void bug() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.g313staticif; | ||
| void bug() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.g313stringmixin; | ||
| void bug() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.g313templatemixin; | ||
| void bug() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.imp16085; | ||
| struct Pass | ||
| { | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import imp16085 : S; | ||
| module imports.imp16085b; | ||
| import imports.imp16085 : S; | ||
|
|
||
| struct Fail | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| module imports.protectionimp; | ||
| private | ||
| { | ||
| void privF() {} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| module test11563core_bitop; | ||
| module imports.test11563core_bitop; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| module imports.test15857a; | ||
| public import imports.test15857b; | ||
| public import imports.test15857c; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.test15857b; | ||
| void bar15857(int) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| module imports.test15857c; | ||
| void bar15857(string) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| module imports_test71; | ||
| module imports.test71; | ||
| import imports = object; | ||
|
|
||
| void foo() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| // REQUIRED_ARGS: -de | ||
| import imports.f313; | ||
| // EXTRA_SOURCES: imports/f313.d | ||
| import foo.bar; | ||
|
|
||
| void test() | ||
| { | ||
| imports.f313.bug(); | ||
| foo.bar.bug(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| // REQUIRED_ARGS: -de | ||
| // EXTRA_SOURCES: imports/a314.d | ||
| module imports.test314; // package imports | ||
|
|
||
| import imports.a314; | ||
| import imports.pkg.a314; | ||
|
|
||
| void main() | ||
| { | ||
| imports.a314.bug("This should work.\n"); | ||
| imports.pkg.a314.bug("This should work.\n"); | ||
| renamed.bug("This should work.\n"); | ||
| bug("This should work.\n"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| EXTRA_SOURCES: imports/nomodname.d | ||
| REQUIRED_ARGS: -Ifail_compilation -de | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/badimport.d(10): Error: module `nomodname` from file fail_compilation/imports/nomodname.d must be imported with 'import nomodname;' | ||
| --- | ||
| */ | ||
| import imports.nomodname; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| EXTRA_SOURCES: imports/incompletemodname.d | ||
| REQUIRED_ARGS: -Ifail_compilation -de | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/badimport2.d(10): Error: module `incompletemodname` from file fail_compilation/imports/incompletemodname.d must be imported with 'import incompletemodname;' | ||
| --- | ||
| */ | ||
| import imports.incompletemodname; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| COMPILED_IMPORTS: imports/incompletemodname.d | ||
| REQUIRED_ARGS: -Ifail_compilation | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/badimport3.d(10): Error: module `wrongpkg.wrongpkgname` from file fail_compilation/imports/wrongpkgname.d must be imported with 'import wrongpkg.wrongpkgname;' | ||
| --- | ||
| */ | ||
| import imports.wrongpkgname; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| EXRTRA_SOURCES: imports/wrong_mod_name.d | ||
| REQUIRED_ARGS: -Ifail_compilation/imports | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/badimport4.d(10): Error: module `wrong_mod_name_bleh` from file fail_compilation/imports/wrong_mod_name.d must be imported with 'import wrong_mod_name_bleh;' | ||
| --- | ||
| */ | ||
| import wrong_mod_name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This effectively imposes that modules inside directories (frequent situation) must have a module declaration. Moreover, the module declaration makes the module contents dependent on the directory in which it resides, thus closing a circular dependency between the file content and its position in the file system. Whenever the module is moved around, it needs to also be touched.
These does not seem desirable qualities. On the contrary, it was appreciated that a given module can be accessed via different packages (within e.g. different projects), via directory aliases, etc. It also seems makes it more difficult to define and use hierarchical packages.
What advantages does introducing this restriction have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it just means that they must be imported with a "non-qualified" name.