On Wednesday, 9 October 2013 at 04:31:55 UTC, Ali Çehreli wrote:
On 10/08/2013 03:12 PM, qznc wrote:
> On Monday, 7 October 2013 at 17:57:11 UTC, Ali Çehreli wrote:
>> To look at just one usage example, the following line
carries two
>> requirements:
>>
>>     auto a = T();
>>     immutable b = a;
>>
>> 1) b will be an immutable copy of a.
>>
>> 2) T will always be usable as in that fashion.
>>
>> If T appears on an API, it is the responibility of the user
to ensure
>> whether they are allowed to treat T in that way. Otherwise,
they risk
>> maintainability if the module decides to change T in any way
that fits
>> the module's needs. If they have not yet advertised that T
can be used
>> as immutable, it should not be.
>
> I do not agree with you, that the user has the responsibility.

I have difficulty agreeing with myself as well. :) However, the power of immutable makes me think so. Interestingly, once a user creates an immutable variable of a type, that type must support that use.

> Rather I
> think the provider of T has the responsibility to maintain
backwards
> compatibility.

Agreed but I don't know how. Here is challenge: Let's start with the following program:

// Library type
struct MyInt
{
    int i;
}

void main()
{
    // User code
    auto a = MyInt(1);
    immutable b = a;
}

Let's assume that the library adds a private dynamic array of ints to that type:

// Library type
struct MyInt
{
    int i;
    private int[] history;    // <-- Added
}

void main()
{
    // User code
    auto a = MyInt(1);
    immutable b = a;          // <-- Existing code breaks
}

Error: cannot implicitly convert expression (a) of type MyInt to immutable(MyInt)

Maybe the fact that D allows this implicit copy to immutable is the problem? If one could require the use of a specific function, this function could be overridden with working behavior. The following code works.

import std.exception: assumeUnique;

struct MyInt
{
  int i;
  private int[] history;    // <-- Added
}

// idup for creating immutable MyInts
immutable(MyInt) idup(const MyInt mi) pure nothrow @trusted {
  MyInt cpy = MyInt(mi.i);
  return cast(immutable) cpy;
}

// special version for performance
immutable(MyInt) idup(immutable MyInt mi) pure nothrow @trusted {
  return mi;
}

unittest {
  auto a = MyInt(1);
  immutable b = a.idup;     // <-- Code does not break
}

D could either remove the implicit-copy-to-immutable or provide a special copy-constructor for immutable structs.

Reply via email to