On Monday, 17 August 2015 at 10:28:33 UTC, thedeemon wrote:
Nope, it "works" only because "r" is unreferenced and gets thrown out. Just try using r.front there, for example, and the error returns.

You're right, it falls short.

But I think r not being referenced is not exactly it. Using front in Ali's func breaks it in the same way. And returning r from func works.

Wait, returning r from func works? Yes:

----
auto func()(uint[] arr, uint context) @nogc
{
    import std.algorithm;
auto r = arr[].map!(delegate(value) { return value * context; });
    return r;
}
void main() @nogc
{
    uint[3] arr = [1,2,3];
    uint context = 2;
    auto r = func(arr[], context);

    import std.algorithm: equal;
    import std.range: only;
    assert(equal(r, only(2, 4, 6)));
}
----

Is that supposed to compile? A closure is needed for the delegate, isn't it? With @nogc, where is the closure stored? This looks like an accepts-invalid bug to me.

It doesn't compile when func is not a template. So maybe the check is broken for templates.

It also doesn't compile with 2.067, so this may be a regression.

Coming back to Ali's code, here's a version that shows that func doesn't need template parameters, but it needs to be a template:

----
import std.stdio;
import std.algorithm;

struct Caller
{
    uint method(uint value) pure @nogc {
        return _context * value;
    }

    uint _context;
}

auto func()(uint[] arr, uint delegate(uint) pure @nogc d) @nogc
{
    return arr.map!(d);
}

void main() @nogc
{
    uint[3] arr = [1,2,3];
    uint context = 2;
    auto c = Caller(context);
    auto d = &c.method;

    auto r = func(arr[], d);

    import std.algorithm: equal;
    import std.range: only;
    assert(equal(r, only(2, 4, 6)));
}
----

I think this relies on the same discrepancy as the problematic code above.

Reply via email to