Issue 17156 - Local function declaration not inferred to be static
Summary: Local function declaration not inferred to be static
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P3 normal
Assignee: No Owner
URL: http://dlang.org/
Keywords:
Depends on:
Blocks:
 
Reported: 2017-02-08 08:13 UTC by Eyal
Modified: 2017-05-13 15:58 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Eyal 2017-02-08 08:13:52 UTC
void f() {
    uint function() a = () => 5; // OK

    static uint s() { return 5; }
    uint function() b = &s; // ALSO OK

    uint g() { return 5; }
    uint function() c = &g; // BOOM! "&g" is a delegate. why?
}


There should not really be a difference between "s" and "g". The "static" there should be inferred from lack of any lexical capture.
Comment 1 Walter Bright 2017-05-12 00:52:43 UTC
The trouble is this:

    uint g() { return 5; }
    ...
    uint delegate() d = &g;

Your proposal would cause that to fail. Inference is done for template 'a' because the assignment is part of the expression. But for the 'g' case, there may be intervening code of this sort:

    uint g() { return 5; }
    uint function() c = &g;
    uint delegate() d = &g;

'g' cannot be both a function and a delegate. So the simple rule is 'static' being there or not sets it to be a function pointer or a delegate. This is consistent with other uses of 'static'.

This is working as designed. Not a bug.
Comment 2 Eyal 2017-05-12 15:55:17 UTC
I see, but this would not be a problem if function was automatically convertible to delegate (std.functional : toDelegate).

Is there any reason that you cannot hand over functions when delegates are expected?

I'd expect something even simpler than std.functional:toDelegate to work, especially if done inside the compiler:

auto toDelegate(R, Args...)(R function(Args args) func) {
    struct delegate_t {
        R function(Args args) ctx;
        R function(R function(Args args), Args args) func;
    }
    static R call_func(R function(Args args) arg, Args args) {
        auto f = arg;
        return f(args);
    }
    auto del = delegate_t(func, &call_func);
    return *cast(R delegate(Args) *)&del;
}
Comment 3 Walter Bright 2017-05-13 15:58:02 UTC
(In reply to Eyal from comment #2)
> I see, but this would not be a problem if function was automatically
> convertible to delegate (std.functional : toDelegate).
> 
> Is there any reason that you cannot hand over functions when delegates are
> expected?

Yes. The ABI of how functions and delegates are passed ensures one cannot be treated as the other.

The compiler could, behind the curtain, generate a wrapper to do this (as you suggest), but that has negative performance implications that users could find very surprising because it would be hidden from them. I prefer the library template solution for that reason.