Skip to content

Commit

Permalink
Make toDelegate safe for function pointers
Browse files Browse the repository at this point in the history
Co-authored-by: Elias Batek <0xEAB@users.noreply.github.com>
  • Loading branch information
Bolpat and 0xEAB committed Dec 29, 2024
1 parent ff25f6d commit 89d37f4
Showing 1 changed file with 37 additions and 7 deletions.
44 changes: 37 additions & 7 deletions std/functional.d
Original file line number Diff line number Diff line change
Expand Up @@ -1814,13 +1814,42 @@ if (isCallable!(F))
{
return fp;
}
else static if (is(F Func == Func*) && is(Func == function) && is(Func Params == __parameters))
{
return () @trusted
{
return buildDelegate(fp);
}();
}
else static if (is(typeof(&F.opCall) == delegate)
|| (is(typeof(&F.opCall) V : V*) && is(V == function)))
{
return toDelegate(&fp.opCall);
}
else
{
return buildDelegate(fp);
}
}

///
@safe unittest
{
static int inc(ref uint num) {
num++;
return 8675309;
}

uint myNum = 0;
auto incMyNumDel = toDelegate(&inc);
auto returnVal = incMyNumDel(myNum);
assert(myNum == 1);
}

private template buildDelegate(F)
if (isCallable!(F))
{
auto buildDelegate(auto ref F fp) {
alias DelType = typeof(&(new DelegateFaker!(F)).doIt);

static struct DelegateFields {
Expand Down Expand Up @@ -1850,21 +1879,22 @@ if (isCallable!(F))
}
}

///
@system unittest
@safe unittest
{
static int inc(ref uint num) {
num++;
return 8675309;
}

uint myNum = 0;
auto incMyNumDel = toDelegate(&inc);
auto returnVal = incMyNumDel(myNum);
assert(myNum == 1);
uint myNum = 0x1337;
struct S1 { int opCall() { inc(myNum); return myNum; } }
static assert(!is(typeof(&s1.opCall) == delegate));
S1 s1;
auto getvals1 = toDelegate(s1);
assert(getvals1() == 0x1338);
}

@system unittest // not @safe due to toDelegate
@system unittest
{
static int inc(ref uint num) {
num++;
Expand Down

0 comments on commit 89d37f4

Please sign in to comment.