www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Let's not make invariants const

reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
Hi,

This:

$ cat test.d
class A
{
     int i;

     invariant()
     {
         i = 42;
     }
}

Currently doesn't compile:

$ dmd test.d
test.d(7): Error: can only initialize const member i inside constructor

(Obviously this example is silly, but it's just meant to illustrate the 
point of this thread.)

I believe this behavior is too strict. I don't agree that the language 
should dictate what *my* invariant can and cannot do. Not to mention 
that the standard library is far from const-friendly enough for this 
strictness to be practically reasonable today (I have tons of cast()s in 
my programs today due to this - not cool).

Does anyone else find this behavior too strict?

-- 
Alex Rønne Petersen
alex lycus.org
http://lycus.org
Aug 03 2012
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
On 03-08-2012 21:19, Alex Rønne Petersen wrote:
 Hi,

 This:

 $ cat test.d
 class A
 {
      int i;

      invariant()
      {
          i = 42;
      }
 }

 Currently doesn't compile:

 $ dmd test.d
 test.d(7): Error: can only initialize const member i inside constructor

 (Obviously this example is silly, but it's just meant to illustrate the
 point of this thread.)

 I believe this behavior is too strict. I don't agree that the language
 should dictate what *my* invariant can and cannot do. Not to mention
 that the standard library is far from const-friendly enough for this
 strictness to be practically reasonable today (I have tons of cast()s in
 my programs today due to this - not cool).

 Does anyone else find this behavior too strict?

I should also mention that invariants weren't const until very recently, so this is also quite the breaking change... -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 03 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 03 Aug 2012 21:19:22 +0200, Alex R=C3=B8nne Petersen <alex lycus=
.org>  =

wrote:

 Hi,

 This:

 $ cat test.d
 class A
 {
      int i;

      invariant()
      {
          i =3D 42;
      }
 }

 Currently doesn't compile:

 $ dmd test.d
 test.d(7): Error: can only initialize const member i inside constructo=

 (Obviously this example is silly, but it's just meant to illustrate th=

 point of this thread.)

 I believe this behavior is too strict. I don't agree that the language=

 should dictate what *my* invariant can and cannot do. Not to mention  =

 that the standard library is far from const-friendly enough for this  =

 strictness to be practically reasonable today (I have tons of cast()s =

 my programs today due to this - not cool).

 Does anyone else find this behavior too strict?

Votes++ In a perfect world... -- = Simen
Aug 03 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Aug 03, 2012 at 09:19:22PM +0200, Alex Rønne Petersen wrote:
[...]
 class A
 {
     int i;
 
     invariant()
     {
         i = 42;
     }
 }
 
 Currently doesn't compile:
 
 $ dmd test.d
 test.d(7): Error: can only initialize const member i inside constructor

 I believe this behavior is too strict.

IMO, if you need to be changing stuff inside invariants, then you're using it wrong. Invariants are intended to verify program logic, not to do things like altering object state. The point is to be able to compile with invariant code turned off, and still have the program work exactly as before. T -- Be in denial for long enough, and one day you'll deny yourself of things you wish you hadn't.
Aug 03 2012
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
On 03-08-2012 21:36, H. S. Teoh wrote:
 On Fri, Aug 03, 2012 at 09:19:22PM +0200, Alex Rønne Petersen wrote:
 [...]
 class A
 {
      int i;

      invariant()
      {
          i = 42;
      }
 }

 Currently doesn't compile:

 $ dmd test.d
 test.d(7): Error: can only initialize const member i inside constructor

 I believe this behavior is too strict.

IMO, if you need to be changing stuff inside invariants, then you're using it wrong. Invariants are intended to verify program logic, not to do things like altering object state. The point is to be able to compile with invariant code turned off, and still have the program work exactly as before. T

So what if, for whatever reason, the invariant needs to track and maintain some state in order to catch some kind of ugly bug? I agree that ideally an invariant should not ever need to change state. But I think in some cases it can be a useful debugging tool. But even ignoring that, making invariants const at this point in time is just not practical. We seem to be doing things in the completely wrong order. The library should be made const-friendly and *then* invariants could be made const (not that I want them to be anyway). -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 03 2012
next sibling parent reply Davidson Corry <davidsoncorry comcast.net> writes:
On 8/3/2012 1:14 PM, Paulo Pinto wrote:
 Personally I feel D's contracts are still a bit off of what Eiffel,

On 8/3/2012 1:01 PM, Alex Rønne Petersen wrote:
 So what if, for whatever reason, the invariant needs to track and
 maintain some state in order to catch some kind of ugly bug?

 I agree that ideally an invariant should not ever need to change state.
 But I think in some cases it can be a useful debugging tool.

The "track and maintain some state" bit usually means capturing some state at entry to the class (via a public method), so that the invariant can at exit from the class compare the new, possibly modified, state to the previous one. This is the purpose of Eiffel's 'old' construct, which D does not have. (Yet.) (One hopes.) (And it would be nice to be able to capture an old *expression* and not just an old variable.) 'old' is used more often with postconditions than with invariants, but it can be useful in both.
 But even ignoring that, making invariants const at this point in time is
 just not practical. We seem to be doing things in the completely wrong
 order. The library should be made const-friendly and *then* invariants
 could be made const (not that I want them to be anyway).

Certainly the libraries should be made as const-correct as possible. But it's not like we are forced to do only the one or the other (except for the insufficient supply of Walters, perhaps...). IMO, invariants should "be made const" (i.e. statically check for side effects) as discussed elsewhere. In fact, I believe that having more rigorous contract checks could *help* improve library code, by making it harder for loose code to get into the library.
Aug 03 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <alex lycus.org> writes:
On 03-08-2012 22:32, Davidson Corry wrote:
 On 8/3/2012 1:14 PM, Paulo Pinto wrote:
 Personally I feel D's contracts are still a bit off of what Eiffel,

On 8/3/2012 1:01 PM, Alex Rønne Petersen wrote:
 So what if, for whatever reason, the invariant needs to track and
 maintain some state in order to catch some kind of ugly bug?

 I agree that ideally an invariant should not ever need to change state.
 But I think in some cases it can be a useful debugging tool.

The "track and maintain some state" bit usually means capturing some state at entry to the class (via a public method), so that the invariant can at exit from the class compare the new, possibly modified, state to the previous one. This is the purpose of Eiffel's 'old' construct, which D does not have. (Yet.) (One hopes.) (And it would be nice to be able to capture an old *expression* and not just an old variable.) 'old' is used more often with postconditions than with invariants, but it can be useful in both.
 But even ignoring that, making invariants const at this point in time is
 just not practical. We seem to be doing things in the completely wrong
 order. The library should be made const-friendly and *then* invariants
 could be made const (not that I want them to be anyway).

Certainly the libraries should be made as const-correct as possible. But it's not like we are forced to do only the one or the other (except for the insufficient supply of Walters, perhaps...). IMO, invariants should "be made const" (i.e. statically check for side effects) as discussed elsewhere. In fact, I believe that having more rigorous contract checks could *help* improve library code, by making it harder for loose code to get into the library.

The problem here is that making invariants const *now* means that using them in conjunction with Phobos code becomes next to impossible. Casting away const will become common practice, and that ain't exactly the way we want to go. :/ -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 03 2012
parent Davidson Corry <davidsoncorry comcast.net> writes:
On 8/3/2012 1:48 PM, Alex Rønne Petersen wrote:
 The problem here is that making invariants const *now* means that using
 them in conjunction with Phobos code becomes next to impossible. Casting
 away const will become common practice, and that ain't exactly the way
 we want to go. :/

Understood and agreed. Casting away const just to get the thing to compile, rather than correcting the code that throws the const-downcheck, is wasted effort (or worse, since it hides the problem.) Perhaps make the invariant const-downcheck a compiler warning, with the understanding that it will become a compiler *error* in some future release? Kind of like an automatic "deprecated" for invariants re this issue?
Aug 04 2012
prev sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 03-08-2012 22:40, bearophile wrote:
 Alex Rønne Petersen:

 So what if, for whatever reason, the invariant needs to track and
 maintain some state in order to catch some kind of ugly bug?

This is legitimate practical need. I know two or more ways to solve that problem, one of them is to implement the prestate (old). That's probably the largest hole in the D implementation of contract programming, and I have felt its need several times. Another solution (that doesn't replace the need for the prestate!) is ghost fields, that are class instance/struct fields usable only inside contracts and that vanish in release mode: http://d.puremagic.com/issues/show_bug.cgi?id=5027 Bye, bearophile

I've used prestate in Spec#/Sing# and can definitely vouch for its usefulness. -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 03 2012
prev sibling parent reply Davidson Corry <davidsoncorry comcast.net> writes:
On 8/3/2012 12:40 PM, bearophile wrote:
 H. S. Teoh:

 IMO, if you need to be changing stuff inside invariants, then you're
 using it wrong. Invariants are intended to verify program logic, not
 to do things like altering object state. The point is to be able to
 compile with invariant code turned off, and still have the program
 work exactly as before.

I agree, modifying the state of the struct/class instance is not the job of contracts and invariants. D contract programming is already not tidy, so better to not make it even more messy. In a perfect world invariants and contracts should be pure too!

Absolutely. Invariant clauses (and contract clauses generally) must not have side effects, lest the class behavior change depending upon whether or not they are compiled into the build. Assigning a value within the invariant clause is definitely a side effect. It is the job of the *constructor* to establish the invariant state, not of the invariant clause (which only *verifies* it). The compiler *should* be catching a side effect in the invariant clause, if it can do so statically.
Aug 03 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 03-08-2012 22:17, Davidson Corry wrote:
 On 8/3/2012 12:40 PM, bearophile wrote:
 H. S. Teoh:

 IMO, if you need to be changing stuff inside invariants, then you're
 using it wrong. Invariants are intended to verify program logic, not
 to do things like altering object state. The point is to be able to
 compile with invariant code turned off, and still have the program
 work exactly as before.

I agree, modifying the state of the struct/class instance is not the job of contracts and invariants. D contract programming is already not tidy, so better to not make it even more messy. In a perfect world invariants and contracts should be pure too!

Absolutely. Invariant clauses (and contract clauses generally) must not have side effects, lest the class behavior change depending upon whether or not they are compiled into the build. Assigning a value within the invariant clause is definitely a side effect.

Of course... it was an example to demonstrate the current situation. It was by no means meant to be a sensible piece of code.
 It is the job of the *constructor* to establish the invariant state,
 not of the invariant clause (which only *verifies* it).

Yes, but sometimes it's useful to track and maintain state in an invariant in order to debug certain bugs that only manifest in systems programming languages like D. Unlike languages like C#, we can get e.g. memory corruption in D. I find that in practice, enforcing const in invariants has not helped me in any way. It has forced me to fix countless errors upon a DMD upgrade, none of which indicated actual problems. That's what I got out of that. The likelihood of an invariant visibly altering program semantics due to side-effects is so low it's not worth the huge breakage IMO. Further, I had to insert casts that cast away constness in some cases because the standard library just isn't const-friendly enough. We need to get our priorities straight.
 The compiler *should* be catching a side effect in the invariant clause,
 if it can do so statically.

Not if it breaks my 30.000 lines source base where not even a single one of the errors caught actual bugs. I refer to this as "waste of time". -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 03 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 03/08/2012 22:41, Alex Rønne Petersen a écrit :
 Further, I had to insert casts that cast away constness in some cases
 because the standard library just isn't const-friendly enough. We need
 to get our priorities straight.

Why don't you think this is actually the issue ? (I do). BTW, const inference could be great to solve that or that problem will arise again and again.
Aug 04 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 IMO, if you need to be changing stuff inside invariants, then 
 you're using it wrong. Invariants are intended to verify 
 program logic, not to do things like altering object state. The 
 point is to be able to compile with invariant code turned off, 
 and still have the program work exactly as before.

I agree, modifying the state of the struct/class instance is not the job of contracts and invariants. D contract programming is already not tidy, so better to not make it even more messy. In a perfect world invariants and contracts should be pure too! Bye, bearophile
Aug 03 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 03 Aug 2012 21:36:41 +0200, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 IMO, if you need to be changing stuff inside invariants, then you're
 using it wrong. Invariants are intended to verify program logic, not to
 do things like altering object state. The point is to be able to compile
 with invariant code turned off, and still have the program work exactly
 as before.

True. Then add in a (standard) library that's not const-correct, and you have invariants that are outright unusable. -- Simen
Aug 03 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 3 August 2012 at 19:43:18 UTC, Simen Kjaeraas wrote:
 On Fri, 03 Aug 2012 21:36:41 +0200, H. S. Teoh 
 <hsteoh quickfur.ath.cx> wrote:

 IMO, if you need to be changing stuff inside invariants, then 
 you're
 using it wrong. Invariants are intended to verify program 
 logic, not to
 do things like altering object state. The point is to be able 
 to compile
 with invariant code turned off, and still have the program 
 work exactly
 as before.

True. Then add in a (standard) library that's not const-correct, and you have invariants that are outright unusable.

Personally I feel D's contracts are still a bit off of what Eiffel, .NET and Ada 2012 offer. -- Paulo
Aug 03 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Alex Rønne Petersen:

 So what if, for whatever reason, the invariant needs to track 
 and maintain some state in order to catch some kind of ugly bug?

This is legitimate practical need. I know two or more ways to solve that problem, one of them is to implement the prestate (old). That's probably the largest hole in the D implementation of contract programming, and I have felt its need several times. Another solution (that doesn't replace the need for the prestate!) is ghost fields, that are class instance/struct fields usable only inside contracts and that vanish in release mode: http://d.puremagic.com/issues/show_bug.cgi?id=5027 Bye, bearophile
Aug 03 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Friday, 3 August 2012 at 20:48:29 UTC, Alex Rønne Petersen 
wrote:
 The problem here is that making invariants const *now* means 
 that using them in conjunction with Phobos code becomes next to 
 impossible. Casting away const will become common practice, and 
 that ain't exactly the way we want to go. :/

Doesn't 'const' only qualify for the object's (this) code? If that's the case, you could have a global object inside a debug statement, then put those inside the invariants so you get your output (say, in a text file), while keeping it const. Having no side effects is pure, meaning global state would be unreachable (and debug already bypasses pure, but not safe).
Aug 03 2012
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 03 Aug 2012 22:40:02 +0200
schrieb "bearophile" <bearophileHUGS lycos.com>:

 Another solution (that doesn't replace the need for the 
 prestate!) is ghost fields, that are class instance/struct fields 
 usable only inside contracts and that vanish in release mode:
 http://d.puremagic.com/issues/show_bug.cgi?id=5027
 
 Bye,
 bearophile

While reading this thread I had the same idea. But the user must be 100% aware, that structs change size in release mode. This can be a real problem for data exchange with libraries using the same struct, in memory mapped files or in files. Just imagine you stored some structured data in a file using the pointer and size of such a struct in release mode. Then you debug the program and you don't realize why the file cannot be loaded any more. If it weren't for the systems programming language part (.sizeof, &...), it could be a nice proposal. -- Marco
Aug 03 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, August 03, 2012 12:36:41 H. S. Teoh wrote:
 IMO, if you need to be changing stuff inside invariants, then you're
 using it wrong. Invariants are intended to verify program logic, not to
 do things like altering object state. The point is to be able to compile
 with invariant code turned off, and still have the program work exactly
 as before.

I think that it's more of a problem of not being able to call non-const functions and the like. I'd definitely be against mutating anything in an invariant, but if your type doesn't work with const very well (and the recent debate about Object and const highlights how that can be a big issue), then forcing stuff like invariants and contracts to be const is problematic. - Jonathan M Davis
Aug 03 2012
prev sibling next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
It's worth pointing out the obvious, i.e. that as long as 'const' 
is physical const instead of logical const (which is always), 
invariants and contracts can't be const, because that would 
restrict them from calling methods that are logically but not 
physically const.

So I think they probably shouldn't be const.
Aug 03 2012
parent travert phare.normalesup.org (Christophe Travert) writes:
"Era Scarecrow" , dans le message (digitalmars.D:174206), a écrit :
   I would think it does however during verbose output specifying 
 if an invariant or contract is changing data and that may alter 
 behavior.

Signatures in some place should be by default const, pure, nothrow. This is the case for invariant() (if you consider it as a function) [1]. However, it is only possible to have different default than non-const, non-pure, throw, if the langage support a way to remove those default attributes. Maybe this should be included in the langage. -- Christophe [1] Actually, I would rather have a langage where all functions are by default const (wrt all parameters, except this), pure, nothrow... But it seems D is not that langage and it not going to be.
Aug 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 4 August 2012 at 06:53:16 UTC, Mehrdad wrote:
 It's worth pointing out the obvious, I.e. that as long as 
 'const' is physical const instead of logical const (which is 
 always), invariants and contracts can't be const, because that 
 would restrict them from calling methods that are logically but 
 not physically const.

 So I think they probably shouldn't be const.

As mentioned before, doesn't 'const' _only_ apply to the current (this) object and not anything else? Besides the contracts can't have lasting side effects that would change logical execution. How would changing the current object in an invariant be correct in release code? I'm not sure if the contracts should have many (or any) restrictions, but at the same time if you remove the contracts, nothing in the code should change the execution; Example: using writeln in an invariant should not change the current object/structure in any form, or anything it is part of. Although not writeln is not 'pure', const shouldn't prevent you from using it (pure or safe declarations may withhold you).
Aug 04 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, August 04, 2012 09:06:19 Era Scarecrow wrote:
   As mentioned before, doesn't 'const' _only_ apply to the current
 (this) object and not anything else? Besides the contracts can't
 have lasting side effects that would change logical execution.
 How would changing the current object in an invariant be correct
 in release code?

The problem is that if the this pointer/reference is const, then you can't call any member functions which aren't const, and you can't call any non-const functions on any member variables, because _they're_ const, because the this pointer/reference is const. And there are plenty of types out there which _can't_ have many of their member functions be const and do what they need to do, because D's const is both physical and transitive (unlike C++'s const). So, it's quite easy to get into a situation, where you can't call much of any functions at all if the this pointer/reference is const even though calling the non-const functions wouldn't actually mutate anything. - Jonathan M Davis
Aug 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 4 August 2012 at 07:15:50 UTC, Jonathan M Davis 
wrote:
 The problem is that if the this pointer/reference is const, 
 then you can't call any member functions which aren't const, 
 and you can't call any non-const functions on any member 
 variables, because _they're_ const, because the this 
 pointer/reference is const. And there are plenty of types out 
 there which _can't_ have many of their member functions be 
 const and do what they need to do, because D's const is both 
 physical and transitive (unlike C++'s const). So, it's quite 
 easy to get into a situation, where you can't call much of any 
 functions at all if the this pointer/reference is const even 
 though calling the non-const functions wouldn't actually mutate 
 anything.

Data-wise I see it both as a problem, and not as a problem. so contracts and invariants and debug statements should have the safe, pure, and const nature stripped for debugging support. I would think it does however during verbose output specifying if an invariant or contract is changing data and that may alter behavior.
Aug 04 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 03/08/2012 21:19, Alex Rønne Petersen a écrit :
 Hi,

 This:

 $ cat test.d
 class A
 {
 int i;

 invariant()
 {
 i = 42;
 }
 }

 Currently doesn't compile:

 $ dmd test.d
 test.d(7): Error: can only initialize const member i inside constructor

 (Obviously this example is silly, but it's just meant to illustrate the
 point of this thread.)

 I believe this behavior is too strict. I don't agree that the language
 should dictate what *my* invariant can and cannot do. Not to mention
 that the standard library is far from const-friendly enough for this
 strictness to be practically reasonable today (I have tons of cast()s in
 my programs today due to this - not cool).

 Does anyone else find this behavior too strict?

I don't. Actually, it save from many mistakes. You are always free to cast away const. This is unsafe, but you are in an invariant and aren't supposed to do non const operation. At the end, this is fair. As usual, a safe behavior is proposed, and ways exists to free yourself from safety. This is Dish. You mention a good point when saying that a lot of lib isn't const friendly and this is true. The problem don't lie into invariant and constness but here.
Aug 04 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, August 04, 2012 10:37:55 deadalnix wrote:
 I don't.
 
 Actually, it save from many mistakes. You are always free to cast away
 const. This is unsafe, but you are in an invariant and aren't supposed
 to do non const operation. At the end, this is fair.

All that would be required to have a const invariant if invariants aren't const by default would be to mark it const. That's how it works with pure (unless invariants are always pure now along with const, in which case, this is how it _worked_ with pure). So, you can have the extra safety if you want it, but as long as invariant is automatically const, you can't safely make in non-const, which is unnecessarily inflexible. D needs to work well with const, but one of the goals is also to make it so that it's not required if you don't want to or can't use it. Forcing invariants to be const goes against this. But that decision was probably made before the recent decisions on Object and const functions (i.e. that toString, toHash, opCmp, and opEquals will no longer be part of Object, so you'll be able to make them whatever constness you want), and I expect that it'll be reverted as long as it's appropriately pointed out to Walter (though it may require someone else creating a pull request with the actual changes). - Jonathan M Davis
Aug 04 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/4/12 4:45 AM, Jonathan M Davis wrote:
 D needs to work well with const, but one of the goals is also to make it so
 that it's not required if you don't want to or can't use it. Forcing
 invariants to be const goes against this. But that decision was probably made
 before the recent decisions on Object and const functions (i.e. that toString,
 toHash, opCmp, and opEquals will no longer be part of Object, so you'll be
 able to make them whatever constness you want), and I expect that it'll be
 reverted as long as it's appropriately pointed out to Walter (though it may
 require someone else creating a pull request with the actual changes).

My opinion in the matter is that invariants are meant to be gatekeeper code that makes sure things stay sane and bug-free. Such code should have special exemptions, much like the debug statement does. Protecting invariants against their own bugs seems a bit extreme to me. I think a stance could be taken either way. Const invariants are like the European police; non-const invariants are like US police. Andrei
Aug 04 2012
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 04 Aug 2012 16:08:42 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 I think a stance could be taken either way. Const invariants are like  
 the European police; non-const invariants are like US police.

Funny, my impression of the US/European police is the exact opposite. -- Simen
Aug 05 2012
prev sibling next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 3 August 2012 at 19:19:24 UTC, Alex Rønne Petersen 
wrote:
 Does anyone else find this behavior too strict?

Yes. Sounds like yet another case of forcing bitwise const on something that should only be logically const. Please stop forcing bitwise constancy on everything. Not everything needs to work with immutable, it should be opt-in (which in this case could mean explicitly marking the invariant as const) for any type.
Aug 05 2012
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 05/08/2012 11:47, Simen Kjaeraas a écrit :
 On Sun, 05 Aug 2012 11:36:56 +0200, Jakob Ovrum <jakobovrum gmail.com>
 wrote:

 On Friday, 3 August 2012 at 19:19:24 UTC, Alex Rønne Petersen wrote:
 Does anyone else find this behavior too strict?

Yes. Sounds like yet another case of forcing bitwise const on something that should only be logically const. Please stop forcing bitwise constancy on everything. Not everything needs to work with immutable, it should be opt-in (which in this case could mean explicitly marking the invariant as const) for any type.

I was about to argue that non-const invariants could not be called when calling const or immutable member functions, but then it hit me that those shouldn't be able to influence the state checked by the invariant anyway.

That is a very good point. Should invariant run on const/immutable method calls ?
Aug 06 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 06-08-2012 19:57, deadalnix wrote:
 Le 05/08/2012 11:47, Simen Kjaeraas a écrit :
 On Sun, 05 Aug 2012 11:36:56 +0200, Jakob Ovrum <jakobovrum gmail.com>
 wrote:

 On Friday, 3 August 2012 at 19:19:24 UTC, Alex Rønne Petersen wrote:
 Does anyone else find this behavior too strict?

Yes. Sounds like yet another case of forcing bitwise const on something that should only be logically const. Please stop forcing bitwise constancy on everything. Not everything needs to work with immutable, it should be opt-in (which in this case could mean explicitly marking the invariant as const) for any type.

I was about to argue that non-const invariants could not be called when calling const or immutable member functions, but then it hit me that those shouldn't be able to influence the state checked by the invariant anyway.

That is a very good point. Should invariant run on const/immutable method calls ?

They should. In the real world, things are not as nice as const and immutable would have you believe. Things can be modified indirectly by the invariant (through a global variable for example), or even by another thread. We need invariants to run as often as possible to catch problems like these instead of pretending they don't exist. -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 06 2012
prev sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 05-08-2012 11:47, Simen Kjaeraas wrote:
 On Sun, 05 Aug 2012 11:36:56 +0200, Jakob Ovrum <jakobovrum gmail.com>
 wrote:

 On Friday, 3 August 2012 at 19:19:24 UTC, Alex Rønne Petersen wrote:
 Does anyone else find this behavior too strict?

Yes. Sounds like yet another case of forcing bitwise const on something that should only be logically const. Please stop forcing bitwise constancy on everything. Not everything needs to work with immutable, it should be opt-in (which in this case could mean explicitly marking the invariant as const) for any type.

I was about to argue that non-const invariants could not be called when calling const or immutable member functions, but then it hit me that those shouldn't be able to influence the state checked by the invariant anyway.

Sure they can. If the invariant can influence something outside of the object, then it can potentially influence the object's members. For example, a global variable could hold a non-const reference to something that the object also has a reference to. Aliasing is a bitch. ;) -- Alex Rønne Petersen alex lycus.org http://lycus.org
Aug 06 2012
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 05 Aug 2012 11:36:56 +0200, Jakob Ovrum <jakobovrum gmail.com>  =

wrote:

 On Friday, 3 August 2012 at 19:19:24 UTC, Alex R=C3=B8nne Petersen wro=

 Does anyone else find this behavior too strict?

Yes. Sounds like yet another case of forcing bitwise const on somethin=

 that should only be logically const.

 Please stop forcing bitwise constancy on everything. Not everything  =

 needs to work with immutable, it should be opt-in (which in this case =

 could mean explicitly marking the invariant as const) for any type.

I was about to argue that non-const invariants could not be called when calling const or immutable member functions, but then it hit me that those shouldn't be able to influence the state checked by the invariant anyway. -- = Simen
Aug 05 2012