www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - method static-ness has no effect on the type?

reply Cauterite <cauterite gmail.com> writes:
See: https://dpaste.dzfl.pl/2ec6780d4b25

We have two methods defined, f1 and f2, where f2 is static but 
they have otherwise identical signatures.
We can see from the disassembly that f1 receives a `this` pointer 
while f2 does not.
Yet, typeof(&f1) == typeof(&f2). This makes no sense, how can the 
compiler even know whether to pass a `this` pointer when both 
methods have same type?
Aug 08 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 08/08/2016 10:30 AM, Cauterite wrote:
 See: https://dpaste.dzfl.pl/2ec6780d4b25
That code is short enough to post it here directly. For easier reference, this is it: ---- struct S { void f1() { auto x = &this; }; static void f2() { static assert(!__traits(compiles, {auto x = &this;})); }; }; static assert(is(typeof(S.f1) == typeof(S.f2))); // ? static assert(is(typeof(&S.f1) == typeof(&S.f2))); // ? static assert(!__traits(isStaticFunction, S.f1)); static assert(__traits(isStaticFunction, S.f2)); void main() { // call f2; S.init.f2(); // mov [ebp-4], S.init; // lea eax, [ebp-4]; // call f1; S.init.f1(); }; ---- (Aside: no semicolons after function/struct declarations in D.)
 We have two methods defined, f1 and f2, where f2 is static but they have
 otherwise identical signatures.
 We can see from the disassembly that f1 receives a `this` pointer while
 f2 does not.
 Yet, typeof(&f1) == typeof(&f2). This makes no sense, how can the
 compiler even know whether to pass a `this` pointer when both methods
 have same type?
The first assert compares the return types of f1 and f2. They both return `void`, so everything's fine there. The second assert is a bit more surprising. `&S.f1` is considered a function, but `&S.init.f1` is a delegate. Obviously, you can't get a proper delegate from just the type. You need an instance of the struct for that. So having `&S.f1` be a delegate would be weird, too. I don't know why `&S.f1` is allowed at all. Maybe there is a good reason, but it also allows bad stuff like this: ---- struct S { void f1(int x) { import std.stdio; writeln(x); } } void main() { void function(int x) f = &S.f1; f(42); /* prints garbage */ } ---- This even works in safe code. It also works when using .funcptr to get the function pointer from a delegate. I'v filed an issue: https://issues.dlang.org/show_bug.cgi?id=16365
Aug 08 2016
parent reply Cauterite <cauterite gmail.com> writes:
On Monday, 8 August 2016 at 10:05:58 UTC, ag0aep6g wrote:
 The first assert compares the return types of f1 and f2. They 
 both return `void`, so everything's fine there.
I think you're mistaken about this. typeof(S.f1) definitely gives the type of the function, not of the return. Try it out: struct S { void f1(int, string, float) {}; }; static assert(typeof(S.f1).stringof == "void(int, string, float)"); ( https://dpaste.dzfl.pl/cda66002120a )
Aug 08 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 08/08/2016 12:14 PM, Cauterite wrote:
 On Monday, 8 August 2016 at 10:05:58 UTC, ag0aep6g wrote:
 The first assert compares the return types of f1 and f2. They both
 return `void`, so everything's fine there.
I think you're mistaken about this. typeof(S.f1) definitely gives the type of the function, not of the return. Try it out:
Yup. My mistake. It's the same as with & then.
Aug 08 2016
parent Cauterite <cauterite gmail.com> writes:
On Monday, 8 August 2016 at 10:21:47 UTC, ag0aep6g wrote:

Also thanks for submitting the bug for me.
Aug 08 2016