Store any callable in an array

ag0aep6g anonymous at example.com
Mon May 7 10:20:22 UTC 2018


On 05/07/2018 04:41 AM, wjoe wrote:
> Could you elaborate on the unsafe destructor please?

If TFunc has an unsafe destructor, asDelegate is also not safe and can't 
be @trusted.

An example of how that can break safety:

----
auto asDelegate(TFunc)(TFunc func) @trusted
{
      import std.functional : toDelegate;
      return toDelegate(func);
}

int* ptr;
size_t length;

struct S
{
     void opCall() {}
     ~this() @system
     {
         ptr[length - 1] = 13;
     }
}

void main() @safe
{
     ptr = new int;
     length = 5; /* Whoops, got the length wrong. */
     immutable int* imm = new int(42);
     auto dg = asDelegate(S.init);
     assert(*imm == 42); /* Fails. Immutability has been broken. */
}
----

The program has undefined behavior, which means it's invalid. And it's 
the fault of the wrong @trusted.

> Are there any other gotchas ?

The postblit function `this(this)` is also commonly overlooked with 
regards to @trusted. It might not be a problem here, though, because 
toDelegate has a `ref` parameter.

An unsafe `alias this` would be another problem. Example:
----
/* ... asDelegate, ptr, length, main as above ... */
struct S
{
     @property T t() @system
     {
         ptr[length - 1] = 13;
         return T.init;
     }
     alias t this;
}
struct T
{
     void opCall() {}
}
----

Those are the things I can see happening in asDelegate.

Additionally, you'd have to check what the toDelegate call does exactly 
before trusting it. And if it turns out that the call can be trusted, 
then you can probably just mark toDelegate itself as @trusted. And then 
there would be no need for asDelegate anymore.


More information about the Digitalmars-d-learn mailing list