Compiler does not automatically resolve to function with same name as module:
fun.d:
import std.stdio;
void fun() { writeln("Hello"); }
funmain.d:
import fun;
void main() { fun(); }
$ dmd -offun fun.d funmain.d
funmain.d(2): Error: function expected before (), not module fun of type void
However, in case of struct-s and classes with same name, there is no problem:
str.d:
struct str { int a; }
strmain.d:
import str;
void main() { str var; var.a = 2; }
$ dmd -ofstr str.d strmain.d
cla.d:
class cla { int a; }
clamain.d:
import cla;
void main() { auto var = new cla; var.a = 2; }
$ dmd -ofcla cla.d clamain.d
If it is possible with types, and indeed it is meaningful to name a module after the main type or function defined therein, there seems to be no reason for not being able to resolve to a function with the same name as a module.
Of course, doing `import fun: fun;` will work, but that is unnecessary verbosity and is not being required even now in the case of types as shown above. In D, the compiler is all powerful and can know which resolution of which symbol is appropriate where. The same capability should apply here also.
Thank you!
Comment #1 by razvan.nitu1305 — 2017-10-20T09:29:35Z
The problem here is that in the first example you are doing symbol resolution while in the second case you are doing type resolution.
Here is what happens in the first case: the generated AST in this case, can be roughly reduced to : IdentifierExp -> CallExp. When semantic is performed on the IdentifierExp node, the symbol "fun" is resolved following these rules [1]. Note that no type check is performed, just plain string comparison, so "fun" is resolved to the import symbol. Later, when semantic is performed on the child node, the CallExp node, the type checks are performed and indeed you cannot call a module declaration as a function, hence the error you receive.
The second case, on the other hand, is doing type resolution, which implicitly checks that the types are equal (through pointer comparison). That is why the second case compiles successfully .
So, by all means the compiler is doing the right thing. Note that calling fun.fun compiles successfully.
I suggest we close this as invalid.
[1] https://dlang.org/spec/module.html#name_lookup
Comment #2 by code — 2017-10-20T22:04:19Z
Yes, there is little chance to support functions, as the same symbol would need to be resolved differently, e.g. in `.fun.fun` it's the module, but in `.fun()` it's supposed to be the function.
While the type resolution seems inconsistent, it is a common Java idiom to name source files after the main class/type, and it's widely used in (older) D libraries.
Comment #3 by schveiguy — 2017-10-20T22:57:14Z
I'm not recommending to reopen, but just to be clear here, the issue is ONLY a problem with top level packages and modules:
For example:
import std.stdio;
void std() {} // error
void stdio() {} // ok
This limits what you can name your top-level modules and packages, because any time you import something, it defines the symbol in the importing. Public imports don't do this. For example std.stdio publicly imports core.stdc.stdio. But I can define a `core` function in the above example.
I know this is because of the rules, and I know that we want to keep things simple. But consider that any library that defines a top-level module (probably because the library is simple) is invading the namespace of whoever imports it.
It might be worth considering alternatives to how it's currently designed/implemented, if only just for top-level modules/packages.