Thread overview
Strage class' with invariant() {} function behaviour
Oct 08, 2008
mumba
Oct 08, 2008
mumba
October 08, 2008
Hello people.

Check this out, and explain please.

class Foo {
    invariant(Object) bar() {
        return new invariant(Object); //return sth caller cannot change
    }
}

So far, so good. Now:

class Foo {
    invariant() {} //some design by contract stuff, nothing related to type's storage classes
    Object bar() { //less restrictive version of the previous func
        return new Object;
    }
}

So far so good. Now let's make a fusion:

class Foo {
    invariant() {}
    invariant(Object) bar() {
        return new invariant(Object);
    }
}

BANG! (dmd v2.014)
variable test.Foo.bar.__result cannot modify invariant

...

Of course, I have some theories, but I wouldn't come here if they were good, so I'll keep them for myself. Tell me yours.

cheers.
October 08, 2008
On Wed, Oct 8, 2008 at 2:34 PM, mumba <qniol@o2.pl> wrote:
> Hello people.
>
> Check this out, and explain please.
>
> class Foo {
>    invariant(Object) bar() {
>        return new invariant(Object); //return sth caller cannot change
>    }
> }
>
> So far, so good. Now:
>
> class Foo {
>    invariant() {} //some design by contract stuff, nothing related to type's storage classes
>    Object bar() { //less restrictive version of the previous func
>        return new Object;
>    }
> }
>
> So far so good. Now let's make a fusion:
>
> class Foo {
>    invariant() {}
>    invariant(Object) bar() {
>        return new invariant(Object);
>    }
> }
>
> BANG! (dmd v2.014)
> variable test.Foo.bar.__result cannot modify invariant
>
> ...
>
> Of course, I have some theories, but I wouldn't come here if they were good, so I'll keep them for myself. Tell me yours.
>
> cheers.
>

D's contracts allow you to put an out contract on a function to see what the result of the function was:

void foo()
out(result) { /* check that result is reasonable */ }
body { /* function body */ }

When you declare a class invariant, it calls the invariant after each
public method is called.  My guess is that D is inserting an implicit
"out(result) { assert(this); }" on each public method, but the out
contract probably hasn't yet been updated and thinks typeof(result) is
just Object, not invariant(Object).  Hence, error.

It's most likely a bug.
October 08, 2008
Jarrett Billingsley Wrote:

>  My guess is that D is inserting an implicit
> "out(result) { assert(this); }" on each public method, but the out
> contract probably hasn't yet been updated and thinks typeof(result) is
> just Object, not invariant(Object).  Hence, error.

Sorry, but I don't understand this sentence :). What do you mean by "updated"? "assert(this) added"? I guess not, since this is what D is actually doing (beginning of the sentence) so how we can even expect having sth done before we did it? Is there some kind of "update" D performs in order to turn types to invariant(types)?
October 08, 2008
On Wed, Oct 8, 2008 at 3:31 PM, mumba <qniol@o2.pl> wrote:
> Jarrett Billingsley Wrote:
>
>>  My guess is that D is inserting an implicit
>> "out(result) { assert(this); }" on each public method, but the out
>> contract probably hasn't yet been updated and thinks typeof(result) is
>> just Object, not invariant(Object).  Hence, error.
>
> Sorry, but I don't understand this sentence :). What do you mean by "updated"? "assert(this) added"? I guess not, since this is what D is actually doing (beginning of the sentence) so how we can even expect having sth done before we did it? Is there some kind of "update" D performs in order to turn types to invariant(types)?
>

By updated I mean that there seem to be some areas in the D2 compiler that still don't know about const and invariant.

assert(this) calls the invariant of 'this'.