Bug 11451 – import statements don't work when compiling several files at once

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2013-11-06T05:15:16Z
Last change time
2024-12-13T18:13:46Z
Assigned to
No Owner
Creator
Atila Neves
Moved to GitHub: dmd#18709 →

Comments

Comment #0 by atila.neves — 2013-11-06T05:15:16Z
This code reproduces the problem: ./foo/bar/baz.d: void bazFunc() { } ./bazuser.d: { void userFunc() { bazFunc(); } dmd -c foo/bar/baz.d; dmd -c bazuser.d # ok dmd -c foo/bar/baz.d bazuser.d bazuser.d(1): Error: module baz from file foo/bar/baz.d must be imported as module 'baz' dmd -c bazuser.d foo/bar/baz.d bazuser.d(1): Error: module baz from file foo/bar/baz.d must be imported as module 'baz' This despite any "module" declaration. This makes using rdmd impossible with the above code.
Comment #1 by public — 2013-11-06T05:25:43Z
Looks like "accepts invalid" for the first (separate compilation) case. You always must have either import statement or explicit "extern" declaration to use the symbol. Should be compilation error in both cases.
Comment #2 by public — 2013-11-06T05:30:00Z
Ah, I see what you mean, you examples are actually incomplete (it will fail to compile with no import statements as expected) Most likely you are trying to import baz.d from bazuser via `import foo.bar.baz` and getting this error. This is expected and by design as module name equals to file name by default and you are importing it via qualified (package) name. Adding `module foo.bar.baz;` at top for baz.d will fix it.
Comment #3 by atila.neves — 2013-11-06T06:10:00Z
(In reply to comment #2) > Ah, I see what you mean, you examples are actually incomplete (it will fail to > compile with no import statements as expected) > > Most likely you are trying to import baz.d from bazuser via `import > foo.bar.baz` and getting this error. This is expected and by design as module > name equals to file name by default and you are importing it via qualified > (package) name. Adding `module foo.bar.baz;` at top for baz.d will fix it. Yeah, sorry, I forgot to include `import foo.bar.baz` at the top of `bazuser.d`. I know that adding `module foo.bar.baz` to `baz.d` will "fix it", unless I decide to import it from somewhere else. Basically now the module needs to know where it will be compiled from to declare itself properly, which doesn't make any sense. And besides, separate compilation works as intended, why would passing in both file names make a difference?
Comment #4 by public — 2013-11-06T06:25:10Z
D module system is tightly tied to the filesystem. When you change the root of import path, module names change by design / spec. All existing D projects that have packages define single "correct" import path for application to compile and assign module names relative to it, it is intended way to go. Now that you say it, it is quite interesting that separate compilation works here. IMHO it shouldn't. For some reason compiling `dmd -c a.d` emits unqualified `U` symbol into symbol file, this is why it does work. As far as I understand, it really should emit a qualified one.
Comment #5 by atila.neves — 2013-11-06T08:15:05Z
(In reply to comment #4) > D module system is tightly tied to the filesystem. When you change the root of > import path, module names change by design / spec. All existing D projects that > have packages define single "correct" import path for application to compile > and assign module names relative to it, it is intended way to go. > > Now that you say it, it is quite interesting that separate compilation works > here. IMHO it shouldn't. For some reason compiling `dmd -c a.d` emits > unqualified `U` symbol into symbol file, this is why it does work. As far as I > understand, it really should emit a qualified one. I know the module system is tied to the filesystem. I think it's an excellent idea. I also understand that the module name changes depending on where you compile it from. This is why when I'm at the root of the fictional project above I import foo.bar.baz, not baz or bar.baz. That's all good, and it works when I compile the files separately. What doesn't work is compiling the files together, for some strange reason. I went back to TDPL after I ran into this my understanding is that if you want to control what name will be used to import it, then go ahead and use "module blah". But that's not what I want, I want to use the directory structure. Which, again, works when invoking dmd separately for each file but not when passing multiple files in. Am I missing something?
Comment #6 by public — 2013-11-06T08:22:11Z
(In reply to comment #5) > Am I missing something? http://dlang.org/module.html "The module name is the file name with the path and extension stripped off." That means that implicit module names are always unqualified and illegal to use with nested source tree. The fact that it works when you do separate compilation is symbol emitting bug. It shouldn't. However, I do agree that changing specification to infer module name to be fully qualified based on used import root path is a good addition to existing system. It will be an enhancement request though.
Comment #7 by atila.neves — 2013-11-07T04:49:14Z
> http://dlang.org/module.html > > "The module name is the file name with the path and extension stripped off." I'm still confused. So when is the module's fully qualified name ever used in the absence of a module declaration? From the link above: ImportDeclaration: import ImportList ; static import ImportList ; ImportList: Import ImportBindings Import , ImportList Import: ModuleFullyQualifiedName ModuleAliasIdentifier = ModuleFullyQualifiedName and: ModuleDeclaration: module ModuleFullyQualifiedName ; ModuleFullyQualifiedName: ModuleName Packages . ModuleName The way I still read it is if the module declaration is not present, then ModuleName is the filename without the path or extension, but ModuleFullyQualifiedName would depend on where compilation takes place.
Comment #8 by public — 2013-11-07T05:08:09Z
(In reply to comment #7) > So when is the module's fully qualified name ever used in > the absence of a module declaration? Never. It is only used when provided explicitly. > The way I still read it is if the module declaration is not present, then > ModuleName is the filename without the path or extension, but > ModuleFullyQualifiedName would depend on where compilation takes place. I guess you may assume that `import` statement and module name are synchronized in some way. This is not true. This is how import happens: 1) `import` statement gets directly converted into relative file path (dots replaced with "/" and ".d" extension added) 2) If file with such relative path exists when searching from one of `-I` paths, its module name is checked. 3) If `module` statement is present in file, it is used as module name. Otherwise it is _always_ unqualified file name stripped from extension. 4) If module name does not match name in import statement, compilation error happens. Comparison is fully qualified, so "src.mymod" != "mymod". Your quoted text is not a language spec, it is just a grammar definition which simply describes what statements are allowed to include qualified module name (== "stuff with dots"). It says nothing about semantics.
Comment #9 by atila.neves — 2013-11-07T05:27:54Z
I think I finally got it, but it took some experimentation with different directory and file names. If I have it right, the only time I can get away with not using a module declaration is when the file will only be imported by files in the same directory as itself. Correct?
Comment #10 by public — 2013-11-07T05:36:24Z
(In reply to comment #9) > I think I finally got it, but it took some experimentation with different > directory and file names. > > If I have it right, the only time I can get away with not using a module > declaration is when the file will only be imported by files in the same > directory as itself. Correct? Yep, exactly. This is exactly what I have meant by "not a bug, but good enhancement request".
Comment #11 by public — 2013-11-26T07:22:38Z
As a possible enhancement on this topic I'd propose to infer module name by default to name qualified from base import path that was used to find the .d file. Assuming that it later will be compiled with same path as base directory, most simple layout should just work without redundant name duplication.
Comment #12 by atila.neves — 2018-06-13T14:31:30Z
I've edited the title because the more pressing concern is that 64-bit dmd on Windows currently (from version 2.080.0 at least) doesn't work. It crashes frequently and/or produces binaries that crash themselves. I've tried using digger, building it myself and even using different versions of host dmd to build it. It must be said that I am copying the built dmd.exe over the one from the installer. I'd create an alternate installer instead but installing the dependencies is non-trivial. This method has worked in the past. I've been racking my brain trying to figure out why dmd would crash itself this way and can't find a reason. I'm not sure why phobos or drumtime would be different given that the new dmd is built from the same tag and the only difference is that it's a 64-bit binary itself instead of 32-bit.
Comment #13 by robert.schadek — 2024-12-13T18:13:46Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18709 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB