[Issue 23761] Trait getOverloads does not retain "this" reference when used with instance
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Wed Mar 8 10:38:13 UTC 2023
https://issues.dlang.org/show_bug.cgi?id=23761
--- Comment #5 from m.bierlee at lostmoment.com ---
(In reply to RazvanN from comment #4)
> (In reply to m.bierlee from comment #3)
> > (In reply to RazvanN from comment #1)
> > > traits(getOverloads) wasn't designed to work on instances as you expect. The
> > > spec doesn't explicitly forbid it [2], but looking at the example and the
> > > implementation, it is implied. The compiler just needs an aggregate type as
> > > the second parameter of traits(getOverloads), but if an expression is
> > > provided it simply extracts the type and it returns a sequence of symbols
> > > (i.e. function pointers). Of course, for free functions you can call the
> > > symbols, but for member functions you need to provide a context pointer
> > > (which can be done by using a delegate and setting the .ptr field [1]).
> > >
> > > In this case, the compiler sees the call to the symbol and assumes that it's
> > > a local symbol. Of course, the error message could be improved, but
> > > currently the frontend cannot reason about the context pointer in this
> > > situation, so it's highly likely that this will remain WONTFIX.
> > >
> > > [1] https://dlang.org/spec/function.html
> > > [2] https://dlang.org/spec/traits.html#getOverloads
> >
> > Thanks for your clarification. Perhaps this could be clarified in the
> > documentation then?
> >
> > Could you provide an example regarding assigning the function and instance
> > to a delegate? Whatever I try myself doesn't work, the compile keeps saying
> > "Error: `this` for `theMethod` needs to be type [...]".
>
> OK, so apparently there is a bug in the example. I tried this:
>
> class PrincipleClass {
> public void theMethod() {
>
> }
> }
>
> class SecondaryClass {
> public void doIt() {
> PrincipleClass instance = new PrincipleClass();
> foreach (overload; __traits(getOverloads, instance, "theMethod"))
> {
> void delegate() callOverload;
> callOverload.funcptr = &overload;
> callOverload.ptr = cast(void*)instance;
> callOverload();
> }
> }
> }
>
> However, I am still getting:
>
> `this` for `theMethod` needs to be type `PrincipleClass` not type
> `test.SecondaryClass`
>
> For line: callOverload.funcptr = &overload;
>
> So then I tried:
>
> auto f = &PrincipleClass.theMethod;
>
> in the foreach scope. This still fails with the same bogus this error
> message.
> So it seems that the bug is that inside a method, the compiler eagerly sets
> the context pointer. Will look into it.
>
> Note 1: The following code compiles successfully.
>
> void main() {
> //new SecondaryClass().doIt();
>
> PrincipleClass instance = new PrincipleClass();
> foreach (overload; __traits(getOverloads, instance, "theMethod"))
> {
> // overload(); -> Error: Need this for theMethod
>
> void delegate() callOverload;
> callOverload.funcptr = &overload;
> callOverload.ptr = cast(void*)instance;
> callOverload();
> }
> }
>
> Note 2: Using traits(getOverloads) and then calling overload() does not make
> any sense. Since you are calling the overload with 0 arguments all the time,
> then it's like you expect to have a single overload. In that case, you can
> just use traits(getMember) and dump the foreach.
>
> __traits(getMember, instance, "theMethod")();
>
> compiles fine.
Thanks for looking into it. Indeed the code doesn't make much sense, it is just
a small snippet of a problem I encountered in a bigger project where it does
make more sense.
--
More information about the Digitalmars-d-bugs
mailing list