Thread overview
Very confusing error message when calling a class method from an invariant
Mar 10, 2021
Meta
Mar 10, 2021
Paul Backus
Mar 10, 2021
Meta
March 10, 2021
class Human {
    static immutable MAX_AGE = 122;

    bool alive = true;
    int age = 0;
    //Error: mutable method onlineapp.Human.checkAge is not callable using a const object
    invariant(checkAge());

    void growOlder()
    in(alive)
    out(; checkAge())
    {
        age++;
        if (age > MAX_AGE)
            die();
    }

    void die()
    in(alive)
    out(; !alive) {
        alive = false;
    }

    bool checkAge() {
        return age >= 0 && age <= MAX_AGE || !alive;
    }
}

void main() {
    Human h = new Human();
    h.growOlder();
}

What the hell does this even mean, and where does it come from? Adding `inout` to `checkAge` actually does cause it to compile and run too. WTF?
March 10, 2021
On Wednesday, 10 March 2021 at 03:39:15 UTC, Meta wrote:
> class Human {
>     static immutable MAX_AGE = 122;
>
>     bool alive = true;
>     int age = 0;
>     //Error: mutable method onlineapp.Human.checkAge is not callable using a const object
>     invariant(checkAge());
[...]
>
> What the hell does this even mean, and where does it come from? Adding `inout` to `checkAge` actually does cause it to compile and run too. WTF?

From the language spec [1]:

> The invariant is in the form of a const member function.

So, inside the invariant, the object is treated as const, which means you can't modify it and can only call const methods.

[1] https://dlang.org/spec/class.html#invariants
March 10, 2021
On Wednesday, 10 March 2021 at 04:57:19 UTC, Paul Backus wrote:
> On Wednesday, 10 March 2021 at 03:39:15 UTC, Meta wrote:
>> class Human {
>>     static immutable MAX_AGE = 122;
>>
>>     bool alive = true;
>>     int age = 0;
>>     //Error: mutable method onlineapp.Human.checkAge is not callable using a const object
>>     invariant(checkAge());
> [...]
>>
>> What the hell does this even mean, and where does it come from? Adding `inout` to `checkAge` actually does cause it to compile and run too. WTF?
>
> From the language spec [1]:
>
>> The invariant is in the form of a const member function.
>
> So, inside the invariant, the object is treated as const, which means you can't modify it and can only call const methods.
>
> [1] https://dlang.org/spec/class.html#invariants

Now that you mention it, I'm pretty sure I've run into this before; I must've forgotten about it. I understand the rationale behind this, but it doesn't really make sense IMO that only invariants treat the object as const, and not pre/post conditions as well. Ah well. Thanks for quick answer.