www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Name lookups in D

reply Dibyendu Majumdar <d.majumdar gmail.com> writes:
This fails:

module a.b.m;

int hello() {
    return 42;
}

extern (C) void main() {
    assert (a.b.m.hello() == 42);
}

Is it supposed to?
Nov 15 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 15 November 2020 at 22:20:12 UTC, Dibyendu Majumdar 
wrote:
 This fails:

 module a.b.m;

 int hello() {
    return 42;
 }

 extern (C) void main() {
    assert (a.b.m.hello() == 42);
 }

 Is it supposed to?
Yes, the fully-qualified name of a module is not in scope unless you `static import` it. There is one exception: you are always allowed to use a fully-qualified name on the right-hand side of an alias declaration. See <https://dlang.org/spec/declaration.html#alias>.
Nov 15 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/15/20 5:38 PM, Paul Backus wrote:
 On Sunday, 15 November 2020 at 22:20:12 UTC, Dibyendu Majumdar wrote:
 This fails:

 module a.b.m;

 int hello() {
    return 42;
 }

 extern (C) void main() {
    assert (a.b.m.hello() == 42);
 }

 Is it supposed to?
Yes, the fully-qualified name of a module is not in scope unless you `static import` it.
This isn't true. you can import a module and still use the FQN: import std.stdio; std.stdio.writeln("bar"); // OK Note, if the module name is a single identifier, you can use it. This seems like a weird limitation based on the fact that the package isn't defined. It was introduced when the imports were fixed, but I'm not sure this was intentional. If I put the above code in, and use the wayback compiler machine at run.dlang.io: Up to 2.070.2: Success and no output 2.071.2 to 2.078.1: Success with output: onlineapp.d(7): Deprecation: package a.b is not accessible here 2.079.1 to 2.083.1: Success with output: onlineapp.d(7): Deprecation: package `a.b` is not accessible here 2.084.1 to 2.086.1: Failure with output: onlineapp.d(7): Error: package `a.b` is not accessible here Since 2.087.1: Failure with output: onlineapp.d(7): Error: undefined identifier `b` in package `a`, perhaps add `static import a.b;` IMO, you should be able to access the package you are defined in. -Steve
Nov 16 2020
next sibling parent Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Monday, 16 November 2020 at 13:07:21 UTC, Steven Schveighoffer 
wrote:
 On 11/15/20 5:38 PM, Paul Backus wrote:
 On Sunday, 15 November 2020 at 22:20:12 UTC, Dibyendu Majumdar 
 wrote:
 This fails:

 module a.b.m;

 int hello() {
    return 42;
 }

 extern (C) void main() {
    assert (a.b.m.hello() == 42);
 }

 Is it supposed to?
This seems like a weird limitation based on the fact that the package isn't defined. IMO, you should be able to access the package you are defined in.
It didn't make sense to me - thank you for confirming. Regards
Nov 16 2020
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/16/2020 5:07 AM, Steven Schveighoffer wrote:
 [...]
Please post to bugzilla.
Nov 20 2020
parent Dibyendu Majumdar <mobile majumdar.org.uk> writes:
On Saturday, 21 November 2020 at 02:02:51 UTC, Walter Bright 
wrote:
 On 11/16/2020 5:07 AM, Steven Schveighoffer wrote:
 [...]
Please post to bugzilla.
https://issues.dlang.org/show_bug.cgi?id=21413
Nov 21 2020
prev sibling parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 16 November 2020 at 13:07:21 UTC, Steven Schveighoffer 
wrote:
 import std.stdio;

 std.stdio.writeln("bar"); // OK
Is this expected? void main () { { import std.stdio; std.stdio.writeln ("test"); // okay } { import std.stdio : writeln; std.stdio.writeln ("test"); // Error: undefined identifier std } }
Dec 10 2020
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 11 December 2020 at 01:34:13 UTC, kdevel wrote:
 Is this expected?
Yes, and this is kinda why I don't like using selective imports. With a normal import, the module name is the only thing actually added to the scope. Everything in that module is found by walking the import chains after not finding it locally (unless you use `static import` which means it does not add it to the chain). With a selective import, the only thing added is the specific name you did. The module name is NOT in scope and there is no chain established. Selective imports are more like making an alias than other imports.
Dec 10 2020
parent reply kdevel <kdevel vogtner.de> writes:
On Friday, 11 December 2020 at 01:38:44 UTC, Adam D. Ruppe wrote:

[...]

 With a normal import, the module name is the only thing 
 actually added to the scope. Everything in that module is found 
 by walking the import chains after not finding it locally 
 (unless you use `static import` which means it does not add it 
 to the chain).
Just 'implemented' the following bug: ~~~ import std.conv; class B { } class D : B { string text; } void main () { B b = new D; string s = b.text; } ~~~ Due to UFCS std.conv.text grabs the object. Only a `static import` or a selective import would reveal the problem during compile time.
Dec 13 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/13/20 4:54 PM, kdevel wrote:
 On Friday, 11 December 2020 at 01:38:44 UTC, Adam D. Ruppe wrote:
 
 [...]
 
 With a normal import, the module name is the only thing actually added 
 to the scope. Everything in that module is found by walking the import 
 chains after not finding it locally (unless you use `static import` 
 which means it does not add it to the chain).
Just 'implemented' the following bug: ~~~ import std.conv; class B { } class D : B {    string text; } void main () {    B b = new D;    string s = b.text; } ~~~ Due to UFCS std.conv.text grabs the object. Only a `static import` or a selective import would reveal the problem during compile time.
This is expected behavior. B does not have a member named "text", and so it looks for a UFCS function to call and finds one. Note that a static import means you have to use the FQN to call text (but text is perfectly fine via UFCS). However, a selective import would still call text as expected. -Steve
Dec 14 2020
parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 14 December 2020 at 16:21:56 UTC, Steven Schveighoffer 
wrote:
[...]
 Just 'implemented' the following bug:
 
 ~~~
 import std.conv;
 
 class B {
 }
 
 class D : B {
     string text;
 }
 
 void main ()
 {
     B b = new D;
     string s = b.text;
 }
 ~~~
 
 Due to UFCS std.conv.text grabs the object. Only a `static 
 import`
 or a selective import would reveal the problem during compile 
 time.
This is expected behavior.
Sure. In the original code the missing downcast was not that easily discernible.
 B does not have a member named "text", and so it looks for a 
 UFCS function to call and finds one.

 Note that a static import means you have to use the FQN to call 
 text (but text is perfectly fine via UFCS). However, a 
 selective import would still call text as expected.
The original code accessed only std.conv.to. A selective import of `to` would have complained and helped to spot the error: q.d(13): Error: no property text for type q.B, perhaps import std.conv; is needed? BTW: Most of the time dmd's guess is accurate.
Dec 14 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/14/20 12:59 PM, kdevel wrote:
 On Monday, 14 December 2020 at 16:21:56 UTC, Steven Schveighoffer wrote:
 This is expected behavior.
Sure. In the original code the missing downcast was not that easily discernible.
I understand. There is sometimes confusion when a ufcs "member" is found. I've seen a lot of weird things like this. But the compiler can only tell what you want from the code you write, it can't look at the intentions behind it. Especially when you make a mistake. I've had countless times where I reach for something.to!somethingelse and I forgot to import std.conv, but I've happened to import std.datetime (which has a similar ufcs `to` function). And the error message is always confusing. I don't think this is fixable. You just have to live with it. It's unfortunate that it compiles, and doesn't give an error. "Best effort" functions like text that *always* compile can be hard to diagnose when you call them by accident.
 B does not have a member named "text", and so it looks for a UFCS 
 function to call and finds one.

 Note that a static import means you have to use the FQN to call text 
 (but text is perfectly fine via UFCS). However, a selective import 
 would still call text as expected.
The original code accessed only std.conv.to. A selective import of `to` would have complained and helped to spot the error:
OK, I thought you meant a selective import of std.conv.text.
 
 q.d(13): Error: no property text for type q.B, perhaps import std.conv; 
 is needed?
 
 BTW: Most of the time dmd's guess is accurate.
Those suggestions are hard-coded into the compiler, and I sometimes wish they were more comprehensive. But I don't see any future in which the compiler is going to suggest "maybe you meant to downcast to type D". It just can't see what you were thinking. -Steve
Dec 14 2020
parent kdevel <kdevel vogtner.de> writes:
On Monday, 14 December 2020 at 18:54:58 UTC, Steven Schveighoffer 
wrote:

 But the compiler can only tell what you want from the code you 
 write, it can't look at the intentions behind it. Especially 
 when you make a mistake.
Until AI takes over this is clearly the case. I just wonder if selective imports are worth the additional typing. They obviously prevent the namespace pollution with greedy function templates like text.
 I've had countless times where I reach for 
 something.to!somethingelse and I forgot to import std.conv, but 
 I've happened to import std.datetime (which has a similar ufcs 
 `to` function).
Thanks for this warning ;-)
Dec 14 2020
prev sibling parent aberba <karabutaworld gmail.com> writes:
On Friday, 11 December 2020 at 01:34:13 UTC, kdevel wrote:
 On Monday, 16 November 2020 at 13:07:21 UTC, Steven 
 Schveighoffer wrote:
 import std.stdio;

 std.stdio.writeln("bar"); // OK
Is this expected? void main () { { import std.stdio; std.stdio.writeln ("test"); // okay } { import std.stdio : writeln; std.stdio.writeln ("test"); // Error: undefined identifier std } }
This behaviour makes sense to me...you've explicitly exposed only that symbol.
Dec 11 2020