Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
March 06, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 m.bierlee@lostmoment.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |m.bierlee@lostmoment.com -- |
March 07, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 RazvanN <razvan.nitu1305@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |razvan.nitu1305@gmail.com --- Comment #1 from RazvanN <razvan.nitu1305@gmail.com> --- 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 -- |
March 07, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 Richard Cattermole <alphaglosined@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |alphaglosined@gmail.com --- Comment #2 from Richard Cattermole <alphaglosined@gmail.com> --- Possible duplicate: https://issues.dlang.org/show_bug.cgi?id=23500 There certainly is a problem here, I had to do a lot of work to workaround this in my own code for handling UDA's. I would suggest that this is indeed not WONTFIX and does need to be solved. -- |
March 07, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 --- Comment #3 from m.bierlee@lostmoment.com --- (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 [...]". -- |
March 08, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 --- Comment #4 from RazvanN <razvan.nitu1305@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. -- |
March 08, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 --- Comment #5 from m.bierlee@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. -- |
March 08, 2023 [Issue 23761] Trait getOverloads does not retain "this" reference when used with instance | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23761 --- Comment #6 from RazvanN <razvan.nitu1305@gmail.com> --- (In reply to m.bierlee from comment #5) > 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. I have created PR: https://github.com/dlang/dmd/pull/14969. This should fix the bogus error message and also allow to take the address of the overload. That way my workaround becomes valid. As for carrying the instance pointer over to the overload, I can look into implementing that. If it is not possible, then maybe we can add a clarification to the spec. -- |
Copyright © 1999-2021 by the D Language Foundation