February 03, 2014
Am Mon, 03 Feb 2014 10:33:11 -0800
schrieb Brad Roberts <braddr@puremagic.com>:

> 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.

Damn those gotchas. Basically lock.try_acquire is pure when it returns false, and if not, the program is terminated anyways so it doesn't make a difference.

I also noticed that contracts don't work at all with shared
objects. Where you synchronize around a mutex inside a method
you have to move all checks into the critical section.
Yeah, its obvious, but when you turn a non-thread-safe
structure into a thread-safe one and have to delete all
in-out-blocks it hurts a bit. :)

-- 
Marco

February 03, 2014
Marco Leise:

> Damn those gotchas. Basically lock.try_acquire is pure when it
> returns false, and if not, the program is terminated anyways so
> it doesn't make a difference.

So an annotation like the proposed @noreturn (similar to GCC function annotation, and useful for functions that do not return, so they can be used where you use assert(0) and the like) is not enough to solve this problem.

Bye,
bearophile
February 03, 2014
If someone implements this test, we could see how many problems it causes in Phobos (and eventually in the D front-end) and perhaps even see if it finds some problem.

Bye,
bearophile
February 04, 2014
On Monday, 3 February 2014 at 14:57:19 UTC, bearophile wrote:
> 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

Aren't these things you might do inside a unittest?
February 04, 2014
Jesse Phillips:

> Aren't these things you might do inside a unittest?

Mutating state and calling impure functions is OK in an unittest. So this code is OK:


int foo(ref int y) pure nothrow {
    return y++;
}
unittest {
    int x;
    ++x;
    assert(x);
    foo(x);
    assert(x);
}


Bye,
bearophile
February 04, 2014
An example of the problem?

http://forum.dlang.org/thread/52EFE127.8070504@yahoo.com?page=2#post-xodootdnxopfyeqmhnjb:40forum.dlang.org

Bye,
bearophile
February 04, 2014
Am Tue, 04 Feb 2014 14:25:14 +0000
schrieb "bearophile" <bearophileHUGS@lycos.com>:

> An example of the problem?
> 
> http://forum.dlang.org/thread/52EFE127.8070504@yahoo.com?page=2#post-xodootdnxopfyeqmhnjb:40forum.dlang.org
> 
> Bye,
> bearophile

Yes, this is definitely why asserts should not have side effects when they succeed. I think maybe the earlier try_lock example could be written more cleanly as:

  assert(lock.is_locked);

Still this requires is_locked to be "strongly pure", which cannot be expressed explicitly in D. (Otherwise it could change the implicit this and cause a side-effect.)

-- 
Marco

February 04, 2014
Marco Leise:

> Yes, this is definitely why asserts should not have side
> effects when they succeed.

Can't you define a impureAssert() in Phobos and use it for the few cases when you need it, and use a pure-only assert() for all other cases?

Bye,
bearophile
February 05, 2014
Am Tue, 04 Feb 2014 22:38:43 +0000
schrieb "bearophile" <bearophileHUGS@lycos.com>:

> Marco Leise:
> 
> > Yes, this is definitely why asserts should not have side effects when they succeed.
> 
> Can't you define a impureAssert() in Phobos and use it for the few cases when you need it, and use a pure-only assert() for all other cases?
> 
> Bye,
> bearophile

What would happen to them in release compiles?

-- 
Marco

February 05, 2014
Marco Leise:

> What would happen to them in release compiles?

Perhaps their body that calls the lazy argument should be wrapped in version(assert) {} else {...}.

Bye,
bearophile