www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why it doesn't compile in D 2.0?

reply aarti_pl <aarti interia.pl> writes:
class Test {
     string t1 = "test";		//Ok!
     char[] t2 = "test".dup;	//Compile error
}

void main(char[][] args) {
}

Error:
hello.d(3): Error: cannot evaluate _adDupT((& 
D12TypeInfo_Aya6__initZ),"test") at compile time
hello.d(3): Error: cannot evaluate _adDupT((& 
D12TypeInfo_Aya6__initZ),"test") at compile time

Is there workaround?

BR
Marcin Kuszczak
(aarti_pl)
Jan 16 2010
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
aarti_pl <aarti interia.pl> wrote:

 class Test {
      string t1 = "test";		//Ok!
      char[] t2 = "test".dup;	//Compile error
 }

 void main(char[][] args) {
 }

 Error:
 hello.d(3): Error: cannot evaluate _adDupT((&  
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((&  
 D12TypeInfo_Aya6__initZ),"test") at compile time

 Is there workaround?

Constant strings are saved in the static data segment of the executable, so the .dup call would need to be executed at runtime. In other words, what this would do is cast const to mutable. If this did compile, changing the contents of t2 would change those contents for all instances of Test, which I assume is not your intention. As for the workaround, write a constructor: class Test { string t1 = "test"; string t2; this( ) { t2 = "test".dup; } } -- Simen
Jan 16 2010
parent reply aarti_pl <aarti interia.pl> writes:
W dniu 2010-01-16 13:26, Simen kjaeraas pisze:
 aarti_pl <aarti interia.pl> wrote:

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 }

 void main(char[][] args) {
 }

 Error:
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time

 Is there workaround?

Constant strings are saved in the static data segment of the executable, so the .dup call would need to be executed at runtime. In other words, what this would do is cast const to mutable. If this did compile, changing the contents of t2 would change those contents for all instances of Test, which I assume is not your intention. As for the workaround, write a constructor: class Test { string t1 = "test"; string t2; this( ) { t2 = "test".dup; } }

I want just simple initialization of variable. Casting of course is no (sane) option. Indeed, in case of classes your workaround will work. But in case of struct? The same problem occurs for structs, but you can not declare default constructor in structs... IMHO .dup should work for initialization of classes/structs. Any other ideas? BR Marcin Kuszczak (aarti_pl)
Jan 16 2010
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
On 01/16/2010 02:01 PM, aarti_pl wrote:
 W dniu 2010-01-16 13:26, Simen kjaeraas pisze:
 aarti_pl <aarti interia.pl> wrote:

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 }

 void main(char[][] args) {
 }

 Error:
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time

 Is there workaround?

Constant strings are saved in the static data segment of the executable, so the .dup call would need to be executed at runtime. In other words, what this would do is cast const to mutable. If this did compile, changing the contents of t2 would change those contents for all instances of Test, which I assume is not your intention. As for the workaround, write a constructor: class Test { string t1 = "test"; string t2; this( ) { t2 = "test".dup; } }

I want just simple initialization of variable. Casting of course is no (sane) option. Indeed, in case of classes your workaround will work. But in case of struct? The same problem occurs for structs, but you can not declare default constructor in structs... IMHO .dup should work for initialization of classes/structs. Any other ideas? BR Marcin Kuszczak (aarti_pl)

Perhaps this is or should be a bug. You can override dup to work in ctfe: char[] dup(string str) { return str.dup; } class Test { string t1 = "test"; //Ok! char[] t2 = "test".dup; //Compile error char[] t3 = "test".dup(); //Ok! } The spec even mentions it under ctfe: 6. as a special case, the following properties can be executed at compile time: .dup .length .keys .values http://www.digitalmars.com/d/2.0/function.html
Jan 16 2010
next sibling parent reply aarti_pl <aarti interia.pl> writes:
W dniu 2010-01-16 15:30, Lutger pisze:
 Perhaps this is or should be a bug. You can override dup to work in ctfe:

 char[] dup(string str)
 {
 return str.dup;
 }

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 char[] t3 = "test".dup(); //Ok!
 }

 The spec even mentions it under ctfe:

 6. as a special case, the following properties can be executed at
 compile time:
 ..dup
 ..length
 ..keys
 ..values

 http://www.digitalmars.com/d/2.0/function.html

Thanks! I will use function dup() as a workaround for now, and will put bug to bugzilla. I still wonder what has CTFE to do with this case. Do you know? I am asking because it's not possible in general case to initialize all variables in classes/structs and in global namespace. E.g. I had to use: Serializer!(TextArchive) serializer; static this() { serializer = new typeof(serializer); } to initialize serializer. I am wondering if with better CTFE we could get it working? BR Marcin Kuszczak (aarti_pl)
Jan 16 2010
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
On 01/16/2010 04:18 PM, aarti_pl wrote:
 W dniu 2010-01-16 15:30, Lutger pisze:
 Perhaps this is or should be a bug. You can override dup to work in ctfe:

 char[] dup(string str)
 {
 return str.dup;
 }

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 char[] t3 = "test".dup(); //Ok!
 }

 The spec even mentions it under ctfe:

 6. as a special case, the following properties can be executed at
 compile time:
 ..dup
 ..length
 ..keys
 ..values

 http://www.digitalmars.com/d/2.0/function.html

Thanks! I will use function dup() as a workaround for now, and will put bug to bugzilla. I still wonder what has CTFE to do with this case. Do you know? I am asking because it's not possible in general case to initialize all variables in classes/structs and in global namespace. E.g. I had to use: Serializer!(TextArchive) serializer; static this() { serializer = new typeof(serializer); } to initialize serializer. I am wondering if with better CTFE we could get it working? BR Marcin Kuszczak (aarti_pl)

ctfe is basically a user defined extension of constant folding, which is also mentioned in the spec that way. So to use it for more complex initialization makes sense, but this is constrained to compile time. From the example of the serializer, all we know is that it allocates memory. Array dup-ing also allocates memory however, so theoretically I see no immediate reason why it would not (eventually) be possible to use ctfe in that case. But it may be difficult to prove statically by the compiler that it is indeed safe to do so.
Jan 16 2010
prev sibling parent Don <nospam nospam.com> writes:
aarti_pl wrote:
 W dniu 2010-01-16 15:30, Lutger pisze:
 Perhaps this is or should be a bug. You can override dup to work in ctfe:

 char[] dup(string str)
 {
 return str.dup;
 }

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 char[] t3 = "test".dup(); //Ok!
 }

 The spec even mentions it under ctfe:

 6. as a special case, the following properties can be executed at
 compile time:
 ..dup
 ..length
 ..keys
 ..values

 http://www.digitalmars.com/d/2.0/function.html

Thanks! I will use function dup() as a workaround for now, and will put bug to bugzilla. I still wonder what has CTFE to do with this case. Do you know? I am asking because it's not possible in general case to initialize all variables in classes/structs and in global namespace. E.g. I had to use: Serializer!(TextArchive) serializer; static this() { serializer = new typeof(serializer); } to initialize serializer. I am wondering if with better CTFE we could get it working? BR Marcin Kuszczak (aarti_pl)

The next DMD release will have *major* CTFE improvements. I believe this will work in the next release. (D1 couldn't compile it before, it can now; I think D2 will be the same).
Jan 16 2010
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
On 01/17/2010 01:38 AM, Simen kjaeraas wrote:
 Lutger <lutger.blijdestijn gmail.com> wrote:

 Perhaps this is or should be a bug. You can override dup to work in ctfe:

 char[] dup(string str)
 {
 return str.dup;
 }

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 char[] t3 = "test".dup(); //Ok!
 }

The problem with this approach is that you now have a pointer to mutable data, the contents of which are stored in the static data segment, and thus actually immutable. Second (and this is related to the first), the pointer will be the same for all instances, and thus changing the contents of one will change the contents of all. IOW, what one (probably) wants in this situation, is a constructor.

Thanks man, this is a big error of mine. Trying to manipulate the char[] does indeed do a segfault! I can't seem to find an explanation in the spec of how initializers are supposed to work, so I assumed incorrectly it would be ok. I find it a bit disturbing that you can end up with a mutable reference to immutable data so easily, without casting or anything.
Jan 17 2010
parent reply aarti_pl <aarti interia.pl> writes:
W dniu 2010-01-17 12:54, Lutger pisze:
 On 01/17/2010 01:38 AM, Simen kjaeraas wrote:
 Lutger <lutger.blijdestijn gmail.com> wrote:

 Perhaps this is or should be a bug. You can override dup to work in
 ctfe:

 char[] dup(string str)
 {
 return str.dup;
 }

 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 char[] t3 = "test".dup(); //Ok!
 }

The problem with this approach is that you now have a pointer to mutable data, the contents of which are stored in the static data segment, and thus actually immutable. Second (and this is related to the first), the pointer will be the same for all instances, and thus changing the contents of one will change the contents of all. IOW, what one (probably) wants in this situation, is a constructor.

Thanks man, this is a big error of mine. Trying to manipulate the char[] does indeed do a segfault! I can't seem to find an explanation in the spec of how initializers are supposed to work, so I assumed incorrectly it would be ok. I find it a bit disturbing that you can end up with a mutable reference to immutable data so easily, without casting or anything.

Well, I don't get it... IMHO .dup makes mutable copy of data (so copy of "test") in mutable area of memory. And it should mean that every pointer points to different area of memory... Am I wrong? BR Marcin Kuszczak (aarti_pl)
Jan 17 2010
parent aarti_pl <aarti interia.pl> writes:
W dniu 2010-01-17 20:56, Simen kjaeraas pisze:
 aarti_pl <aarti interia.pl> wrote:

 Well, I don't get it...

 IMHO .dup makes mutable copy of data (so copy of "test") in mutable
 area of memory. And it should mean that every pointer points to
 different area of memory...

 Am I wrong?

You're mostly right. However, this happens at compile time, so the mutable data is mutable no longer once its been stored in the executable. IOW, "Test".dup is executed once at compile time, and the result stored in Test.init. Then, at runtime, Test.init is copied onto each new instance of the struct/class. "Test".dup is not executed at runtime. As Lutger pointed out, this smells of a bug. Sadly, fixing that bug would not overcome the problem of having no default constructors for structs. -- Simen

Well, in such a case you are right. It's not what I would like to have... It will be indeed source of bugs. BR Marcin Kuszczak (aarti_pl)
Jan 18 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Lutger <lutger.blijdestijn gmail.com> wrote:

 Perhaps this is or should be a bug. You can override dup to work in ctfe:

 char[] dup(string str)
 {
      return str.dup;
 }

 class Test {
      string t1 = "test";        //Ok!
      char[] t2 = "test".dup;    //Compile error
      char[] t3 = "test".dup();  //Ok!
 }

The problem with this approach is that you now have a pointer to mutable data, the contents of which are stored in the static data segment, and thus actually immutable. Second (and this is related to the first), the pointer will be the same for all instances, and thus changing the contents of one will change the contents of all. IOW, what one (probably) wants in this situation, is a constructor. -- Simen
Jan 16 2010
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
aarti_pl wrote:
 
 class Test {
     string t1 = "test";        //Ok!
     char[] t2 = "test".dup;    //Compile error
 }
 
 void main(char[][] args) {
 }
 
 Error:
 hello.d(3): Error: cannot evaluate _adDupT((& 
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((& 
 D12TypeInfo_Aya6__initZ),"test") at compile time
 
 Is there workaround?
 
 BR
 Marcin Kuszczak
 (aarti_pl)

Workaround: It works in dmd2, svn 337 and later <g>.
Jan 17 2010
parent reply aarti_pl <aarti interia.pl> writes:
W dniu 2010-01-17 19:38, Don pisze:
 aarti_pl wrote:
 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 }

 void main(char[][] args) {
 }

 Error:
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time

 Is there workaround?

 BR
 Marcin Kuszczak
 (aarti_pl)

Workaround: It works in dmd2, svn 337 and later <g>.

Wow. I even could not report it as a bug. That is really fast bug fixing :-) Could you please explain what has initialization of variables to do with CTFE? As far as I understand it should be done on runtime... So why is there compile time execution involved? And other questions. Would it be possible to initialize more complex types with better CTFE? I see it as quite major issue when I can not write in class definition or in global scope: auto serializer = new Serializer!(TextArchive)(); BR Marcin Kuszczak (aarti_pl)
Jan 17 2010
parent Don <nospam nospam.com> writes:
aarti_pl wrote:
 W dniu 2010-01-17 19:38, Don pisze:
 aarti_pl wrote:
 class Test {
 string t1 = "test"; //Ok!
 char[] t2 = "test".dup; //Compile error
 }

 void main(char[][] args) {
 }

 Error:
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time
 hello.d(3): Error: cannot evaluate _adDupT((&
 D12TypeInfo_Aya6__initZ),"test") at compile time

 Is there workaround?

 BR
 Marcin Kuszczak
 (aarti_pl)

Workaround: It works in dmd2, svn 337 and later <g>.

Wow. I even could not report it as a bug. That is really fast bug fixing :-)

It wasn't specifically a fix of this bug. Some long-standing CTFE limitations were fixed, which make lots of things start working.
 Could you please explain what has initialization of variables to do with 
 CTFE? As far as I understand it should be done on runtime... So why is 
 there compile time execution involved?

It shouldn't be happening. There's a bug somewhere.
 And other questions. Would it be possible to initialize more complex 
 types with better CTFE? I see it as quite major issue when I can not 
 write in class definition or in global scope:
 
 auto serializer = new Serializer!(TextArchive)();

If you can't do that now, that's a serious bug. But classes will eventually work in CTFE.
Jan 20 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
aarti_pl <aarti interia.pl> wrote:

 Well, I don't get it...

 IMHO .dup makes mutable copy of data (so copy of "test") in mutable area  
 of memory. And it should mean that every pointer points to different  
 area of memory...

 Am I wrong?

You're mostly right. However, this happens at compile time, so the mutable data is mutable no longer once its been stored in the executable. IOW, "Test".dup is executed once at compile time, and the result stored in Test.init. Then, at runtime, Test.init is copied onto each new instance of the struct/class. "Test".dup is not executed at runtime. As Lutger pointed out, this smells of a bug. Sadly, fixing that bug would not overcome the problem of having no default constructors for structs. -- Simen
Jan 17 2010