August 02, 2014
On 08/02/2014 09:01 PM, Walter Bright wrote:
>
> I think at this point it is quite clear that D's assert is about the
> programmer saying this expression evaluates to true or it's a
> programming bug.

That was already obvious to most before the discussion started.

In any case, the way you'd need to put it in order to make a meaningful statement is e.g. that such failures abort the program in non-release and lead to undefined behaviour in release. Just state the plain semantics.

This behaviour is 'right' by definition, but is not backed up by any deeper reason or close-to-universally convincing design rationale. Please let it go.

>
>
> If other languages use assert to mean "the compiler must prove this to be true"
> then that's fine for those languages,

Thanks for finally admitting a point like this.

> but it isn't what D's assert is, or can ever be.

It is enough if what D's assert is and has been so far does not change. Not using asserts as sources of undefined behaviour when using the switch that has traditionally been used to disable them would already be sufficient. Why do you think there should be no compromise giving all the parties what they want?
August 02, 2014
Am Sat, 02 Aug 2014 12:19:41 -0700
schrieb Walter Bright <newshound2@digitalmars.com>:

> On 8/2/2014 6:20 AM, Artur Skawina via Digitalmars-d wrote:
> > The bug was _introduced_ by the assert, the code was 100% correct.
> 
> Asserts are part of the code, and writing incorrect asserts is writing buggy code.
> 

Just some meta points:

I just want to point out that nobody wants to hear 'your code was buggy anyway' after a compiler update broke working code. A few months ago you and Andrei were talking about PR and you often said that D is now 'stable' and 'ready for production'. But we still hear claims on reddit and other sites that D is unstable, breaks code with every release, etc.

And you still think that changing the behavior of assert is a good idea? Even if assert was always meant to work like this, even if the spec clearly defined it this will be a PR disaster. People don't care what was in the spec, the only thing they know is the code worked before, now it doesn't work anymore ==> blame it on the compiler/language.

Just envision the situation when somebody post on reddit 'My code has
been broken by this compiler release' then spents quite some
time to track it down and complains about the assert changes? Will you
then reply 'You're code was broken anyway'?

What about Scott Meyers basically telling us that we should make the language 'predictable' for the users? Doesn't the existence and size of this discussion already prove that making assert work like assume will be unexpected for many people? You even admitted that in other languages assert has a different meaning. You argued against the name 'volatile' cause it has a different meaning in other languages. How does this not apply to assert/assume? You might ask for Scotts opinion about this case if you don't believe the people in this thread.

Does anybody have some numbers about the (best case) performance benefits? Do such performance benefits only manifest if we place assume everywhere or do we have 'hot' code paths? If we have 'hot' code paths, adding 'assume' is easy to do. If we have to place assume everywhere then this is an argument for reusing assert. Making such a decision without any numbers, based only gut feeling is not a good idea.


(Also regarding DIP65 and other issues with inconsistencies in the
language it's amazing how we absolutely can't break code there, but in
this case it's OK, because the code was already broken anyway. You
could probably construct such an argument for every breaking change and
this makes breaking changes unpredictable and will reinforce the
image of D as an unstable language)
August 02, 2014
On 08/02/14 21:19, Walter Bright via Digitalmars-d wrote:
> On 8/2/2014 6:20 AM, Artur Skawina via Digitalmars-d wrote:
>> The bug was _introduced_ by the assert, the code was 100% correct.
> 
> Asserts are part of the code, and writing incorrect asserts is writing buggy code.

This was about incorrect asserts from one part of the program infecting other (correct) parts. Nobody is saying that such a program isn't buggy. Most, if not all, programs have bugs. Your assert (re-)definition makes the assert /assumptions/, which are unchecked in release builds, _override_ other explicit checks. A wrong assert is not necessarily less likely than wrong code.

There's nothing wrong with `assume`, it's very useful for optimizations. But it's too dangerous to tack `assume` onto `assert`. If they are kept separate then it's at least possible to carefully audit every 'assume'. People *will* use them for micro-optimizations, and they *will* make mistakes.

artur
August 02, 2014
On 8/2/14, 11:55 AM, Walter Bright wrote:
> On 8/2/2014 8:08 AM, Andrei Alexandrescu wrote:
>> On 8/2/14, 5:44 AM, Artur Skawina via Digitalmars-d wrote:
>>>    auto fx(ubyte* p, size_t len) @safe {
>>>        assert_(len>0);
>>>        if (len>=1)
>>>           return p[0];
>>>        return -1;
>>>     }
>>
>> As an aside I think it's a bug that this function passes @safe. It
>> should not be
>> able to safely dereference the pointer because it may be e.g. just
>> past the end
>> of the array. Has this been submitted as a bug? -- Andrei
>>
>
> There's more than one way to think about it. We could disable all
> pointer dereferences, but another way is to fall back on the presumption
> that arguments to @safe functions must themselves be valid.
>
> I.e. is this @safe:
>
>     &array[length]
>
> ? How could a pointer past the end be created in @safe code?

The way I see it, if we allow pointer dereference in @safe code, we must make sure that @safe code can never produce a past-the-end pointer.

Assume we choose that, there's still murky ground:

@system fun(int[] p) {
   gun(p.ptr + p.length);
}

@safe gun(int* p) {
   if (p) *p = 42;
}

This passes semantic checking but is unsafe and unsafety is in the @safe code. Well, that's fine, we might say. The problem is this works against our stance that "inspect @system code by hand, @safe code will take care of itself". The problem is that pointers just past the end have this weird property "the pointer is okay but not for dereferencing".


Andrei

August 02, 2014
On 8/2/14, 1:02 PM, Johannes Pfau wrote:
> I just want to point out that nobody wants to hear 'your code was buggy
> anyway' after a compiler update broke working code.

Hmmm... code that fails assertions is hardly working. -- Andrei
August 02, 2014
On Saturday, 2 August 2014 at 20:27:09 UTC, Andrei Alexandrescu wrote:
> Hmmm... code that fails assertions is hardly working. -- Andrei

It is not the code that fails the assertion, it is the asserted proposition that has not be satisfied by the axioms in the program as it has been formulated in the context. It does not mean "can not be satisfied", but "has not been satisfied".

The proposition and the code can be correct and still fail to satisfy the proposition, if the axioms provided are insufficient. Such as missing type info, deficiencies in the runtime, bugs in the compiler, conditions in the environment++.

People who care a lot about correctness, that is, the guys that do embedded system programming, have sane alternatives. Such as compilers formally proven to follow the language spec of C:

http://compcert.inria.fr/

No D compiler is verified, thus it is a probable source for missing or wrong axioms. Which in itself is a good reason to not turn asserts into assumes. IF you need another one.


By turning programming by contract upside-down D basically kills itself as a system programming language. The term "design by contract" has implications. Turning the postconditions into axioms is not one of them. Quite the opposite. I betcha a mean lawyer would describe a compiler doing that with the phrase "malicious intent"… and no copyright license can protect you from that.


Telling people who want a system level programming language that they should ship debug builds because release mode is dangerous and has a high risk of violating the code if the annotations cannot be met, for the sake of doing better local optimization with a shitty  backend isn't particularly encouraging. If I wasn't looking for a system level programming language I'd think it hilarious. But I don't. I think it is sad that the threshold for taking advice is so high.

No sane person can claim D is aiming to be a safer language than C++ after this debate.
August 02, 2014
On Saturday, 2 August 2014 at 21:25:40 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 2 August 2014 at 20:27:09 UTC, Andrei Alexandrescu wrote:
>> Hmmm... code that fails assertions is hardly working. -- Andrei
>
> It is not the code that fails the assertion, it is the asserted proposition that has not be satisfied by the axioms in the program as it has been formulated in the context. It does not mean "can not be satisfied", but "has not been satisfied".

Don't you agree, that a program that throws AssertError in non -release* build is broken?

* this is not the opposite of debug
August 02, 2014
On Saturday, 2 August 2014 at 21:36:11 UTC, Tobias Pankrath wrote:
> On Saturday, 2 August 2014 at 21:25:40 UTC, Ola Fosheim Grøstad wrote:
>> On Saturday, 2 August 2014 at 20:27:09 UTC, Andrei Alexandrescu wrote:
>>> Hmmm... code that fails assertions is hardly working. -- Andrei
>>
>> It is not the code that fails the assertion, it is the asserted proposition that has not be satisfied by the axioms in the program as it has been formulated in the context. It does not mean "can not be satisfied", but "has not been satisfied".
>
> Don't you agree, that a program that throws AssertError in non -release* build is broken?
>
> * this is not the opposite of debug

By this definition of 'broken', I assert that most shipped software is broken.
August 02, 2014
Am 02.08.2014 22:02, schrieb Johannes Pfau:
> Am Sat, 02 Aug 2014 12:19:41 -0700
> schrieb Walter Bright <newshound2@digitalmars.com>:
>
>> On 8/2/2014 6:20 AM, Artur Skawina via Digitalmars-d wrote:
>>> The bug was _introduced_ by the assert, the code was 100% correct.
>>
>> Asserts are part of the code, and writing incorrect asserts is
>> writing buggy code.
>>
>
> Just some meta points:
>
> I just want to point out that nobody wants to hear 'your code was buggy
> anyway' after a compiler update broke working code. A few months ago
> you and Andrei were talking about PR and you often said that D is now
> 'stable' and 'ready for production'. But we still hear claims on reddit
> and other sites that D is unstable, breaks code with every release, etc.
>
> And you still think that changing the behavior of assert is a good
> idea? Even if assert was always meant to work like this, even if the
> spec clearly defined it this will be a PR disaster. People don't care
> what was in the spec, the only thing they know is the code worked

And it's not even in the spec, at least not explicitly (maybe it's now, but it hasn't been a few  days ago).

Cheers
Daniel
August 02, 2014
On Saturday, 2 August 2014 at 20:23:53 UTC, Andrei Alexandrescu wrote:
> @system fun(int[] p) {
>    gun(p.ptr + p.length);
> }
>
> @safe gun(int* p) {
>    if (p) *p = 42;
> }
>
> This passes semantic checking but is unsafe and unsafety is in the @safe code. Well, that's fine, we might say. The problem is this works against our stance that "inspect @system code by hand, @safe code will take care of itself".

No! Calling gun like this is just the same as calling "gun(cast(int*)0xdeadbeef)". You wouldn't argue that the @safe code is at fault there either. Or when passing an array slice with an invalid .ptr to a @safe function. It's not like you would routinely pass p.ptr + p.length to _any_ function with a single pointer argument (except maybe for a setter for the end of an iterator pair or something like that).

Yes, p.ptr + p.length is merely invalid invalid to dereference, as opposed to being completely undefined behavior by itself (assuming C rules). But I don't see how this changes anything about the fact that fun() invokes a function with invalid parameters (@safe or not).

Cheers,
David