The following errors out with "main.d(5): Error: undefined identifier 'mod'":
main.d
---
import test;
import test.mod;
void main() {
test.mod.func();
}
---
test/package.d
---
module test;
---
test/mod.d
---
module test.mod;
void func() {}
---
Seems like ".test" now refers to the module instead of the package and thus there is no sub module "mod". Tested on DMD 2.064.2.
Comment #1 by k.hara.pg — 2014-01-04T23:24:21Z
(In reply to comment #0)
> The following errors out with "main.d(5): Error: undefined identifier 'mod'":
>
> main.d
> ---
> import test;
> import test.mod;
>
> void main() {
> test.mod.func();
> }
> ---
Currently this is by design. If you use fully qualified name that starts with "test.", test/package.d is always preferred to avoid ambiguity.
Comment #2 by sludwig — 2014-01-05T01:08:27Z
So how would I specify a qualified name in test.mod?
Comment #3 by k.hara.pg — 2014-01-05T01:19:53Z
(In reply to comment #2)
> So how would I specify a qualified name in test.mod?
There's no way, if you import both test/package.d and test/mod.d.
I think it is legitimate limitation of the new package.d feature.
Comment #4 by sludwig — 2014-01-05T01:55:42Z
I think this is actually totally unacceptable and a *serious* design flaw. What this means is that it is now impossible to reference any sub module of "test" as soon as "test" is imported. This seems to be based on the assumption that "package.d" modules always import all modules of their package, which is just wrong. There are many possible reasons why it would exclude certain modules.
This also means that it is now impossible to disambiguate conflicting symbols when one of them is in such a sub module. This completely breaks the module system.
A real world example, where it is important to be able to handle this cleanly, is an automatically generated function that iterates over all modules of a project (It's a unit test runner that runs all unit tests for each module). It contains code similar this:
---
static import test;
static import test.mod;
alias AllModules = TypeTuple!(test, test.mod); // error
main() {
foreach (mod; AllModules) ...
}
---
The only half reasonable thing that could be done there is to generally ignore all "package.d" modules. And that is based on the assumption that "package.d" modules *only* import all sub modules and have no own declarations, which, in general, again is wrong.
Also, if there is no NG or conference discussion that I didn't see, there is no sign in the original DIP that this issue was even considered before implementing it. In this case, calling it by design may be a slight exaggeration.
Comment #5 by code — 2014-05-30T16:33:57Z
I agree with Söhnke here, it should still be possible to import submodules and it should also be possible to use fully qualified names.
Comment #6 by issues.dlang — 2014-06-02T23:53:01Z
I also agree with Sönke. There should be no difference between publicly imported modules in package.d and publicly imported modules in any other module. All package.d should be doing is making it so that when you import the package, you import package.d instead. It shouldn't have any other effects.
import test;
import test.mod;
should work just as well as
import std.array;
import std.range;
does. std.array.uninitializedArray doesn't suddenly stop working just because you also imported std.range, which publicly imports std.array.
Comment #7 by issues.dlang — 2014-06-02T23:56:09Z
Also, keep in mind that the whole reason to add package.d to the language in the first place was to be able to break up a module into a package, in which case, it's intended as a migration path and not necessarily as something permanent, so making it so that importing a package conflicts with importing its individual modules is very likely to cause problems - especially if new modules with code that wasn't in the original module that was split are added after it's been split (since they likely wouldn't be publicly imported in the package.d file, because that's unnecessary for migration).
Comment #8 by bus_dbugzilla — 2015-05-12T16:33:47Z
I've hit this problem too, and it's a pain in the ass. It makes it nearly impossible to resolve a symbol ambiguity whenever a package.d is involved. It effectively destroys the ability for "package.d" to do it's primary intended job: Let module authors break up a module without breaking user code. This needs fixed.
I have found out that renamed imports in the can be used as a workaround:
test/package.d
---
module test;
import mod = test.mod;
---
test/mod.d
---
module test.mod;
import std.stdio;
void func(){writeln("hello world");}
---
main.d
---
import test;
import test.mod;
void main() {
func();
}
---
compiled and worked as expected (prints "hello world")
Comment #11 by dlang-bugzilla — 2017-07-26T09:54:35Z
*** Issue 17683 has been marked as a duplicate of this issue. ***
Comment #12 by code — 2017-10-15T08:12:02Z
Weird, only seems to fail for top-level packages, but not for nested `std.pkg` and `std.pkg.mod` cases.
@BorisCarvajal updated dlang/dmd pull request #10745 "Fix Issues 20530, 20537 - resolve trait isPackage/isModule and is(package/module) quirks" fixing this issue:
- Fix Issue 11847 - sub-pkg not available as qualified name (test case)
https://github.com/dlang/dmd/pull/10745
Comment #15 by dlang-bot — 2020-02-11T03:11:14Z
dlang/dmd pull request #10745 "Fix Issues 20530, 20537 - resolve trait isPackage/isModule and is(package/module) quirks" was merged into stable:
- e2d0de02abe32002f8aaff879bb6a44dae978b70 by Boris Carvajal:
Fix Issue 11847 - sub-pkg not available as qualified name (test case)
https://github.com/dlang/dmd/pull/10745