see: https://forum.dlang.org/post/[email protected]
An example:
import std.experimental.all;
auto assumePure(T)(T t)
if (isFunctionPointer!T || isDelegate!T)
{
enum attrs = functionAttributes!T | FunctionAttribute.pure_;
return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
}
struct A
{
@disable this();
this(size_t i) { ctors++; this.i = i; writeln("CTOR ", i); }
~this() { dtors++; writeln("DTOR ", i); }
void dbg() { ctors++; writeln("POSTBLIT ", i); }
pure this(this)
{
assumePure(&dbg)();
}
static size_t ctors = 0;
static size_t dtors = 0;
size_t i;
}
struct Range
{
//@property size_t length = 4; // Uncomment this line for a similar result!
@property A front() { return A(count); }
void popFront() { count++; }
@property empty() { return count > 3; }
size_t count = 0;
}
void main()
{
// This is never freed, apparently
{
auto tmp = Range();
tmp.array.writeln;
}
import core.memory;
GC.collect();
}
static ~this()
{
writeln(A.ctors, "ctors vs ", A.dtors, " dtors");
}
Comment #1 by schveiguy — 2018-06-15T18:10:59Z
The issue is with array using uninitializedArray to allocate. This function does not (and really cannot) initialize the proper GC bits to call the destructors properly.
std.array.array should use normal array allocation functions when the type being allocated has a destructor.