www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Error in assignment to 'this' inside constructor

reply "TommiT" <tommitissari hotmail.com> writes:
I'm trying to assign (or simply bit-copy) over 'this' inside a 
constructor. There's an error when compile-time constructing the 
object. Is this a bug in DMD (2.062) ?

module main;

struct Test
{
     enum Test t = Test(1);
     int v;

     this(int)
     {
         v = 123;
     }

     this(int, int)
     {
         this = t;
     }
}

void main()
{
     Test t1 = Test(11, 22);
     writeln(t1.v); // Prints: 123

     enum t2 = Test(11, 22); // Error:
     // CTFE internal error: unsupported assignment this = 
Test(123)
}
May 11 2013
next sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
On Saturday, 11 May 2013 at 14:34:41 UTC, TommiT wrote:
 I'm trying to assign (or simply bit-copy) over 'this' inside a 
 constructor. There's an error when compile-time constructing 
 the object. Is this a bug in DMD (2.062) ?

 module main;

 struct Test
 {
     enum Test t = Test(1);
     int v;

     this(int)
     {
         v = 123;
     }

     this(int, int)
     {
         this = t;
     }
 }

 void main()
 {
     Test t1 = Test(11, 22);
     writeln(t1.v); // Prints: 123

     enum t2 = Test(11, 22); // Error:
     // CTFE internal error: unsupported assignment this = 
 Test(123)
 }
what? structs has value semantics, every time you assign a struct to variable it assign its copy. you also don't have to have constructor for structs, it initializes it fields in left-to-right order or so. struct A { int x; } void main() { A s1 = A(1); A s2 = A(2); A s3; s3 = s2; s2.x = 5; assert(s3.x == 2); assert(s2.x == 5); }
May 11 2013
parent reply "TommiT" <tommitissari hotmail.com> writes:
On Sunday, 12 May 2013 at 03:32:44 UTC, evilrat wrote:
 what? structs has value semantics, every time you assign a 
 struct to variable it assign its copy.

 you also don't have to have constructor for structs, it 
 initializes it fields in left-to-right order or so.

 [..]
Yes, I know that. But I'm not trying to write a struct such as 'Test' in my example above. 'Test' is just the simplest example I could make in order to showcase the (assumed) compiler bug. The struct that I *am* trying to make does indeed need a constructor and it's a very complex one and I do need a way to assign different compile-time-constant values of that struct type over 'this' inside the constructor. Anyway, if no-one tells me otherwise, I'll just assume it's a compiler bug and make a bug-report about it.
May 12 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Sunday, 12 May 2013 at 07:51:39 UTC, TommiT wrote:
 On Sunday, 12 May 2013 at 03:32:44 UTC, evilrat wrote:
 what? structs has value semantics, every time you assign a 
 struct to variable it assign its copy.

 you also don't have to have constructor for structs, it 
 initializes it fields in left-to-right order or so.

 [..]
Yes, I know that. But I'm not trying to write a struct such as 'Test' in my example above. 'Test' is just the simplest example I could make in order to showcase the (assumed) compiler bug. The struct that I *am* trying to make does indeed need a constructor and it's a very complex one and I do need a way to assign different compile-time-constant values of that struct type over 'this' inside the constructor. Anyway, if no-one tells me otherwise, I'll just assume it's a compiler bug and make a bug-report about it.
the problem with structs in your case is that this a value type, so may be you could use copy contructor? struct Something { // copy ctor this(Something s) {} } now just imagine how do you change "this" for a variable(or simply variable itself) which tried to copy something over itself? the closest possible thing is a reference, and that behavior seems absolutely logically correct, otherwise if modifying "this" would be allowed that would be easy way to do lots of errors where you don't expect them. but still if you think it's a bug fill a request or try also 2.063 beta.
May 12 2013
next sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
oops. nevermind i've forgot about how it done in D :(
you'd better read about it in language reference.
May 12 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
oh right,
struct A {
this(this) { copy referenced mem here}
}

or
struct A {
ref A opAssign(ref const A other) { this = other; return this; }
}

so if you have fields that should be fully copied like array this 
is the place to do it, otherwise there is a reference arguments, 
if both is no go for you then this behavior would make more 
trouble than benefits and thats.

so gather all up here are some little example
----

struct A
{	
	int x;
	int[] array;
	
	this(int x) { this.x = x; array ~= x; }
	this(this) { array = array.dup; }
	
	ref A opAssign(ref const A other) { this = other; return this; }
}

void main()
{
A a1 = A(1);
A a2 = A(2);
A a3 = a2;

a2.x = 5;

assert(a2.x == 5);
assert(a2.array[0] == 5);

assert(a3.x == 2);
assert(a3.array[0] == 2);

assert(a2.array.length == 1);
assert(a3.array.length == 1);

}
May 12 2013
parent "TommiT" <tommitissari hotmail.com> writes:
On Sunday, 12 May 2013 at 11:27:50 UTC, evilrat wrote:
 oh right,
 struct A {
 this(this) { copy referenced mem here}
 }

 or
 struct A {
 ref A opAssign(ref const A other) { this = other; return this; }
 }

 so if you have fields that should be fully copied like array 
 this is the place to do it, otherwise there is a reference 
 arguments, if both is no go for you then this behavior would 
 make more trouble than benefits and thats.

 so gather all up here are some little example
 ----

 struct A
 {	
 	int x;
 	int[] array;
 	
 	this(int x) { this.x = x; array ~= x; }
 	this(this) { array = array.dup; }
 	
 	ref A opAssign(ref const A other) { this = other; return this; 
 }
 }

 void main()
 {
 A a1 = A(1);
 A a2 = A(2);
 A a3 = a2;

 a2.x = 5;

 assert(a2.x == 5);
 assert(a2.array[0] == 5);

 assert(a3.x == 2);
 assert(a3.array[0] == 2);

 assert(a2.array.length == 1);
 assert(a3.array.length == 1);

 }
You're assigning to 'this', i.e. calling assignment operator, inside the assignment operator. That results in an infinite recursion. That code never calls the assignment operator though, but try a1 = a2 for example and that should crash.
May 12 2013
prev sibling parent "TommiT" <tommitissari hotmail.com> writes:
On Sunday, 12 May 2013 at 10:38:41 UTC, evilrat wrote:
 the problem with structs in your case is that this a value 
 type, so may be you could use copy contructor?

 struct Something {
 // copy ctor
 this(Something s) {}
 }
D doesn't have copy constructors. What you have there is just a regular constructor.
May 12 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/11/2013 04:34 PM, TommiT wrote:
 ...
      // CTFE internal error: unsupported assignment this = Test(123)
 ...
An "internal error" is always a compiler bug.
May 12 2013
parent "TommiT" <tommitissari hotmail.com> writes:
On Sunday, 12 May 2013 at 16:18:00 UTC, Timon Gehr wrote:
 On 05/11/2013 04:34 PM, TommiT wrote:
 ...
     // CTFE internal error: unsupported assignment this = 
 Test(123)
 ...
An "internal error" is always a compiler bug.
Thanks. Bug report there: http://d.puremagic.com/issues/show_bug.cgi?id=10069
May 12 2013