DIP 1006 - Preliminary Review Round 1

Timon Gehr timon.gehr at gmx.ch
Mon Mar 5 15:48:12 UTC 2018


On 05.03.2018 11:25, Walter Bright wrote:
> On 3/4/2018 3:06 PM, Timon Gehr wrote:
>> On 04.03.2018 22:49, Walter Bright wrote:
>>>> Not necessarily. If the code contains an explicit assertion that the 
>>>> index is in bounds, then, according to the language specification, 
>>>> the bounds check may be removed with -release.
>>>
>>> D, as all languages that I know of do implicitly or explicitly, 
>>> generates code based on the "as if" rule.
>>> ...
>>
>> Impossible. You wrote a Java compiler.
> 
> Even in Java, the compiler generates code that, from the user's point of 
> view, behaves "as if" the code was actually what was specified. For a 
> trivial example, replacing x*2 with x<<1. Not having this means no 
> optimizations can be done.
> ...

I guess I misunderstood what you meant when you said "as if". I thought 
you meant that for all languages you know, when assertions are disabled, 
the compiler behaves "as if" the check was actually there and was known 
to succeed, even though the check is actually not there and may have 
failed if it was.

> 
>> All languages that use your "as if" rule are memory unsafe.
>> Zero languages that use the "as if" rule have any memory safe subset 
>> that includes assertions.
>> In D, assert is @safe, and it should remain @safe.
> 
>>>> I find the reasoning in terms of "on"/"off" confusing anyway.
>>>> Does "off" mean "contract/assertion removed", or does it mean 
>>>> "failure is UB"?
>>>
>>> "Off" means the check is removed. If the check does not hold, the 
>>> program enters an invalid state, whether or not the check was 
>>> actually done. An invalid state means subsequent execution is UB.
>>
>> Why is potential memory corruption to be expected when using @safe 
>> language features with a flag to disable contract checks?
> 
> Because the checks provide extra information to the compiler that it can 
> use to generate better code. If that extra information is not true, then 
> the better code will be invalid.
> ...

My question is not why it is the case technically, I was asking for a 
_rationale_ for this apparently silly behavior. I.e., why is this a good 
idea from the point of view of language design?

Again: assert is @safe. Compiler hints are @system. Why should assert 
give compiler hints?

> Memory safety is only one class of errors in a program. If the program 
> has entered a state that is not accounted for by the programmer, the 
> rest of the program's execution will be not predictable.
> ...

But the whole point of having memory safety is to not have UB when the 
programmer screwed up. Behavior not foreseen by the programmer (a bug) 
is not the same as behavior unconstrained by the language specification 
(UB).

> 
>> This makes no sense. This is not useful behavior. There are convenient 
>> ways to support potentially unsound compilation hints that do not do 
>> this. Contracts and compilation hints should be orthogonal. Contracts 
>> should be potentially @safe, compilation hints should be @system always.
>>
>> Note that _actual removal_ is the only use case of 'disabling 
>> contracts' that I care about, and I think many D programmers who use 
>> "off" will also have this behavior in mind. Yet this is not even an 
>> option.
> 
> I don't see much use for this behavior, unless you want to continue 
> running the program after an assert failure, which I cannot recommend 
> and the language is not designed to support.

'in'-contracts catch AssertError when being composed. How can the 
language not be designed to support that?

Except for this case, the assertion is not _supposed_ to fail for my use 
cases, and I don't really need the language to explicitly "support that 
use case". The situation is the following:

- I usually don't want UB in programs I am working on. I want the 
runtime behavior of the programs to be determined by the source code, 
such that every behavior observed in the wild (intended or unintended) 
can be traced back to the source code (potentially in a 
non-deterministic way, e.g. void initialization of an integer constant). 
This should be the case always, even if me or someone else on my team 
made a mistake. The @safe D subset is supposed to give this guarantee. 
What good is @safe if it does not guarantee absence of buffer overrun 
attacks?

- Checking assertions can be too costly, so it should be possible to 
disable the check.

- Using existing assertions as compiler hints is not necessary. (Without 
having checked it, I'm sure that LDC/GDC have a more suitable intrinsic 
for this already.)

As far as I can discern, forcing disabled asserts to give compiler hints 
has no upsides.

> But you can always do 
> something like:
> 
>     version (ignore_asserts) { } else { assert(...); }
> ...

I know. Actually version(assert) assert(...); also works. However, this 
is too verbose, especially in contracts. I'd like a solution that does 
not require me to change the source code. Ideally, I just want the Java 
behavior (with reversed defaults).

> which would optionally remove both the runtime check and any compiler 
> use of the assert. Or you could use 
> https://dlang.org/library/std/exception/enforce.html which has no 
> influence on compiler semantics.
> ...

(enforce is _completely unrelated_ to the current discussion.)

Contracts are designed to be used with built-in assert. Built-in assert 
is convenient.

If the point of 'assert' is to give compiler hints (for me this is not 
even a use case of assert at all), then it should be @system.

> 
>> At the very least, the DIP should be up-front about this.
>> I'm still not even sure that Mathias Lang intended the UB semantics.
> 
> It being UB was my doing, not Mathias'. DIP1006 is not redefining the 
> semantics of what assert does.

This is not really about assert semantics, this is about the semantics 
of "disabling the check". There was no "-check=off" flag before.

The DIP uses terminology such as "disable assertions" as opposed to 
"disable assertion checks (but introduce compiler hints)".

Contracts are supposed to increase safety, not to reduce it (ask 
Bertrand Meyer).



More information about the Digitalmars-d mailing list