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.