September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 23 September 2014 at 19:18:08 UTC, H. S. Teoh via Digitalmars-d wrote:
> But this would cause a compile error:
>
> ----mod.d----
> module mod;
> string x, y;
>
> ----main.d----
> void main() {
> int x, y, z;
> import mod;
>
> x++; // Error: ambiguous symbol 'x', could be local
> // variable 'x' or mod.x
> }
>
>
> T
How do you disambiguate to say "the x I want is the local one" ?
IMO, simply make it that local imports work like global ones, but scoped. Global imports don't have this issue, why should local imports have special rules?
|
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Tue, Sep 23, 2014 at 07:47:59PM +0000, monarch_dodra via Digitalmars-d wrote: > On Tuesday, 23 September 2014 at 19:18:08 UTC, H. S. Teoh via Digitalmars-d wrote: > >But this would cause a compile error: > > > > ----mod.d---- > > module mod; > > string x, y; > > > > ----main.d---- > > void main() { > > int x, y, z; > > import mod; > > > > x++; // Error: ambiguous symbol 'x', could be local > > // variable 'x' or mod.x > > } > > > > > >T > > How do you disambiguate to say "the x I want is the local one" ? > > IMO, simply make it that local imports work like global ones, but scoped. Global imports don't have this issue, why should local imports have special rules? Sounds reasonable. How would that be implemented, though? Currently, in the compiler, lookup is implemented via a linked list of Scope objects that contain, among other things, a symbol table for the symbols declared in that scope. A local import achieves locality by adding symbols to the current (i.e., innermost) Scope, since doing otherwise would cause those symbols to "spill" into the outer scopes and they will persist past the lifetime of the current scope. OTOH, it's this importing into the innermost scope that causes this issue to begin with, since by definition, the innermost scope takes precedence over outer scopes, so the imported symbols would shadow symbols declared in outer scopes. Implementing what you suggest would either involve treating imported symbols separately (by having multiple parents per scope, which quickly devolves into a mess, or otherwise having sibling pointers to imported scopes, which also greatly complicates lookup logic), or sticking symbols into outer scopes and keeping track of which symbols were imported where so that they can be removed after we leave the current scope -- which is fragile and would again add tons of complications to the compiler. T -- What do you get if you drop a piano down a mineshaft? A flat minor. |
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 23 September 2014 at 20:10:35 UTC, H. S. Teoh via Digitalmars-d wrote: > Sounds reasonable. How would that be implemented, though? Currently, in > the compiler, lookup is implemented via a linked list of Scope objects > that contain, among other things, a symbol table for the symbols > declared in that scope. A local import achieves locality by adding > symbols to the current (i.e., innermost) Scope, since doing otherwise > would cause those symbols to "spill" into the outer scopes and they will > persist past the lifetime of the current scope. Arguably, that's not my problem... > OTOH, it's this importing into the innermost scope that causes this > issue to begin with, since by definition, the innermost scope takes > precedence over outer scopes, so the imported symbols would shadow > symbols declared in outer scopes. I think that's the issue here. Are we actually importing "into" the innermost scope, while shadowing any previous imports? AFAIK, that's a behavior which is reserved for selective imports. As I said, local imports, IMO, should behave in all aspects as a global import. It simply only exists during its scope, but is not actually any more "internal" than the rest. If a local import creates a symbol ambiguity, then it's ambiguous, and compilation ceases. I think that's the behavior we should be going for. > Implementing what you suggest would either involve treating imported > symbols separately (by having multiple parents per scope, which quickly > devolves into a mess, or otherwise having sibling pointers to imported > scopes, which also greatly complicates lookup logic), or sticking > symbols into outer scopes and keeping track of which symbols were > imported where so that they can be removed after we leave the current > scope -- which is fragile and would again add tons of complications to > the compiler. > > > T Unfortunately, I don't know how the compiler works. |
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu:
> I've raised https://issues.dlang.org/show_bug.cgi?id=10378 to critical. Please chime in with ideas for a good solution. Thanks! -- Andrei
I think this code:
import foo;
void main() {}
should import only the "foo" identifier in the current module/scope (or fail to do so). This requires you to use foo.bar to access the name bar inside foo (and all the names inside the module are private on default, so you need to add a "public" to the ones you want to be visible outside the module). Plus if you want to avoid specifying the module/package in your module you can also use:
import foo: bar;
You can also do this, but this is discouraged:
import foo: *;
This last command is refused if some name shadowing happens.
When the module name clashes with a local name you have to use a renaming import:
void main(string[] args) {
import margs = args;
}
But this design can't be used now in D. So I suggest to add anti hijacking logic similar to the with() command. When such name hiding errors are generated by a local import, the programmer has to list imported names, or use renamed imports.
Bye,
bearophile
|
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 23 September 2014 at 18:52:13 UTC, H. S. Teoh via
Digitalmars-d wrote:
> 1) Change lookup rules so that symbols pulled in by local import are
> found last. Walter has stated that he disagrees with this approach
> because it complicates symbol lookup rules.
>
That is dead simple compared to alias this, opDispatch or with
statement. That is a non argument.
This solution is simple (ie look local symbols, then look imports
is easy to understand) and would prevent hijacking and introduce
much less complications than alternatives.
|
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 23 September 2014 at 19:03:28 UTC, H. S. Teoh via
Digitalmars-d wrote:
> Good luck convincing Walter, then. :-( Or maybe if we can convince
> Andrei to twist his arm hard enough... :-P
>
In SDC? doing this represent ~30 lines on a 600+ line identifier
resolution (plus several other hundred line disambiguation for
overload and/or templates, constructor, IFTI and so on, that
aren't handled there).
|
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 23 September 2014 at 18:34:51 UTC, Andrei Alexandrescu wrote: > I've raised https://issues.dlang.org/show_bug.cgi?id=10378 to critical. Please chime in with ideas for a good solution. Thanks! -- Andrei In the meantime, anybody who wants to know if their code is vulnerable to this problem can grab D-Scanner from git master and run the style checker. https://github.com/Hackerpilot/Dscanner/commit/95c8b1b19a1ec235aa50b7e9c2e0f4d5a4b1d404 |
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 09/23/2014 10:19 PM, monarch_dodra wrote:
>
> As I said, local imports, IMO, should behave in all aspects as a global
> import. It simply only exists during its scope, but is not actually any
> more "internal" than the rest. If a local import creates a symbol
> ambiguity, then it's ambiguous, and compilation ceases. I think that's
> the behavior we should be going for.
I have previously suggested to first look up symbols in local scopes, and only if no match is found within the current module, all imports that are in visible scopes are considered. I think this has the effect you are after. Is this what you are proposing?
|
September 23, 2014 Re: Local imports hide local symbols | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Alexander | On 09/23/2014 09:01 PM, Peter Alexander wrote:
> On Tuesday, 23 September 2014 at 18:52:13 UTC, H. S. Teoh via
> Digitalmars-d wrote:
>> 1) Change lookup rules so that symbols pulled in by local import are
>> found last. Walter has stated that he disagrees with this approach
>> because it complicates symbol lookup rules.
>
> This.
Agreed, but only if this is implemented such that more deeply nested imports do not shadow less deeply nested imports.
I.e. if modules 'a' and 'b' both declare variables 'foo', then:
import a;
int fun(int foo){
import b; // fine
return foo; // fine, refers to parameter
}
auto gun(){
import b;
return foo; // error, could be a.foo or b.foo
}
|
Copyright © 1999-2021 by the D Language Foundation