On Thursday, 12 August 2021 at 09:14:02 UTC, Paul Backus wrote:
> On Thursday, 12 August 2021 at 08:42:27 UTC, Learner wrote:
> struct A {
int[] data
this(ref return scope A rhs) { data = ths.data.dup; }
}
Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable
What is an inout
copy constructor? What should I change in A?
When the compiler generates a copy constructor for a struct, it generates it with the following signature:
this(ref return scope inout(typeof(this)) src) inout
(Source: https://dlang.org/spec/struct.html#implicit-copy-constructors)
Notice that both the src
object and the object being constructed (this
) are qualified with inout
.
inout
is a special type qualifier that allows the same function to be used for mutable, const
, and immutable
arguments. To make this work, the compiler imposes heavy restrictions on what you can do with an inout
-qualified object--only operations that are valid on mutable, const
, and immutable
objects are allowed for inout
.
(Source: https://dlang.org/spec/function.html#inout-functions)
A
's copy constructor does not have any type qualifiers on its rhs
argument or its this
reference, so both default to mutable. In other words: A
's copy constructor can only be used to construct a mutable copy from a mutable original object. It cannot be used to construct an inout
copy from an inout
object.
In order to make the generated copy constructor work, you need to give A
a copy constructor that can copy inout
objects. There are two possibilities here:
- Make
A
's copy constructor inout
: this(ref return scope inout A rhs) inout
- Make
A
's copy constructor const
: this(ref return scope const A rhs) const
While option 2. is not working:
struct A {
int[] data;
this(ref return scope const A rhs) const {}
}
Error: Generating an `inout` copy constructor for `struct A` failed, therefore instances of it are uncopyable
Option .1 actually works, with an empty body, while it fails with the actual body:
struct A {
int[] data;
this(ref return scope inout A rhs) inout { data = rhs.data.dup; }
}
Error: cannot implicitly convert expression `dup(cast(const(int)[])rhs.data)` of type `int[]` to `inout(int[])`
It seems that there is no easy way to transition from a postblit to a copy constructor, no?