D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3909 - toDelegate handles only a tiny subset of function pointer types
Summary: toDelegate handles only a tiny subset of function pointer types
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P2 major
Assignee: No Owner
URL:
Keywords:
Depends on: 1818
Blocks:
  Show dependency treegraph
 
Reported: 2010-03-08 23:33 UTC by Max Samukha
Modified: 2021-01-09 19:05 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Max Samukha 2010-03-08 23:33:42 UTC
Current implementation of toDelegate requires parameter and return types of the argument to be accessible from std.functional, meaning that it won't accept most of function pointers taking or returning instances of UDTs:

----
import std.functional;

struct S
{
}

void foo(S s)
{
}

void main()
{
    auto dg = &toDelegate(&foo);
}

Error: identifier 'S' is not defined
----

The cause is the mixed-in delegate type generated from the function pointer type's stringof, which is invalid in the context of the template declaration.
A workaround is to avoid the stringof like this:

alias ParameterTypeTuple!(F) Params;
// mixed-in string:
alias <storage classes> ReturnType!(F) delegate(<storage classes> Params[0], ... <storage classes> Params[$ - 1]) Dg;

where <storage classes> are extracted from F's stringof (isRef, isOut, isLazy may work too)
Comment 1 Max Samukha 2010-03-09 00:01:42 UTC
In the test case,

auto dg = &toDelegate(&foo);

should be

auto dg = toDelegate(&foo);
Comment 2 David Simcha 2010-05-25 06:29:49 UTC
I just noticed this report now.  Really, the reason this code is so poorly designed (I wrote it, and I'll admit in hindsight that it does suck) is bug 1818.  The stupid mixin hack was a last-minute workaround for this bug and wasn't thought through properly.  This is noted in the comments:

functional.d around line 550:

    // Workaround for DMD Bug 1818.
    mixin("alias " ~ ReturnType!(F).stringof ~
        " delegate" ~ ParameterTypeTuple!(F).stringof ~ " DelType;");

    version(none) {
        // What the code would be if it weren't for bug 1818:
        alias ReturnType!(F) delegate(ParameterTypeTuple!(F)) DelType;
    }
Comment 3 Max Samukha 2010-05-25 08:12:12 UTC
(In reply to comment #2)
> I just noticed this report now.  Really, the reason this code is so poorly
> designed (I wrote it, and I'll admit in hindsight that it does suck) is bug
> 1818.  The stupid mixin hack was a last-minute workaround for this bug and
> wasn't thought through properly.  This is noted in the comments:
> 
> functional.d around line 550:
> 
>     // Workaround for DMD Bug 1818.
>     mixin("alias " ~ ReturnType!(F).stringof ~
>         " delegate" ~ ParameterTypeTuple!(F).stringof ~ " DelType;");
> 
>     version(none) {
>         // What the code would be if it weren't for bug 1818:
>         alias ReturnType!(F) delegate(ParameterTypeTuple!(F)) DelType;
>     }

Phobos has recently acquired functionality for extracting storage classes from functions and function parameters. I haven't given it a close look but it seems to do that by parsing mangled names. Hacky but should make it possible to correctly generate function types based on other function types.
Comment 4 Shin Fujishiro 2010-05-27 22:12:09 UTC
I commited a hacky workaround in svn r1561.  Now it works with user-defined types and function attributes (such as pure).  But I leave this bug opened becuase the bug is not completely fixed.
Comment 5 Bolpat 2021-01-09 19:05:58 UTC
This code snippet:

import std.functional;
struct S { }
void foo(S s) { }
void main() { auto dg = toDelegate(&foo); }

compiled on all dmd versions since 2.060; I won't go into the hurdle and find out which version it got fixed. Closing this.