digitalmars.D.learn - why is this cast required?
- DanielG (17/20) Sep 25 ```d
- Dejan Lekic (25/45) Sep 25 Unfortunately you've hit a limitation of how the compiler
- DanielG (9/9) Sep 25 I see, thank you!
- monkyyy (8/9) Sep 25 delegates are twice as big as raw function pointers; when doing
- Dejan Lekic (17/28) Sep 26 You could answer your own question yourself by thinking why the
- DanielG (32/32) Sep 26 I appreciate the reply, but that's not the question I am asking.
- Dejan Lekic (10/20) Sep 26 A function argument generally has to be given a type independent
- DanielG (2/2) Sep 26 Ah, I see now! Thank you, that was exactly the information I was
- Himanshu Sharma (2/13) Oct 05 great information
- Tannesover (5/27) Oct 07 This is a classic issue with overload resolution in D. To clean
```d
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`
Sep 25
On Friday, 25 September 2026 at 11:14:50 UTC, DanielG wrote:
```d
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:
```d
exec([
delegate () => 1,
() => two(),
]);
```
, or by using an explicitly typed variable, which also provides
the necessary context:
```d
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.
Sep 25
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?
Sep 25
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.
Sep 25
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 ```d 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.
Sep 26
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.
```d
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?
}
}
```
Sep 26
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.
Sep 26
Ah, I see now! Thank you, that was exactly the information I was looking for.
Sep 26
On Saturday, 26 September 2026 at 19:39:35 UTC, Dejan Lekic wrote:On Saturday, 26 September 2026 at 16:49:48 UTC, DanielG wrote:great information[...]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.
Oct 05
On Friday, 25 September 2026 at 11:14:50 UTC, DanielG wrote:
```d
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(),
]);
}
```
https://slopegame-2.io
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`
This is a classic issue with overload resolution in D. To clean
up the code without using an explicit cast, you can wrap the
array elements with std.algorithm.map!toDelegate or mark the
individual function pointer with toDelegate.
Oct 07









monkyyy <crazymonkyyy gmail.com> 