D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.

Issue 2740

Summary: Template Mixins do not work as advertised
Product: D Reporter: Andrew Livesay <andrew.livesay>
Component: dmdAssignee: No Owner <nobody>
Status: RESOLVED FIXED
Severity: critical CC: akb825, bruno.do.medeiros+deebugz, bugzilla, clugdbug, dsimcha, k.hara.pg
Priority: P2 Keywords: accepts-invalid, patch
Version: D2
Hardware: x86
OS: All

Description Andrew Livesay 2009年03月17日 21:13:34 UTC
// As I understand TFM, all three calls to go() should be printing 'false'.
import std.stdio;
interface IFooable {
 bool foo();
}
template TFoo() {
 bool foo() { return true; } 
}
class Foo : IFooable {
 mixin TFoo;
 bool foo() { return false; }
}
class _Foo : IFooable {
 mixin TFoo;
}
class Foo2 : _Foo {
 bool foo() { return false; }
}
class Foo3 : IFooable {
 bool foo() { return false; }
}
void go(IFooable p) {
 writefln(p.foo);
}
void main() {
 Foo p = new Foo();
 Foo2 p2 = new Foo2();
 Foo3 p3 = new Foo3();
 go(p); // output is "true" <------- Why isn't this false?
 go(p2); // output is "false"
 go(p3); // output is "false"
}
Comment 1 Andrew Livesay 2009年03月17日 21:31:21 UTC
Issue appears to be dependent on the order the mixin is imported. If you redefine foo() before "mixin TFoo;", it works as expected.
Comment 2 David Simcha 2010年09月08日 10:40:17 UTC
This seems to happen iff the class is called from its interface handle:
import std.stdio;
interface IFooable {
 bool foo();
}
mixin template TFoo() {
 override bool foo() { return true; }
}
class Foo : IFooable {
 mixin TFoo;
 override bool foo() { return false; }
}
void go(IFooable p) {
 writeln(p.foo);
}
void main() {
 Foo p = new Foo();
 go(p); // true
 writeln(p.foo); // false
 IFooable i = p;
 writeln(i.foo); // true
}
Marking as critical because this is an extremely subtle wrong-code bug that can lead to some pretty frustrating debugging.
Comment 3 David Simcha 2010年09月08日 10:42:34 UTC
Oh yeah, doesn't happen for abstract classes either. Looks like only the interface vtbl info is wrong.
import std.stdio;
abstract class IFooable {
 abstract bool foo();
}
mixin template TFoo() {
 override bool foo() { return true; }
}
class Foo : IFooable {
 mixin TFoo;
 override bool foo() { return false; }
}
void go(IFooable p) {
 writeln(p.foo);
}
void main() {
 Foo p = new Foo();
 go(p); // false
 writeln(p.foo); // false
 IFooable i = p;
 writeln(i.foo); // false
}
Comment 4 Bruno Medeiros 2010年12月03日 06:33:18 UTC
Hum, I suspect the code above should not even compile. Instantiating the mixin "is analogous to cutting and pasting the body of the template into the location of the mixin." http://www.digitalmars.com/d/2.0/template-mixin.html
Thus it should be the same as:
class Foo : IFooable {
 bool foo() { return false; }
 bool foo() { return false; }
}
which should be a semantic error, I think. See http://d.puremagic.com/issues/show_bug.cgi?id=5312 
Comment 5 anonymous4 2010年12月03日 11:57:37 UTC
The right code can't be generated for such input.
Comment 6 akb825 2011年02月19日 12:18:10 UTC
(In reply to comment #4)
> Hum, I suspect the code above should not even compile. Instantiating the mixin 
> "is analogous to cutting and pasting the body of the template into the location
> of the mixin." http://www.digitalmars.com/d/2.0/template-mixin.html
> Thus it should be the same as:
> 
> class Foo : IFooable {
> bool foo() { return false; }
> bool foo() { return false; }
> }
> 
> 
> which should be a semantic error, I think. See
> http://d.puremagic.com/issues/show_bug.cgi?id=5312 
From http://www.digitalmars.com/d/2.0/template-mixin.html: "The declarations in a mixin are ‘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." In other words, declarations in the current scope always hide declarations in the mixin.
Comment 7 Kenji Hara 2011年07月09日 16:45:34 UTC
https://github.com/D-Programming-Language/dmd/pull/223 

AltStyle によって変換されたページ (->オリジナル) /