Nested delegates and closure allocations

Anonymouse zorael at gmail.com
Tue Jan 16 15:39:07 UTC 2024


On Tuesday, 16 January 2024 at 13:45:22 UTC, FeepingCreature 
wrote:
>> Am I safe as long as I don't do something like, pass 
>> `&sendThing` as an argument to `std.concurrency.receive`?
>
> Yes.

Thank you.

And to make sure I don't misunderstand the spec; in the case I 
*do* have a delegate I want to pass elsewhere, and `scope dg = 
&myFun;` *does* compile, passing that `dg` around won't allocate 
a closure?

```d
void foo(Thing thing) @nogc
{
     void sendThing(const string where, int i)
     {
         send(thing, where, i);
     }

     receiveTimeout(Duration.zero, &sendThing);
}
```

The above naturally won't compile because 
`std.concurrency.receiveTimeout` requires the garbage collector, 
but notably in the error message, this is included;

```
onlineapp.d(10): Error: function `onlineapp.foo` is `@nogc` yet 
allocates closure for `foo()` with the GC
onlineapp.d(12):        `onlineapp.foo.sendThing` closes over 
variable `thing` at onlineapp.d(10)
```

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?


More information about the Digitalmars-d-learn mailing list