March 13, 2021
On 11.03.21 23:39, Walter Bright wrote:
> On 3/11/2021 10:43 AM, Timon Gehr wrote:
>> I haven't had time yet to contribute a thorough review, but one thing that stands out to me is that there seems to be no discussion of interaction with `const`/`immutable`, etc. Given that that's a source of unsoundness for postblit, maybe it deserves some explicit consideration?
> 
> All the problems with const/immutable revolved around postblit. That's why this proposal has zero reliance on postblit.

My concern was that similar mistakes can be repeated. You don't ensure correctness just by avoiding the precise set of previous mistakes; it's always possible to make new, slightly different mistakes.

The design of immutable and the design of postblit took place independently of each other and they ended up being incompatible. Why is the same thing not happening now? The DIP seems to assume there is no such thing as immutable, just like postblit did. A naive implementation of the DIP might therefore implicitly cast away immutable, just like postblit did.
March 13, 2021
On Friday, 12 March 2021 at 23:52:00 UTC, Timon Gehr wrote:
> On 11.03.21 23:39, Walter Bright wrote:
>> On 3/11/2021 10:43 AM, Timon Gehr wrote:
>>> [...]
>> 
>> All the problems with const/immutable revolved around postblit. That's why this proposal has zero reliance on postblit.
>
> My concern was that similar mistakes can be repeated. You don't ensure correctness just by avoiding the precise set of previous mistakes; it's always possible to make new, slightly different mistakes.
>
> The design of immutable and the design of postblit took place independently of each other and they ended up being incompatible. Why is the same thing not happening now? The DIP seems to assume there is no such thing as immutable, just like postblit did. A naive implementation of the DIP might therefore implicitly cast away immutable, just like postblit did.

Is the specific issue here a move from an immutable struct breaking the immutable-contract silently?

Thank you for raising it even if not because this needs to be hashed out properly.
March 13, 2021
On 13.03.21 01:29, Max Haughton wrote:
> On Friday, 12 March 2021 at 23:52:00 UTC, Timon Gehr wrote:
>> On 11.03.21 23:39, Walter Bright wrote:
>>> On 3/11/2021 10:43 AM, Timon Gehr wrote:
>>>> [...]
>>>
>>> All the problems with const/immutable revolved around postblit. That's why this proposal has zero reliance on postblit.
>>
>> My concern was that similar mistakes can be repeated. You don't ensure correctness just by avoiding the precise set of previous mistakes; it's always possible to make new, slightly different mistakes.
>>
>> The design of immutable and the design of postblit took place independently of each other and they ended up being incompatible. Why is the same thing not happening now? The DIP seems to assume there is no such thing as immutable, just like postblit did. A naive implementation of the DIP might therefore implicitly cast away immutable, just like postblit did.
> 
> Is the specific issue here a move from an immutable struct breaking the immutable-contract silently?
> ...


Yes, one thing that could conceivably go wrong is this:

@safe:
int* global;

struct S{
    int* x;
    this(S other){
        global=other.x;
        this.x=other.x;
    }
    // ...
}

void main(){
    immutable s=S(new int);
    immutable t=s; // s moved, so move constructor is called
    assert(t.x is global.x);
}

This is similar to what went wrong with postblit.

> Thank you for raising it even if not because this needs to be hashed out properly.

Exactly, the issue is basically, even if what happens is not memory corruption, maybe the DIP should state what it is that does happen. :)

E.g., I think it would be good to address questions like those somehow:

Is moving an immutable object allowed? (E.g., with @system variables I think you could have a @trusted immutable object that's backed by malloc and deallocated on destruction, can we move that?)


Is this a move constructor?

struct S{
    this(immutable(S) other)immutable{ ... }
}


On an unrelated note, I guess the DIP should also show how to actually declare a copy constructor. Is it this(ref S) ?
March 12, 2021
On 3/11/2021 10:56 AM, 12345swordy wrote:
> How does it handle move constructors when a class have struct type variable that is being alias this?

#DIP1040 only applies to structs, not classes.
March 12, 2021
On 3/12/2021 3:47 PM, tsbockman wrote:
> ...

You make a good point, that the user should define both the Move Assignment and Move Constructor, or neither. Just one of the pair should be an error. I agree that it would be red flag if just one appeared in the code, indicative that the programmer did not think it through.
March 13, 2021
On Saturday, 13 March 2021 at 03:12:02 UTC, Walter Bright wrote:
> On 3/12/2021 3:47 PM, tsbockman wrote:
>> ...
>
> You make a good point, that the user should define both the Move Assignment and Move Constructor, or neither. Just one of the pair should be an error. I agree that it would be red flag if just one appeared in the code, indicative that the programmer did not think it through.

The whole notion of move assignement is a hack inherited from C++ and don't really make sense for D.

As soon as you have 2 objects, you are out of the pure move scenario, and you need to deal with this fact. C++ does so by putting the source object in a null state and then destroying it. You cannot have *2* objects and then not destroy one and expect things to not have a ton of edge cases just like postblit for copy does (because you have the exact same problem in reverse there, you had *1* object when you wanted *2*).
March 13, 2021
On Saturday, 13 March 2021 at 03:06:35 UTC, Walter Bright wrote:
> On 3/11/2021 10:56 AM, 12345swordy wrote:
>> How does it handle move constructors when a class have struct type variable that is being alias this?
>
> #DIP1040 only applies to structs, not classes.

That doesn't answer the question. How does the DIP interact with the current alias this system?
If I alias this a struct variable with move schematics in struct/class definition called A, does A have the move schematics of the struct variable? Replying "only applied to structs and not classes" isn't helpful here. I am not talking about defining move schematics for classes, I am talking about the class inheriting the struct that has move schematics defined, via alias this.

- Alex
March 13, 2021
On Saturday, 13 March 2021 at 19:47:35 UTC, 12345swordy wrote:
> On Saturday, 13 March 2021 at 03:06:35 UTC, Walter Bright wrote:
>> On 3/11/2021 10:56 AM, 12345swordy wrote:
>>> How does it handle move constructors when a class have struct type variable that is being alias this?
>>
>> #DIP1040 only applies to structs, not classes.
>
> That doesn't answer the question. How does the DIP interact with the current alias this system?
> If I alias this a struct variable with move schematics in struct/class definition called A, does A have the move schematics of the struct variable? Replying "only applied to structs and not classes" isn't helpful here. I am not talking about defining move schematics for classes, I am talking about the class inheriting the struct that has move schematics defined, via alias this.
>
> - Alex

Considering alias this is just an identifier resolution rule, why would you expect any interaction whatsoever with move semantics?
March 14, 2021
On Saturday, 13 March 2021 at 21:09:33 UTC, deadalnix wrote:
> On Saturday, 13 March 2021 at 19:47:35 UTC, 12345swordy wrote:
>> On Saturday, 13 March 2021 at 03:06:35 UTC, Walter Bright wrote:
>>> On 3/11/2021 10:56 AM, 12345swordy wrote:
>>>> How does it handle move constructors when a class have struct type variable that is being alias this?
>>>
>>> #DIP1040 only applies to structs, not classes.
>>
>> That doesn't answer the question. How does the DIP interact with the current alias this system?
>> If I alias this a struct variable with move schematics in struct/class definition called A, does A have the move schematics of the struct variable? Replying "only applied to structs and not classes" isn't helpful here. I am not talking about defining move schematics for classes, I am talking about the class inheriting the struct that has move schematics defined, via alias this.
>>
>> - Alex
>
> Considering alias this is just an identifier resolution rule, why would you expect any interaction whatsoever with move semantics?

You are making an argument from silence fallacy, if you are asserting that there is no interaction between move semantics with alias this by the virtue of not being mentioning in the dip at all.

- Alex
March 14, 2021
On Saturday, 13 March 2021 at 19:47:35 UTC, 12345swordy wrote:
> How does the DIP interact with the current alias this system?
> If I alias this a struct variable with move schematics in struct/class definition called A, does A have the move schematics of the struct variable?

According to the DIP, if A does not define explicit custom move operators, it gets implicit default field-by-field move operators:

> If a Move Constructor is not defined for a struct that has a Move Assignment Operator, a default Move Constructor is defined and implemented as a move for each of its fields, in lexical order.
> ...
> If a Move Assignment Operator is not defined for a struct that has a Move Constructor, a default Move Assignment Operator is defined and implemented as a move for each of its fields, in lexical order.

So, A's own move operators (whether explicit custom or implicit default) should hide any that it might otherwise pick up via alias this. The DIP should probably be updated to make this interaction with alias this explicit, though.