www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Segfault upon modifying immutable AA in static this

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
This snippet

     static immutable words = [ `zero`, `one`, `two` ];

     static immutable ubyte[string] wordsAA;

     static this()
     {
         foreach (ubyte i, e; words) { wordsAA[e] = i; }
     }

compiles and links on dmd git master but run segfaults.

Removing immutable qualifier from wordsAA avoids the segfeault.

Are static module ctors allowed to modify immutable data or this 
a DMD bug?
Jan 24 2015
next sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
The issue originates from module level intialization of static 
immutable AAs at

https://github.com/nordlow/justd/blob/master/conv_ex.d

Do I have to change the initialization of the AAs to be 
explicitly inline at definition of the AAs or can I preserve my 
convenient foreach over the AAs in the `static this` to 
automatically get the integer value to be stored?

Note that this does not segdefault on latest stable DMD 2.066.
Jan 24 2015
next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Saturday, 24 January 2015 at 13:29:36 UTC, Nordlöw wrote:
 The issue originates from module level intialization of static 
 immutable AAs at

 https://github.com/nordlow/justd/blob/master/conv_ex.d

 Do I have to change the initialization of the AAs to be 
 explicitly inline at definition of the AAs or can I preserve my 
 convenient foreach over the AAs in the `static this` to 
 automatically get the integer value to be stored?

 Note that this does not segdefault on latest stable DMD 2.066.
Also note that removing the immutable keyword from the AAs make by conversion function non-pure which I would like to avoid if possible.
Jan 24 2015
prev sibling parent "Kenji Hara" <k.hara.pg gmail.com> writes:
On Saturday, 24 January 2015 at 13:29:36 UTC, Nordlöw wrote:
 The issue originates from module level intialization of static 
 immutable AAs at

 https://github.com/nordlow/justd/blob/master/conv_ex.d

 Do I have to change the initialization of the AAs to be 
 explicitly inline at definition of the AAs or can I preserve my 
 convenient foreach over the AAs in the `static this` to 
 automatically get the integer value to be stored?

 Note that this does not segdefault on latest stable DMD 2.066.
It's a regression in git-head. https://issues.dlang.org/show_bug.cgi?id=14038 Kenji Hara
Jan 24 2015
prev sibling next sibling parent "anonymous" <anonymous example.com> writes:
On Saturday, 24 January 2015 at 13:24:02 UTC, Nordlöw wrote:
 This snippet

     static immutable words = [ `zero`, `one`, `two` ];

     static immutable ubyte[string] wordsAA;

     static this()
     {
         foreach (ubyte i, e; words) { wordsAA[e] = i; }
     }

 compiles and links on dmd git master but run segfaults.

 Removing immutable qualifier from wordsAA avoids the segfeault.

 Are static module ctors allowed to modify immutable data or 
 this a DMD bug?
They are definitely allowed to initialize immutable data, i.e. write once. I don't know if you're allowed to change it repeatedly. You can change your code to write only once: static this() { import std.exception: assumeUnique; ubyte[string] tmp; foreach (ubyte i, e; words) { tmp[e] = i; } wordsAA = assumeUnique(tmp); /* Don't alter tmp from here on. */ }
Jan 24 2015
prev sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Saturday, January 24, 2015 13:24:01 Nordlöw via Digitalmars-d-learn wrote:
 This snippet

      static immutable words = [ `zero`, `one`, `two` ];

      static immutable ubyte[string] wordsAA;

      static this()
      {
          foreach (ubyte i, e; words) { wordsAA[e] = i; }
      }

 compiles and links on dmd git master but run segfaults.

 Removing immutable qualifier from wordsAA avoids the segfeault.

 Are static module ctors allowed to modify immutable data or this
 a DMD bug?
immutable variables can only be initialized and cannot be assigned to. The fact that wordsAA[e] = i; even compiles is most definitely a bug, but constructors are of a bit of a special place for immutable variables, since they can be initialized there rather than being directly initialized, and clearly something in how that is handled in the compiler is buggy. i.e. code like wordsAA = value; would be illegal outside of a constructor, because wordsAA is immutable, but it's legal, because it's inside of a constructor associated with it (in this case, a static constructor for a static variable). So, presumably, whatever in the compiler makes that legal has a bug that makes it think that wordsAA[e] = i; is legal when it isn't. In any case, if you want to initialize an immutable array or AA or whatnot where you can't just directly initialize it but rather need multiple operations, then you need to create a mutable one that gets converted to an immutable one - either by casting it to immutable when assigning it to the immutable variable (in which case, you need to be sure that no mutable reference to it continues to exist) or by writing a pure function to create it and return it, in which case, it will implicitly convert to immutable, because the compiler knows that no mutuable references to it exist. So, something like this should work static immutable words = [ `zero`, `one`, `two` ]; static immutable ubyte[string] wordsAA; static this() { auto initWordsAA() pure { ubyte[string] retval; foreach(ubyte i, e; words) retval[e] = i; return retval; } wordsAA = initWordsAA(); } You should report the segfault as a bug though. Your original code should not compile, because wordsAA[e] = i; is quite illegal due to wordsAA's immutability. - Jonathan M Davis
Jan 24 2015