Thread overview
Feature request: empty behavior on assert failure
May 11, 2022
Dukc
May 11, 2022
rikki cattermole
May 11, 2022
Dukc
May 11, 2022
max haughton
May 11, 2022
Dukc
May 11, 2022
Tejas
May 11, 2022

I think we're lacking a good option for assert failure behaviour for released code. Basically, we have two options.

One, crashing on assert failure. This may be a performance problem. It is customary for D code to assume the assertions will be removed on released code, and thus they are often used with little regard for performance.

Two, undefined behaviour. Of course, if an assert has gone boom it's not good news no matter what we do. The problem with undefined behaviour is that it defeats the purpose of leaving bounds checks in released code:

@safe pure int fun(int[] arg)
{ import std.algorithm, std.range;
  assert(arg.length >= 10);
  // Cannot go out of bounds without violating the assertion above.
  // Array bounds check may be skipped.
  return arg.takeExactly(10).sum;
}

IMO we need an option for the compiler to delete the assertions, without being allowed to assume the assertion holds. The compiler would still be free to crash on assertion failure, if it deems that better for performance, but it could not trigger undefined behaviour. In other words, the compiler would treat assert(x) the same as:

if(!x)
{ int v = void;
  if(v > 0) assert(false);
}

I also think this option should be the default, unless -boundscheck=off.

May 11, 2022
In case you don't about this flag:

 -checkaction=[D|C|halt|context]
                    behavior on assert/boundscheck/finalswitch failure

Behavior on assert/boundscheck/finalswitch failure:
  =[h|help|?]    List information on all available choices
  =D             Usual D behavior of throwing an AssertError
  =C             Call the C runtime library assert failure function
  =halt          Halt the program execution (very lightweight)
  =context       Use D assert with context information (when available)
May 11, 2022
On Wednesday, 11 May 2022 at 09:31:42 UTC, rikki cattermole wrote:
> In case you don't about this flag:
>
>  -checkaction=[D|C|halt|context]
>                     behavior on assert/boundscheck/finalswitch failure
>
> Behavior on assert/boundscheck/finalswitch failure:
>   =[h|help|?]    List information on all available choices
>   =D             Usual D behavior of throwing an AssertError
>   =C             Call the C runtime library assert failure function
>   =halt          Halt the program execution (very lightweight)
>   =context       Use D assert with context information (when available)

I do. It lets one to choose between different ways to crash the program on assertion failure. It does not let to continue with defined behaviour.
May 11, 2022

On Wednesday, 11 May 2022 at 09:26:43 UTC, Dukc wrote:

>

I think we're lacking a good option for assert failure behaviour for released code. Basically, we have two options.

One, crashing on assert failure. This may be a performance problem. It is customary for D code to assume the assertions will be removed on released code, and thus they are often used with little regard for performance.

Two, undefined behaviour. Of course, if an assert has gone boom it's not good news no matter what we do. The problem with undefined behaviour is that it defeats the purpose of leaving bounds checks in released code:

@safe pure int fun(int[] arg)
{ import std.algorithm, std.range;
  assert(arg.length >= 10);
  // Cannot go out of bounds without violating the assertion above.
  // Array bounds check may be skipped.
  return arg.takeExactly(10).sum;
}

IMO we need an option for the compiler to delete the assertions, without being allowed to assume the assertion holds. The compiler would still be free to crash on assertion failure, if it deems that better for performance, but it could not trigger undefined behaviour. In other words, the compiler would treat assert(x) the same as:

if(!x)
{ int v = void;
  if(v > 0) assert(false);
}

I also think this option should be the default, unless -boundscheck=off.

https://d.godbolt.org/z/ax4v5v9j3

If the assertions are turned off via release the assertions are completely gone, the optimizer doesn't know about them.

I'd also like to note that anthropomorphizing compilers can be foolish, the "compiler" doesn't consciously do any undefined behaviour wrangling with D as per se because the backend/s don't really know anything about D.

May 11, 2022

On Wednesday, 11 May 2022 at 09:47:32 UTC, max haughton wrote:

>

If the assertions are turned off via release the assertions are completely gone, the optimizer doesn't know about them.

Great! Only a spec change needed then.

>

I'd also like to note that anthropomorphizing compilers can be foolish,

What's anthropomorphising?

>

the "compiler" doesn't consciously do any undefined
behaviour wrangling with D as per se because the backend/s don't really know anything about D.

With the present spec there's no guarantee this will remain the case though: https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic .

May 11, 2022

On Wednesday, 11 May 2022 at 10:12:16 UTC, Dukc wrote:

>

On Wednesday, 11 May 2022 at 09:47:32 UTC, max haughton wrote:

>

If the assertions are turned off via release the assertions are completely gone, the optimizer doesn't know about them.

Great! Only a spec change needed then.

>

I'd also like to note that anthropomorphizing compilers can be foolish,

What's anthropomorphising?

>

the "compiler" doesn't consciously do any undefined
behaviour wrangling with D as per se because the backend/s don't really know anything about D.

With the present spec there's no guarantee this will remain the case though: https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic .

source : https://en.wikipedia.org/wiki/Anthropomorphism

>

Anthropomorphism is the attribution of human traits, emotions, or intentions to non-human entities.