July 31, 2014
On 7/31/14, 4:54 PM, H. S. Teoh via Digitalmars-d wrote:
> 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
>

That's exactly my point, thank you for summing that up :-)

I don't see the point of having a "-release" flag. It should be renamed to "-a-bit-faster-but-unsafe".

I think there are other languages that do quite well in terms of performance without disabling bounds checks and other stuff.
July 31, 2014
On Thursday, 31 July 2014 at 19:03:14 UTC, Walter Bright wrote:
> On 7/31/2014 3:24 AM, ponce wrote:
>> On Thursday, 31 July 2014 at 09:13:53 UTC, Walter Bright wrote:
>>> It says more than that:
>>>
>>> "The expression assert(0) is a special case; it signifies that it is
>>> unreachable code. Either AssertError is thrown at runtime if it is reachable,
>>> or the execution is halted (on the x86 processor, a HLT instruction can be
>>> used to halt execution). The optimization and code generation phases of
>>> compilation may assume that it is unreachable code."
>>>
>>>  -- http://dlang.org/expression.html#AssertExpression
>>
>> You said "the compiler won't remove it".
>
> Right, and it doesn't.

This is in direct contradiction to the quoted spec excerpt. If the backend can assume that something is unreachable code, why on earth should it need to actually emit that code? A small example:

---
void foo(int a) {
   if (a == 42) assert(0);
   // Do something else.
}
---

If the compiler is free to assume that the assert is unreachable, please explain to me what stops it from inferring that the branch is never taken and transforming the example to the equivalent of:

---
void foo(int a) {
   // Do something else.
}
---

LDC would do this today if we implemented the regarding assuming unreachability (we currently emit a halt – actually a ud2 trap on x86 – instead).

I've had the questionable pleasure of tracking down a couple of related issues in LLVM and the LDC codegen, so please take my word for it: Requiring any particular behavior such as halting in a case that can be assumed to be unreachable is at odds with how the term "unreachable" is used in the wild – at least in projects like GCC and LLVM.

Cheers,
David
July 31, 2014
On Thu, Jul 31, 2014 at 05:17:13PM -0300, Ary Borenszweig via Digitalmars-d wrote:
> On 7/31/14, 4:54 PM, H. S. Teoh via Digitalmars-d wrote:
[...]
> >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
> >
> 
> That's exactly my point, thank you for summing that up :-)
> 
> I don't see the point of having a "-release" flag. It should be renamed to "-a-bit-faster-but-unsafe".

It's probably named -release because traditionally, turning off asserts and bounds checks is what is normally done when building a C/C++ project for release. (C/C++ don't have built-in bounds checks, but I've seen projects that use macros for manually implementing this, which are #define'd away when building for release.)


> I think there are other languages that do quite well in terms of performance without disabling bounds checks and other stuff.

It depends on what you're doing. If you have assert's in CPU intensive inner loops, turning them off can make a big difference in performance.


T

-- 
Almost all proofs have bugs, but almost all theorems are true. -- Paul Pedersen
July 31, 2014
On Thursday, 31 July 2014 at 19:54:47 UTC, Jonathan M Davis wrote:
> 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 […]

Well, no, as the portion of the spec Walter quoted specifically states that the compiler can *assume* the assert(0) to be unreachable. If you can assume something, you don't have to prove it any longer for any sane definition of "assume".

If this is not something we want, we need to fix the spec instead of trying to argue around the problem.

David
July 31, 2014
On 07/31/2014 09:37 PM, Jonathan M Davis wrote:
> 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,

No, according to the OP -release assumes assertions to be true.

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

Unfortunately, if used pervasively, assertions and contracts and whatnot may actually hog the speed of a program in a way that breaks the deal.

Disabling assertions (and whatnot), assuming assertions to be true (and disabling whatnot) and leaving all assertions and whatnot in are different trade-offs, of which assuming all assertions to be true is the most dangerous one. Why hide this behaviour in '-release'?

> just don't use -release and use -boundscheck=safe to get the bounds
> checking changes that -release does.
>
> - Jonathan M Davis

This leaves assertions and contracts in though.

July 31, 2014
On Wednesday, 30 July 2014 at 22:01:23 UTC, Walter Bright wrote:
>
> 3. Use of assert to validate input is utterly wrong and will not be supported. Use such constructs at your own risk.
...
> 6. enforce() is meant to check for input errors (environmental errors are considered input).
>
> 7. using enforce() to check for program bugs is utterly wrong. enforce() is a library creation, the core language does not recognize it.

Could you expand on what you consider input?  For example, if a
function has an "in" contract that validates input parameters, is
the determination that a parameter is invalid a program bug or
simply invalid input?  If you consider this invalid input that
should be checked by enforce(), can you explain why?
July 31, 2014
On 07/31/2014 10:33 PM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Jul 31, 2014 at 05:17:13PM -0300, Ary Borenszweig via Digitalmars-d wrote:
>> >On 7/31/14, 4:54 PM, H. S. Teoh via Digitalmars-d wrote:
> [...]
>>> > >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
>>> > >
>> >
>> >That's exactly my point, thank you for summing that up:-)
>> >
>> >I don't see the point of having a "-release" flag. It should be
>> >renamed to "-a-bit-faster-but-unsafe".
> It's probably named -release because traditionally, turning off asserts
> and bounds checks is what is normally done when building a C/C++ project
> for release. (C/C++ don't have built-in bounds checks, but I've seen
> projects that use macros for manually implementing this, which are
> #define'd away when building for release.)
>
>

The suggestion is not: 'make -release disable assertions.' it is 'failing assertions are undefined behaviour in -release'.
July 31, 2014
On Thursday, 31 July 2014 at 20:52:30 UTC, Sean Kelly wrote:
> On Wednesday, 30 July 2014 at 22:01:23 UTC, Walter Bright wrote:
>>
>> 3. Use of assert to validate input is utterly wrong and will not be supported. Use such constructs at your own risk.
> ...
>> 6. enforce() is meant to check for input errors (environmental errors are considered input).
>>
>> 7. using enforce() to check for program bugs is utterly wrong. enforce() is a library creation, the core language does not recognize it.
>
> Could you expand on what you consider input?  For example, if a
> function has an "in" contract that validates input parameters, is
> the determination that a parameter is invalid a program bug or
> simply invalid input?  If you consider this invalid input that
> should be checked by enforce(), can you explain why?

This also puzzles me. There is the point where the two types of errors blend to the point of being uncomfortable.

Eg: a program generates files in X format and can also read them with a X parser. Its X parser will only ever read output generated by itself. Should input errors in X parser be checked with assert or exceptions?
July 31, 2014
On 07/31/2014 09:54 PM, Jonathan M Davis wrote:
> 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.

Indeed. Now note that the compiler is arguing from the same standpoint that you were just now.

> The compiler would have to be
> able to prove that reaching the HALT instruction was impossible in order
> to remove it

The compiler is able to prove this immediately. The goal it needs to prove ('control flow does not reach assert(0)') is an assumption made by Walter and the language specification and readily available.

Note that I'd be happier with the state of affairs if you were right about this.
July 31, 2014
On 7/31/2014 1:52 PM, Sean Kelly wrote:
> Could you expand on what you consider input?

All state processed by the program that comes from outside the program. That would include:

1. user input
2. the file system
3. uninitialized memory
4. interprocess shared memory
5. anything received from system APIs, device drivers, and DLLs that are not part of the program
6. resource availability and exhaustion


> For example, if a
> function has an "in" contract that validates input parameters, is
> the determination that a parameter is invalid a program bug or
> simply invalid input?

An "in" contract failure is a program bug. Contracts are ASSERTIONS ABOUT THE CORRECTNESS OF THE PROGRAM LOGIC. They are not assertions about the program's input.

> If you consider this invalid input that
> should be checked by enforce(), can you explain why?

This says it better than I can:

http://en.wikipedia.org/wiki/Design_by_contract