On 09/19/2016 01:27 PM, Lodovico Giaretta wrote:
As we all should know, std.conv.emplace does not play well with closures:

void main()
{
    int x = 42;
    struct S
    {
        auto getX() { return x; }
    }

    S s;
    assert(s.getX == x);

    auto ps = someBuffer.emplace!S();
    assert(s.getX == x);                // SEGFAULT!
}

Should probably be `assert(ps.getX == x);`.

Note that it would also segfault with `auto ps = S.init;`, and for the same reason: missing context pointer.

As this is not fixable (we cannot pass closures around in D), we should
IMHO forbid such usages of emplace (i.e. static assert(!isNested!S))

I was already working on this, when I stumbled upon this unittest in
std.conv (simplified):

unittest
{
    int i = 0;
    struct S1
    {
        void foo(){++i;}
    }
    S1 sa = void;
    S1 sb;
    emplace(&sa, sb);   // automagically works
    sa.foo();
    assert(i == 1);
}

Of course there's no way to distinguish between this (legitimate?) use
case and the former one, so preventing those segfaults will also
prohibit this kind of usage.

There is a difference, though: You're copying an existing object here, including the context pointer. So maybe we could disallow the variant above that writes the .init value, and still allow the copying variant.

Reply via email to