www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Why implicit conversion of string literal to char[] does not works?

reply "Michal Minich" <michal.minich gmail.com> writes:
void main ()
{
     char[] str = "abc";
     // Error: cannot implicitly convert expression ("abc")
     // of type string to char[]
}

I thought there is no harm in that?
Jul 02 2013
next sibling parent reply "Michal Minich" <michal.minich gmail.com> writes:
Sorry for posting to announce.
Jul 02 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 2 July 2013 at 09:11:44 UTC, Michal Minich wrote:
 Sorry for posting to announce.
In future please post these questions to digitalmars.D.learn The reason you can't implicitly convert a string to a char[] is because string is an alias to immutable(char)[] Therefore, you would be providing a mutable window to immutable data, which is disallowed unless you *explicitly* ask for it (see below). You can explicitly cast string to char[], but it is undefined behaviour to modify the contents of the result (i.e. don't cast away immutable unless you absolutely have to and even then be very very careful).
Jul 02 2013
parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Tuesday, 2 July 2013 at 10:09:10 UTC, John Colvin wrote:
 The reason you can't implicitly convert a string to a char[] is 
 because string is an alias to immutable(char)[]

 Therefore, you would be providing a mutable window to immutable 
 data, which is disallowed unless you *explicitly* ask for it 
 (see below).
would be -> might be
 You can explicitly cast string to char[], but it is undefined 
 behaviour to modify the contents of the result
ok (i.e. don't cast
 away immutable unless you absolutely have to and even then be 
 very very careful).
This is not correct. You should can not cast when you 'absolutely have to' but when you can prove by means not available to compiler that the data being casted are in fact mutable. And the 'proving' of this is what you should be careful about. But ... I'm asking only about implicit conversion of string literal, not arbitrary expressions of string type.
Jul 02 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote:
 But ... I'm asking only about implicit conversion of string 
 literal, not arbitrary expressions of string type.
char[] str = "abc".dup;
Jul 02 2013
parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Tuesday, 2 July 2013 at 11:29:05 UTC, Dicebot wrote:
 On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote:
 But ... I'm asking only about implicit conversion of string 
 literal, not arbitrary expressions of string type.
char[] str = "abc".dup;
Thanks, that is workaround I didn't know about. I'm really interested about reasons why it doesn't works (without dup/cast). At some point it had to be disabled. But I really cannot find a reason why that would be useful.
Jul 02 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 2 July 2013 at 11:33:16 UTC, Michal Minich wrote:
 char[] str = "abc".dup;
Thanks, that is workaround I didn't know about. I'm really interested about reasons why it doesn't works (without dup/cast). At some point it had to be disabled. But I really cannot find a reason why that would be useful.
It is not a workaround but an expected approach. You are trying to get a mutable slice from an immutable array. There is no way this can be legal. And allowing mutable string literals just asks for trouble: char[] str1 = "abc"; char[] str2 = "abc"; str1[0] = 'x'; assert(str2 == "abc"); // pass of fail? Please note that this works: char[3] str = "abc"; Here literal data is copied to a static array and concerns that matter with a slice are not valid anymore.
Jul 02 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/2/13, Michal Minich <michal.minich gmail.com> wrote:
 I'm really interested about reasons why it doesn't works (without
 dup/cast).
It's probably to avoid implicit memory allocations.
Jul 02 2013
prev sibling parent reply "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 02 Jul 2013 12:33:14 +0100, Michal Minich  
<michal.minich gmail.com> wrote:

 On Tuesday, 2 July 2013 at 11:29:05 UTC, Dicebot wrote:
 On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote:
 But ... I'm asking only about implicit conversion of string literal,  
 not arbitrary expressions of string type.
char[] str = "abc".dup;
Thanks, that is workaround I didn't know about. I'm really interested about reasons why it doesn't works (without dup/cast). At some point it had to be disabled. But I really cannot find a reason why that would be useful.
It is done for performance reasons. On UNIX the compiler will put the literal "abc" into read only memory. It could/should do the same on windows but doesn't yet (I believe). So, the compiler is treating them as such, by giving them the type immutable(char)[] (AKA string). And, the spec should, if it doesn't, define string literals to be immutable. In older versions of DMD we didn't have string AKA immutable(char), in fact at one point we didn't have immutable at all. At that time, "abc" was typed as char[] and people on UNIX systems ran headlong into an access violation attempting to write to ROM :p R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 02 2013
parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Tuesday, 2 July 2013 at 13:07:40 UTC, Regan Heath wrote:
 It is done for performance reasons.  On UNIX the compiler will 
 put the literal "abc" into read only memory.  It could/should 
 do the same on windows but doesn't yet (I believe).

 So, the compiler is treating them as such, by giving them the 
 type immutable(char)[] (AKA string).

 And, the spec should, if it doesn't, define string literals to 
 be immutable.
Ok I understand. What I did as a first thing when I get error on "char[] x = "a" was "char x = cast(char[])"a", Which was obviously incorrect - as the "a" was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this (If one implementation (dmd/win) makes this valid, it still doesn't mean compiler should honor implementation over specification - amusing it is specified that strings go into rom...)" Also, given you explanation, I see it as good to type "auto x = "a" as string, but give explicit notation char[] x = "a" - I don't see reason to not allow string literal to be typed as both char[] and string at the same time, and convert to char[] - and also place in ram, if explicitly asked. The only reason that comes now to mi mind is when working with old code base - before auto and immutable(char)[] .. the code had to use char[] x = "a", but these must be all eliminated by now....
Jul 02 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 2 July 2013 at 13:33:10 UTC, Michal Minich wrote:
 Ok I understand. What I did as a first thing when I get error 
 on "char[] x = "a" was "char x = cast(char[])"a", Which was 
 obviously incorrect - as the "a" was/should be placed in rom. 
 So if this expression is allays wrong - casting string literal 
 to mutable, then compiler should emit an error on this
explicit cast means a order from a programmer "type system, I know what I am doing, don't even try to bother me". You should never use casts to simply suppress errors (unless absolutely sure) in the very first place.
Jul 02 2013
parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Tuesday, 2 July 2013 at 13:39:36 UTC, Dicebot wrote:
 On Tuesday, 2 July 2013 at 13:33:10 UTC, Michal Minich wrote:
 Ok I understand. What I did as a first thing when I get error 
 on "char[] x = "a" was "char x = cast(char[])"a", Which was 
 obviously incorrect - as the "a" was/should be placed in rom. 
 So if this expression is allays wrong - casting string literal 
 to mutable, then compiler should emit an error on this
explicit cast means a order from a programmer "type system, I know what I am doing, don't even try to bother me". You should never use casts to simply suppress errors (unless absolutely sure) in the very first place.
I completely agree. The other thing is, for the less aware programmers, a warning on non-linux and a error on linux might be nice. As this cast (on linux), will _allways_ result in undefined behavior. It is something compiler can easily tell, and advice "use .dup instead of cast..."
Jul 02 2013
parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Tuesday, 2 July 2013 at 13:51:15 UTC, Michal Minich wrote:
 As this cast (on linux), will _allways_ result in undefined 
 behavior. It is something compiler can  easily tell, and advice 
 "use .dup instead of cast..."
Casting away const/immutable is not undefined, modifying const/immutable data is. Since you cast away immutable the compiler can no longer prevent you from making such modifications.
Jul 02 2013
parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Tuesday, 2 July 2013 at 14:26:54 UTC, Jesse Phillips wrote:
 On Tuesday, 2 July 2013 at 13:51:15 UTC, Michal Minich wrote:
 As this cast (on linux), will _allways_ result in undefined 
 behavior. It is something compiler can  easily tell, and 
 advice "use .dup instead of cast..."
Casting away const/immutable is not undefined, modifying const/immutable data is. Since you cast away immutable the compiler can no longer prevent you from making such modifications.
You are right, the cast itself will not result in undefined behavior. But it might give you value on which any write operation will. So why not warn programer of such behavior when we can know it statically.
Jul 02 2013
parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 02 Jul 2013 16:20:04 +0100, Michal Minich  
<michal.minich gmail.com> wrote:

 On Tuesday, 2 July 2013 at 14:26:54 UTC, Jesse Phillips wrote:
 On Tuesday, 2 July 2013 at 13:51:15 UTC, Michal Minich wrote:
 As this cast (on linux), will _allways_ result in undefined behavior.  
 It is something compiler can  easily tell, and advice "use .dup  
 instead of cast..."
Casting away const/immutable is not undefined, modifying const/immutable data is. Since you cast away immutable the compiler can no longer prevent you from making such modifications.
You are right, the cast itself will not result in undefined behavior. But it might give you value on which any write operation will. So why not warn programer of such behavior when we can know it statically.
Ideally we would. However, 99.9% of cases will not be this simple/static, so adding this feature to the compiler is not cost effective.. at this stage. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 02 2013
prev sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 02 Jul 2013 14:33:09 +0100, Michal Minich  
<michal.minich gmail.com> wrote:

 On Tuesday, 2 July 2013 at 13:07:40 UTC, Regan Heath wrote:
 It is done for performance reasons.  On UNIX the compiler will put the  
 literal "abc" into read only memory.  It could/should do the same on  
 windows but doesn't yet (I believe).

 So, the compiler is treating them as such, by giving them the type  
 immutable(char)[] (AKA string).

 And, the spec should, if it doesn't, define string literals to be  
 immutable.
Ok I understand. What I did as a first thing when I get error on "char[] x = "a" was "char x = cast(char[])"a", Which was obviously incorrect - as the "a" was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this (If one implementation (dmd/win) makes this valid, it still doesn't mean compiler should honor implementation over specification - amusing it is specified that strings go into rom...)"
As Dicebot has replied, cast() is the mechanism the programmer uses to force the compiler to do what s/he wants regardless of what it thinks. The compiler assumes that if cast() is used that the programmer knows what they're doing. Only use cast() if you have no other option. In this simple case, the compiler could detect the error, or as you say below take the cast(char[]) as a hint to place the "a" in RAM instead. But, 99.9% of cases are more complex than this simple one, so the cost/benefit of detecting the error make it very low priority, perhaps never to be implemented. Likewise for the place in RAM idea. Both/either would be nice, but neither is necessary now provide a lot of benefit.
 Also, given you explanation, I see it as good to type "auto x = "a" as  
 string, but give explicit notation char[] x = "a" - I don't see reason  
 to not allow string literal to be typed as both char[] and string at the  
 same time, and convert to char[] - and also place in ram, if explicitly  
 asked.
To explicitly place "a" in RAM you would write char[] x = "a".dup; Or: char[] x = new char[1]; x[0] = 'a';
 The only reason that comes now to mi mind is when working with old code  
 base - before auto and immutable(char)[] .. the code had to use char[] x  
 = "a", but these must be all eliminated by now....
Old code using char[] x = "a" was technically invalid (it just happened to run ok on windows, or linux if no mutation was done) and will now error as such. For old code raising this error the correct solution .. - if mutable is required is to add ".dup". - if mutable is not required is to replace "char[]" with "string" or "auto". R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 02 2013
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote:
 On Tuesday, 2 July 2013 at 10:09:10 UTC, John Colvin wrote:
 The reason you can't implicitly convert a string to a char[] 
 is because string is an alias to immutable(char)[]

 Therefore, you would be providing a mutable window to 
 immutable data, which is disallowed unless you *explicitly* 
 ask for it (see below).
would be -> might be
no, "would be" is correct. char is mutable, immutable(char) is not. By definition char[] is a mutable view of data, immutable(char)[] is not.
 You can explicitly cast string to char[], but it is undefined 
 behaviour to modify the contents of the result
ok (i.e. don't cast
 away immutable unless you absolutely have to and even then be 
 very very careful).
This is not correct. You should can not cast when you 'absolutely have to' but when you can prove by means not available to compiler that the data being casted are in fact mutable. And the 'proving' of this is what you should be careful about.
Eek... no, unless i'm misunderstanding you or you made a typo, that's not the case at all. Don't mutate anything that has a live (and used?)* immutable reference to it. Just because the data was mutable before being cast to immutable, doesn't mean you can just cast away immutable and mutate it. Or, alternatively presented: You can cast to or away from immutable when you can prove by any means that the data being casted are not mutated through any reference after the creation of or before the final use of any immutable references. Erring on the safe side, you might want to wait for the immutable references to be actually dead and gone before any mutation. * Would like some clarification on whether it is the usage of the immutable reference or the lifetime that counts, if anyone knows for sure.
Jul 02 2013
prev sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 2 July 2013 at 09:10:33 UTC, Michal Minich wrote:
 void main ()
 {
     char[] str = "abc";
     // Error: cannot implicitly convert expression ("abc")
     // of type string to char[]
 }

 I thought there is no harm in that?
char[] str = ['a', 'b', 'c']; This will only allocate once without placing data in object file. This is caused by obsolete Cism moved into modern language to treat string literals as constant objects (perhaps reasoning was made in 1980s in memory constraints of those times). Ideally char[] str = "abc" should be as normal as int[] arr = [0,1,2] allowing to play with data as much as you wish.
Jul 02 2013