www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Rethink copy and move constructors

reply Dejan Lekic <dejan.lekic gmail.com> writes:
Please, instead of atrocities like `this(ref return scope 
typeof(this) rhs)`
can we, for the love of God, have simple

```d
this(MyType rhs)  disable;           // copy
this(MyType rhs)  move { ... }       // move
```

???

Even better, can we adopt Rust move-by-default strategy? This 
deserves a DIP from someone smarter than me. Can we please get 
rid of the super-buggy and super-ugly `this(ref return scope 
typeof(this) rhs)` (I am losing words and can't find suitable 
pejoratives) in favour of something that really makes sense, and 
avoid humiliation from communities outside D as they really laugh 
when they see this!

Or simply call them `copyThis` and `moveThis` or something, just 
do not use this nonsense above that already somehow got into the 
codebase, probably because whoever proposed is good friend of our 
BDFL!
May 24
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 25/05/2026 2:44 AM, Dejan Lekic wrote:
 Even better, can we adopt Rust move-by-default strategy? This deserves a 
 DIP from someone smarter than me. Can we please get rid of the super- 
 buggy and super-ugly |this(ref return scope typeof(this) rhs)| (I am 
 losing words and can't find suitable pejoratives) in favour of something 
 that really makes sense, and avoid humiliation from communities outside 
 D as they really laugh when they see this!
For D copy by default is the better solution, as it also applies to pointers. However, to get us an ownership transfer system, we'd probably want a type qualifier based one. Like isolated from Midori. But before that can be added, we need a borrow checker to protect it, and with that a DFA engine that can be on by default. Which I'm actively working on.
May 24
parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Sunday, 24 May 2026 at 16:12:44 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 For D copy by default is the better solution, as it also 
 applies to pointers.

 However, to get us an ownership transfer system, we'd probably 
 want a type qualifier based one. Like isolated from Midori.

 But before that can be added, we need a borrow checker to 
 protect it, and with that a DFA engine that can be on by 
 default. Which I'm actively working on.
OK. Copy by default it is! - Can we please make those constructors (copy and move) for humans please? Or you do not want to do move at all and rely on the current D approach of automated move of things compiler can deduce as moveable? I am fine with that too if it is properly documented, so we know what to do! I wonder how many people from D community even know what is the right approach depending on a use-case here, considering how obscure is the current copy constructor signature, and the fact that disable this(this) takes precedence...
May 24
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 25/05/2026 6:28 AM, Dejan Lekic wrote:
 On Sunday, 24 May 2026 at 16:12:44 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 For D copy by default is the better solution, as it also applies to 
 pointers.

 However, to get us an ownership transfer system, we'd probably want a 
 type qualifier based one. Like isolated from Midori.

 But before that can be added, we need a borrow checker to protect it, 
 and with that a DFA engine that can be on by default. Which I'm 
 actively working on.
OK. Copy by default it is! - Can we please make those constructors (copy and move) for humans please? Or you do not want to do move at all and rely on the current D approach of automated move of things compiler can deduce as moveable? I am fine with that too if it is properly documented, so we know what to do! I wonder how many people from D community even know what is the right approach depending on a use-case here, considering how obscure is the current copy constructor signature, and the fact that disable this(this) takes precedence...
The copy constructors and move constructor declaration has been discussed quite extensively. As for calling it? A type qualifier would trigger it automatically, rather than the copy constructor.
May 24
prev sibling next sibling parent libxmoc <libxmoc gmail.com> writes:
On Sunday, 24 May 2026 at 14:44:51 UTC, Dejan Lekic wrote:
 Please, instead of atrocities like `this(ref return scope 
 typeof(this) rhs)`
 can we, for the love of God, have simple

 ```d
 this(MyType rhs)  disable;           // copy
 this(MyType rhs)  move { ... }       // move
 ```

 ???

 Even better, can we adopt Rust move-by-default strategy? This 
 deserves a DIP from someone smarter than me. Can we please get 
 rid of the super-buggy and super-ugly `this(ref return scope 
 typeof(this) rhs)` (I am losing words and can't find suitable 
 pejoratives) in favour of something that really makes sense, 
 and avoid humiliation from communities outside D as they really 
 laugh when they see this!

 Or simply call them `copyThis` and `moveThis` or something, 
 just do not use this nonsense above that already somehow got 
 into the codebase, probably because whoever proposed is good 
 friend of our BDFL!
+1, this is a much cleaner way of handling it. I bet that whoever came up with the monstrosity that it is today don't even use them, and probably no longer use D.
May 25
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 5/24/26 16:44, Dejan Lekic wrote:
 Can we please get rid of the super-buggy and super-ugly `this(ref return 
 scope typeof(this) rhs)` (I am losing words and can't find suitable 
 pejoratives)
You forgot `inout`. Try this: ```d import std.range; struct S{ this(ref return scope S rhs){} } struct T{ S s; } void main(){ auto x=[T()].dup; } ``` This works: ```d import std.range; struct S{ this(ref return scope inout S rhs)inout{} } struct T{ S s; } void main(){ auto x=[T()].dup; } ``` Also, this still does not work (probably a bug): ```d import std.range; struct S{ this(ref S rhs){} } struct T{ S s; this(ref T rhs){ this.s = rhs.s; } } void main(){ auto x=[T()].dup; } ``` Anyway, ```d this(S rhs){} this(ref S rhs){} ``` actually makes quite a bit of sense to me, that seems sane. DIP1000? Not so much, but at least you do not have to bother with it if you don't want/need to check pointer escaping. Trying to push `inout` and/or `const` on unsuspecting users? That's the point where I too would reach for any suitable pejoratives. ;)
May 25
prev sibling parent reply c-smile <andrew sciter.com> writes:
On Sunday, 24 May 2026 at 14:44:51 UTC, Dejan Lekic wrote:
 Please, instead of atrocities like `this(ref return scope 
 typeof(this) rhs)`
 can we, for the love of God, have simple

 ```d
 this(MyType rhs)  disable;           // copy
 this(MyType rhs)  move { ... }       // move
 ```
I am with you here too. According to the Principle of Least Astonishment copy constructor should be just this ``` this(ref S rhs) {...} ``` While move constructor is more rare so it is fine to have it as ``` this(ref S rhs) move {...} ``` Actually bumped into this in Sciter/D where I thought that `this(ref S rhs)` is the copy CTOR. Alternatively but worse IMO: ``` this(ref const S rhs) // copy constructor ```
May 25
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 5/26/26 06:04, c-smile wrote:
 
 Actually bumped into this in Sciter/D where I thought that `this(ref S 
 rhs)` is the copy CTOR.
 ...
It is: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1018.md
 Inside a struct definition, a declaration is a copy constructor 
declaration if it is a constructor declaration that takes the first parameter as a nondefaulted reference to the same type as the struct being defined. A constructor declaration is a copy constructor declaration if it meets the following requirements: https://dlang.org/spec/struct.html#struct-copy-constructor * It takes exactly one parameter without a default argument, followed by any number of parameters with default arguments. * Its first parameter is a ref parameter. * The type of its first parameter is the same type as typeof(this), optionally with one or more type qualifiers applied to it. * It is not a template constructor declaration. I don't know why `return scope` is used in all examples.
 Alternatively but worse IMO:
 
 ```
 this(ref const S rhs) // copy constructor
 ```
This is also a copy constructor under the current rules. If the suggestion is to _require_ `const`, then _of course not_, that makes no sense.
May 26
parent Dejan Lekic <dejan.lekic gmail.com> writes:
On Tuesday, 26 May 2026 at 09:46:04 UTC, Timon Gehr wrote:
 I don't know why `return scope` is used in all examples.
I found it at the very bottom of the DIP document:
 The DIP was subsequently modified, with the consent of the 
 Language Maintainers, to add return scope to the copy 
 constructor parameter in the code snippets as an example of 
 good practice.
May 26