digitalmars.D.bugs - [Issue 15328] New: Postblit not called
- via Digitalmars-d-bugs (125/125) Nov 13 2015 https://issues.dlang.org/show_bug.cgi?id=15328
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 puremagic.com Reporter: andrei 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() {} --
Nov 13 2015