Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 03, 2014 Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
A nice blog post about assertions, preconditions, invariants and their usage: http://blog.regehr.org/archives/1091 It shows how D avoids some troubles, and offers most of what's needed. > The checkRep() Idiom It could go in the D invariant. I use it often. > The second way to accidentally change the state of the > program is like this: > > assert (treeDepth() == 7); > > but unfortunately treeDepth() changes the value in some > variable or heap cell, perhaps via a longish call chain. > > In case it isn't totally clear, the problem with side-effects > in assertions is that we'll test our program for a while, decide it's good, and do a release build with assertions turned off and of course suddenly it doesn't work. Or, it might be the release version that works but our debug build is broken by a side-effecting assertion. Dealing with these problems is highly demoralizing since assertions are supposed > to save time, not eat it up. I feel certain that there are static analyzers that warn about this kind of thing. In fact, > the original paper about the work that became Coverity's tool mentions exactly this analysis in Section 4.1, and also gives plenty of examples of this bug. This is an area where language support for controlling side effects would be useful. Such support is extremely primitive in C/C++. On this topic I have recently added an Enhancement Request, to disallow side effects in assert(): https://d.puremagic.com/issues/show_bug.cgi?id=12028 Two simple examples of code that is meant to be forbidden: int foo(ref int y) pure nothrow { return y++; } void main() { int x; assert(++x); assert(foo(x)); } Bye, bearophile |
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | "bearophile" wrote in message news:yzopesnnlgidhelsrrci@forum.dlang.org... > assert(foo(x)); Having the compiler see inside function bodies is problematic. |
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Murphy | Daniel Murphy:
>> assert(foo(x));
>
> Having the compiler see inside function bodies is problematic.
Why do you need that? You can tell that foo() is not strongly pure from its signature. That's enough.
Bye,
bearophile
|
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | "bearophile" wrote in message news:qfqkkpkdialejlknrpyx@forum.dlang.org... > Why do you need that? You can tell that foo() is not strongly pure from its signature. That's enough. Enough to tell it _might_ have a side effect, not enough to know it _will_. The number of false positives would make it near useless. |
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Murphy | Daniel Murphy:
> Enough to tell it _might_ have a side effect, not enough to know it _will_. The number of false positives would make it near useless.
How many impure functions do you call in your asserts?
In D we have a purity system, and now it works well enough. It's a good idea to actually start use it, for asserts, contracts, parallelism, etc.
Bye,
bearophile
|
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 3 February 2014 17:00, bearophile <bearophileHUGS@lycos.com> wrote:
> Daniel Murphy:
>
>
>> Enough to tell it _might_ have a side effect, not enough to know it _will_. The number of false positives would make it near useless.
>
>
> How many impure functions do you call in your asserts?
Rephrase to 'How many *functions* do you call in your asserts?'
If a function has a side effect (or returns), I'd have thought that
typically people want to store that value first, then test it using
assert().
Regards
Iain.
|
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | "bearophile" wrote in message news:aifyouczfuqhdgubpfsw@forum.dlang.org... > How many impure functions do you call in your asserts? > In D we have a purity system, and now it works well enough. It's a good idea to actually start use it, for asserts, contracts, parallelism, etc. Do you really want to force all codebases to 'pure'ify all their functions? A function call in an assert might be a red flag, but it certainly isn't a bug. |
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Murphy | Daniel Murphy: > Do you really want to force all codebases to 'pure'ify all their functions? What percentage of your functions are transitively called in your asserts? In my code it's a small percentage. > A function call in an assert might be a red flag, but it certainly isn't a bug. I agree. I am suggesting to disallow just impure functions in asserts. We have an acceptably good type system, but are we afraid of using it? Bye, bearophile |
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | I have one semi-large code base where I validate the locking semantics by adding assert(!lock.try_acquire)'s. That's clearly a side effect, but also clearly should never have one if the code is correct.
On 2/3/14, 10:20 AM, bearophile wrote:
> Daniel Murphy:
>
>> Do you really want to force all codebases to 'pure'ify all their
>> functions?
>
> What percentage of your functions are transitively called in your
> asserts? In my code it's a small percentage.
>
>
>> A function call in an assert might be a red flag, but it certainly
>> isn't a bug.
>
> I agree. I am suggesting to disallow just impure functions in asserts.
>
> We have an acceptably good type system, but are we afraid of using it?
>
> Bye,
> bearophile
|
February 03, 2014 Re: Disallow side effects in assert | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Roberts | Brad Roberts:
> I have one semi-large code base where I validate the locking semantics by adding assert(!lock.try_acquire)'s. That's clearly a side effect, but also clearly should never have one if the code is correct.
I see, and you can't you use a special library-defined assert for that purpose.
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation