Thread overview
method static-ness has no effect on the type?
Aug 08, 2016
Cauterite
Aug 08, 2016
ag0aep6g
Aug 08, 2016
Cauterite
Aug 08, 2016
ag0aep6g
Aug 08, 2016
Cauterite
August 08, 2016
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?
August 08, 2016
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
August 08, 2016
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 )
August 08, 2016
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.

August 08, 2016
On Monday, 8 August 2016 at 10:21:47 UTC, ag0aep6g wrote:
>

Also thanks for submitting the bug for me.