Thread overview
why is this cast required?

2 days ago

DanielG

2 days ago

Dejan Lekic

2 days ago

DanielG

2 days ago

monkyyy

1 day ago

Dejan Lekic

1 day ago

DanielG

23 hours ago

Dejan Lekic

21 hours ago

DanielG

2 days ago

why is this cast required?
Gravatar of DanielGPosted by DanielGPermalinkReply
Gravatar of DanielG
alias IntFunc = int delegate();

void exec(IntFunc[] funcs) {}

void main()
{
	int two() => 2;

	exec(
		// why do I have to cast to the exact type that exec() already takes?
		cast(IntFunc[])
		[
			() => 1,
			() => two(),
		]);
}

Without the cast, the error is:

>

Error: incompatible types for (() => 1) : (() => two()): int function() pure nothrow @nogc @safe and int delegate() pure nothrow @nogc @safe

2 days ago

Re: why is this cast required?
Gravatar of Dejan LekicPosted by Dejan Lekic
in reply to DanielG
PermalinkReply

Dejan Lekic

Gravatar of Dejan Lekic

Posted in reply to DanielG

On Friday, 25 September 2026 at 11:14:50 UTC, DanielG wrote:

>

alias IntFunc = int delegate();

void exec(IntFunc[] funcs) {}

void main()
{
	int two() => 2;

	exec(
		// why do I have to cast to the exact type that exec() already takes?
		cast(IntFunc[])
		[
			() => 1,
			() => two(),
		]);
}

Without the cast, the error is:

>

Error: incompatible types for (() => 1) : (() => two()): int function() pure nothrow @nogc @safe and int delegate() pure nothrow @nogc @safe

Unfortunately you've hit a limitation of how the compiler propagates the expected type into an array literal used as a function argument.

You can avoid the cast by explicitly making the first lambda a delegate:

exec([
    delegate () => 1,
    () => two(),
]);

, or by using an explicitly typed variable, which also provides the necessary context:

IntFunc[] funcs = [
    () => 1,
    () => two(),
];
exec(funcs);

Why? - Because () => 1 needs no enclosing context so it is inferred as a function pointer, while () => two() calls a non-static nested function and will be treated as a delegate by the compiler.

2 days ago

Re: why is this cast required?
Gravatar of DanielGPosted by DanielG
in reply to Dejan Lekic
PermalinkReply

DanielG

Gravatar of DanielG

Posted in reply to Dejan Lekic

I see, thank you!

Do you (or anyone else) know the reason for that limitation? Is there some obvious situation where the ambiguity is preferable, versus simply inferring - or trying to infer - the expected type?

ie, superficially it seems like the compiler could say, "Hey, they are trying to use this array in the context of a [type X] argument - let's assume that for the moment, and see if it works."

Put another way, why is a function argument treated differently than the right side of an explicitly-typed variable assignment?

2 days ago

Re: why is this cast required?
Gravatar of monkyyyPosted by monkyyy
in reply to DanielG
PermalinkReply

monkyyy

Gravatar of monkyyy

Posted in reply to DanielG

On Friday, 25 September 2026 at 15:52:04 UTC, DanielG wrote:

>

Do you (or anyone else) know the reason for that limitation?

delegates are twice as big as raw function pointers; when doing airplane surgery it would be irresponsible to add an extra dozenial bytes of ram usage as the airplane may fall out of the sky.

Theres a toDelegate thats suppose to handle it; I think as they added more and more wont-work keywords the situation kept getting worse.

1 day ago

Re: why is this cast required?
Gravatar of Dejan LekicPosted by Dejan Lekic
in reply to DanielG
PermalinkReply

Dejan Lekic

Gravatar of Dejan Lekic

Posted in reply to DanielG

On Friday, 25 September 2026 at 15:52:04 UTC, DanielG wrote:

>

I see, thank you!

Do you (or anyone else) know the reason for that limitation? Is there some obvious situation where the ambiguity is preferable, versus simply inferring - or trying to infer - the expected type?

ie, superficially it seems like the compiler could say, "Hey, they are trying to use this array in the context of a [type X] argument - let's assume that for the moment, and see if it works."

Put another way, why is a function argument treated differently than the right side of an explicitly-typed variable assignment?

You could answer your own question yourself by thinking why the

exec([
    delegate () => 1,
    () => two(),
]);

workaround works? Think, what is the difference between () => 1 and delegate () => 1 ? - The () => 1 lambda does not access any variables or functions in the outer scope. As it is completely self-contained D will optimise it and make it into a raw function pointer (int function()). So, you end up with this kind of array literal: [ int function(), int delegate() ] . An array like this will be rejected by compiler, so I "fixed" it in my previous post by explicitly making the first element a delegate, and that works.

1 day ago

Re: why is this cast required?
Gravatar of DanielGPosted by DanielG
in reply to Dejan Lekic
PermalinkReply

DanielG

Gravatar of DanielG

Posted in reply to Dejan Lekic

I appreciate the reply, but that's not the question I am asking.

I am asking why there's a difference between an explicitly typed variable, and an explicitly typed function argument - both of which 'receive' the mixed-type array literal.

The compiler will implicitly upgrade the function pointers to delegates in one case, but not the other. What is the basis, or philosophy behind this policy?

Why do variable assignments receive this treatment, but not function arguments?

IMO this violates the Principle of Least Astonishment.

alias IntFunc = int delegate();

void main()
{
	int two() => 2;

	// automatically upgrades function pointers to delegates
	// which is exactly what we'd expect ...
	IntFunc[] explicit = [
		() => 1,
		() => two()
	];

	void func(IntFunc[] arg) {
		// but in the case of a function,
		// our VERY EXPLICIT type parameter is seemingly ignored.
		// there is no coercion/upgrading of function pointers to delegates
		//   at the call site, as with the variable.
		// BUT WHY?
		// what is the reasoning?
	}
}

23 hours ago

Re: why is this cast required?
Gravatar of Dejan LekicPosted by Dejan Lekic
in reply to DanielG
PermalinkReply

Dejan Lekic

Gravatar of Dejan Lekic

Posted in reply to DanielG

On Saturday, 26 September 2026 at 16:49:48 UTC, DanielG wrote:

>

I appreciate the reply, but that's not the question I am asking.

I am asking why there's a difference between an explicitly typed variable, and an explicitly typed function argument - both of which 'receive' the mixed-type array literal.

The compiler will implicitly upgrade the function pointers to delegates in one case, but not the other. What is the basis, or philosophy behind this policy?

Why do variable assignments receive this treatment, but not function arguments?

IMO this violates the Principle of Least Astonishment.

A function argument generally has to be given a type independent of which parameter type it'll end up matching, because overload resolution needs to compare each argument's own type against every candidate's parameter types to pick the best match — if argument inference depended on "the parameter type of whichever overload gets picked," that's circular. A variable declaration ( IntFunc[] explicit = [...] ) doesn't have this problem: there's exactly one destination type, known up front, so the compiler can safely bias the literal toward it.

21 hours ago

Re: why is this cast required?
Gravatar of DanielGPosted by DanielG
in reply to Dejan Lekic
PermalinkReply

DanielG

Gravatar of DanielG

Posted in reply to Dejan Lekic

Ah, I see now! Thank you, that was exactly the information I was looking for.