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 ***