View mode: basic / threaded / horizontal-split · Log in · Help
August 04, 2011
More than one invariant per struct/class
I would like to use a template mixin to add some fields to a struct, but 
I'd also like the template to add additional invariant checks without 
having to remember to add this for all struct/classes that mixes in this 
code.

class C {
    int a;
}

mixin template EmbedC() {
    C _c;

    // oops.. more than one invariant
    invariant() {
        assert(_c);
    }

    void close() {
        _c = null;
    }
}

struct S {
    int i = 10;
    invariant() {
        assert(i >= 10);
    }

    mixin EmbedC!();
}

void main() {
    S s;
    s.close();
    s._c.a = 10; // access violation, but I want assertion from invariant
}
August 04, 2011
Re: More than one invariant per struct/class
On 04-08-2011 11:32, simendsjo wrote:
> I would like to use a template mixin to add some fields to a struct, but
> I'd also like the template to add additional invariant checks without
> having to remember to add this for all struct/classes that mixes in this
> code.
>
> class C {
> int a;
> }
>
> mixin template EmbedC() {
> C _c;
>
> // oops.. more than one invariant
> invariant() {
> assert(_c);
> }
>
> void close() {
> _c = null;
> }
> }
>
> struct S {
> int i = 10;
> invariant() {
> assert(i >= 10);
> }
>
> mixin EmbedC!();
> }
>
> void main() {
> S s;
> s.close();
> s._c.a = 10; // access violation, but I want assertion from invariant
> }

This sounds reasonable and useful to me.

- Alex
August 04, 2011
Re: More than one invariant per struct/class
On Thu, 04 Aug 2011 11:32:03 +0200, simendsjo <simendsjo@gmail.com> wrote:

> I would like to use a template mixin to add some fields to a struct, but  
> I'd also like the template to add additional invariant checks without  
> having to remember to add this for all struct/classes that mixes in this  
> code.
>
> class C {
>      int a;
> }
>
> mixin template EmbedC() {
>      C _c;
>
>      // oops.. more than one invariant
>      invariant() {
>          assert(_c);
>      }
>
>      void close() {
>          _c = null;
>      }
> }
>
> struct S {
>      int i = 10;
>      invariant() {
>          assert(i >= 10);
>      }
>
>      mixin EmbedC!();
> }
>
> void main() {
>      S s;
>      s.close();
>      s._c.a = 10; // access violation, but I want assertion from  
> invariant
> }

What happens if you replace assert(_c) with assert(_c !is null)?
August 04, 2011
Re: More than one invariant per struct/class
On 04.08.2011 12:30, Pelle wrote:
> On Thu, 04 Aug 2011 11:32:03 +0200, simendsjo <simendsjo@gmail.com> wrote:
>
>> I would like to use a template mixin to add some fields to a struct,
>> but I'd also like the template to add additional invariant checks
>> without having to remember to add this for all struct/classes that
>> mixes in this code.
>>
>> class C {
>> int a;
>> }
>>
>> mixin template EmbedC() {
>> C _c;
>>
>> // oops.. more than one invariant
>> invariant() {
>> assert(_c);
>> }
>>
>> void close() {
>> _c = null;
>> }
>> }
>>
>> struct S {
>> int i = 10;
>> invariant() {
>> assert(i >= 10);
>> }
>>
>> mixin EmbedC!();
>> }
>>
>> void main() {
>> S s;
>> s.close();
>> s._c.a = 10; // access violation, but I want assertion from invariant
>> }
>
> What happens if you replace assert(_c) with assert(_c !is null)?

The problem is that you cannot include more than one invariant() in a 
struct or class.

struct S {
    invariant() {}
    invariant() {} // blows up
}

void main() {}

I could easily change the design for my use case, but I don't see why 
this restriction exists. Perhaps some more experienced users can comment 
on this.
August 04, 2011
Re: More than one invariant per struct/class
On Thu, 04 Aug 2011 12:40:48 +0200, simendsjo <simendsjo@gmail.com> wrote:
> On 04.08.2011 12:30, Pelle wrote:
>> What happens if you replace assert(_c) with assert(_c !is null)?
>
> The problem is that you cannot include more than one invariant() in a  
> struct or class.

IIRC assert(obj) gets rewritten to obj.__invariant() or something like  
that, which segfaults if obj is null. I thought that maybe that was why  
the code didn't work. :--)
August 06, 2011
Re: More than one invariant per struct/class
On 04.08.2011 11:32, simendsjo wrote:
> I would like to use a template mixin to add some fields to a struct, but
> I'd also like the template to add additional invariant checks without
> having to remember to add this for all struct/classes that mixes in this
> code.
>
> class C {
> int a;
> }
>
> mixin template EmbedC() {
> C _c;
>
> // oops.. more than one invariant
> invariant() {
> assert(_c);
> }
>
> void close() {
> _c = null;
> }
> }
>
> struct S {
> int i = 10;
> invariant() {
> assert(i >= 10);
> }
>
> mixin EmbedC!();
> }
>
> void main() {
> S s;
> s.close();
> s._c.a = 10; // access violation, but I want assertion from invariant
> }

Should I create a feature request to support more than one invariant?
It's pretty obvious that it works as designed given the nice error 
message though..
August 06, 2011
Re: More than one invariant per struct/class
On Saturday 06 August 2011 22:40:15 simendsjo wrote:
> On 04.08.2011 11:32, simendsjo wrote:
> > I would like to use a template mixin to add some fields to a struct, but
> > I'd also like the template to add additional invariant checks without
> > having to remember to add this for all struct/classes that mixes in this
> > code.
> > 
> > class C {
> > int a;
> > }
> > 
> > mixin template EmbedC() {
> > C _c;
> > 
> > // oops.. more than one invariant
> > invariant() {
> > assert(_c);
> > }
> > 
> > void close() {
> > _c = null;
> > }
> > }
> > 
> > struct S {
> > int i = 10;
> > invariant() {
> > assert(i >= 10);
> > }
> > 
> > mixin EmbedC!();
> > }
> > 
> > void main() {
> > S s;
> > s.close();
> > s._c.a = 10; // access violation, but I want assertion from invariant
> > }
> 
> Should I create a feature request to support more than one invariant?
> It's pretty obvious that it works as designed given the nice error
> message though..

Feel free to create a feature request on it. It may even get the language 
changed. However, having more than one invariant complicates things a bit, 
since right now, it's easy for the runtime to just call the one invariant. If 
you had multiple invariants, they would have to be merged somehow by the 
compiler. It's completely doable, but it definitely complicates things, which 
is probably why it doesn't work that way now.

If you wanted to be able to do it now though, I'd suggest that the mixins not 
have invariants but that they have functions which you then have to call in 
the invariant of the type that they're being mixed into. It's more error 
prone, since you could forget to call one of those functions in the invariant, 
but it allows you to have invariants of a sort in the mixed in code and still 
only have one invariant for the type.

- Jonathan M Davis
August 08, 2011
Re: More than one invariant per struct/class
On Sat, 06 Aug 2011 22:53:31 +0200, Jonathan M Davis <jmdavisProg@gmx.com>  
wrote:

> Feel free to create a feature request on it. It may even get the language
> changed. However, having more than one invariant complicates things a  
> bit,
> since right now, it's easy for the runtime to just call the one  
> invariant. If
> you had multiple invariants, they would have to be merged somehow by the
> compiler. It's completely doable, but it definitely complicates things,  
> which
> is probably why it doesn't work that way now.

unittests are already merged this way, so it should be easy.
August 08, 2011
Re: More than one invariant per struct/class
On 06.08.2011 22:53, Jonathan M Davis wrote:
> On Saturday 06 August 2011 22:40:15 simendsjo wrote:
>> On 04.08.2011 11:32, simendsjo wrote:
>>> I would like to use a template mixin to add some fields to a struct, but
>>> I'd also like the template to add additional invariant checks without
>>> having to remember to add this for all struct/classes that mixes in this
>>> code.
>>>
>>> class C {
>>> int a;
>>> }
>>>
>>> mixin template EmbedC() {
>>> C _c;
>>>
>>> // oops.. more than one invariant
>>> invariant() {
>>> assert(_c);
>>> }
>>>
>>> void close() {
>>> _c = null;
>>> }
>>> }
>>>
>>> struct S {
>>> int i = 10;
>>> invariant() {
>>> assert(i>= 10);
>>> }
>>>
>>> mixin EmbedC!();
>>> }
>>>
>>> void main() {
>>> S s;
>>> s.close();
>>> s._c.a = 10; // access violation, but I want assertion from invariant
>>> }
>>
>> Should I create a feature request to support more than one invariant?
>> It's pretty obvious that it works as designed given the nice error
>> message though..
>
> Feel free to create a feature request on it. It may even get the language
> changed. However, having more than one invariant complicates things a bit,
> since right now, it's easy for the runtime to just call the one invariant. If
> you had multiple invariants, they would have to be merged somehow by the
> compiler. It's completely doable, but it definitely complicates things, which
> is probably why it doesn't work that way now.
>
> If you wanted to be able to do it now though, I'd suggest that the mixins not
> have invariants but that they have functions which you then have to call in
> the invariant of the type that they're being mixed into. It's more error
> prone, since you could forget to call one of those functions in the invariant,
> but it allows you to have invariants of a sort in the mixed in code and still
> only have one invariant for the type.
>
> - Jonathan M Davis

http://d.puremagic.com/issues/show_bug.cgi?id=6453
Top | Discussion index | About this forum | D home