[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