www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Constructor qualifiers; bug or expected behavior?

reply RazvanN <razvan.nitu1305 gmail.com> writes:
Hi all,

Let's say we have this code:

struct B
{
     int a;
     this(int a) immutable
     {
         this.a = 7;
     }

     this(int a)
     {
         this.a = 10;
     }
}

void main()
{
     B a = immutable B(2);
     writeln(a.a);
     a.a = 4;

     immutable B a2 = immutable B(3);
     writeln(a2.a);
     a2.a = 3;        // error : cannot modify
}

Both a and a2 will be constructed using the immutable 
constructor, however a is not immutable (a.a = 4 will compile 
fine). Is this the intended behavior? Shouldn't the compiler warn 
me that I'm trying to create a mutable object using the 
constructor for an immutable object? I couldn't find any 
documentation about this.
Apr 02 2018
next sibling parent reply Eduard Staniloiu <edi33416 gmail.com> writes:
On Monday, 2 April 2018 at 10:26:32 UTC, RazvanN wrote:
 Hi all,

 Let's say we have this code:

 struct B
 {
     int a;
     this(int a) immutable
     {
         this.a = 7;
     }

     this(int a)
     {
         this.a = 10;
     }
 }

 void main()
 {
     B a = immutable B(2);
     writeln(a.a);
     a.a = 4;
type `B`
     immutable B a2 = immutable B(3);
     writeln(a2.a);
     a2.a = 3;        // error : cannot modify
 }

 Both a and a2 will be constructed using the immutable 
 constructor, however a is not immutable (a.a = 4 will compile 
 fine). Is this the intended behavior? Shouldn't the compiler 
 warn me that I'm trying to create a mutable object using the 
 constructor for an immutable object? I couldn't find any 
 documentation about this.
The compiler does an implicit conversion from the type `immutable B` to the type `B`. It is able to do safely do so because `struct B` has only value types that can be copied. The same thing happens for immutable x = 1; int y = x; If you add an indirection in `struct B`, as such struct B { int a; int* p; /* ... */ } Then you can see that the implicit conversion fails with "onlineapp.d(22): Error: cannot implicitly convert expression B(0, null).this(2) of type immutable(B) to B" I put the code at https://run.dlang.io/gist/83756973012fcb4fec2660a39ffdad90&args=-unittest?args=-unittest The same conversion rules that apply to built in qualified types applies to structs. I'm guessing the same is for classes but I haven't played that much with those so a second opinion would be nice :) Cheers, Edi
Apr 02 2018
parent Seb <seb wilzba.ch> writes:
On Monday, 2 April 2018 at 11:41:55 UTC, Eduard Staniloiu wrote:
 On Monday, 2 April 2018 at 10:26:32 UTC, RazvanN wrote:
 [...]
The compiler does an implicit conversion from the type `immutable B` to the type `B`. It is able to do safely do so because `struct B` has only value types that can be copied. The same thing happens for immutable x = 1; int y = x; If you add an indirection in `struct B`, as such struct B { int a; int* p; /* ... */ } Then you can see that the implicit conversion fails with "onlineapp.d(22): Error: cannot implicitly convert expression B(0, null).this(2) of type immutable(B) to B" I put the code at https://run.dlang.io/gist/83756973012fcb4fec2660a39ffdad90&args=-unittest?args=-unittest The same conversion rules that apply to built in qualified types applies to structs. I'm guessing the same is for classes but I haven't played that much with those so a second opinion would be nice :) Cheers, Edi
FYI sth. seems to have gone wrong with the current migration to authenticated Gists. Sorry about the inconvenience, the hotfix is already in the deploy queue and for this - the exported URL should have been: https://run.dlang.io/gist/83756973012fcb4fec2660a39ffdad90?args=-unittest
Apr 02 2018
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 02, 2018 at 10:26:32AM +0000, RazvanN via Digitalmars-d-learn wrote:
 Hi all,
 
 Let's say we have this code:
 
 struct B
 {
     int a;
     this(int a) immutable
     {
         this.a = 7;
     }
 
     this(int a)
     {
         this.a = 10;
     }
 }
 
 void main()
 {
     B a = immutable B(2);
     writeln(a.a);
     a.a = 4;
 
     immutable B a2 = immutable B(3);
     writeln(a2.a);
     a2.a = 3;        // error : cannot modify
 }
 
 Both a and a2 will be constructed using the immutable constructor,
 however a is not immutable (a.a = 4 will compile fine). Is this the
 intended behavior?
 Shouldn't the compiler warn me that I'm trying to create a mutable
 object using the constructor for an immutable object? I couldn't find
 any documentation about this.
What's happening here is that B is a value type, meaning that assignment makes a copy of the object. Since B has no fields that contain indirections, when a copy of B is made, it is completely independent of the original immutable object, so it's perfectly fine to make the copy mutable. T -- Meat: euphemism for dead animal. -- Flora
Apr 02 2018