Casting non-aliased mutable arrays to immutable in return values

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at
Tue Aug 29 09:41:48 PDT 2017

On Tuesday, August 29, 2017 16:09:17 Per Nordlöw via Digitalmars-d-learn 
> Is it recommended to cast an unaliased array to `immutable` after
> it has been initialized?
> The reason for asking is that I would like the following function
> void[] rawReadNullTerminated(string path)
>      @safe
> {
>      import std.stdio : File;
>      auto file = File(path, `rb`);
>      import std.array : uninitializedArray;
>      ubyte[] data = uninitializedArray!(ubyte[])(file.size + 1);
>      file.rawRead(data);
>      data[file.size] = 0;     // null terminator for sentinel
>      return data;                // TODO can we cast this to
> `immutable(void)[]`?
> }
> to have an immutable return type.
> I'm aware of that I need to verify the contexts as UTF-8 if I
> want to treat it as text.

It's perfectly legitimate to construct an object as mutable and then cast it
to immutable if there are no other mutable references to it - that's what
std.exception.assumeUnique is for. It does the cast for you while
documenting your intent. However, the better solution if you can do it is to
create the object in a pure function that returns it. Then, it can be
implicitly converted to immutable so long as the compiler can guarantee that
the return value was not passed to the function. In this particular case,
you'd probably create a pure, nested function that took the File object and
returned the array.

Now, as for immutable(void)[], that seems pretty weird to me. Normally, when
folks use void[], it doesn't have any qualifiers on it. But I don't know
that there's actually a problem using qualifiers on it. Certainly, it
compiles. I'd probably just use immutable(ubyte)[] and not anything with
void, but this is obviously just a snippet of your code, and I have no idea
what the rest of it is doing, so something with void instead of ubyte may
very well be the correct solution. You'll obviously have to be the judge of
that. But pretty much the only time that I'd use any kind of void array
though is when accepting arbitrary arrays of data that is going to be
converted to bytes (e.g. for a socket). I wouldn't pass it around. I don't
know what other folks would do though.

Regardless, using assumeUnique or using a pure function to construct the
object and implicitly convert it to immutable works for types in general.

- Jonathan M Davis

More information about the Digitalmars-d-learn mailing list