On Monday, 19 November 2018 at 12:28:43 UTC, Dennis wrote:
On Monday, 19 November 2018 at 02:39:32 UTC, Stanislav Blinov wrote:
You're skimming the examples ;)

I'm not saying your examples don't work, I'm trying to understand the minimum requirements. You said:

"That's [constructors needing to be pure is] only for types with indirections (pointers), since `pure` guarantees that you do not mutate any global state."

My example was only to show that:
- a const constructor is insufficient for creating an immutable struct S - an immutable or pure constructor is sufficient for creating an immutable struct S

Yes, that's what I meant.

You also showed that an inout constructor is sufficient too.

I don't understand why not any constructor would work. After all:

"value types are all copyable between mutable/const/immutable. So even if `return x + y` would yield a `const T`, you can still instantiate a T from it."

Because the rules still hold:

this(int) -> __ctor(T, int);
this(int) const -> __ctor(const T, int);
this(int) immutable -> __ctor(immutable T, int);

Recall that member functions (including constructors) are just functions in disguise:
...
what that boils down to, conceptually, is:

I get what inout does know. But continuing on the constructor lowering, what strikes me is that:

S __ctor(ref const S this, int x) {
    this.x = x; // allowed, while `this` is a const(S)!
    // return this; automatically inserted
}

Knowing that a constructor may mutate the const(this) or immutable(this) members, why can't a mutable(this) constructor be called on an immutable(this), *unless* it is pure (which seems irrelevant to me)?

Because it's not mutation, it's initialization. Just like you write:

const int x = 1; // initializes a const int
x = 10; // error, can't mutate

...the first assignment to a member in a constructor is initialization:

struct S {
    int x;
    this(int x) immutable {
        this.x = x; // ok, initialization
        this.x = 5; // error, can't mutate
    }
}

When a ctor is `pure`, the compiler knows it doesn't mutate any state other than the object's, so it allows conversion to all three qualifiers.

What you can do, however, if you don't have an const/immutable constructor, is call a mutable constructor explicitly, so long as conversion is possible (i.e. value types):

struct S {
    this(int) /* not immutable */ {}
}

immutable S x = 1; // error
immutable S x = S(1); // ok

Reply via email to