March 06, 2018
On Tuesday, 6 March 2018 at 18:49:42 UTC, Paolo Invernizzi wrote:
> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
>
> /Paolo

Easy:
the custom check itself could be wrong
the custom check itself is right, but the implementation is wrong even though it may passed your unit tests.
March 06, 2018
On Tuesday, March 06, 2018 18:49:42 Paolo Invernizzi via Digitalmars-d wrote:
> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
>
> If the program must HALT on this or that, well, what is better than an explicit piece of unremovable code that do that? Instead of writing 'assert', one should write 'enforce'.

1. It's quite common for folks to want to add debugging checks that are compiled out in -release. That's exactly what assert is for in pretty much every lanugage that has it. It's what folks expect to use and what your average programmer will use without thinking about @safety issues at all. It's what everyone uses right now, and I'm pretty sure that almost everyone using it has no clue that Walter considers it okay for assertions to introduce optimizations which are not memory safe, and if/when he does do so, a lot of D code will suddenly have @safe code which is not memory safe. Such problems will hopefully be hit rarely, because hopefully, the code will have been well-tested, and the assertions will have found all of the related bugs, but there's every possibility that some bugs will manage to not be caught, thereby resulting in @safe code being unsafe. No one is going to be looking to use solutions other than assertions for what assertions are for unless we start telling everyone to avoid assertions, because they make @safe code unsafe. And honestly, if assertions make @safe code unsafe, I don't see a good argument for using them at all. If I didn't care about code being @safe, I wouldn't be using @safe. @safe is supposed to guarantee that the code is memory safe.

2. I think that it's fundamentally a terrible idea to allow built-in language features to violate @safe. Aside from issues related to @trusted being misused, @safe code should be guaranteed to be memory safe, and it should be considered a bug any time that it isn't. That's why @safe exists. No one should have to be looking at @safe code to track down memory safety problems. And if they do, then @safe is not doing it's job. Array bounds checks are left in @safe code for exactly these reasons.

I'm all for introducing optimizations that do not violate @safe, but if we allow @safe code to be unsafe, then why do we even have it?

- Jonathan M Davis

March 07, 2018
On 06.03.2018 10:02, Walter Bright wrote:
> On 3/6/2018 12:45 AM, Timon Gehr wrote:
>> Anyway, "do not use assert" is not the solution, as I have explained many times now.
> 
> My interpretation is you want D assert to behave like C assert.

This interpretation is wrong. I, as well as other people, want a compiler option to make the compiler ignore D asserts and contracts. Not more, not less.

> C assert and enforce are purely creatures of the library, with semantics defined by their library implementation, and have no effect on the core language.
> ...

That's a meaningless proposition. The current D -release assert behavior can be implemented in a library (just trigger UB in the false branch).

> I recommend creating your own library assert, call it 'check' for example, and give it the semantics you wish. You can even have it expand to nothing for release builds.
> ...

Well, awesome. Now I need to make everyone on the project as well as external libraries, such as Phobos, use my 'check' function, when the contract documentation tells them to use assert and does not even hint at the downsides. No, thanks. I'd rather fork the compiler.

But I have explained this (and further reasons) already. I suspect you did not read my posts. A few others have. I'll try to keep this one shorter.

> Creating library asserts is why D has special support for __FILE__ and __LINE__ like C does, and for the same reasons.

What I want is special support for sane built-in assert semantics using a compiler flag. That does not mean that there cannot _also_ be a flag to unleash the nasal demons upon unworthy programmers who were stupid enough to collaborate with someone who imported an external library that was written by somebody who had a bad day one time and left in a wrong assertion.

Again: There is no reason why we need to force one behavior over the other. This should be configurable.
March 07, 2018
On 06.03.2018 11:17, Walter Bright wrote:
> On 3/6/2018 1:58 AM, Jonathan M Davis wrote:
>> [...]
> 
> The entire point of making assert a core language feature was so that the compiler could take advantage of it to generate better code.

It does not need to be a core language feature for that.
It seems that you did the right thing for the wrong reasons.

> It's been like that for D since day 1. It has always been documented to do that. It has been discussed many times in this n.g. over the years with loooong threads. I designed it that way so that D could potentially produce better code than other languages in ways they could not match.
> 
> There is no other purpose to making it a core language feature.
> ...

Yes. The (only!) purpose is standardization. asserts and contracts are a core language feature for similar reasons why unit tests are a core language feature.

> ...
> 
> Or just don't turn off assert checking. Personally, I use asserts in a way that they add little overhead so they can remain active in the release build.
> ...

Not everybody runs only their own code.

> It's entirely under your control.

It is not. Could we please make it that way?
March 07, 2018
On 06.03.2018 19:49, Paolo Invernizzi wrote:
> 
> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
> ...

I have explained why. UB is non-modular and you don't (want to) control all the code that you use. Also, enforce cannot be disabled. And no, keeping the check or introducing UB are not the only sensible options.
March 07, 2018
On Tuesday, 6 March 2018 at 20:03:11 UTC, Jonathan M Davis wrote:
> On Tuesday, March 06, 2018 18:49:42 Paolo Invernizzi via Digitalmars-d wrote:
>> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
>>
>> If the program must HALT on this or that, well, what is better than an explicit piece of unremovable code that do that? Instead of writing 'assert', one should write 'enforce'.
>
> 1. It's quite common for folks to want to add debugging checks that are compiled out in -release. That's exactly what assert is for in pretty much every lanugage that has it. It's what folks expect to use and what your average programmer will use without thinking about @safety issues at all. It's what everyone uses right now, and I'm pretty sure that almost everyone using it has no clue that Walter considers it okay for assertions to introduce optimizations which are not memory safe, and if/when he does do so, a lot of D code will suddenly have @safe code which is not memory safe. Such problems will hopefully be hit rarely, because hopefully, the code will have been well-tested, and the assertions will have found all of the related bugs, but there's every possibility that some bugs will manage to not be caught, thereby resulting in @safe code being unsafe. No one is going to be looking to use solutions other than assertions for what assertions are for unless we start telling everyone to avoid assertions, because they make @safe code unsafe. And honestly, if assertions make @safe code unsafe, I don't see a good argument for using them at all. If I didn't care about code being @safe, I wouldn't be using @safe. @safe is supposed to guarantee that the code is memory safe.

Understood. Are asking that UB should not include memory corruptions?

> 2. I think that it's fundamentally a terrible idea to allow built-in language features to violate @safe. Aside from issues related to @trusted being misused, @safe code should be guaranteed to be memory safe, and it should be considered a bug any time that it isn't. That's why @safe exists. No one should have to be looking at @safe code to track down memory safety problems. And if they do, then @safe is not doing it's job. Array bounds checks are left in @safe code for exactly these reasons.

So, the request is to just leave assert active as a default in @safe code, like the bounds checks?

> I'm all for introducing optimizations that do not violate @safe, but if we allow @safe code to be unsafe, then why do we even have it?

So, the reasoning is that UB should not lead to memory corruption, right?

/P

March 07, 2018
On Tuesday, 6 March 2018 at 23:50:20 UTC, Timon Gehr wrote:
> On 06.03.2018 10:02, Walter Bright wrote:
>> On 3/6/2018 12:45 AM, Timon Gehr wrote:
>>> Anyway, "do not use assert" is not the solution, as I have explained many times now.
>> 
>> My interpretation is you want D assert to behave like C assert.
>
> This interpretation is wrong. I, as well as other people, want a compiler option to make the compiler ignore D asserts and contracts. Not more, not less.

Is it an option having the compiler not to remove the asserts from @safe code, like bounds check?

Just to understand, otherwise, if the assert is removed and it does not hold, you are in UB, so the request is to guarantee memory safety in a UB state, right?

The point I don't grasp is why keep running in UB in @safe is acceptable, while memory corruption not.

>> Creating library asserts is why D has special support for __FILE__ and __LINE__ like C does, and for the same reasons.
>
> What I want is special support for sane built-in assert semantics using a compiler flag.

and that's a reasonable request, that, IMHO, does not hurts anybody....

> That does not mean that there cannot _also_ be a flag to unleash the nasal demons upon unworthy programmers who were stupid enough to collaborate with someone who imported an external library that was written by somebody who had a bad day one time and left in a wrong assertion.

That's a process management problem, I think.
Debug version of external libraries can be requested, and the author can be reported about  the bad-day wrong assert. I know, if I can catch it...

> Again: There is no reason why we need to force one behavior over the other. This should be configurable.

I'm all in for having the maximum flexibility in configuration, but I would stick with Walter as keeping its idea as the default.

/Paolo

March 07, 2018
On Wednesday, 7 March 2018 at 00:11:33 UTC, Timon Gehr wrote:
> On 06.03.2018 19:49, Paolo Invernizzi wrote:
>> 
>> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
>> ...
>
> I have explained why. UB is non-modular and you don't (want to) control all the code that you use.

As I've written, you should ask for debug versions of every closed source library that it's used in a project, it's always a win-only things to do.

> Also, enforce cannot be disabled.

Because if you use it instead of assert, the enforce has just detected a bug, so it's just doing the sane thing to join that cases: stop the execution because the process is entering UB.

> And no, keeping the check or introducing UB are not the only sensible options.

Just to understand, as I've already asked: do we aim at UB that guarantees no memory corruptions?

/Paolo


March 07, 2018
On Wednesday, March 07, 2018 08:39:30 Paolo Invernizzi via Digitalmars-d wrote:
> On Tuesday, 6 March 2018 at 20:03:11 UTC, Jonathan M Davis wrote:
> > On Tuesday, March 06, 2018 18:49:42 Paolo Invernizzi via
> >
> > Digitalmars-d wrote:
> >> I simply don't understand why enforce or a custom check can't be used @safe code, if you want that behaviour.
> >>
> >> If the program must HALT on this or that, well, what is better than an explicit piece of unremovable code that do that? Instead of writing 'assert', one should write 'enforce'.
> >
> > 1. It's quite common for folks to want to add debugging checks that are compiled out in -release. That's exactly what assert is for in pretty much every lanugage that has it. It's what folks expect to use and what your average programmer will use without thinking about @safety issues at all. It's what everyone uses right now, and I'm pretty sure that almost everyone using it has no clue that Walter considers it okay for assertions to introduce optimizations which are not memory safe, and if/when he does do so, a lot of D code will suddenly have @safe code which is not memory safe. Such problems will hopefully be hit rarely, because hopefully, the code will have been well-tested, and the assertions will have found all of the related bugs, but there's every possibility that some bugs will manage to not be caught, thereby resulting in @safe code being unsafe. No one is going to be looking to use solutions other than assertions for what assertions are for unless we start telling everyone to avoid assertions, because they make @safe code unsafe. And honestly, if assertions make @safe code unsafe, I don't see a good argument for using them at all. If I didn't care about code being @safe, I wouldn't be using @safe. @safe is supposed to guarantee that the code is memory safe.
>
> Understood. Are asking that UB should not include memory corruptions?

I'm saying that whatever optimizations are enabled by assertions should be guaranteed to not include memory corruptions.

> > 2. I think that it's fundamentally a terrible idea to allow built-in language features to violate @safe. Aside from issues related to @trusted being misused, @safe code should be guaranteed to be memory safe, and it should be considered a bug any time that it isn't. That's why @safe exists. No one should have to be looking at @safe code to track down memory safety problems. And if they do, then @safe is not doing it's job. Array bounds checks are left in @safe code for exactly these reasons.
>
> So, the request is to just leave assert active as a default in @safe code, like the bounds checks?

No. I'm saying that no optimizations should be enabled which introduce potential memory corruption. Assertions should have zero impact on whether code is @safe or not unless the code in the condition or which is generating the message for the assertion is @system, and it's no more reasonable to assume that an assertion is going to pass than it is to assume that bounds checking won't fail. Regardless, the key thing here is that @safe code should be guaranteed to be @safe so long as @trusted code is vetted properly. It should _never_ be possible for the compiler to introduce memory safety issues into @safe code.

> > I'm all for introducing optimizations that do not violate @safe, but if we allow @safe code to be unsafe, then why do we even have it?
>
> So, the reasoning is that UB should not lead to memory corruption, right?

The reasoning is that no @safe code should ever have memory corruptions in it unless it calls @trusted code that was incorrectly vetted by the programmer. The compiler is supposed to guarantee that @safe code is @safe just like it's supposed to guarantee that a const variable isn't mutated or that a pure function doesn't access mutable, global variables. And as such, introducing anything into @safe code which could be memory unsafe is a violation of the compiler's responsibility.

- Jonathan M Davis

March 07, 2018
On Wednesday, 7 March 2018 at 09:11:10 UTC, Jonathan M Davis wrote:

>> So, the request is to just leave assert active as a default in @safe code, like the bounds checks?

> No. I'm saying that no optimizations should be enabled which introduce potential memory corruption. Assertions should have zero impact on whether code is @safe or not unless the code in the condition or which is generating the message for the assertion is @system, and it's no more reasonable to assume that an assertion is going to pass than it is to assume that bounds checking won't fail. Regardless, the key thing here is that @safe code should be guaranteed to be @safe so long as @trusted code is vetted properly. It should _never_ be possible for the compiler to introduce memory safety issues into @safe code.

>> So, the reasoning is that UB should not lead to memory corruption, right?

> The reasoning is that no @safe code should ever have memory corruptions in it unless it calls @trusted code that was incorrectly vetted by the programmer. The compiler is supposed to guarantee that @safe code is @safe just like it's supposed to guarantee that a const variable isn't mutated or that a pure function doesn't access mutable, global variables. And as such, introducing anything into @safe code which could be memory unsafe is a violation of the compiler's responsibility.

Jonathan, I understand your reasoning, but it's not what I'm asking: are we asking for UB that do not lead to memory corruption?

/Paolo