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:

```d
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:

1. Make `A`'s copy constructor `inout`: `this(ref return scope inout A rhs) inout` 2. 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?



Reply via email to