Bug 8074 – template-mixin example contradicts text
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dlang.org
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-05-09T09:52:00Z
Last change time
2014-04-24T23:03:04Z
Keywords
pull, spec
Assigned to
andrej.mitrovich
Creator
tim.dolores
Comments
Comment #0 by tim.dolores — 2012-05-09T09:52:31Z
The text says:
"If two different mixins are put in the same scope, and each define a declaration with the same name, there is an ambiguity error when the declaration is referenced"
However, the example *does* compile with no error, and runs the Bar.func() method. Here is the exact code I'm using:
$ cat mix08.d
import std.stdio, std.exception;
/*
If two different mixins are put in the same scope, and each define a
declaration with the same name, there is an ambiguity error when the
declaration is referenced:
*/
mixin template Foo() {
int x = 5;
void func(int x) { writeln("Foo.func(), x = ", x); }
}
mixin template Bar() {
int x = 4;
void func() { writeln("Bar.func(), x = ", x); }
}
mixin Foo;
mixin Bar;
void main() {
//writefln("x = %d", x); // error, x is ambiguous
/*
The call to func() is ambiguous because Foo.func and Bar.func are in
different scopes.
*/
func(); // error, func is ambiguous
}
$ dmd|grep DMD
DMD64 D Compiler v2.059
$ dmd -w mix08.d
$ ./mix08
Bar.func(), x = 4
$
I don't know if the text is wrong, or if DMD is wrong.
Comment #2 by andrej.mitrovich — 2013-02-06T20:22:31Z
I seriously doubt we could implement this now without breaking code. Chances are people are using it to inject multiple function overloads.
I think we'll simply have to edit that part out of the website. Andrei do you agree?
Comment #3 by andrei — 2013-02-07T09:21:17Z
We should fix this, it's clearly a crass error. We can't afford to arbitrarily pick the last lexical declaration in case of an ambiguity.
Comment #4 by andrej.mitrovich — 2013-02-07T09:53:20Z
(In reply to comment #3)
> We should fix this, it's clearly a crass error. We can't afford to arbitrarily
> pick the last lexical declaration in case of an ambiguity.
But there is no ambiguity, the two functions are:
void func(int x) { writeln("Foo.func(), x = ", x); }
void func() { writeln("Bar.func(), x = ", x); }
Neither of these can hijack one another.
Comment #5 by andrej.mitrovich — 2013-02-07T09:54:00Z
(In reply to comment #4)
> (In reply to comment #3)
> > We should fix this, it's clearly a crass error. We can't afford to arbitrarily
> > pick the last lexical declaration in case of an ambiguity.
>
> But there is no ambiguity, the two functions are:
>
> void func(int x) { writeln("Foo.func(), x = ", x); }
> void func() { writeln("Bar.func(), x = ", x); }
>
> Neither of these can hijack one another.
Edit: Well except the case of taking the address of such a function which could prove problematic.
Comment #6 by k.hara.pg — 2013-02-14T09:01:34Z
I think there is no ambiguity for current behavior.
I can explain it based on the 'overload set resolution rule'.
Please regard these mixin declarations as two import statements.
mixin Foo;
mixin Bar;
void main() { func(); }
Can be considered to:
import foo;
import bar;
void main() { func(); }
And each module contains following declarations.
module foo; // ---
int x = 5;
void func(int x) { writeln("Foo.func(), x = ", x); }
module bar; // ---
int x = 4;
void func() { writeln("Bar.func(), x = ", x); }
Finally, the 'func()' is resolved to the call of bar.func.
"compiler will resolve an ambiguous mixin-ed symbol by regarding it as overload set.." - This is much reasonable and consistent rule. If 'foo' is called with some arguments but cannot eliminate the ambiguity, it will be error. Otherwise simply will succeed to call.
Comment #7 by code — 2013-05-20T11:34:15Z
(In reply to comment #6)
> I can explain it based on the 'overload set resolution rule'.
Yes, according to http://dlang.org/template-mixin.html these form an overload set and only one of the sets has a match.
(In reply to comment #5)
> Edit: Well except the case of taking the address of such a function which could > prove problematic.
No problem here, you just have to specify the function type.
void foo() {}
void foo(int) {}
void main()
{
void function() a1 = &foo;
void function(int) a2 = &foo;
auto b1 = cast(void function())&foo;
auto b2 = cast(void function(int))&foo;
assert(cast(void*)a1 !is cast(void*)a2);
assert(a1 is b1);
assert(a2 is b2);
}
Comment #8 by dlang-bugzilla — 2014-03-20T09:12:45Z
I noticed this behavior today:
///////// test.d ////////
template T()
{
void foo(string s) {}
}
void foo() {}
mixin T;
void main()
{
foo("Test");
}
/////////////////////////
This will not compile - the module-level foo hides the mixed-in one, which essentially makes the mixin a noop.
Is this intentional? It makes it impossible to use mixins to generate additional overloads for a function.
Comment #9 by andrej.mitrovich — 2014-04-23T11:11:35Z