[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