digitalmars.D.bugs - [Issue 20458] New: CRTP + pass alias to virtual member to mixin =
- d-bugmail puremagic.com (76/76) Dec 19 2019 https://issues.dlang.org/show_bug.cgi?id=20458
https://issues.dlang.org/show_bug.cgi?id=20458 Issue ID: 20458 Summary: CRTP + pass alias to virtual member to mixin = runtime crash Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nobody puremagic.com Reporter: destructionator gmail.com Encountered this during my android/jni stuff. Easier to describe with code than with words: ---- mixin template Impl(T, string name){ alias a = __traits(getMember, T, name); // comment this and it works static void impl() { auto t = new T(); __traits(getMember, t, name)(); } } class A(CRTP) { static foreach(memberName; __traits(derivedMembers, CRTP)) mixin Impl!(CRTP, memberName); } class Foo : A!Foo { void test() { import core.stdc.stdio; printf("Success\n"); } } void main() { Foo.impl(); } ---- Compiles successfully. Running it leads to crash. Make `class Foo` into `final class Foo` and it works. Put `final` on `void test` instead and it works here, but adding more members can result in the wrong method being called. Leads me to believe the virtual function slot gets confused. Comment that `alias a = ....` line in there and it works. So the fundamental problem is related to the alias being present in the mixin template, even if never used. So the alias of the virtual derived member appearing in the base class. However, I believe the use of the curiously-recurring template pattern is necessary to trigger the bug though since I've been unable to reproduce the crash without that. This is the most I have been able to minimize it... the original version is: --- mixin template Impl(T, alias a) { static void impl() { auto t = new T(); __traits(getMember, t, __traits(identifier, a))(); } } class A(CRTP) { static foreach(memberName; __traits(derivedMembers, CRTP)) mixin Impl!(CRTP, __traits(getMember, CRTP, memberName)); } class Foo : A!Foo { void test() { import core.stdc.stdio; printf("Success\n"); } } void main() { Foo.impl(); } --- And I think it is worth noting that one too: just *passing* the alias to the mixin template also results in the same behavior. It doesn't have to explicitly mixin the alias, as long as it is present there. --
Dec 19 2019