[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 09:17:20 UTC 2023


https://issues.dlang.org/show_bug.cgi?id=23761

--- Comment #4 from RazvanN <razvan.nitu1305 at gmail.com> ---
(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.

--


More information about the Digitalmars-d-bugs mailing list