www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - struct postblit not called, but still destructed

reply "Lemonfiend" <lemon fie.nd> writes:
When a struct is passed to a function as argument, it is first 
copied and at the end destructed. But in the following code it is 
not copied, yet still destructed?

module main;

import std.stdio;

struct C
{
	A[] _objs;

	this(A[] objs...)
	{
		writeln(`  C this()`);
		_objs = objs;

		// A.this(this) is not called
		// yet A.~this IS called
	}
}

struct B
{
	A sup;
	alias sup this;

	this(A a)
	{
		writeln(count, ` B this()`);
		sup = a;
	}
}

struct A
{	
	static int count;

	this(int n)
	{
		count++;
		writeln(count, ` A this()`);
	}

	this(this)
	{
		count++;
		writeln(count, ` A this(this)`);
	}

	~this()
	{
		count--;
		writeln(count, ` A ~this()`);
	}
}

void main()
{
	A a = A(1);
	writeln(a.count == 1);

	B b = B(a);
	writeln(a.count == 2);

	C c = C(b);
	writeln(a.count == 3);
}
Jan 19 2014
next sibling parent "Lemonfiend" <lemon fie.nd> writes:
I just tried the new beta, and the issue remains.
Jan 19 2014
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 19.01.2014 18:48, schrieb Lemonfiend:
 import std.stdio;

 struct C
 {
      A[] _objs;

      this(A[] objs...)
      {
          writeln(`  C this()`);
          _objs = objs;

          // A.this(this) is not called
          // yet A.~this IS called
      }
 }

 struct B
 {
      A sup;
      alias sup this;

      this(A a)
      {
          writeln(count, ` B this()`);
          sup = a;
      }
 }

 struct A
 {
      static int count;

      this(int n)
      {
          count++;
          writeln(count, ` A this()`);
      }

      this(this)
      {
          count++;
          writeln(count, ` A this(this)`);
      }

      ~this()
      {
          count--;
          writeln(count, ` A ~this()`);
      }
 }

 void main()
 {
      A a = A(1);
      writeln(a.count == 1);

      B b = B(a);
      writeln(a.count == 2);

      C c = C(b);
      writeln(a.count == 3);
 }
Yes this looks like a bug to me. Please file a bug report at https://d.puremagic.com/issues/ Kind Regards Benjamin Thaut
Jan 19 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 19 January 2014 at 19:24:23 UTC, Benjamin Thaut wrote:
 Yes this looks like a bug to me. Please file a bug report at 
 https://d.puremagic.com/issues/

 Kind Regards
 Benjamin Thaut
Here is a reduced case: //---- import std.stdio; struct B { A sup; this(A a) { writeln("Here"); sup = a; writeln("There"); } } struct A { static int count; this(int n) { writeln("A.this()"); } this(this) { writeln("A.this(this)"); } ~this() { writeln("A.~this()"); } } void main() { A a = A(1); writeln("Start"); B b = B(a); writeln("End"); } //---- A.this() Start A.this(this) Here A.this(this) //!!! A.~this() //!!! There A.~this() End A.~this() A.~this() //---- I think the behavior is not *strictly* incorrect: When you write: sup = a; it triggers a postblit of "a" into "sup". To do said postblit, you destroy sup. It's the way it works :/ Arguably, since it is initialization, we could avoid the destruction altogether, but it's not strictly *wrong*. I'll file it as an ER, and try to get Kenji on it.
Jan 19 2014
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 19 January 2014 at 20:46:06 UTC, monarch_dodra wrote:
 I'll file it as an ER, and try to get Kenji on it.
https://d.puremagic.com/issues/show_bug.cgi?id=11952 As a workaround, it is usually recommended in the destructor to try to detect "initial state", and do nothing in such cases. This is generally recommended anyways, since the .init state could mess up your count: void main() { //Scope { A a; //No increment count }//Destruction assert(A.count == 0); //Fails } I'd say disabling "this()" would help, but in this case, your example code still fails... I'll bump the report to bug because of this.
Jan 19 2014
prev sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 19 January 2014 at 20:46:06 UTC, monarch_dodra wrote:
 I think the behavior is not *strictly* incorrect: When you 
 write:
 sup = a;

 it triggers a postblit of "a" into "sup". To do said postblit, 
 you destroy sup. It's the way it works :/

 Arguably, since it is initialization, we could avoid the 
 destruction altogether, but it's not strictly *wrong*.

 I'll file it as an ER, and try to get Kenji on it.
It is rather bug than ER because recently there was work to recognize such cases (initial assignment in constructors) as initialization, not just assignment. However I am not sure here because these changes were not documented properly.
Jan 20 2014