Bug 10103 – template mixin with property overloads

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-05-17T02:31:00Z
Last change time
2013-10-24T02:21:52Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
SebastianGraf

Attachments

IDFilenameSummaryContent-TypeSize
1281mixproperty.dAlternative example of problemtext/x-dsrc339
1282mixproperty2.dSecond example of bug still in existencetext/x-dsrc339

Comments

Comment #0 by SebastianGraf — 2013-05-17T02:31:31Z
If you mix in getters and setters in seperate template mixins, it fails to compile on first property-like usage. Strangely, you may use both overloads if you treat them like functions (e.g. the first examples in main below). I think this is related to http://d.puremagic.com/issues/show_bug.cgi?id=1686 and http://d.puremagic.com/issues/show_bug.cgi?id=9235. Offending code: mixin template Getter() { @property auto x() { return _x; } } mixin template Setter() { @property void x(int x) { _x = x; } } struct Foo { int _x; mixin Getter!(); // definition order is irrelevant mixin Setter!(); } void main() { auto f = Foo(4); auto x1 = f.x(); //fine f.x(2); // fine auto x2 = f.x; // Error: expression has no value f.x = 3; // Error: f.x is not an lvalue }
Comment #1 by k.hara.pg — 2013-05-17T22:10:31Z
Comment #2 by github-bugzilla — 2013-05-20T09:13:01Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/e892946b376b8365bc6cefd896e5e3e6a1219b16 fix Issue 10103 - template mixin with property overloads https://github.com/D-Programming-Language/dmd/commit/fa4a52c8e832f43081349332ea3d274d976c54ca Merge pull request #2047 from 9rnsr/fix10103 Issue 10103 - template mixin with property overloads
Comment #3 by github-bugzilla — 2013-05-29T18:25:59Z
Commit pushed to 2.063 at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/76d09dfa5ef28176f666aa6f50038ed6a48b830b Fix 2.063 branch breaking Bug10103 is not yet fixed in 2.063 branch.
Comment #4 by github-bugzilla — 2013-06-01T16:02:28Z
Comment #5 by joseph.wakeling — 2013-10-23T23:39:05Z
Created attachment 1281 Alternative example of problem The problem does not appear to be resolved in all cases. See attached code, where a class takes _one_ of the implementations (getter _or_ setter) via a mixin, and the other is local.
Comment #6 by joseph.wakeling — 2013-10-23T23:40:30Z
Created attachment 1282 Second example of bug still in existence This second example has the _getter_ obtained via mixin, while the setter is in the class itself.
Comment #7 by joseph.wakeling — 2013-10-23T23:42:49Z
The current fix does not cover all possible cases. The two recently-attached examples show cases where, of a getter/setter property pair, a class implements one of them locally and obtains the other via a mixin. In both cases errors result: $ rdmd mixproperty.d mixproperty.d(30): Error: a.foo is not an lvalue $ rdmd mixproperty2.d mixproperty2.d(31): Error: function mixproperty2.A.foo (const(int) f) is not callable using argument types ()
Comment #8 by k.hara.pg — 2013-10-24T00:37:15Z
(In reply to comment #7) > The current fix does not cover all possible cases. The two recently-attached > examples show cases where, of a getter/setter property pair, a class implements > one of them locally and obtains the other via a mixin. In both cases errors > result: > > $ rdmd mixproperty.d > mixproperty.d(30): Error: a.foo is not an lvalue > > $ rdmd mixproperty2.d > mixproperty2.d(31): Error: function mixproperty2.A.foo (const(int) f) is > not callable using argument types () No. The two cases does not work as you expected. **It's by design**. mixin template B() { void foo(int n) {} } class C { void foo() {} // Mixed-in symbol foo(int) won't be automatically merged with foo(). // In other words, C.foo() hides C.B!().foo(int) normally. mixin B; } void main() { auto c = new C; c.foo(); // OK c.foo(1); // NG, foo() is not callable using argument types (int) } If you want to make workable both c.foo() and c.foo(1), you need to change the mixin declaration as follows. class C { ... mixin B x; alias foo = x.foo; // merge foo(int) in the overload set 'C.foo' } void main() { auto c = new C; c.foo(); // OK c.foo(1); // OK } I know that currently D does not have a feature to do it automatically. If you want to do it, you could design a language enhancement to resolve the issue. Change back the issue status.
Comment #9 by joseph.wakeling — 2013-10-24T02:21:52Z
Thanks for the explanation, Kenji -- apologies for the misunderstanding, but at least we now have this special case documented here :-)