February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #21 from Walter Bright <bugzilla@digitalmars.com> ---
(In reply to ag0aep6g from comment #19)

Thank you for providing a simple and clear test case to illustrate the issue. It is indeed a problem that the order of imports is mattering, as this breaks a fundamental tenet of D's import system.

I have not thought about this thoroughly, but I suspect the core of a fix can be along the lines of detecting that an explicit import of bar.d is done using two different names in the same module.

This is a lot more focused in effect than the PR.

--
February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #22 from Timothee Cour <timothee.cour2@gmail.com> ---
I don't understand why the current behavior is desired.

Is there any single use case that can't be achieved without existing option such as -mv?

-mv=<package.module>=<filespec>  use <filespec> as source file for <package.module>

--
February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #23 from Jonathan Marler <johnnymarler@gmail.com> ---
> I have not thought about this thoroughly, but I suspect the core of a fix can be along the lines of detecting that an explicit import of bar.d is done using two different names in the same module.

I think you'll find that this is "easier said than done".  The name that was used to import a module is no longer available once the import is processed. The compiler just adds the module to the proper location in thy symbol table and moves on.

Essentially, you need a way to reverse a symbol lookup.  You need to be able to take a Module object and lookup the name that was used to import it.  This will require either a new list field for all imports, or a new list field for all "importees", or you will need to walk the entire symbol table tree every time you want to check if there is a conflict.

The place in the code where you would perform this check is in `dimport.d` in the load function.  Near the top of the funciton there is a branch `if (s.isModule()), and you can insert the check right there.

However, I don't know why we would go through all the trouble to support this. You'd be adding a fair amount of runtime overhead for every import statement or more memory to cache the reverse lookups.  Not to mention the extra complexity this is going to introduce.  And the use case where this actually works is so narrow, it only works if the module are not compiled in the same compiler invocation...

--
February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #24 from Jonathan Marler <johnnymarler@gmail.com> ---
> I have not thought about this thoroughly, but I suspect the core of a fix can be along the lines of detecting that an explicit import of bar.d is done using two different names in the same module.

After having a bit of a think I realized this still doesn't solve the problem. I can change the example to show that module order also changes compilation...observe:

--- main.d
import ibar, ibaz;
void main()
{
    ibarfunc();
    ibazfunc();
}

--- ibar.d
import bar, std.stdio;
void ibarfunc()
{
    writeln(thing);
}

--- ibaz.d
import baz, std.stdio;
void ibazfunc()
{
    writeln(thing);
}

--- bar.d
module baz;
enum thing = "this is baz from bar.d";

--- baz.d
module bar;
enum thing = "this is bar from baz.d";


dmd ibar.d ibaz.d -run main.d
OUTPUT:
this is baz from bar.d
this is baz from bar.d

dmd ibaz.d ibar.d -run main.d
OUTPUT:
this is bar from baz.d
this is bar from baz.d


Note that in the case the same module is not imported with different names in the same file.  So fixing that won't fix this issue.

--
February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #25 from ag0aep6g@gmail.com ---
(In reply to Walter Bright from comment #21)
> I suspect the core of a fix
> can be along the lines of detecting that an explicit import of bar.d is done
> using two different names in the same module.

That would fix a problem, but not this Bugzilla issue.

If you want to attack the issue at hand in the spec, then I suggest we get to that before fixing related-but-not-identical cases. An attempt at amending the spec is likely to reveal more interesting cases.

Also, so far we focused on accepts-invalid cases where we'd like DMD to throw an error instead, but the lack of verification can also lead to wrong code when the wrong module is accepted before the right one is attempted.

Example:


pkg/hello_world.d:
----
module pkg.hello_world;
import std.stdio; /* Should import Phobos's std.stdio. */
void main()
{
    writeln("Hello, world!"); /* Should print "Hello, world!". */
}
----

pkg/std/stdio.d:
----
module pkg.std.stdio; /* NOTE: Not std.stdio. */
void writeln()(string s) /* Template makes for a shorter example. */
{
    import core.stdc.stdio;
    printf("Goodbye, cruel world!\n");
}
----

`cd pkg; dmd hello_world.d && ./hello_world; cd ..`:
----
Goodbye, cruel world!
----


Note that I have no custom module std.stdio. DMD incorrectly picks up pkg.std.stdio as std.stdio, because it ignores the module declaration. Instead, it should look at the module declaration, see that pkg.std.stdio is not std.stdio, and then continue the search for the real std.stdio.

Maybe this too can be fixed without addressing the core problem of missing verification (e.g. with a "best match" kind of thing). But I'm afraid this way leads down a rabbit hole of special cases. In my opinion, it would be better to have a clean cut, maybe with a deprecation period.

--
February 14, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #26 from Jonathan Marler <johnnymarler@gmail.com> ---
After more pondering I believe I've been able to pin down the fundamental problem.

TLDR: The current import semantics fundamentally break import order and module order invariance.

To demonstrate let me describe current import semantics.

import foo;

When the compiler sees this, it first checks if a module has been loaded whose "module name" is `foo`.  The important part is "if a module has been loaded". If this check fails, then it falls back to searching the fileystem for a file matching the import name.  Note that when this occurs, the file that ends up matching the import may not have a "module name" matching the name used to import it.  And this is the fundamental problem.

What this means is that based on what modules have previously been loaded (either via previous modules or previous imports in the same file) the semantics of the import change.  In one case, the import causes a previously loaded module to be imported, and in the other case, it will query the file system for the module.  Since module names don't have to match filenames, this means that the same import can result in loading different modules.  The important distinction is that this change isn't caused by different command line arguments, it's cause by changing the import order or the module order, which breaks order invariance.

--
February 16, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #27 from Jonathan Marler <johnnymarler@gmail.com> ---
Ok.

Walter/Andrei have decided they don't want to drop support to allow an import to match the filename without matching the module name.

Luckily, we have found a way to detect when order invariance is violated while still supporting existing semantics.

So the fix to this issue is to change the spec.  An import name may represent a module name, or a filename, whose module name may not match the file it is contained in.  The solution for the order invariance problem is to detect and assert an error when a module is imported with different names.

--
February 16, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

--- Comment #28 from Timothee Cour <timothee.cour2@gmail.com> ---
Re-asking since no-one answered this:

Is there any single use case that current (broken) behavior allows that
couldn't be done with existing option such as -mv?
```
-mv=<package.module>=<filespec>  use <filespec> as source file for
<package.module>
```

If the answer is 'no but we don't want to break code that relied on this broken behavior', could we at least start deprecation process for this or issue a warning to use -mv instead?

--
October 29, 2018
https://issues.dlang.org/show_bug.cgi?id=15086

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=18517

--
February 06, 2021
https://issues.dlang.org/show_bug.cgi?id=15086

kdevel <kdevel@vogtner.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kdevel@vogtner.de

--