View mode: basic / threaded / horizontal-split · Log in · Help
June 16, 2010
Class/struct invariants
Are D invariants supposed to be so "relaxed"? They don't get called with default constructors:


struct Foo {
   int x = 0;
   this(int xx) { this.x = xx; }
   invariant() { assert(x == 1); }
}
struct Bar {
   int x = 0;
   invariant() { assert(x == 1); }
}
class CFoo {
   int x = 0;
   this(int xx) { this.x = xx; }
   invariant() { assert(x == 1); }
}
class CBar {
   int x = 0;
   invariant() { assert(x == 1); }
}
void main() {
   Foo f1;                  // no asserts
   Foo f2 = Foo();          // no asserts
   // Foo f3 = Foo(0);      // asserts, good

   Bar b1;                  // no asserts
   Bar b2 = Bar();          // no asserts
   Bar b3 = Bar(0);         // no asserts

   //assert(b3);            // can't be used
   // b3.__invariant();     // asserts

   //CFoo f3 = new CFoo(0); // asserts, good

   CBar cb2 = new CBar();   // no asserts
   //assert(cb2);           // asserts, good
}


Bye,
bearophile
June 16, 2010
Re: Class/struct invariants
On Tue, 15 Jun 2010 21:29:27 -0400, bearophile <bearophileHUGS@lycos.com>  
wrote:

> Are D invariants supposed to be so "relaxed"? They don't get called with  
> default constructors:
>
>
> struct Foo {
>     int x = 0;
>     this(int xx) { this.x = xx; }
>     invariant() { assert(x == 1); }
> }
> struct Bar {
>     int x = 0;
>     invariant() { assert(x == 1); }
> }
> class CFoo {
>     int x = 0;
>     this(int xx) { this.x = xx; }
>     invariant() { assert(x == 1); }
> }
> class CBar {
>     int x = 0;
>     invariant() { assert(x == 1); }
> }
> void main() {
>     Foo f1;                  // no asserts
>     Foo f2 = Foo();          // no asserts
>     // Foo f3 = Foo(0);      // asserts, good
>
>     Bar b1;                  // no asserts
>     Bar b2 = Bar();          // no asserts
>     Bar b3 = Bar(0);         // no asserts
>
>     //assert(b3);            // can't be used
>     // b3.__invariant();     // asserts
>
>     //CFoo f3 = new CFoo(0); // asserts, good
>
>     CBar cb2 = new CBar();   // no asserts
>     //assert(cb2);           // asserts, good
> }

Default construction for structs is a weird animal in D.  A struct can  
always be default constructed and is always initialized to s.init.  This  
allows you to construct for instance an array of structs with simple  
memory copying.

During default struct construction, no constructors are run (they aren't  
allowed anyways) and no invariants are run.  What would be the point of  
running an invariant during default construction?  The only think it could  
possibly do is make code like this:

S s;

Fail without -release, and pass with -release.  I don't see the value in  
that.

-Steve
June 16, 2010
Re: Class/struct invariants
Steven Schveighoffer:
> During default struct construction, no constructors are run (they aren't  
> allowed anyways) and no invariants are run.  What would be the point of  
> running an invariant during default construction?  The only think it could  
> possibly do is make code like this:
> S s;
> Fail without -release, and pass with -release.  I don't see the value in  
> that.

Thank you for your answers, I was trying to understand.
Of all the examples I have shown this can be the worst:


struct Foo {
   int x;
   invariant() { assert(x > 0); }
}
void main() {
   Foo f = Foo(-10);
}

Here I'd like the compiler to assert (at compile time or at runtime), or to refuse an invariant in structs like that, where I think D has no way to enforce it (unless you call __invariant(), but this is silly).
Later I can write a "bug" report about this.

Bye,
bearophile
June 16, 2010
Re: Class/struct invariants
Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> During default struct construction, no constructors are run (they aren't  
> allowed anyways) and no invariants are run.  What would be the point of  
> running an invariant during default construction?  The only think it  
> could possibly do is make code like this:
>
> S s;
>
> Fail without -release, and pass with -release.  I don't see the value in  
> that.

Ah, but I do. If it is an error to create an uninitialized struct of
type S, then the above code is a bug, is it not?

-- 
Simen
June 16, 2010
Re: Class/struct invariants
On Wed, 16 Jun 2010 10:58:28 -0400, Simen kjaeraas  
<simen.kjaras@gmail.com> wrote:

> Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>> During default struct construction, no constructors are run (they  
>> aren't allowed anyways) and no invariants are run.  What would be the  
>> point of running an invariant during default construction?  The only  
>> think it could possibly do is make code like this:
>>
>> S s;
>>
>> Fail without -release, and pass with -release.  I don't see the value  
>> in that.
>
> Ah, but I do. If it is an error to create an uninitialized struct of
> type S, then the above code is a bug, is it not?

Yes, but an invariant doesn't guarantee that, since it is non-existent in  
release mode, and a compile time error is better.

What you want is to be able to disable the default constructor.  Andrei  
has hinted it might be a future improvement on other threads.

-Steve
June 16, 2010
Re: Class/struct invariants
Steven Schveighoffer:
> What you want is to be able to disable the default constructor.  Andrei  
> has hinted it might be a future improvement on other threads.

It's a good idea. I just hope this disabling will have an explicit & readable syntax (maybe @disable can be used here).

Bye,
bearophile
June 16, 2010
Re: Class/struct invariants
http://d.puremagic.com/issues/show_bug.cgi?id=4331
June 17, 2010
Re: Class/struct invariants
bearophile wrote:
> Are D invariants supposed to be so "relaxed"? They don't get called with default constructors:
<snip>

http://d.puremagic.com/issues/show_bug.cgi?id=519

Stewart.
June 17, 2010
Re: Class/struct invariants
Stewart Gordon:
> http://d.puremagic.com/issues/show_bug.cgi?id=519

Thank you, then my bug 4329 is a dupe, I'll mark it so :-)

Bye,
bearophile
Top | Discussion index | About this forum | D home