Thread overview
Destructor called twice.
Feb 25, 2018
TheFlyingFiddle
Feb 25, 2018
ketmar
Feb 26, 2018
TheFlyingFiddle
February 25, 2018
When writing some code to setup properties in a chain function manner I ran into some unexpected behavior with destructors.

Example:

struct S {
    int a, b;

    ref S foo(int b) {
        this.b = b;
        return this;
    }

    this(int ab) {
        this.a = this.b = ab;
        printf("ctor a=%d, b=%d\n", a, b);
    }

    ~this() {
        printf("dtor a=%d b=%d\n", a, b);
    }


}

void main()
{
    auto s0 = S(0).foo(1);
    auto s1 = S(1).foo(2).foo(3).foo(4);
    auto s2 = S(2);
    s2.foo(5).foo(6).foo(7);
}

//Output is
ctor 0
dtor 0 1
ctor 1
dtor 1 4
ctor a=2, b=2
dtor a=2 b=7
dtor 1 4
dtor 0 1


For s0,s1 the destructor is called twice but s2 works as I would expect.

Taking a look with dmd -vcg-ast provided this:
void main()
{
    S s0 = ((S __slS3 = S(, );) , __slS3).this(0).foo(1);
    try
    {
    	S s1 = ((S __slS4 = S(, );) , __slS4).this(1).foo(2).foo(3).foo(4);
    	try
    	{
    	    S s2 = s2 = S , s2.this(2);
    	    try
    	    {
    		s2.foo(5).foo(6).foo(7);
    	    }
    	    finally
    		s2.~this();
    	}
    	finally
    	    s1.~this();
    }
    finally
    	s0.~this();
    return 0;
}

The two extra dtor calls are not visible here but I guess they are caused by the temporary variables that are created and then go out of scope directly. Am I doing something wrong or is this a bug?



February 25, 2018
add postblit debug prints, and you will see.
February 26, 2018
On Sunday, 25 February 2018 at 21:35:33 UTC, ketmar wrote:
> add postblit debug prints, and you will see.

I get that it will call the postblit since it creates a temporary.

What I expected though was that.

auto s = S(0).foo(1);

Would become something like:

S s; s.__ctor(0).foo(1);

But maybe this would not be consistent behavior?

I'm wondering why it creates the temporary in the first place.