Thread overview
[Issue 5028] New: Problem with named mixins in base class and derived class
Oct 09, 2010
Ivo Kasiuk
Feb 06, 2011
Brad Roberts
May 04, 2012
Denis
Feb 24, 2013
Damian
Feb 24, 2013
Denis Shelomovskij
Feb 24, 2013
Andrej Mitrovic
October 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=5028

           Summary: Problem with named mixins in base class and derived
                    class
           Product: D
           Version: D2
          Platform: x86_64
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: i.kasiuk@gmx.de


--- Comment #0 from Ivo Kasiuk <i.kasiuk@gmx.de> 2010-10-09 11:56:25 PDT ---
In the following example, B.tb.f() collides with A.ta.f():

$ cat test.d
mixin template T() {
  final void f(/*typeof(this) dummy=null*/) { }
}
class A {
  mixin T ta;
}
class B : A {
  mixin T tb;
}
void main() {
  B b = new B();
  b.ta.f();
  b.tb.f();
}
$ dmd test
test.d(2): Error: function test.B.T!().f cannot override final function
test.A.T!().f
test.d(8): Error: mixin test.B.T!() error instantiating


This can be fixed with the commented-out code in the second line.
The error also does not occur if there is a second instance of T in A.

And if f() is not declared final the code does compile but the program
behaviour changes:

$ cat test.d
import std.stdio;
mixin template T(int i) {
  void f() { writefln("%d", i); }
}
class A {
  mixin T!(1) ta;
}
class B : A {
  mixin T!(2) tb;
}
void main() {
  B b = new B();
  b.ta.f();
  b.tb.f();
}
$ dmd test
$ ./test
2
2


So b.ta.f() actually calls b.tb.f() instead (this does not happen if f is
final).
I am not sure if any of this is exactly wrong. However, I find it very hard to
predict what will compile and how it will behave. In particular, the
significantly different results when declaring the method final or non-final or
when adding a second instance of T to A are rather surprising.

The following example uses the Signal template from std.signals and also does not behave as I would have expected:

$ cat test.d
import std.stdio;
import std.signals;
class A {
  mixin Signal!() sa;
  void a() { writeln("a()"); }
  this() { sa.connect(&a); }
}
class B : A {
  mixin Signal!() sb;
  void b() { writeln("b()"); }
  this() { sb.connect(&b); }
}
void main() {
  B b = new B();
  b.sa.emit();
  b.sb.emit();
}
$ dmd test
$ ./test
a()
b()
a()
b()


Tested with DMD v2.049.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 06, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5028


Brad Roberts <braddr@puremagic.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Platform|x86_64                      |x86


--- Comment #1 from Brad Roberts <braddr@puremagic.com> 2011-02-06 15:40:31 PST ---
Mass migration of bugs marked as x86-64 to just x86.  The platform run on isn't what's relevant, it's if the app is a 32 or 64 bit app.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 04, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=5028


Denis <verylonglogin.reg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |verylonglogin.reg@gmail.com


--- Comment #2 from Denis <verylonglogin.reg@gmail.com> 2012-05-04 16:51:24 MSD ---
The issue is that this doesn't compile:
---
mixin template T() { final void f() { } }

class A { mixin T ta; }
class B : A { mixin T tb; }
---

We need a general solution here. Looks like
---
class A { mixin T; }
class B : A { mixin T tb; }
---
and
---
class A { mixin T ta; }
class B : A { mixin T; }
---
and
---
class A { final void f() { } }
class B : A { mixin T tb; }
---
and
---
class A { mixin T ta; }
class B : A { final void f() { } }
---
should also compile.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 24, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=5028


Damian <damianday@hotmail.co.uk> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |damianday@hotmail.co.uk


--- Comment #3 from Damian <damianday@hotmail.co.uk> 2013-02-24 09:28:47 PST ---
I ran into this bug using std.signals and is currently a blocker for me, making std.signals useless, so I must use another mechanism. This is a example:

import std.signals;

class ClassA
{
    public mixin Signal!(int) addNumber1;
}

class ClassB : ClassA
{
    public mixin Signal!(int) addNumber2;
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 24, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=5028



--- Comment #4 from Denis Shelomovskij <verylonglogin.reg@gmail.com> 2013-02-24 23:11:51 MSK ---
(In reply to comment #3)
> I ran into this bug using std.signals and is currently a blocker for me, making std.signals useless, so I must use another mechanism. This is a example:
> 
> import std.signals;
> 
> class ClassA
> {
>     public mixin Signal!(int) addNumber1;
> }
> 
> class ClassB : ClassA
> {
>     public mixin Signal!(int) addNumber2;
> }

A workaround:
Add dummy signal `private mixin Signal!(int) __dummy;` to `ClassA`.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 24, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=5028


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #5 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-02-24 13:29:19 PST ---
(In reply to comment #2)
> The issue is that this doesn't compile:
> ---
> mixin template T() { final void f() { } }
> 
> class A { mixin T ta; }
> class B : A { mixin T tb; }
> ---

This would be an enhancement request though, the spec doesn't say the symbols are only visible by using 'ta' and 'tb'.

The issue name here is a misnomer, it's unrelated to base/derived classes.

See also: http://d.puremagic.com/issues/show_bug.cgi?id=8785 http://d.puremagic.com/issues/show_bug.cgi?id=8033

So this would really be an enhancement request to make symbols in mixin templates unavailable in the current scope when a mixin identifier is used:

mixin template T() { final void f() { } }
class A { mixin T ta; }
class B : A { mixin T tb; }

With the enhancement only A.ta.f() and B.tb.f() would be visible, A.f() and
B.f() would be invisible.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------