struct S {
int a;
void fun() {
this.a = 1;
}
}
void main() {
auto fp = &S.fun;
fp();
}
Outputs:
object.Error: Access Violation
The solution is either to delegalize it or (better) include the hidden parameter into the function pointer signature. So that &S.fun would be of type void function(ref S).
Comment #1 by yebblies — 2011-06-12T22:09:28Z
*** Issue 5986 has been marked as a duplicate of this issue. ***
Comment #2 by yebblies — 2011-06-18T23:35:49Z
*** Issue 5328 has been marked as a duplicate of this issue. ***
Comment #3 by yebblies — 2011-07-11T09:44:12Z
*** Issue 6287 has been marked as a duplicate of this issue. ***
Comment #4 by yebblies — 2012-01-29T21:57:39Z
Related to: Issue 2557 - inconsistent behavior when taking reference to member without instance
This behavior encourages memory corruption. At the least it should return void*.
Comment #5 by yebblies — 2012-01-29T22:17:48Z
Related to issue 2672.
Comment #6 by yebblies — 2012-10-28T13:47:38Z
*** Issue 8114 has been marked as a duplicate of this issue. ***
Comment #7 by yebblies — 2014-02-15T07:18:59Z
*** Issue 12154 has been marked as a duplicate of this issue. ***
Comment #8 by yebblies — 2014-12-31T06:45:45Z
*** Issue 12773 has been marked as a duplicate of this issue. ***
Comment #9 by sprink.noreply — 2017-01-11T16:58:29Z
*** Issue 17080 has been marked as a duplicate of this issue. ***
Comment #10 by dlang — 2017-01-11T17:39:08Z
helpful info: The type of `fun` in the provided example is `void function ( )`
Comment #11 by slavo5150 — 2017-12-05T00:55:35Z
A little more information about this issue and the test case:
struct S {
int a;
void fun()
{
this.a = 1;
}
}
void main()
{
auto fp = &S.fun;
fp();
}
There may be 2 schools of thought on how this should behave:
(1) `auto fp = &S.fun;` is trying to get the address of a non-static function through a type. Instead, it can be argued that the programmer should have written `S s; auto fp = &s.fun;` Notice the lower-case `s`.
(2) `&S.fun` should return a `void function(S* s)` instead of a `void function()`
If (1) were implemented the compiler would emit an error at `auto fp = &S.fun;` because it is trying get the address of a non-static `fun` through the type `S`.
If (2) were implemented the compiler would emit an error at `fp();` because a context pointer was not supplied as an argument. In other words it should be `fp(&s)`.
Comment #12 by schveiguy — 2017-12-05T15:23:36Z
Isn't this the type/pointer assigned to delegates?
e.g.:
S s;
auto dg = &s.fun;
assert(dg.funcptr == &S.fun);
So it could be useful if you are doing something funky with the function pointer portion of a delegate. Like for instance, selecting at runtime which function pointer to use.
My preference would be to embed in the type of the function pointer, the fact that it takes a hidden context pointer. Then the compiler can disallow simply calling it without stuffing it into a delegate.
Comment #13 by slavo5150 — 2017-12-05T16:20:48Z
> My preference would be to embed in the type of the function pointer, the
> fact that it takes a hidden context pointer. Then the compiler can disallow
> simply calling it without stuffing it into a delegate.
Is that different from (2) in comment 11?
Comment #14 by schveiguy — 2017-12-05T17:33:15Z
(In reply to Mike Franklin from comment #13)
> > My preference would be to embed in the type of the function pointer, the
> > fact that it takes a hidden context pointer. Then the compiler can disallow
> > simply calling it without stuffing it into a delegate.
>
> Is that different from (2) in comment 11?
Yes, I would want to introduce a new piece of the type system, e.g.:
void function(this)
which means "I can only be called when in a delegate".
At the moment, we can't type the context pointer, since it's void *, and the types will have problems if you are playing fast and loose with the delegate internals (there is definitely code out there that plays with delegate function pointers).
Perhaps there is room here to have loose type requirements, but I don't know how that might break existing code. Worth exploring, though.
Comment #15 by default_357-line — 2018-01-17T07:26:28Z
Here's a subset of this that should be fixed immediately:
class S {
void fun() { }
static void function() fun2() { return &fun; }
}
There is *no* good reason to allow this, because you can always do &S.fun explicitly. This looks *way* too innocuous for the horror that it is.
Comment #16 by bugzilla — 2018-03-04T01:29:43Z
If `@safe` is added, the example fails to compile with:
test.d(9): Error: `this` reference necessary to take address of member `fun` in `@safe` function `main`
which is expected behavior.
Comment #17 by default_357-line — 2018-03-04T09:51:57Z
Right, but I think it's more of a syntax issue. Taking the address of a member function without a this pointer may in rare cases be useful, but I don't see what purpose it serves that we're able to take the address without even using the class name, ie. &fun in static.
Comment #18 by petar.p.kirov — 2020-08-27T13:08:50Z
Reopening as this issue is a too ugly issue to be left unaddressed.
I suggest the following plan going forward:
1. Deprecate the expression &<AggregateType>.<memberFunction> even in @system code, but allow the equivalent:
&__traits(getMember, <AggregateType>, "<memberFunction>")
as we need to have migration path for the small amount of code that is able to correctly use &<AggregateType>.<memberFunction>
2. After deprecation period is finished, reintroduce the &<AggregateType>.<memberFunction> but with different semantics: retunring a delegate with context pointer set to null.
Comment #19 by razvan.nitu1305 — 2022-12-09T12:16:09Z
*** Issue 21862 has been marked as a duplicate of this issue. ***
Comment #20 by razvan.nitu1305 — 2022-12-09T12:57:14Z
*** Issue 17080 has been marked as a duplicate of this issue. ***
Comment #21 by razvan.nitu1305 — 2022-12-09T13:00:19Z
Raising severity for this issue as it is a long standing hole.
Comment #22 by razvan.nitu1305 — 2022-12-12T15:02:52Z
*** Issue 21195 has been marked as a duplicate of this issue. ***
Comment #23 by dlang-bot — 2022-12-12T16:47:15Z
@RazvanN7 created dlang/dmd pull request #14688 "Fix Issue 3720 - Taking address of member functions possible without an instance" fixing this issue:
- Fix Issue 3720 - Taking address of member functions possible without an instance
https://github.com/dlang/dmd/pull/14688
Comment #24 by qs.il.paperinik — 2023-02-20T16:17:17Z
@Zombine(In reply to ZombineDev from comment #18)
> […]
>
> 2. After deprecation period is finished, reintroduce the
> &<AggregateType>.<memberFunction> but with different semantics: retunring a
> delegate with context pointer set to null.
Why? If I want a delegate with a null pointer context and member function mfunc, today I can do
```d
alias T = the-aggregate-type;
auto dg = &(cast(T*)null).mfunc;
```
As an added benefit, it is absolutely clear what happens.
If that is not defined behavior because of supposed null pointer dereference, we can just make it a special-case and allow it.
Comment #25 by maxsamukha — 2023-03-30T10:00:28Z
Everybody who actually tried to implement a reflection library in D would want local function (pointer) types to include the context pointer as an explicit parameter (as suggested here, for example https://github.com/dlang/dmd/pull/14688#issuecomment-1347358238).
Comment #26 by razvan.nitu1305 — 2023-03-30T14:49:13Z
*** Issue 13850 has been marked as a duplicate of this issue. ***
Comment #27 by qs.il.paperinik — 2023-05-04T11:01:22Z
Given
```d
struct T
{
ref int memFunc(return ref int i) return @safe immutable { return i; }
}
```
I guess the only reasonable thing `typeof(&T.memFunc)` could be is:
```d
ref int function(return ref immutable T, return ref int i) @safe
```
We can argue about whether the `T` parameter must be `ref`, but unless we have a mechanism to express “bind by mutable reference irrespective of value category” (this is how member functions bind the `this` object) as a parameter storage class, the only option is `ref`. Copy isn’t an option, not all types are copyable. `in` isn’t an option because it makes mutable objects `const`.
DMD’s answer for `typeof(&T.memFunc)` is nonsense:
```d
ref int function(return ref int i) immutable return @safe
```
Both, `immutable` and `return` make no sense on a function pointer type and do not even parse.
Comment #28 by razvan.nitu1305 — 2023-05-18T10:46:13Z
*** Issue 17315 has been marked as a duplicate of this issue. ***
Comment #29 by robert.schadek — 2024-12-13T17:51:14Z