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.