[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