Bug 21195 – Delegate to method created without a `this` in certain contexts

Status
RESOLVED
Resolution
DUPLICATE
Severity
critical
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-08-25T05:07:41Z
Last change time
2022-12-12T15:02:52Z
Keywords
accepts-invalid, industry, wrong-code
Assigned to
No Owner
Creator
Tomer Filiba (weka)

Comments

Comment #0 by tomer — 2020-08-25T05:07:41Z
i had code similar to this ``` import std.stdio; void function() callback; struct S { static void getter() { callback = &func; <<<< this shouldn't compile, `func` needs `this` } void func() { writefln("func(this=%s)", &this); } } void main() { S.getter(); callback(); } ``` output: ``` func(this=1) ``` which is obviously means `this` is corrupted and trying to touch any members of it would segfault. if instead i write ``` void main() { S s; callback = &s.func; } ``` i get the expected ``` Error: cannot implicitly convert expression &s.func of type void delegate() to void function() ``` but it seems that in the context of a static function, it skips checking that i have a `this` to get a delegate
Comment #1 by kinke — 2020-08-26T19:06:12Z
This isn't restricted to the context of static functions, this is also accepted: struct S { void func() { import std.stdio; printf("func(this=%p)\n", &this); } } void main() { void function() f = &S.func; f(); }
Comment #2 by simen.kjaras — 2020-08-27T08:37:13Z
The issue here is not what you think. 'callback' is a function, not a delegate, and &S.func is indeed a function. This is hinted at by the error message saying "cannot implicitly convert expression &s.func of type void delegate() to void function()". Now, it can certainly be argued that the type of &S.func should be void function(S), but for some reason it is not, and this has been a known issue (issue 2672) for at least 11 years. *** This issue has been marked as a duplicate of issue 2672 ***
Comment #3 by tomer — 2020-08-27T09:16:56Z
Simen, it's not the type of `S.func` or whatever, it's the & operator -- it should fail when trying to create a delegate to a method without a `this` The actual production code had a copy-paste error, it was more of the following: ``` struct Client { __gshared static PoolDict(int, Client, 1024) dict; static Client* getClient(int key) { if (key !in dict) { dict[key] = Client(...); registerTimer(5.minutes, &closeInactive); } } void closeInactive() { // a happy little method } } ``` if should have been ``` registerTimer(5.minutes, &dict[key].closeInactive); ``` don't worry about dict, it has a pool for the values, so it will not move objects. taking pointers to it is safe. my point is that ``` &closeInactive ``` shouldn't compile, because this expression cannot be a (correct) type
Comment #4 by simen.kjaras — 2020-08-27T11:06:25Z
I don't disagree there is a bug here, only that I think it's an instance of 2672. Let's say I want a pointer to the closeInactive function, but I will assign the context later. Should I then have to instantiate a Client, grab the delegate, null the context pointer, and destroy the Client instance before I have a pristine function pointer for future use? If 2672 is fixed (and it bloody well should be), hopefully registerTimer would choke upon getting a void function(Client) instead of the expected void delegate(). > it's the & operator -- it should fail when trying to create a delegate But it's not trying to create a delegate. It's trying and succeeding at creating a function pointer, which has the wrong signature due to issue 2672.
Comment #5 by kinke — 2020-08-27T12:00:14Z
(In reply to Simen Kjaeraas from comment #4) > > it's the & operator -- it should fail when trying to create a delegate > > But it's not trying to create a delegate. It's trying and succeeding at > creating a function pointer, which has the wrong signature due to issue 2672. It should try to create a delegate and either fail or create one with a null context. A function pointer can generally NOT be used to represent a method, because the `this` pointer is special ABI-wise and can NOT be assumed to simply be the first argument, so changing the signature to `void function(S*)` does NOT work.
Comment #6 by petar.p.kirov — 2020-08-27T13:20:22Z
Issue 2672 is about the type of the expression <delegate_obj>.funcptr, while I think this issue is actually duplicate of issue 3720.
Comment #7 by razvan.nitu1305 — 2022-12-12T15:02:52Z
*** This issue has been marked as a duplicate of issue 3720 ***