Bug 8983 – Overload introduced behind mixin template can't be called from another overload

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-11-08T14:24:00Z
Last change time
2012-11-09T04:53:18Z
Assigned to
nobody
Creator
turkeyman

Comments

Comment #0 by turkeyman — 2012-11-08T14:24:24Z
http://dpaste.dzfl.pl/f955d02a test(int) can't call the overload text(int, float) introduced behind the mixin template. If you paste that mixin directly (remove the mixin template) it works. Again here: mixin template MixOverload() { mixin( "int test(int x, float y) { return x + cast(int)y; }" ); } struct Test { mixin MixOverload; // <- introduce an overload for test() void test(int x) { test(x, 1); // call the overload defined in the mixin } } Output: /home/c950/c254.d(13): Error: function c254.Test.test (int x) is not callable using argument types (int,int) /home/c950/c254.d(13): Error: function c254.Test.test (int x) is not callable using argument types (int,int) /home/c950/c254.d(13): Error: expected 1 arguments, not 2 for non-variadic function type void(int x)
Comment #1 by bugzilla — 2012-11-08T14:54:35Z
This actually isn't a bug. Inserting a template mixin creates a new nested scope, and names not in that nested scope override the ones in it. Your code can be made to work in two ways. But first we need to give a name to the nested scope: mixin MixOverload; becomes: mixin MixOverload nn; Now, the mixin template names can be prefixed with nn: void test(int x) { nn.test(x, 1); // call the overload defined in the mixin } which works. Alternatively, the nested scope can be aliased into the current scope with: alias nn.test test; and now: void test(int x) { test(x, 1); // call the overload defined in the mixin } will work, as aa.test will be overloaded with test.
Comment #2 by samukha — 2012-11-09T01:43:32Z
One unfortunate consequence of the nested scope rule is we cannot use unnamed mixins for adding definitions to declarations. mixin template Foo() { void foo() {} } class A { void foo(); mixin Foo; } results in undefined reference.
Comment #3 by maxim — 2012-11-09T02:59:41Z
(In reply to comment #2) > One unfortunate consequence of the nested scope rule is we cannot use unnamed > mixins for adding definitions to declarations. > > mixin template Foo() > { > void foo() {} > } > > class A > { > void foo(); > mixin Foo; > } > > results in undefined reference. Even if there were no nested scope, this still would not work because function with omitted body is expected to appear in another object file: class A { void foo(); void foo() {} } void main() { (new A).foo; } will fail because foo matches "both foo and foo". This contradicts to C practice and does not make sense because dmd artificially creates ambiguity between function declaration and its own body. I complained in Bugzilla but was told that such practice in redundant in C and need not supported even as enhancement.
Comment #4 by samukha — 2012-11-09T04:34:35Z
(In reply to comment #3) > > Even if there were no nested scope, this still would not work because function > with omitted body is expected to appear in another object file: > That changed recently. Now class A { void foo(); void foo() { } void bar(); mixin(q{ void bar() {} }); } void main() { auto a = new A; a.foo(); a.bar(); } works as expected.
Comment #5 by maxim — 2012-11-09T04:38:29Z
(In reply to comment #4) > (In reply to comment #3) > > > > > Even if there were no nested scope, this still would not work because function > > with omitted body is expected to appear in another object file: > > > > That changed recently. Now > > class A > { > void foo(); > void foo() { } > > void bar(); > mixin(q{ void bar() {} }); > } > > void main() > { > auto a = new A; > a.foo(); > a.bar(); > } > > works as expected. Do you compile it with version from git? Dmd 2.060 rejects this. When it was fixed?
Comment #6 by samukha — 2012-11-09T04:46:29Z
(In reply to comment #5) git
Comment #7 by samukha — 2012-11-09T04:53:18Z
Note that variable definitions still fail: extern int x; int x; // conflict