May 18, 2013
On Saturday, May 18, 2013 22:30:30 Rainer Schuetze wrote:
> I think the new behaviour is consistent with symbol lookup rules, but I'm not so sure about import rules. The actual case that triggered the issue was with the base class in a different file. Usually non-public imports in a module don't have an effect on another module that imports the module. In this case it has.

I would argue that the import would need to be _protected_ in order for derived classes to be affected by it if they're not in the same file. Having a private import affect something outside of the file that it's in violates the access rules.

Technically, I don't think that the idea of a protected import exists at the moment, but I think that it's going to have to be added if we're going to have imports follow the symbol lookup rules rather than simply having them restrict themselves to the scope that they're in lexically, which is honestly how I thought that they worked - the fact that they'd have any impact on derived types surprised me considerably.

But also, if you start following symbol lookup rules for whether local imports are visible or not, then you'd have to worry about public imports in a class affecting things in weird ways too. It seems _much_ cleaner to me to just restrict local imports to lexical scope, and I don't see how that would be inconsistent or surprising given that they're import statements, not symbols.

> Actually, I can live with it, but I cannot see a reasonable use case for the new behaviour. My rule of thumb would be to not use local import in classes. Otherwise all imported symbols are treated as static members with respect to lookup, hiding global functions or variables in derived classes.

Yeah. if importing at class scope affects anything outside of that lexical scope (including derived classes), I would then strongly argue that using class-level imports is bad practice and that if you need the import that much, it should be a top-level import. It's just going to cause function hijacking problems to have class-level imports. Function-level imports at least encapsulate things nicely. The class-level ones seem to be doing the opposite.

- Jonathan M Davis
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 18, 2013
On Sat, 18 May 2013 15:20:58 -0700
Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Saturday, May 18, 2013 22:30:30 Rainer Schuetze wrote:
> > I think the new behaviour is consistent with symbol lookup rules, but I'm not so sure about import rules. The actual case that triggered the issue was with the base class in a different file. Usually non-public imports in a module don't have an effect on another module that imports the module. In this case it has.
> 
> I would argue that the import would need to be _protected_ in order for derived classes to be affected by it if they're not in the same file. Having a private import affect something outside of the file that it's in violates the access rules.
> 

I think that's a reasonable way of looking at it. Private imports inside a class should naturally *be* private.

> 
> It
> seems _much_ cleaner to me to just restrict local imports to lexical
> scope, and I don't see how that would be inconsistent or surprising
> given that they're import statements, not symbols.
> 

I also have always thought of imports as being a "lexical scope" thing.
(FWIW).

> 
> I would then strongly
> argue that using class-level imports is bad practice and that if you
> need the import that much, it should be a top-level import.

I think that would be a common sentiment. At least, I know I'd be doing
the same. *Even without* the risk of function hijacking, it just
seems very messy: Private imports should never have any affect
outside the current module (Or for that matter, the current lexical
scope.)

Like you, I can live with it as well (provided there's no chance of
hijacking), but the current 2.063 beta's behavior definitely does not
win on the "simplicity" and "consistency" fronts.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 19, 2013
This behavior is intended change.

From 2.063, UFCS name lookup finds *most inner* imported name.

module test;
void map(alias func, T)(T){}  // dummy
void main() {
    import std.algorithm;
    auto r = [1,2,3].map!(a=>a*2);    // hit std.algorithm.map instead of
test.map
}

As already Walter says, the precedence is now changed as same as normal name lookup rule.

Kenji Hara


2013/5/19 Andrej Mitrovic <andrej.mitrovich@gmail.com>

> On 5/18/13, Walter Bright <walter@digitalmars.com> wrote:
> > I don't agree. A base class's scope must override the top level module scope.
> >
> > Also, a base class can always override what a derived class does. This is not hijacking.
>
> Don't you see that this change in behavior is going to surprise a lot of people? It's intuitive to me that this is going to cause trouble down the road. A base class could be in another file, in another library, and if the library writer decides to introduce a scoped import, suddenly the user's code might end up calling the wrong function (if the type signatures are the same the user will have *no idea* what happened). This is the definition of function hijacking.
>
> If it is a feature, it is not properly documented, and I can't tell which pull request changed the behavior so I don't know whether to put it in the changelog or not.
>
> Kenji, maybe you know?
> _______________________________________________
> dmd-beta mailing list
> dmd-beta@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>


May 19, 2013
2013/5/19 Rainer Schuetze <r.sagitario@gmx.de>

> On 18.05.2013 21:51, Walter Bright wrote:
>>
>> I agree that it is changing behavior, and should be properly documented. However, I also believe it is correct behavior and fixed a bug.
>>
>> It's *always* true that when you change a base class, you affect the derived classes.
>>
>
> I think the new behaviour is consistent with symbol lookup rules, but I'm not so sure about import rules. The actual case that triggered the issue was with the base class in a different file. Usually non-public imports in a module don't have an effect on another module that imports the module. In this case it has.
>
> Actually, I can live with it, but I cannot see a reasonable use case for the new behaviour. My rule of thumb would be to not use local import in classes. Otherwise all imported symbols are treated as static members with respect to lookup, hiding global functions or variables in derived classes.


Hmm, in module level, import declaration will add name lookup path _in private_.

module a;
import std.algorithm;   // default is private

module b;
import a;
void main() {
    [1,2,3].map!(a=>a);  // Error: no property 'map' for type 'int[]'
}

But with current master, import declaration in base class member adds name
lookup path _in public_.
I had not recognize this behavior.

class A {
    import std.algorithm;  // default is public!?
}
class B : A {
    void test() {
        auto r = [1,2,3].map!(a=>a);    // succeeds to compile
    }
}
void main() {
    auto r = B.map!(a=>a)([1,2,3]);    // also succeeds to compile
}

I think this is inconsistent, and class case should be fixed.

Kenji Hara


May 19, 2013
On 5/19/13, Kenji Hara <k.hara.pg@gmail.com> wrote:
> This behavior is intended change.
>
> From 2.063, UFCS name lookup finds *most inner* imported name.
>
> module test;
> void map(alias func, T)(T){}  // dummy
> void main() {
>     import std.algorithm;
>     auto r = [1,2,3].map!(a=>a*2);    // hit std.algorithm.map instead of
> test.map
> }

Right, that's a cool feature. I'll add this specific feature to the
changelog, and await what to do about class imports.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

1 2
Next ›   Last »