Nested delegates and closure allocations

FeepingCreature feepingcreature at gmail.com
Tue Jan 16 17:21:12 UTC 2024


On Tuesday, 16 January 2024 at 15:39:07 UTC, Anonymouse wrote:
> If I make a `scope` variable of the delegate and pass *it* to 
> `receiveTimeout`, there no longer seems to be any mention of 
> the closure in the error (given 2.092 or later).
>
> ```d
> void foo(Thing thing) @nogc
> {
>     void sendThing(const string where, int i)
>     {
>         send(thing, where, i);
>     }
>
>     scope scopeSendThing = &sendThing;
>     receiveTimeout(Duration.zero, scopeSendThing);
> }
> ```
>
> Ignoring that it doesn't compile for other reasons; provided 
> `scope scopeSendThing = &sendThing;` compiles -- as in, 
> `&sendThing` is eligible for `scope` -- is this a valid 
> workaround?

Correct. The problem is that `receiveTimeout` is defined as a 
template variadic function: it *can* take a scoped function, but 
it doesn't (can't) declare that its argument is always scoped, so 
since scoped parameters are opt-in, it defaults to unscoped. And 
&sendThing has to also default to unscoped, because you can pass 
unscoped values to scoped parameters but not the other way 
around, so it defaults to the most generic type available. With 
your scoped variable you provide DMD the critical hint that 
actually you want the closure to be scoped, and once the value is 
scoped it stays scoped.


More information about the Digitalmars-d-learn mailing list