www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - mixin template silently `override` without even a warning message!

reply mw <mingwu gmail.com> writes:
Hi,

I just found another problem:

```
import std;

template Foo() {
     void foo() {writeln("F");}
     void bar() {foo();}  // fixed to Foo.foo()
}

class A {
     mixin Foo;
     void foo() {writeln("A");}  // I accidentally added this new 
name-clashed method
}

void main() {
     A a = new A();
     a.bar();  // print F
     a.foo();  // print A
}
```

1) class A ends with two methods `foo()` with the same signature!

2) whether the foo() in bar() should be fixed to Foo.foo() 
(non-virtual) is debatable (I can see the reason on both sides).

3) BUT, the compiler should at least issue a warning message, so 
the programmer is aware of this name clash. Even when a sub-class 
override a super-class virtual method, the compiler enforces the 
user to add `override` keyword, but why not in this case?


Has this problem be discussed before? and what's the conclusion?
Oct 09 2022
next sibling parent mw <mingwu gmail.com> writes:
Even more fun when we have attribute of the same name:

```
import std;

template Foo() {
     int a;
     void foo() {writeln(a);}
     void bar() {foo();}
}

class A {
     mixin Foo;
     int a;
     void foo() {writeln(a);}
}

void main() {
     A a = new A();
     a.a = 911;
     a.bar();  // print 0
     a.foo();  // print 911
}
```

So `class A` has another hidden `Foo.a` attribute, but cannot 
read / write it's value outside of Foo?
Oct 09 2022
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Sunday, 9 October 2022 at 07:10:57 UTC, mw wrote:


 Has this problem be discussed before? and what's the conclusion?
This is documented behavior:
 The declarations in a mixin are placed in a nested scope and 
 then ‘imported’ into the surrounding scope. If the name of a 
 declaration in a mixin is the same as a declaration in the 
 surrounding scope, the surrounding declaration overrides the 
 mixin one:
And then:
 If a mixin has an Identifier, it can be used to disambiguate 
 between conflicting symbols:
https://dlang.org/spec/template-mixin.html#mixin_scope
Oct 09 2022
parent reply mw <mingwu gmail.com> writes:
On Sunday, 9 October 2022 at 07:24:13 UTC, Mike Parker wrote:
 On Sunday, 9 October 2022 at 07:10:57 UTC, mw wrote:


 Has this problem be discussed before? and what's the 
 conclusion?
This is documented behavior:
 The declarations in a mixin are placed in a nested scope and 
 then ‘imported’ into the surrounding scope. If the name of a 
 declaration in a mixin is the same as a declaration in the 
 surrounding scope, the surrounding declaration overrides the 
 mixin one:
And then:
 If a mixin has an Identifier, it can be used to disambiguate 
 between conflicting symbols:
https://dlang.org/spec/template-mixin.html#mixin_scope
OK, it's chosen behavior, that's fine. BUT, as I said, can the compiler issue a warning message?
Oct 09 2022
next sibling parent mw <mingwu gmail.com> writes:
On Sunday, 9 October 2022 at 07:27:54 UTC, mw wrote:
 On Sunday, 9 October 2022 at 07:24:13 UTC, Mike Parker wrote:
 On Sunday, 9 October 2022 at 07:10:57 UTC, mw wrote:


 Has this problem be discussed before? and what's the 
 conclusion?
This is documented behavior:
 The declarations in a mixin are placed in a nested scope and 
 then ‘imported’ into the surrounding scope. If the name of a 
 declaration in a mixin is the same as a declaration in the 
 surrounding scope, the surrounding declaration overrides the 
 mixin one:
And then:
 If a mixin has an Identifier, it can be used to disambiguate 
 between conflicting symbols:
https://dlang.org/spec/template-mixin.html#mixin_scope
OK, it's chosen behavior, that's fine. BUT, as I said, can the compiler issue a warning message?
Especially, this kind of `overrides` is not the same as the class virtual method override: as I showed in my OP, Foo.bar() is fixed to call Foo.foo(); so we are abuse the concept `override` here. Let's call it `scope override` to differentiate from `virtual override`, can the compiler at least issue a warning message?
Oct 09 2022
prev sibling parent mw <mingwu gmail.com> writes:
On Sunday, 9 October 2022 at 07:27:54 UTC, mw wrote:
 On Sunday, 9 October 2022 at 07:24:13 UTC, Mike Parker wrote:
 On Sunday, 9 October 2022 at 07:10:57 UTC, mw wrote:


 Has this problem be discussed before? and what's the 
 conclusion?
This is documented behavior:
 The declarations in a mixin are placed in a nested scope and 
 then ‘imported’ into the surrounding scope. If the name of a 
 declaration in a mixin is the same as a declaration in the 
 surrounding scope, the surrounding declaration overrides the 
 mixin one:
And then:
 If a mixin has an Identifier, it can be used to disambiguate 
 between conflicting symbols:
https://dlang.org/spec/template-mixin.html#mixin_scope
OK, it's chosen behavior, that's fine. BUT, as I said, can the compiler issue a warning message?
Especially, this kind of `overrides` is not the same as the class virtual method override: as I showed in my OP, Foo.bar() is fixed to call Foo.foo(), no `override` happening; so we are abuse the concept `override` here. Let's call it `scope override` to differentiate from `virtual override`, can the compiler at least issue a warning message?
Oct 09 2022
prev sibling parent Adam D Ruppe <destructionator gmail.com> writes:
On Sunday, 9 October 2022 at 07:10:57 UTC, mw wrote:
 template Foo() {
     void foo() {writeln("F");}
     void bar() {foo();}  // fixed to Foo.foo()
 }
You can do void bar() { this.foo(); } to explicitly call whichever one ended up on the object itself. Otherwise mixin templates work like their own unit with their own namespace.
 3) BUT, the compiler should at least issue a warning message, 
 so the programmer is aware of this name clash.
The name "clash" is one of the specific reasons for the mixin template, if it warned there it would be annoying...
Oct 09 2022