digitalmars.D.announce - Why implicit conversion of string literal to char[] does not works?
- Michal Minich (7/7) Jul 02 2013 void main ()
- Michal Minich (1/1) Jul 02 2013 Sorry for posting to announce.
- John Colvin (11/12) Jul 02 2013 In future please post these questions to digitalmars.D.learn
- Michal Minich (10/19) Jul 02 2013 ok
- Dicebot (2/4) Jul 02 2013 char[] str = "abc".dup;
- Michal Minich (5/9) Jul 02 2013 Thanks, that is workaround I didn't know about.
- Dicebot (13/18) Jul 02 2013 It is not a workaround but an expected approach. You are trying
- Andrej Mitrovic (2/4) Jul 02 2013 It's probably to avoid implicit memory allocations.
- Regan Heath (16/26) Jul 02 2013 It is done for performance reasons. On UNIX the compiler will put the
- Michal Minich (17/24) Jul 02 2013 Ok I understand. What I did as a first thing when I get error on
- Dicebot (5/10) Jul 02 2013 explicit cast means a order from a programmer "type system, I
- Michal Minich (7/17) Jul 02 2013 I completely agree.
- Jesse Phillips (4/7) Jul 02 2013 Casting away const/immutable is not undefined, modifying
- Michal Minich (5/13) Jul 02 2013 You are right, the cast itself will not result in undefined
- Regan Heath (8/20) Jul 02 2013 Ideally we would. However, 99.9% of cases will not be this simple/stati...
- Regan Heath (27/53) Jul 02 2013 As Dicebot has replied, cast() is the mechanism the programmer uses to
- John Colvin (20/40) Jul 02 2013 no, "would be" is correct. char is mutable, immutable(char) is
- Maxim Fomin (8/15) Jul 02 2013 char[] str = ['a', 'b', 'c'];
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
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
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 beYou can explicitly cast string to char[], but it is undefined behaviour to modify the contents of the resultok (i.e. don't castaway 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
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
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: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.But ... I'm asking only about implicit conversion of string literal, not arbitrary expressions of string type.char[] str = "abc".dup;
Jul 02 2013
On Tuesday, 2 July 2013 at 11:33:16 UTC, Michal Minich wrote: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.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
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
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: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/On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote: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.But ... I'm asking only about implicit conversion of string literal, not arbitrary expressions of string type.char[] str = "abc".dup;
Jul 02 2013
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
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 thisexplicit 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
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: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..."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 thisexplicit 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
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
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: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.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
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: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/On Tuesday, 2 July 2013 at 13:51:15 UTC, Michal Minich wrote: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.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
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: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.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.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
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: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.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 beEek... 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.You can explicitly cast string to char[], but it is undefined behaviour to modify the contents of the resultok (i.e. don't castaway 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.
Jul 02 2013
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