On 11/2/2014 8:54 PM, Sean Kelly wrote:
On Monday, 3 November 2014 at 03:29:05 UTC, Walter Bright wrote:
I got into the habit of layering in asserts to stop the program when it went
bad. "Do not pass go, do not collect $200" is the only strategy that has a
hope of working under such systems.
The tough thing is that in D, contracts serve as this early warning system, but
the errors this system catches are also sometimes benign

If it is benign is not known until it is debugged by a human.

and sometimes the
programmer knows that they're benign, but if the person writing the test did so
with an assert then the decision of how to respond to the error has been made
for him.

The person who wrote "assert" decided that it was a non-recoverable programming bug. I deliberately wrote "bug", and not "error".


It is my duty to explain how to use the features of the language correctly,
including how and why they work the way they do. The how, why, and best
practices are not part of a language specification.
I don't entirely agree.  The standard library serves as the how and how and best
practices for a language, and while a programmer can go against this, it's often
like swimming upstream.  For better or worse, we need to establish how
parameters are validated and such in Phobos, and this will serve as the template
for nearly all code written in D.

Definitely Phobos should exhibit best practices. Whether bad function argument values are input/environmental errors or bugs is decidable only on a case-by-case basis. There is no overarching rule.

Input/environmental errors must not use assert to detect them.


To be fair, assert currently does unwinding.  It always has.  The proposal is
that it should not.

Not entirely - a function with only asserts in it is considered "nothrow" and callers may not have exception handlers for them.


The reason I initiated this thread is to point out the correct way to use
assert() and to get that into the culture of best practices for D. This is
because if I don't, then in the vacuum people will tend to fill that vacuum
with misunderstandings and misuse.

It is an extremely important topic.

I still feel like there's something really important here that we're all
grasping at but it hasn't quite come to the fore yet. Along the lines of the
idea that a @safe program may be able to recover from a logic error.  It seems
like a uniquely D thing insofar as systems languages are concerned.

It's a false hope. D cannot offer any guarantees of recovery from programming bugs. Asserts, by definition, can never happen. So when they do, something is broken. Broken programs are not recoverable because one cannot know why they broke until they are debugged. As I mentioned to Dicebot, @safe only applies to the function's logic. D programs can call C functions. C functions are not safe. There can be compiler bugs. There can be other threads corrupting memory. There can be hardware failures, operating system bugs, etc., that resulting in tripping the assert.

If a programmer "knows" a bug is benign and wants to recover from it, D has a mechanism for it - enforce(). I do not understand the desire to bash assert() into behaving like enforce(). Just use enforce() in the first place.

The idea was brought up that one may be using a library that uses assert() to detect input/environmental errors. I do not understand using a library in a system that must be made robust, having the source code to the library, and not being allowed to change that source code to fix bugs in it. A robust application cannot be made using such a library - assert() misuse will not be the only problem with it.


If the operating system can't handle resource recovery for a process
terminating, it is an unusable operating system.
There are all kinds of resources, and not all of them are local to the system.
Everything will eventually recover though, it just won't happen immediately as
is the case with resource cleanup within a process.

I'd say that is a poor design for an operating system. Be that as it may, if you want to recover from assert()s, use enforce() instead.


There are other consequences from trying to make assert() recoverable:

1. functions with assert()s cannot be "nothrow"
2. assert()s cannot provide hints to the optimizer

Those are high prices to pay for a systems performance language.

Reply via email to