dynamic arrays of immutable question: Are the elements actually mutable

monarch_dodra monarchdodra at gmail.com
Wed Jan 9 05:38:13 PST 2013


On Wednesday, 9 January 2013 at 12:38:13 UTC, Jonathan M Davis 
wrote:
>
> When you append to array, the elements being added are in 
> untyped memory. So,
> no mutation of immutable anything is going on at all.

Ok, I guess that makes sense.

> I don't know what Appender is doing, but casting away immutable 
> and mutating
> anything is undefined behavior. However, if you _know_ that the 
> data is
> actually mutable, then you can get away with it. It's still 
> technically
> undefined behavior though. Pretty much the only place that it 
> would make sense
> to do that that I can think of is with std.concurrency, but 
> again, I don't
> know what Appender is doing.

Hum...

Appender uses "arr.length = arr.capacity" so as to mark the array 
as "used" so that if anybody tries to append to the array, it 
will not interfere with appender. Does this operation "make the 
memory typed"?

Here is a reduced test case of what appender does

http://dpaste.dzfl.pl/d8fce486

//----
import std.stdio;

void main()
{
     //The initial array
     immutable(int)[] arr1 = [0, 1, 2, 3];

     //The same array, aliased as mutable;
     int[] arr2 = cast(int[])arr1;

     //Change underlying range size so that other appends to arr1 
cause relocation
     size_t capacity = arr1.capacity;
     if (capacity > arr1.length)
     {
         auto tmp = arr2;
         tmp.length = tmp.capacity;
         assert(arr2.ptr == tmp.ptr);
         assert(arr1.capacity == 0);
     }
     else
         assert(0); //To make sure we are actually testing 
something

     //Write to the not yet written but reserved to zone
     for ( ; arr2.length < capacity; )
     {
         immutable len = arr2.length;
         arr2.ptr[len] = cast(int)len; //HERE
         arr2 = arr2.ptr[0 .. len + 1];
     }

     //Check arr2
     writeln(arr2);
}
//----

The original line I am concerned about is "HERE": Is this a legal 
mutation?

On topic, the actual code in Appender looks like this
//----
//Type of item is "U", with "isImplicitlyConvertible!(U, T)"
_data.arr.ptr[len] = cast(Unqual!T)item;
//----
Worth noting is:
* This will bigtime fail if T has a constructor (should use 
emplace).
* Also, is that cast even legal?

If emplace is able to modify the user provided immutable array, 
then wouldn't it be better off storing an actual "T[]" (instead 
of (Unqual!T)[]): This would avoid any abusive use of casts, and 
preserve the qualified type, right?


More information about the Digitalmars-d-learn mailing list