[Issue 15328] New: Postblit not called
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Fri Nov 13 08:59:33 PST 2015
https://issues.dlang.org/show_bug.cgi?id=15328
Issue ID: 15328
Summary: Postblit not called
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: major
Priority: P1
Component: druntime
Assignee: nobody at puremagic.com
Reporter: andrei at erdani.com
I have a rather complicated repro that could use fresh eyes for simplification.
The gist of it is the the function Range save() { return this; } does not call
the postblit.
struct List(T)
{
import std.traits;
private struct Node
{
T payload;
Node* next;
uint refs;
}
// layout {
private const(Node)* root;
// } layout
private @trusted static void incRef(const Node* n)
{
if (n) ++*(cast(uint*) &(n.refs));
}
private @trusted static void decRefUnchecked(const Node* n)
{
assert(n && n.refs > 1);
--*(cast(uint*) &(n.refs));
}
// Entry point, decRef and destroy+deallocate if down to zero
private static void decRef(const Node* n)
{
assert(n);
if (n.refs > 1)
{
decRefUnchecked(n);
return;
}
static if (hasMember!(T, "__dtor"))
n.payload.__dtor();
}
this(this)
{
incRef(root);
}
~this()
{
for (auto n = root; n;)
{
if (n.refs > 1)
{
decRefUnchecked(n);
return;
}
auto goner = n;
n = n.next;
static if (hasMember!(T, "__dtor"))
goner.payload.__dtor();
}
}
private this(const Node* n)
{
root = n;
}
/**
* Returns a new $(D List) consisting of $(D head) followed by the contents
of $(D this).
* Complexity: $(BIGOH n).
*/
List opBinaryRight(string op)(T head)
if (op == "~")
{
List result;
import std.conv : emplace;
auto n = new const Node(head, root, 1);
incRef(root);
result.root = n;
return result;
}
auto opSlice() inout
{
static struct Range
{
// layout {
private const(Node)* root;
// } layout
this(this)
{
incRef(root);
}
~this()
{
if (!root) return;
assert(root.refs >= 1);
decRef(root);
}
Range save()
{
return this;
}
}
incRef(root);
auto result = Range(root);
return result;
}
}
unittest
{
auto lst = 1 ~ (2 ~ (3 ~ List!(immutable int)()));
auto lst2 = 42 ~ lst;
auto range = lst2[];
assert(lst.root.refs == 2);
auto range1 = range.save;
assert(lst.root.refs == 3); // fails
}
void main() {}
--
More information about the Digitalmars-d-bugs
mailing list