Thread overview
Error in assignment to 'this' inside constructor
May 11, 2013
TommiT
May 12, 2013
evilrat
May 12, 2013
TommiT
May 12, 2013
evilrat
May 12, 2013
evilrat
May 12, 2013
evilrat
May 12, 2013
TommiT
May 12, 2013
TommiT
May 12, 2013
Timon Gehr
May 12, 2013
TommiT
May 11, 2013
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 12, 2013
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 12, 2013
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
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
oops. nevermind i've forgot about how it done in D :(
you'd better read about it in language reference.
May 12, 2013
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
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
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
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
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