July 31, 2014
On 07/31/14 20:14, Daniel Murphy via Digitalmars-d wrote:
> "Tofu Ninja"  wrote in message news:mhhtxjlrvtqhzztxidbe@forum.dlang.org...
> 
>> With that logic(and the proposed optimizations that this whole thing is about), weird stuff like this happens...
>>
>> void foo(int x)
>> {
>>      if(x != 0) throw ...;
>>      assert(x == 0);
>> }
>>
>> The if check could be removed because assert will be assumed to always be true in release... so x could never not equal 0.... the assert just nuked my scrubbing logic...
> 
> The if can't be removed - and it's fairly easy to see why.  In the control flow path that contains the assert, the compiler is _already_ sure that x == 0.  The assert adds no new information.

As long as the assert is 100% correct. If you have a hundred+ asserts
and a 1% error rate...
A wrong assert could (under the proposed model) propagate the wrong
assumptions both ways. Silently disabling other checks that would
have otherwise caught the error.

Imagine creating a hotfix for some newly discovered bug, and forgetting to update an assert expression somewhere. Unless the problem is triggered while testing a non-release build, you may end up shipping a broken product, even one with bugs that were not present in the original. Now imagine that somebody else will handle the next report. He/she will look at the code, see absolutely no problems with it, all necessary checks will be there... Figuring out that a) an assert is the cause, and b) which one it is, will be a very interesting process...


> The corner case is "assert(0)".  It means "if the program got to here, the impossible has happened."

It's vaguely defined, overloaded, and not currently treated that way. Arguably it could mean 'this path won't ever be reached, trust me', but redefining it now is obviously not possible. (doing this would of course make assert(0) extremely dangerous)

artur
July 31, 2014
On Thu, Jul 31, 2014 at 03:43:48PM -0300, Ary Borenszweig via Digitalmars-d wrote:
> On 7/31/14, 4:37 AM, Walter Bright wrote:
> >On 7/30/2014 4:05 PM, Ary Borenszweig wrote:
> >>On 7/30/14, 7:01 PM, Walter Bright wrote:
> >>>I'd like to sum up my position and intent on all this.
> >>>
> >>>7. using enforce() to check for program bugs is utterly wrong.
> >>>enforce() is a library creation, the core language does not
> >>>recognize it.
> >>
> >>What do you suggest to use to check program bugs?
> >
> >assert()
> 
> Then you are potentially releasing programs with bugs that are of undefined behavior, instead of halting the program immediately.

Isn't that already what you're doing with the current behaviour of assert? Not only in D, but also in C/C++.


T

-- 
When solving a problem, take care that you do not become part of the problem.
July 31, 2014
On Thursday, 31 July 2014 at 18:43:49 UTC, Ary Borenszweig wrote:
> On 7/31/14, 4:37 AM, Walter Bright wrote:
>> On 7/30/2014 4:05 PM, Ary Borenszweig wrote:
>>> On 7/30/14, 7:01 PM, Walter Bright wrote:
>>>> I'd like to sum up my position and intent on all this.
>>>>
>>>> 7. using enforce() to check for program bugs is utterly wrong. enforce()
>>>> is a library creation, the core language does not recognize it.
>>>
>>> What do you suggest to use to check program bugs?
>>
>> assert()
>
> Then you are potentially releasing programs with bugs that are of undefined behavior, instead of halting the program immediately.

Then don't build with -release. You can even build with -boundscheck=safe if you want to turn off bounds checking in @system code like -release does. IIRC, the only things that -release does are disable assertions, disable contracts, turn assert(0) into a halt instruction, and disable bounds checking in @system and @trusted code. So, if you want to keep the assertions and contracts and whatnot in, just don't use -release and use -boundscheck=safe to get the bounds checking changes that -release does.

- Jonathan M Davis
July 31, 2014
On 7/31/14, 4:34 PM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Jul 31, 2014 at 03:43:48PM -0300, Ary Borenszweig via Digitalmars-d wrote:
>> On 7/31/14, 4:37 AM, Walter Bright wrote:
>>> On 7/30/2014 4:05 PM, Ary Borenszweig wrote:
>>>> On 7/30/14, 7:01 PM, Walter Bright wrote:
>>>>> I'd like to sum up my position and intent on all this.
>>>>>
>>>>> 7. using enforce() to check for program bugs is utterly wrong.
>>>>> enforce() is a library creation, the core language does not
>>>>> recognize it.
>>>>
>>>> What do you suggest to use to check program bugs?
>>>
>>> assert()
>>
>> Then you are potentially releasing programs with bugs that are of
>> undefined behavior, instead of halting the program immediately.
>
> Isn't that already what you're doing with the current behaviour of
> assert? Not only in D, but also in C/C++.
>
>
> T
>

I don't program in those languages, and if I did I would always use exceptions (at least in C++). I don't want to compromise the safety of my programs and if they fail I want to get a clean backtrace, not some random undefined behaviour resulting in a segfault.
July 31, 2014
On Thursday, 31 July 2014 at 19:36:34 UTC, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Jul 31, 2014 at 03:43:48PM -0300, Ary Borenszweig via Digitalmars-d wrote:
>> On 7/31/14, 4:37 AM, Walter Bright wrote:
>> >On 7/30/2014 4:05 PM, Ary Borenszweig wrote:
>> >>On 7/30/14, 7:01 PM, Walter Bright wrote:
>> >>>I'd like to sum up my position and intent on all this.
>> >>>
>> >>>7. using enforce() to check for program bugs is utterly wrong.
>> >>>enforce() is a library creation, the core language does not
>> >>>recognize it.
>> >>
>> >>What do you suggest to use to check program bugs?
>> >
>> >assert()
>> 
>> Then you are potentially releasing programs with bugs that are of
>> undefined behavior, instead of halting the program immediately.
>
> Isn't that already what you're doing with the current behaviour of
> assert? Not only in D, but also in C/C++.

Yes, but I think that his point was that he wants a way to check programming bugs in release mode, and Walter was saying not to use enforce for checking programming bugs. So, that leaves the question of how to check them in release mode, since assertions won't work in release mode. But the answer to that is normally to not compile in release mode. And I believe that dmd gives enough control over that that you can get everything that -release does without disabling assertions using flags other than -release.

- Jonathan M Davis
July 31, 2014
On 07/31/14 19:22, John Colvin via Digitalmars-d wrote:
> On Thursday, 31 July 2014 at 15:26:27 UTC, Artur Skawina via Digitalmars-d wrote:
>> On 07/31/14 15:44, Daniel Gibson via Digitalmars-d wrote:
>>> And don't forget this (rather old) case: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8537
>>> (I really don't get why anyone would want such an optimization: I want an optimizer to use clever inlining, use SSE etc where it makes sense and stuff like that - but not to remove code I wrote.)
>>
>> That is actually not a bug, but a perfectly valid optimization. The compiler isn't clairvoyant and can not know that some data that you wrote, but never read back, matters.

> Any idea how dead store removal interacts with the modern C(++) memory model? Another thread could hold a reference to the memory being written to.

In case of local/stack and TLS objects the compiler can often prove that there are no other refs (eg because the address is never escaped).

artur
July 31, 2014
On 07/31/2014 08:58 PM, Walter Bright wrote:
> On 7/31/2014 4:28 AM, David Bregman wrote:
>> Sigh. Of course you can assume the condition after a runtime check has
>> been
>> inserted. You just showed that
>>
>> assert(x); assume(x);
>>
>> is semantically equivalent to
>> assert(x);
>>
>> as long as the runtime check is not elided. (no -release)
>
> No. I showed that you cannot have an assert without the assume.

No you did not. However:

* You showed that an additional 'assume' would not have any effect if the check is never elided.

* You showed that the state of knowledge about the program state of the optimizer are the same after processing a halting runtime check and after processing an 'assume'.

I don't think anybody is contesting that. Now try to zoom your focus out a little, and think about _what if_ the assertion and the assumption are actually wrong? Why does it make sense to conflate them in this case?

> That makes them equivalent that direction.
>
> For the other direction, adding in a runtime check for an assume is
> going to be expected of an implementation.

Yes if 'assert' does what 'assert' does now, and if 'assume' does what 'assert' does now, then 'assert' and 'assume' do the same. I agree with that, but the premise is unrelated to this discussion. You are moving the goal posts.

> And, in fact, since the
> runtime check won't change the semantics if the assume is correct, they
> are equivalent.
> ...

"If the 'assume'/'assert' are correct" is not a sound assumption to make. You are not the compiler, you are the programmer. We are discussing _about_ programs, not _within_ programs.

> I.e. for practical purposes, they are the same thing.

All assertions being correct is not a given 'for practical purposes'. You are arguing in the context of a theoretical ideal and this context alone.
July 31, 2014
On Thursday, 31 July 2014 at 19:11:55 UTC, Timon Gehr wrote:
> On 07/31/2014 09:03 PM, Walter Bright wrote:
>> It means if the control flow does actually get there, a HALT is executed.
>>
>
> And assuming control flow does not actually get there?

Then the HALT instruction is never hit. The compiler would have to be able to prove that reaching the HALT instruction was impossible in order to remove it (in which case, I would assume that it would remove it, but I wouldn't expect that to happen very often).

- Jonathan M Davis
July 31, 2014
On Thu, Jul 31, 2014 at 07:39:54PM +0000, Jonathan M Davis via Digitalmars-d wrote:
> On Thursday, 31 July 2014 at 19:36:34 UTC, H. S. Teoh via Digitalmars-d wrote:
> >On Thu, Jul 31, 2014 at 03:43:48PM -0300, Ary Borenszweig via Digitalmars-d wrote:
[...]
> >>>>What do you suggest to use to check program bugs?
> >>>
> >>>assert()
> >>
> >>Then you are potentially releasing programs with bugs that are of undefined behavior, instead of halting the program immediately.
> >
> >Isn't that already what you're doing with the current behaviour of assert? Not only in D, but also in C/C++.
> 
> Yes, but I think that his point was that he wants a way to check programming bugs in release mode, and Walter was saying not to use enforce for checking programming bugs. So, that leaves the question of how to check them in release mode, since assertions won't work in release mode. But the answer to that is normally to not compile in release mode. And I believe that dmd gives enough control over that that you can get everything that -release does without disabling assertions using flags other than -release.
[...]

Ah, I see.

But doesn't that just mean that you shouldn't use -release, period? AFAIK, the only thing -release does it to remove various safety checks, like array bounds checks, asserts, contracts (which are generally written using asserts), etc.. I'd think that Ary wouldn't want any of these disabled, so he shouldn't use -release at all. There's already -O and -inline to enable what people generally expect from a release build, so -release wouldn't really be needed at all.

Right?


T

-- 
Some ideas are so stupid that only intellectuals could believe them. -- George Orwell
July 31, 2014
On Thursday, 31 July 2014 at 19:03:14 UTC, Walter Bright wrote:
>
> It means if the control flow does actually get there, a HALT is executed.

Fine.