www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - checkedint call removal

reply "bearophile" <bearophileHUGS lycos.com> writes:
The core.checkedint module isn't meant to be used directly like 
this, it has the bricks to build partially library-defined safe 
integral types:


void main(in string[] args) {
     import std.stdio, std.conv, core.checkedint;

     assert(args.length == 3);
     immutable xy = args[1 .. $].to!(int[2]);

     bool overflow = false;
     immutable result = muls(xy[0], xy[1], overflow);
     assert(!overflow);
     writeln("Product: ", result);
}


Calls to core.checkedint functions are eventually meant to be 
replaced by faster compiler intrisics in all D compiler, that use 
the carry and overflow bits present in most CPUs.

But to be more useful, the compiler should replace safe integral 
operations with regular (faster) integral operations where it 
statically knows they can't overflow/underflow. In D there is 
value range propagation (that probably will be improved in 
future) that can be used for this. If the compiler replaces the 
calls to core.checkedint functions with intrinsics, it can also 
replace some calls with regular operations where it sees the 
value range makes an overflow impossible. This is a naive example:


void main() {
     import std.stdio, core.checkedint;
	
	ubyte x = 100;
	ubyte y = 200;	

     bool overflow = false;
     immutable result = muls(x, y, overflow);
     assert(!overflow);
     writeln("Product: ", result);
}


With a library-defined type the first program could look:


void main(in string[] args) {
     import std.stdio, std.conv, std.safeintegral;

     assert(args.length == 3);
     SInt x = args[1].to!int;
     SInt y = args[2].to!int;

     immutable result = x * y;
     assert(!result.overflow);
     writeln("Product: ", result);
}


where the operator "*" of SInt calls muls().


But while operations with ubyte and int values are able to use 
the range of values (to avoid casts), a library-defined type like 
SInt that calls muls() currently loses the knowledge of the range 
of the operands. How do you solve this problem? If you solve this 
problem for SInt, you can solve it for lot of other 
library-defined types.

A possible piece of the solution is the recently suggested 
__trait(valueRange, exp), but alone that's not enough.

Bye,
bearophile
Jul 27 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/27/2014 6:52 AM, bearophile wrote:
 A possible piece of the solution is the recently suggested __trait(valueRange,
 exp), but alone that's not enough.
Instead of adding more language features, purpose existing ones: assert(exp >= min && exp <= max);
Jul 27 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Instead of adding more language features, purpose existing ones:

     assert(exp >= min && exp <= max);
I don't see how this can solve the problem I have discussed. Please explain better. Bye, bearophile
Jul 27 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/27/2014 1:54 PM, bearophile wrote:
 Walter Bright:

 Instead of adding more language features, purpose existing ones:

     assert(exp >= min && exp <= max);
I don't see how this can solve the problem I have discussed. Please explain better.
That tells the compiler that the exp is within min and max after that point.
Jul 27 2014
parent reply "Ola Fosheim Gr" <ola.fosheim.grostad+dlang gmail.com> writes:
On Monday, 28 July 2014 at 04:44:04 UTC, Walter Bright wrote:
 On 7/27/2014 1:54 PM, bearophile wrote:
 Walter Bright:

 Instead of adding more language features, purpose existing 
 ones:

    assert(exp >= min && exp <= max);
I don't see how this can solve the problem I have discussed. Please explain better.
That tells the compiler that the exp is within min and max after that point.
Conflating run time debug checks with programmer provided guarantees sounds dangerous. Call it "assume" not "assert" then.
Jul 27 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter:

Instead of adding more language features,<
Perhaps you can't solve this problem in a sufficiently clean way without adding language features (and a assume() is not the solution, see below). --------------------- Ola Fosheim:
 Conflating run time debug checks with programmer provided 
 guarantees sounds dangerous. Call it "assume" not "assert" then.
But this still missed the point. I am not interested in annotations, in this thread I am not asking for a built-in assume() (or for some weird kind kind of assert() that is much worse). Let's go back to the second example I've shown: void main() { import std.stdio, core.checkedint; ubyte x = 100; ubyte y = 200; bool overflow = false; immutable result = muls(x, y, overflow); assert(!overflow); writeln("Product: ", result); } Here I am not willing to add an assume(). Here at the call point of muls() x and y have a full range of ubytes, so the range analysis tell the compiler their product will not overflow, so it can replace the muls() with a regular product and leave overflow untouched. This is faster. The same kind of optimization is desired for a SInt or other library-defined types. So the point of this discussion is how to do this. The problem is that the compiler has some static information about ranges, but to optimize away user-defined types such information needs to be read and given to "static ifs" to replace the calls to muls() to calls to regular operations. Bye, bearophile
Jul 28 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 08:42:16 UTC, bearophile wrote:
 The same kind of optimization is desired for a SInt or other 
 library-defined types. So the point of this discussion is how 
 to do this. The problem is that the compiler has some static 
 information about ranges, but to optimize away user-defined 
 types such information needs to be read and given to "static 
 ifs" to replace the calls to muls() to calls to regular 
 operations.
Not sure if this is the right way to do carry/overflow optimization, but I can see the value of having range information when doing CTFE for building minimal lookup tables/perfect hashing etc. IMO muls should yield 2N bits of output for N bits input, then the compiler should do strength reduction. Adds should be done on N+1 bits types, using 33 bit output for 32 bits input, then strength reduce it to >=32 bit output if both operands are 31 bits or less?
Jul 28 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ola Fosheim Grøstad:

 IMO muls should yield 2N bits of output for N bits input, then 
 the compiler should do strength reduction.

 Adds should be done on N+1 bits types, using 33 bit output for 
 32 bits input, then strength reduce it to >=32 bit output if 
 both operands are 31 bits or less?
I copy here a comment I've written here: https://github.com/D-Programming-Language/phobos/pull/1866#issuecomment-50216839 A core.checkedint function like muls() accepts two ints or two longs. What if you have a uint and int? An example: void main() { import std.stdio, core.checkedint; int x = -1; uint y = 3_000_000_000; writeln(x, " ", y); writeln(x * y); bool overflow = false; immutable r1 = muls(x, y, overflow); writeln(r1, " ", overflow); overflow = false; immutable r2 = mulu(x, y, overflow); writeln(r2, " ", overflow); } It outputs: -1 3000000000 1294967296 1294967296 false 1294967296 true Here the overflow boolean from the muls() is false, but the result is wrong (it's -3_000_000_000 that is not representable by both ints and uints). Bye, bearophile
Jul 28 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 09:46:34 UTC, bearophile wrote:
     uint y = 3_000_000_000;
     writeln(x, " ", y);
     writeln(x * y);
D promotes int to uint, right? Which is a bad idea. It should promote to long, right?
     bool overflow = false;
     immutable r1 = muls(x, y, overflow);
Why does muls accept this without an explicit cast to signed operands long? If the result is signed, the operands should be signed?
     overflow = false;
     immutable r2 = mulu(x, y, overflow);
Well, it overflows because you multiply 0xfffffffff with 3000000000 if it promotes int to uint, but the result would still be incorrect without an overflow if the values were -1 and 1. You would get 0xffffffff without an overflow/underflow. (I might get it all wrong here, I didn't run the code.) However, if you manually remove overflow checks, you probably need to check that you still get vectorized output with auto-vectorization. Maybe it is better that the backend deals with it. Dunno.
Jul 28 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ola Fosheim Grøstad:

 D promotes int to uint, right? Which is a bad idea. It should 
 promote to long, right?
The purpose of safe integral operations like muls() is to detect overflow bugs at run-time. If they don't detect bugs, they are not useful. Bye, bearophile
Jul 28 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 11:13:28 UTC, bearophile wrote:
 The purpose of safe integral operations like muls() is to 
 detect overflow bugs at run-time. If they don't detect bugs, 
 they are not useful.
Yes, but if you define the parameters to be long, then it will work. Right?
Jul 28 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 The purpose of safe integral operations like muls() is to 
 detect overflow bugs at run-time. If they don't detect bugs, 
 they are not useful.
I think it detects the overflow correctly even if you use the (uint, int) argument pair, because the usual conversions are used, and I think the mulu is called, that returns the overflow boolean as true. Bye, bearophile
Jul 28 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/28/2014 1:42 AM, bearophile wrote:
 void main() {
      import std.stdio, core.checkedint;

      ubyte x = 100;
      ubyte y = 200;

      bool overflow = false;
      immutable result = muls(x, y, overflow);
      assert(!overflow);
      writeln("Product: ", result);
 }


 Here I am not willing to add an assume(). Here at the call point of muls() x
and
 y have a full range of ubytes, so the range analysis tell the compiler their
 product will not overflow, so it can replace the muls() with a regular product
 and leave overflow untouched. This is faster.
Here there are no new language features required. muls() being an intrinsic means the compiler knows about it. The compiler already does data flow analysis on constants, meaning it knows that x is 100, and will replace subsequent instances of x with 100. This is called "constant propagation", and has been a standard feature of compilers for 30 years. Some optimizers (not including dmd's) go further with this data flow analysis and do ranges. assert()s are mined by the optimizer for information about ranges. ('assume' adds absolutely nothing here.) With this, since the compiler knows about muls(), it can optimize it. The point being: NO NEW LANGUAGE FEATURES ARE NECESSARY bearophile, I know you are interested in these sorts of things, but you are unaware of routine data flow analysis that compilers have done for decades. I strongly recommend you pick up a compiler book like "Compilers Principles Techniques and Tools" and thumb through the optimization section. I think you'll find it enjoyable and useful.
Jul 28 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Here there are no new language features required. muls() being 
 an intrinsic means the compiler knows about it. The compiler 
 already does data flow analysis on constants, meaning it knows 
 that x is 100,
Another example program, hopefully more clear: void main(in string[] args) { import std.stdio, std.conv, std.experimental.safeintegral; assert(args.length == 3); immutable ubyte ux = args[1].to!ubyte; immutable ubyte uy = args[2].to!ubyte; SInt x = ux; SInt y = uy; immutable SInt result = x * y; assert(!result.overflow); writeln("Product: ", result); } Here SInt is a safe integral struct, that overloads the operators like "*" and internally calls muls(). In this program x and y are not constants (like in my original program, but here it's more visible). What I'd like is the compiler to replace the call to muls() inside the opBinary() of SInt with a simple unsafe integer multiplication because the value range of x and y is [0, 255] for both, so the compiler knows the multiplication can't overflow. How do you do this with no additional language features? In my opinion the opBinary() of SInt needs a way to know at compile-time that the range of the two inputs are small enough to not overflow (so opBinary() becomes like a template with two instantiations). Bye, bearophile
Jul 29 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 4:03 PM, bearophile wrote:
 How do you do this with no additional language features?
Data flow analysis can figure that example out. If it can't for a more complex one, you can do: assert(x >= 0 && x <= 255); assert(y >= 0 && y <= 255); The optimizer can certainly use asserts to provide semantic information (even though the dmd one doesn't at the moment). Again, I know you like reading about new languages and language features. I think you'd enjoy that even more supplemented with a book on how compilers work internally, in particular, how data flow analysis works and what it can do.
Jul 29 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Data flow analysis can figure that example out.
Sorry, my mistake, what I am discussing about should not need much flow analysis. Here x and y are immutable: void main(in string[] args) { import std.stdio, std.conv; assert(args.length == 3); immutable ubyte ux = args[1].to!ubyte; immutable ubyte uy = args[2].to!ubyte; immutable int x = ux; immutable int y = uy; immutable int result = x * y; writeln("Product: ", result); } In the current D compiler x and y keep a value range of ubytes (despite they are ints), so here D knows the expression "x * y" can't overflow, so even this is accepted with no casts needed: immutable ushort result = x * y; Now let's convert that code with SInt (x and y are still immutable, unlike in my precedent post): void main(in string[] args) { import std.stdio, std.conv, std.experimental.safeintegral; assert(args.length == 3); immutable ubyte ux = args[1].to!ubyte; immutable ubyte uy = args[2].to!ubyte; immutable SInt x = ux; immutable SInt y = uy; immutable SInt result = x * y; assert(!result.overflow); writeln("Product: ", result); } What's I'd like is a way for x and y (that are of the library-defined type SInt) to keep the value range of an ubyte. So the compiler is able to rewrite this: immutable SInt result = x * y; removing the call to muls() and replacing it with a regular multiplication, that is faster, even when no inlining happens. (To do this SInt needs two different "instantiations" of its opBinary("*") ).
 If it can't for a more complex one, you can do:

   assert(x >= 0 && x <= 255);
   assert(y >= 0 && y <= 255);
For such simple situations I don't want user annotations. The only code needed to make this request work should be already written inside the implementation of SInt and similar user-defined types. And assume() and assert() are two different things, used for different purposes. Do not give the same name to two so different features, if you want to keep a language sane. Info about assume in Microsoft C++: http://msdn.microsoft.com/en-us/library/1b3fsfxw.aspx
 The optimizer can certainly use asserts to provide semantic 
 information (even though the dmd one doesn't at the moment).
This is not a good idea. That's the job for assume(), not for assert. In general assert() verifies something is true, and if it's false, the program just raises an assert error, that is even recoverable. An assert leaves a condition testing inside the binary in debug builds. An assume() doesn't need to leave a test condition inside the binary, even in debug builds. It doesn't raise run-time errors. It's just a way to tell the compiler that some predicate is true, and the optimization stages of the compiler have to try to use this information to optimize the code. You can't mix or replace the two things, because a mistake in an assert() doesn't cause your program to burn, it just raises a compile-time error. A programmer mistake in an assume() burns your house. assert() can be used freely in your code, to make sure you have not done a mistake. assume() is only for special situations where you know something is true, that the compiler can't prove by itself.
 Again, I know you like reading about new languages and language 
 features. I think you'd enjoy that even more supplemented with 
 a book on how compilers work internally, in particular, how 
 data flow analysis works and what it can do.
I will read more about that topic. Bye, bearophile
Jul 30 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 09:12:56 UTC, bearophile wrote:
 And assume() and assert() are two different things, used for 
 different purposes. Do not give the same name to two so 
 different features, if you want to keep a language sane.
Exactly. If you want to establish that the provided input is never zero and that the program doesn't need to be correct in that case, you do this: assume(input!=0); If you want to specify that the input should be prevented from being zero, you do this: if(input!=0){ assert(input!=0); }
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 5:52 AM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Wednesday, 30 July 2014 at 09:12:56 UTC, bearophile wrote:
 And assume() and assert() are two different things, used for different
 purposes. Do not give the same name to two so different features, if you want
 to keep a language sane.
Exactly. If you want to establish that the provided input is never zero and that the program doesn't need to be correct in that case, you do this: assume(input!=0); If you want to specify that the input should be prevented from being zero, you do this: if(input!=0){ assert(input!=0); }
Now you're trying to use assert to validate user input. This is a terrible, terrible misunderstanding of assert.
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 20:33:41 UTC, Walter Bright wrote:
 assume(input!=0);

 If you want to specify that the input should be prevented from 
 being zero, you
 do this:

 if(input!=0){
   assert(input!=0);
 }
Now you're trying to use assert to validate user input. This is a terrible, terrible misunderstanding of assert.
Can you please read the Hoare article form 1969? This is getting really annoying. I am not trying to use assert to validate user input. I am verifying that the program is in compliance with the specification. Basically doing a partial proof of the theorem in the assert on the fly. Example 1: assume(x!=0) // define an axiom "x!=0" Example 2: if(x!=0){ assert(x!=0) // prove theorem "x!=0" (successful) } Example 3: assert(x!=0) // prove theorem "x!=0" (failure) Example 4: assume(x!=0); // define "x!=0" (impose constraint) assert(x!=0); // prove theorem "x!=0" (successful) I can't do better than this! Think of assume() as preconditions and assert() as postconditions. Note also that you could use an existing theorem prover to prove a function correct, then machine translate it into D code with assume() and assert() and other machinery needed for provable correct programming in D. Don't dismiss the distinction without thinking about it. Read Hoare's article, it is pretty well written.
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 1:45 PM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 Can you please read the Hoare article form 1969? This is getting really
annoying.
Ironically, your wikipedia entry on Hoare references http://en.wikipedia.org/wiki/Assertion_(computing) which is exactly what D's assert does.
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 11:15 PM, Walter Bright wrote:
 On 7/30/2014 1:45 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 Can you please read the Hoare article form 1969? This is getting
 really annoying.
Ironically, your wikipedia entry on Hoare references http://en.wikipedia.org/wiki/Assertion_(computing) which is exactly what D's assert does.
Did you read the article? http://en.wikipedia.org/wiki/Assertion_%28computing%29#Disabling_assertions '[...] disabling assertion checking can mean that a program that would have aborted will continue to run. This is sometimes preferable.' This is not what DMD does in -release where assertions are 'disabled'. It follows a diametrally opposite philosophy.
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:30 PM, Timon Gehr wrote:
 Did you read the article?

 http://en.wikipedia.org/wiki/Assertion_%28computing%29#Disabling_assertions

 '[...] disabling assertion checking can mean that a program that would have
 aborted will continue to run. This is sometimes preferable.'

 This is not what DMD does in -release where assertions are 'disabled'. It
 follows a diametrally opposite philosophy.
Not at all. The Wikipedia article does not argue that the program will continue in a valid state.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 12:39 AM, Walter Bright wrote:
 On 7/30/2014 2:30 PM, Timon Gehr wrote:
 Did you read the article?

 http://en.wikipedia.org/wiki/Assertion_%28computing%29#Disabling_assertions


 '[...] disabling assertion checking can mean that a program that would
 have
 aborted will continue to run. This is sometimes preferable.'

 This is not what DMD does in -release where assertions are 'disabled'. It
 follows a diametrally opposite philosophy.
Not at all. The Wikipedia article does not argue that the program will continue in a valid state.
Then you must also hold the belief that continuing to run in an invalid state is sometimes preferable?
Jul 30 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 a way for x and y (that are of the library-defined type SInt) 
 to keep the value range of an ubyte.
Such management of value ranges by library code could also allow to modify the implementation of iota to compile this: void main() { import std.range, std.algorithm; auto result = iota(20).map!(i => char(i + 'a')); } That mimics with library code this program that today compiles (thanks to various improvements in foreach range handling: void main() { foreach (immutable i; 0 .. 20) char c = char(i + 'a'); } You can probably special-case iota() in the compiler, to allow the first program (because in D the x..y is not first class, unfortunately), but if you offer more generic tools usable by library code you can use them in many other situations. Bye, bearophile
Jul 30 2014
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:12 AM, bearophile wrote:
 The optimizer can certainly use asserts to provide semantic information (even
 though the dmd one doesn't at the moment).
This is not a good idea. That's the job for assume(), not for assert.
The two are without distinction.
 In general assert() verifies something is true, and if it's false, the program
 just raises an assert error, that is even recoverable.
No, it is not recoverable.
 assert() can be used freely in your code, to make sure you have not done a
 mistake. assume() is only for special situations where you know something is
 true, that the compiler can't prove by itself.
Again, everything you say is true for assume is true for assert, and vice versa.
Jul 30 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:12 AM, bearophile wrote:
 Info about assume in Microsoft C++:
 http://msdn.microsoft.com/en-us/library/1b3fsfxw.aspx
Note that document shows how assert is implemented using assume. I.e. they are the same thing. Intriguingly, the __assume(0) behavior is even special cased like D's assert(0). C++ continues to adopt D features :-)
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 10:39 PM, Walter Bright wrote:
 On 7/30/2014 2:12 AM, bearophile wrote:
 Info about assume in Microsoft C++:
 http://msdn.microsoft.com/en-us/library/1b3fsfxw.aspx
Note that document shows how assert
Some random ASSERT macro with custom behaviour. That article shows a few alternatives for an ASSERT macro, one of which is basically what D's assert expression does. The primitives used are ( (e) || assert(__FILE__, __LINE__)) and __assume(e); Because the compiler does not seem know that 'assert' never returns, they shove in an __assume after it. #define ASSERT(e) ( ((e) || assert(__FILE__, __LINE__)), __assume(e)) This is an implementation detail. One can just as well do e.g.: #ifdef DEBUG # define ASSERT(e) ( ((e) || assert(__FILE__, __LINE__) ) #else # define ASSERT(e) #endif #define ASSUME(e) __assume(e) and this and similar options avoid undefined behaviour in non-DEBUG mode caused on ASSERT, while still having the possibility of giving optimization hints explicitly in the form of ASSUME. In this case, the distinction is important even operationally, and it would be a sane alternative to the current approach. There is no a priori absolute single true way when discussing alternatives, and frankly, this should be obvious.
 is implemented using assume. I.e. they are the same thing.
 ...
Yes, and writeln is obviously the same thing as a hello world program.
 Intriguingly, the __assume(0) behavior is even special cased like D's
 assert(0). ...
It is not special cased at all. It is documented specially, because not everyone seems to be that deep into logic.
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:21 PM, Timon Gehr wrote:
 Because the compiler does not seem know that 'assert' never returns, they shove
 in an __assume after it.
The critical bit of misunderstanding here is the C standard *requires* that assert be implemented as a macro, and that NDEBUG will totally disable it. Microsoft needed to add a builtin feature so that the correct assert semantics can be reliably obtained by the optimizer. It's a mistake to infer from that that assert and assume are different.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 11:39 PM, Walter Bright wrote:
 On 7/30/2014 2:21 PM, Timon Gehr wrote:
 Because the compiler does not seem know that 'assert' never returns,
 they shove
 in an __assume after it.
The critical bit of misunderstanding here is the C standard *requires* that assert be implemented as a macro,
There is no such misunderstanding. I know this.
 and that NDEBUG will totally disable it.
The example implementation based on NDEBUG there does not provide this, rather, NDEBUG leaves the optimizer hint in.
 Microsoft needed to add a builtin feature so that the
 correct assert semantics can be reliably obtained by the optimizer.
 ...
What makes the second implementation with both assert and __assume there 'correct'? Does the C standard specify undefined behaviour if the assert expression has side-effects?
 It's a mistake to infer from that that assert and assume are different.
I don't need to rely on the MSVC++ compiler to see this. (But the __assume they have can be used to pass hints to the optimizer even if it does not happen in the context of an assertion, which I think was bearophile's point.)
Jul 30 2014
prev sibling next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 27 July 2014 at 20:20:54 UTC, Walter Bright wrote:
 On 7/27/2014 6:52 AM, bearophile wrote:
 A possible piece of the solution is the recently suggested 
 __trait(valueRange,
 exp), but alone that's not enough.
Instead of adding more language features, purpose existing ones: assert(exp >= min && exp <= max);
That's great for communicating bounds from code to the compiler, but what bearophile is talking about is accessing the compiler's value rage propagation information in code. The other way around.
Jul 27 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 27 July 2014 at 20:20:54 UTC, Walter Bright wrote:
 On 7/27/2014 6:52 AM, bearophile wrote:
 A possible piece of the solution is the recently suggested 
 __trait(valueRange,
 exp), but alone that's not enough.
Instead of adding more language features, purpose existing ones: assert(exp >= min && exp <= max);
To what extent can a compiler use assertions? Can it work backwards from an assert to affect previous code? void foo(int a) { enforce(a & 1); assert(a & 1); } void bar() { assert(a & 1); enforce(a & 1); } Which, if either, of those calls to enforce can be removed?
Jul 28 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"John Colvin"  wrote in message news:iguetbdxlyilavlizqry forum.dlang.org...

 To what extent can a compiler use assertions? Can it work backwards from 
 an assert to affect previous code?

 void foo(int a)
 {
      enforce(a & 1);
      assert(a & 1);
 }
The assert is dead code, because it will never be reached if (a & 1) is false.
 void bar()
 {
      assert(a & 1);
      enforce(a & 1);
 }
The throw inside enforce is dead code, because it will never be reached if (a & 1) is false. The compiler is free to remove dead code, because it doesn't change the program's behaviour.
Jul 28 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 July 2014 at 12:08:39 UTC, Daniel Murphy wrote:
 "John Colvin"  wrote in message 
 news:iguetbdxlyilavlizqry forum.dlang.org...

 To what extent can a compiler use assertions? Can it work 
 backwards from an assert to affect previous code?

 void foo(int a)
 {
     enforce(a & 1);
     assert(a & 1);
 }
The assert is dead code, because it will never be reached if (a & 1) is false.
 void bar()
 {
     assert(a & 1);
     enforce(a & 1);
 }
The throw inside enforce is dead code, because it will never be reached if (a & 1) is false. The compiler is free to remove dead code, because it doesn't change the program's behaviour.
Ok. What about this: int c; void foo(int a) { if(a < 0) c++; assert(a > 0); } I presume that cannot be optimised away entirely to: void foo(int a) {} ?
Jul 28 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 July 2014 at 12:52:07 UTC, John Colvin wrote:
 On Monday, 28 July 2014 at 12:08:39 UTC, Daniel Murphy wrote:
 "John Colvin"  wrote in message 
 news:iguetbdxlyilavlizqry forum.dlang.org...

 To what extent can a compiler use assertions? Can it work 
 backwards from an assert to affect previous code?

 void foo(int a)
 {
    enforce(a & 1);
    assert(a & 1);
 }
The assert is dead code, because it will never be reached if (a & 1) is false.
 void bar()
 {
    assert(a & 1);
    enforce(a & 1);
 }
The throw inside enforce is dead code, because it will never be reached if (a & 1) is false. The compiler is free to remove dead code, because it doesn't change the program's behaviour.
Ok. What about this: int c; void foo(int a) { if(a < 0) c++; assert(a > 0); } I presume that cannot be optimised away entirely to: void foo(int a) {} ?
sorry, I mean void foo(int a) { assert(a > 0); } of course you can't optimise away the check.
Jul 28 2014
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"John Colvin"  wrote in message news:zzmgkwlzggrrtdtjbico forum.dlang.org...
 Ok. What about this:

 int c;

 void foo(int a)
 {
     if(a < 0) c++;
     assert(a > 0);
 }

 I presume that cannot be optimised away entirely to:

 ...

 void foo(int a)
 {
      assert(a > 0);
 }

 of course you can't optimise away the check.
No, because that would change the observable behaviour. The compiler can do stuff like: uint x = ...; assert(x < 256); ubyte y = x & 0xFF; becomes uint x = ...; assert(x < 256); ubyte y = x; or assert(y == 8); auto n = x / y; becomes assert(y == 8); auto n = y >> 3; Allowing things like this: assert(x < 256); ubyte y = x; // no mask/cast required is technically possible but questionable. You could also (in theory) propagate range information via an out contract: int myMathFunc(int x) out(result) { assert(result >= 0 && result < 17); } body { < some incomprehensible mathmatical stuff that the compiler can't understand > } void main() { auto v = myMathFunc(99); ubyte b = v; // According to the out contract, v must fit in a ubyte }
Jul 28 2014
prev sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 12:53:20 UTC, John Colvin wrote:
 int c;

 void foo(int a)
 {
    if(a < 0) c++;
    assert(a > 0);
 }

 I presume that cannot be optimised away entirely to:

 void foo(int a) {}

 ?
sorry, I mean void foo(int a) { assert(a > 0); } of course you can't optimise away the check.
Please guys, you should not change code-gen based on asserts. They are not proofs, they are candidates for formal verification of correctness. They are in essence embedded break-point checks. If you allow asserts to affect codegen then it becomes a very unsafe feature. It's like having a undetected bug in a unit-test introduce bugs in the released program. 8-I Anyway, without a barrier, you probably could do code motion if you know that you will reach HALT and that is considered illegal. For system programming language reaching HALT should probably be considered legal and you cannot do code motion based on that. In essence, when and where you can move code depends on barriers… But since you don't actually get HALT from assert() in release mode, it makes no sense to argue the point either…
Jul 28 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:vqlvigvgcplkuohudsju forum.dlang.org...

 Please guys, you should not change code-gen based on asserts. They are not 
 proofs, they are candidates for formal verification of correctness. They 
 are in essence embedded break-point checks. If you allow asserts to affect 
 codegen then it becomes a very unsafe feature. It's like having a 
 undetected bug in a unit-test introduce bugs in the released program. 8-I
The compiler is allowed to not check assertions in release mode. This is because a program that would fail an assertion is a broken program, and by specifying -release you are telling the compiler to assume all assertions pass. I don't see any reason the compiler shouldn't be allowed to change code-gen based on asserts. One murky area is that assert(0) is currently used to mean both 'unreachable' and 'unimplemented'. It's unclear what the compiler is allowed to do with an assert(0) in release mode.
Jul 28 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 13:31:50 UTC, Daniel Murphy wrote:
 The compiler is allowed to not check assertions in release 
 mode.  This is because a program that would fail an assertion 
 is a broken program, and by specifying -release you are telling 
 the compiler to assume all assertions pass.  I don't see any 
 reason the compiler shouldn't be allowed to change code-gen 
 based on asserts.
In that case I will write my own assert() that doesn't have this behaviour. Nobody who cares about program verification and correctness will touch this. It means that you have to formally prove every single assert() to be correct. This is HARD. Hoare logic is _very_ difficult even for simple programs. assert() is no guarantee for correctness, it is basically a break-point check. A sloppy request from the programmer to check some constraint that possibly could be overspecified, and that could silently pass. The the optimizer might assume that "length<1024" etc and create all kinds of problems. Assert() are useful debugging tools, but not a codegen feature. A good debugger could allow you to turn them on/off or let you continue after hitting one. That's useful.
Jul 28 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:scibhjsiolgykujqxwbx forum.dlang.org...

 In that case I will write my own assert() that doesn't have this 
 behaviour. Nobody who cares about program verification and correctness 
 will touch this.
Yes.
 assert() is no guarantee for correctness, it is basically a break-point 
 check. A sloppy request from the programmer to check some constraint that 
 possibly could be overspecified, and that could silently pass. The the 
 optimizer might assume that "length<1024" etc and create all kinds of 
 problems.
Yes, writing code wrong can result in the wrong thing happening. A non-release build will always retain the asserts.
 Assert() are useful debugging tools, but not a codegen feature. A good 
 debugger could allow you to turn them on/off or let you continue after 
 hitting one. That's useful.
If this is what you want you shouldn't be using assert. This is not what assert means in D.
Jul 28 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 13:50:29 UTC, Daniel Murphy wrote:
 Yes, writing code wrong can result in the wrong thing 
 happening.  A non-release build will always retain the asserts.
No, writing wrong code is one thing. Having a single typo in a constraint-test cause memory unsafety undetected is a disaster. And many such typos _will_ go undetected. Let's say you want to test "divisor >= 0", but end up with "divisor != 0" => division_by_zero failure even if the code is correct. Adding assert() should increase quality, not decrease it. Adding asserts will increase the probability of wrong constraints entering the codebase. That means with the regime indicated here you should write as few assert() statements as possible.
 Assert() are useful debugging tools, but not a codegen 
 feature. A good debugger could allow you to turn them on/off 
 or let you continue after hitting one. That's useful.
If this is what you want you shouldn't be using assert. This is not what assert means in D.
Where in the spec does it say that assert is a tool for specifying optimization constraints? That would be a disaster.
Jul 28 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:ejbwjvylulclchhehlnw forum.dlang.org...

 No, writing wrong code is one thing.

 Having a single typo in a constraint-test cause memory unsafety undetected 
 is a disaster. And many such typos _will_ go undetected.
Sure, because having single typos in other parts of your code causing memory unsafety are totally not a disaster. And those never go undetected.
 Let's say you want to test "divisor >= 0", but end up with "divisor != 0" 
 => division_by_zero failure even if the code is correct.
Let's say you want to add two numbers, but instead of writing 'a + b' you write 'a - b'!!!! The program fails even though you totally meant to write the correct code.
 Adding assert() should increase quality, not decrease it. Adding asserts 
 will increase the probability of wrong constraints entering the codebase. 
 That means with the regime indicated here you should write as few assert() 
 statements as possible.
I disagree. If you do not want your assertion removed then don't compile with -release.
 Where in the spec does it say that assert is a tool for specifying 
 optimization constraints?
Where in the spec does it say assert is a tool for inserting breakpoints? Asserts are a tool for conveying to the compiler certain conditions that you expect to be true.
Jul 28 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 15:07:07 UTC, Daniel Murphy wrote:
 Let's say you want to add two numbers, but instead of writing 
 'a + b' you write 'a - b'!!!!  The program fails even though 
 you totally meant to write the correct code.
You are trolling me. :-[ Verification is not specification. D stands for DOOMED if this goes through. If asserts were used as optimization constraints then the viral nature of this will undermine all codebases that use libraries. Make one frigging function call, pass through a overstated assert and all your precious handcrafted if-checks evaporates without notice. Goodbye protection against division-by-zero, NaN, out-of-bounds checks etc.
 I disagree.  If you do not want your assertion removed then 
 don't compile with -release.
Asserts are there to harness programs, not to weaken them.
 Where in the spec does it say assert is a tool for inserting 
 breakpoints?
It says they inject checks. Not semantic constraints. They are not verified.
 Asserts are a tool for conveying to the compiler certain 
 conditions that you expect to be true.
No, assert() is a tool for testing that certain constraints hold at RUNTIME, because you failed to prove them.
Jul 28 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad 
wrote:
 If asserts were used as optimization constraints
all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it. bool foo(int a) { //let's handwrite a simple assert if(a >= 0) { exit(EXIT_FAILURE); } //and then do something. return a < 0; } Of course the compiler is free to rewrite that as bool foo(int a) { if(a >= 0) { exit(EXIT_FAILURE); } return true; } Why should the situation be different if I use the builtin `assert` instead?
Jul 28 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
 On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad 
 wrote:
 If asserts were used as optimization constraints
all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it. bool foo(int a) { //let's handwrite a simple assert if(a >= 0) { exit(EXIT_FAILURE); } //and then do something. return a < 0; } Of course the compiler is free to rewrite that as bool foo(int a) { if(a >= 0) { exit(EXIT_FAILURE); } return true; } Why should the situation be different if I use the builtin `assert` instead?
admittedly this requires knowing that exit() won't return control back to the function. With a dummy return it will still work though: bool foo(int a) { //let's handwrite a simple assert if(a >= 0) { exit(EXIT_FAILURE); return false; //dummy return } //and then do something. return a < 0; }
Jul 28 2014
prev sibling next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
 If asserts were used as optimization constraints
all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it.
Yes, because they are not to have side-effects. If asserts change behaviour, then they have side-effects. You add "asserts" as a weak form for verification of partial correctness. That is based on the probability of not repeating the same mistake twice being less than specifying it once implicitly in the executed code. Then you test it with limited coverage of potential inputs. That means: 1. you don't know if the specified program is correct 2. you don't know if the partial verification (which is weak) is correct 3. you don't know if 2. contradicts 1. Then you remove the verification test in release. If you then continue to assume that 2. is true then you are potentially worse off than just having 1. You basically introduce contradictions by having a high probability of using facts that are not represented in the specified program (unless you have formally proven the facts to hold, no partial testing can cover this).
 Why should the situation be different if I use the builtin 
 `assert` instead?
No difference. Except with a builtin you can get additional debugger support, so that you don't have to recompile when following a complicated trace that trigger asserts.
Jul 28 2014
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 19:16:24 UTC, Ola Fosheim Grøstad 
wrote:
 Why should the situation be different if I use the builtin 
 `assert` instead?
No difference. Except with a builtin you can get additional debugger support, so that you don't have to recompile when following a complicated trace that trigger asserts.
Well, actually, that is not correct. There are other advantages too. If the compiler guarantees that asserts don't have side effects (on optimization) and aren't affected by the optimizer then you are more likely to see the same behaviour in debug and release builds even with heavy optimization turned on (such as various math approximations). E.g. you can verify with exact math in the assert() that the fast-math approximations the optimizer makes on running code are within the acceptable tolerance level.
Jul 28 2014
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
 On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad 
 wrote:
 If asserts were used as optimization constraints
all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it. bool foo(int a) { //let's handwrite a simple assert if(a >= 0) { exit(EXIT_FAILURE); } //and then do something. return a < 0; } Of course the compiler is free to rewrite that as bool foo(int a) { if(a >= 0) { exit(EXIT_FAILURE); } return true; } Why should the situation be different if I use the builtin `assert` instead?
The problem is that in release mode, the asserts are removed. It would then be a very big mistake to still take them into account for optimizations, as if they were actually there. To take your code: assert(a >= 0); return a < 0; is equivalent to assert(a >= 0); return true; but only in non-release mode. In release mode, this effectively becomes return a < 0; which is _not_ equivalent to return true; I believe this is was Ola is protesting about, and I agree with him. Such optimizations must only happen if the check stays.
Jul 29 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 29 July 2014 at 09:40:27 UTC, Marc Schütz wrote:
 On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
 On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad 
 wrote:
 If asserts were used as optimization constraints
all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it. bool foo(int a) { //let's handwrite a simple assert if(a >= 0) { exit(EXIT_FAILURE); } //and then do something. return a < 0; } Of course the compiler is free to rewrite that as bool foo(int a) { if(a >= 0) { exit(EXIT_FAILURE); } return true; } Why should the situation be different if I use the builtin `assert` instead?
The problem is that in release mode, the asserts are removed. It would then be a very big mistake to still take them into account for optimizations, as if they were actually there. To take your code: assert(a >= 0); return a < 0; is equivalent to assert(a >= 0); return true; but only in non-release mode. In release mode, this effectively becomes return a < 0; which is _not_ equivalent to return true; I believe this is was Ola is protesting about, and I agree with him. Such optimizations must only happen if the check stays.
you mean assert(a < 0) or assert(!(a >= 0)) right? In a correct program (a necessary but not sufficient condition for which is to not violate it's asserts) it is the same. The program is in error if a > 0, whether the assert is compiled in or not. Running in debug mode can simply mean "check my assumptions".
Jul 29 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 10:40:33 UTC, John Colvin wrote:
 In a correct program (a necessary but not sufficient condition 
 for which is to not violate it's asserts) it is the same.
Define a correct program. This is a correct program: S = full specification ( say in prolog or haskell ) P = implementation in an imperative language A = valid input TheoremProver( S(x) == P(x) for all x in A ) Yes, in that case you can take any theorems derived from S applied to P and use them for optimization. In all other cases, injecting theorems more or less randomly into P and then testing them for a small subset of A will never lead to correct theorems pertaining to P. Thus they cannot be used for optimizing P either.
Jul 29 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/29/2014 08:54 PM, "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Tuesday, 29 July 2014 at 10:40:33 UTC, John Colvin wrote:
 In a correct program (a necessary but not sufficient condition for
 which is to not violate it's asserts) it is the same.
Define a correct program. This is a correct program: S = full specification ( say in prolog or haskell )
(Prolog and Haskell are not particularly natural languages for specification.)
Jul 29 2014
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 29 July 2014 at 10:40:33 UTC, John Colvin wrote:
 On Tuesday, 29 July 2014 at 09:40:27 UTC, Marc Schütz wrote:
    assert(a >= 0);
    return a < 0;

 is equivalent to

    assert(a >= 0);
    return true;

 but only in non-release mode. In release mode, this 
 effectively becomes

    return a < 0;

 which is _not_ equivalent to

    return true;

 I believe this is was Ola is protesting about, and I agree 
 with him. Such optimizations must only happen if the check 
 stays.
you mean assert(a < 0) or assert(!(a >= 0)) right?
Ah, yes, of course. Alternatively, `return false;`.
 In a correct program (a necessary but not sufficient condition 
 for which is to not violate it's asserts) it is the same.

 The program is in error if a > 0, whether the assert is 
 compiled in or not. Running in debug mode can simply mean 
 "check my assumptions".
Yes, it only breaks if the program is incorrect. The difference is that it asserts in non-release mode, and just goes on and produces garbage in release mode. Now, it's of course a valid standpoint to say that your program is going to break anyway, because your assumptions (that you expressed by `assert`) were wrong. But on the other hand, you additionally inserted checks (`a < 0`) to test for it. The above examples are artificial, but in reality these additional checks could be located in an external library, and could have been written by a different author. It might not be such a good idea to circumvent the checks. In this sense, asserts would indeed make the library code - which might have been completely safe by itself - suddenly unsafe. Of course, this is only relevant if the compiler first optimizes, and then removes the asserts (in release mode). If it removes the asserts first, and optimizes after, everything is fine.
Jul 29 2014
prev sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:cgljkngsjwkspfixdfgy forum.dlang.org...

 On Monday, 28 July 2014 at 15:07:07 UTC, Daniel Murphy wrote:
 Let's say you want to add two numbers, but instead of writing 'a + b' 
 you write 'a - b'!!!!  The program fails even though you totally meant 
 to write the correct code.
You are trolling me. :-[
Yes. I think you'll find advanced optimizers are already doing this sort of thing to your code, when it decides code is unreachable. Enabling optimizations can make code-gen unpredictable, especially when used on broken code. In C/C++ this is often due to undefined behaviour. Using assert to pass arbitrary information to the optimizer would allow for some fantastic opportunities. Just imagine how close to perfection the compiler can get with these constraints: void vectorizedFunction(int* a, int* b, size_t len) in { assert(noOverlap(a, b, len)); assert(len % 16 == 0); } body { < some kind of code that can benefit from vectorization > } Sure, we could add a new construct (ie 'assume') to the language, and use that to pass information. But are they really different? Assert says 'the program is in error if this is not true'. -release says 'compile my program as if it has no errors'. These two combined give the compiler a huge amount of power.
Jul 28 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Daniel Murphy:

 Sure, we could add a new construct (ie 'assume') to the 
 language, and use that to pass information.  But are they 
 really different?
Conflating the two concepts with a single name is a mistake that will cause troubles. Different features need different names or different syntax. Bye, bearophile
Jul 28 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"bearophile"  wrote in message news:sfgfebbskhatxqlzthpr forum.dlang.org...

 Conflating the two concepts with a single name is a mistake that will 
 cause troubles. Different features need different names or different 
 syntax.
Did you read the rest of my post? Assert already fits this feature, we just don't take advantage of it like we could.
Jul 28 2014
prev sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 28 July 2014 at 16:32:46 UTC, Daniel Murphy wrote:
 Yes.  I think you'll find advanced optimizers are already doing 
 this sort of thing to your code, when it decides code is 
 unreachable.
The problem is that the code is not unreachable when you compile with -release.
 Sure, we could add a new construct (ie 'assume') to the 
 language, and use that to pass information.  But are they 
 really different?
The difference is that if you assume(), then you have to formally prove it to hold. That means it cannot be allowed to contradict the program code. It is very important to keep the provided facts and the derived properties separate.
 Assert says 'the program is in error if this is not true'.
enforce() says: always runtime check this (?) assert() says: this ought to hold when I do testing assume() says: I have proven this to hold prove() says: don't generate code until you can prove this to hold
 -release says 'compile my program as if it has no errors'.
-release says: compile my program without runtime checks for correctness -no-assume might say: ignore all assumptions, I don't trust myself -assume-is-assert(): turn assumptions into runtime checks etc.
 These two combined give the compiler a huge amount of power.
Yes, if used carefully, but the language and/or compiler have to treat user provided facts differently than derived knowledge that originates within the executable code. assert() is not really for providing facts, it is for testing them. So the threshold for providing an assertion is low if it is completely free of side effects (in release), but the threshold for providing an assumption should be very high.
Jul 28 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
 assert() says: this ought to hold when I do testing
 assume() says: I have proven this to hold
Just as another example of how these two are different: You might want to assert() that you have enough headroom in a statically allocated buffer when testing. Say you assert that the buffer is never more than 50% full for normal loads. You obviously don't want the -release build to make such an assumption! So the content of an assert() is in this regard different from a prove(). It can sometimes be desirable to put too strong constraints on the program when testing, then relax it on release to get that extra headroom for "odd situations". You can probably make the same argument for tolerances in computations that are approximate/randomized/iterative. Testing for a tight tolerance does not mean that you want the optimizer to assume that the tolerance is always within that bound. You want some extra headroom in release to be sure that it behaves correctly under more difficult circumstances.
Jul 28 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/28/2014 1:49 PM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 You might want to assert() that you have enough headroom in a statically
 allocated buffer when testing. Say you assert that the buffer is never more
than
 50% full for normal loads. You obviously don't want the -release build to make
 such an assumption!
You're misunderstanding and misusing assert. 'assume' is completely redundant with 'assert'. To have different debug builds, use debug statements.
Jul 28 2014
next sibling parent "Ola Fosheim Gr" <ola.fosheim.grostad+dlang gmail.com> writes:
On Tuesday, 29 July 2014 at 01:07:44 UTC, Walter Bright wrote:
 You're misunderstanding and misusing assert.

 'assume' is completely redundant with 'assert'.
Nope, you are conflating what is proven by what is not proven an by what cannot be proven. If it is proven, then you don't need headroom at all!
Jul 28 2014
prev sibling next sibling parent reply "Ola Fosheim Gr" <ola.fosheim.grostad+dlang gmail.com> writes:
I find it worrying that you take so lightly on basic correctness. 
Asserts are entirely probabilistic in nature. What you are 
arguing for is a regime where a single bad assert can result in 
the user's disk getting wiped even though you had protections in 
place in the code without asserts that would have prevented it. 
That is horrible.

With 500 asserts and a 99.9% chance of a single assert not 
contradicting the program you have ~40% chance of having 
contradictions.

I guess that makes D a  safe language...
Jul 28 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Gr"  wrote in message 
news:kpfxpgdpakuqrdziawxl forum.dlang.org...

 I find it worrying that you take so lightly on basic correctness. Asserts 
 are entirely probabilistic in nature. What you are arguing for is a regime 
 where a single bad assert can result in the user's disk getting wiped even 
 though you had protections in place in the code without asserts that would 
 have prevented it. That is horrible.
The idea is you test your code with assertions enabled, and then only use '-release' when you are sure your program functions correctly. If you are doing critical work or do not trust program input, either do not disable assertions or use a tool like enforce that does not get disabled in release mode.
Jul 28 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 29 July 2014 at 06:35:06 UTC, Daniel Murphy wrote:
 The idea is you test your code with assertions enabled, and 
 then only use '-release' when you are sure your program 
 functions correctly.

 If you are doing critical work or do not trust program input, 
 either do not disable assertions or use a tool like enforce 
 that does not get disabled in release mode.
This is what makes D design by contract almost useless when writing network services :( Unless you have 100% code coverage (and I mean literally 100%) you can't be sure enough to disable assertions with arbitrary user input. And even if you have full coverage you still can't be sure I guess that qualifies as "critical work" but, really, any work is critical when failure results in money loss.
Jul 29 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 12:00 AM, Dicebot wrote:
 On Tuesday, 29 July 2014 at 06:35:06 UTC, Daniel Murphy wrote:
 The idea is you test your code with assertions enabled, and then only use
 '-release' when you are sure your program functions correctly.

 If you are doing critical work or do not trust program input, either do not
 disable assertions or use a tool like enforce that does not get disabled in
 release mode.
This is what makes D design by contract almost useless when writing network services :( Unless you have 100% code coverage (and I mean literally 100%) you can't be sure enough to disable assertions with arbitrary user input. And even if you have full coverage you still can't be sure
You can choose to disable assertions with a switch, or not. Having a choice up to you doesn't make it useless. Also, assertions are not for validating user input.
Jul 29 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 29 July 2014 at 07:31:26 UTC, Walter Bright wrote:
 You can choose to disable assertions with a switch, or not. 
 Having a choice up to you doesn't make it useless.
Yes I know what are options to make it work. I don't know how to make it work "in a good style". This is not just D problem - I feel like something is missing in the design by contract idea, something that actually can make it robust enough to be used without "oh crap" moments.
 Also, assertions are not for validating user input.
This is one of problems. When writing library function you don't exactly know if input is going to be user input. Use enforces - and it won't be possible to optimize away redundant checks. Use assertions and issue may slip uncaught. It feels like for contracts to really work some good implementation of red-green code zones is necessarily, to be able to distinguish user input call paths from internal ones during compilation time.
Jul 29 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 29 July 2014 at 10:13:45 UTC, Dicebot wrote:
 This is one of problems. When writing library function you 
 don't exactly know if input is going to be user input. Use 
 enforces - and it won't be possible to optimize away redundant 
 checks. Use assertions and issue may slip uncaught.
I have taken to using versions and enforce for this. Something like: version(noChecks){} else { version = checks; } void foo(int a) { version(checks) enforce(a > 0); // do work } so the user of the library has to explicitly disable the checks when compiling the library, independent of -release. Also, all functions should document their input assumptions. Binary libraries is a bit different though, I guess you have to distribute 3 versions: debug, release and release-noChecks
Jul 29 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 3:13 AM, Dicebot wrote:
 On Tuesday, 29 July 2014 at 07:31:26 UTC, Walter Bright wrote:
 You can choose to disable assertions with a switch, or not. Having a choice up
 to you doesn't make it useless.
Yes I know what are options to make it work. I don't know how to make it work "in a good style". This is not just D problem - I feel like something is missing in the design by contract idea, something that actually can make it robust enough to be used without "oh crap" moments.
To have an assert despite -release, you can do things like: assert(exp); => if (!exp) assert(0); I generally leave asserts in for released code in my projects. You can see this in dmd which often exhibits a fault as a tripped assert. But if for nothing else, a way to turn them off gives the developer an easy way to see exactly how much they cost him in performance, so he can make the best decision for his application. I've also been known to use debug versioning to add a bunch of extra testing code for dev testing.
 Also, assertions are not for validating user input.
This is one of problems. When writing library function you don't exactly know if input is going to be user input. Use enforces - and it won't be possible to optimize away redundant checks. Use assertions and issue may slip uncaught.
It's a serious, serious mistake to use asserts for user input validation. If passing raw user input to a library function, unless that function is specifically documented to validate it, you've made a big mistake. Asserts are meant to test for logic bugs in the program. Nothing else.
 It feels like for contracts to really work some good implementation of
red-green
 code zones is necessarily, to be able to distinguish user input call paths from
 internal ones during compilation time.
That's not what contracts are for (beating a dead horse). Joel Spolsky made a suggestion I like - have raw user input be of a different type than validated input. That way, functions are clearly and checkably red-green zoned.
Jul 29 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/29/14, 12:35 PM, Walter Bright wrote:
 On 7/29/2014 3:13 AM, Dicebot wrote:
 On Tuesday, 29 July 2014 at 07:31:26 UTC, Walter Bright wrote:
 You can choose to disable assertions with a switch, or not. Having a
 choice up
 to you doesn't make it useless.
Yes I know what are options to make it work. I don't know how to make it work "in a good style". This is not just D problem - I feel like something is missing in the design by contract idea, something that actually can make it robust enough to be used without "oh crap" moments.
To have an assert despite -release, you can do things like: assert(exp); => if (!exp) assert(0);
Fancier: exp || assert(0) is still an expression.
 I generally leave asserts in for released code in my projects. You can
 see this in dmd which often exhibits a fault as a tripped assert.
I wonder how fast dmd would be if we turned assertions off. Would be an interesting experiment to run. Andrei
Jul 29 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Andrei Alexandrescu"  wrote in message news:lr8tcf$l1t$1 digitalmars.com...

 Fancier: exp || assert(0) is still an expression.
Fancier is not always better.
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 6:43 AM, Daniel Murphy wrote:
 "Andrei Alexandrescu"  wrote in message
 news:lr8tcf$l1t$1 digitalmars.com...

 Fancier: exp || assert(0) is still an expression.
Fancier is not always better.
It's better when you need an expression. -- Andrei
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Andrei Alexandrescu"  wrote in message 
news:lrb1ru$30ag$1 digitalmars.com...

 It's better when you need an expression. -- Andrei
Nooooo! That's the kind of thinking that leads to using the comma operator!!!!
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 8:17 AM, Daniel Murphy wrote:
 "Andrei Alexandrescu"  wrote in message
 news:lrb1ru$30ag$1 digitalmars.com...

 It's better when you need an expression. -- Andrei
Nooooo! That's the kind of thinking that leads to using the comma operator!!!!
For that there are lambdas. Before this becomes a silly debate, I was half-serious in the following sense: I get uncomfortable when people say a statement is equivalent with an expression, because replacement can be tedious. I often use that idiom to replace assert with "always assert" inside expressions. Andrei
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Andrei Alexandrescu"  wrote in message news:lrb9jb$57u$1 digitalmars.com...

 Before this becomes a silly debate, I was half-serious in the following 
 sense: I get uncomfortable when people say a statement is equivalent with 
 an expression, because replacement can be tedious. I often use that idiom 
 to replace assert with "always assert" inside expressions.
I guess that's a difference in our programming styles - I never use assert as an expression. I don't like code that uses && || ?: for control flow. Maybe it's because I started with basic? I just looks ugly to me, like you're trying to hide it.
Jul 30 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 29 July 2014 at 19:35:31 UTC, Walter Bright wrote:
 To have an assert despite -release, you can do things like:

    assert(exp);  =>  if (!exp) assert(0);

 I generally leave asserts in for released code in my projects.
You honestly don't smell a problem here? There is a default behavior dmd uses and you (compiler author!) disable it because non-default one seems more practical. If this does not indicate something is wrong with the system I don't now what does.
 You can see this in dmd which often exhibits a fault as a 
 tripped assert.
Exactly. And same is for our Sociomantic projects - those never get compiled with -release because programs have bugs and you want to be able to detect bugs instead of corrupting the service. asserts indicate bug in program logic but removing them in release builds means letting those bugs lose. In practice I can't imagine a situation where one can afford such risk, not even with 100% test coverage (because code paths that trigger assertions are not covered in a working program)
 It's a serious, serious mistake to use asserts for user input 
 validation. If passing raw user input to a library function, 
 unless that function is specifically documented to validate it, 
 you've made a big mistake.
I know it all well and it doesn't help in practice even tiny bit. It is not something as naive as just calling the function with user input. All such cases are programming bugs that do not get caught by tests but trigger upon user input code paths. Bugs that will get unnoticed if default -release is used.
 It feels like for contracts to really work some good 
 implementation of red-green
 code zones is necessarily, to be able to distinguish user 
 input call paths from
 internal ones during compilation time.
That's not what contracts are for (beating a dead horse). Joel Spolsky made a suggestion I like - have raw user input be of a different type than validated input. That way, functions are clearly and checkably red-green zoned.
Ironically it is the very same thing I have suggested in quoted part but you call it wrong :) Thew way it interacts with contracts is that it becomes possible to define validated program sub-system known at compile-time which has much better chance to be tested good enough to afford omitting assertions and contracts.
Jul 30 2014
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Walter Bright"  wrote in message news:lr8t23$kof$1 digitalmars.com...

 To have an assert despite -release, you can do things like:

     assert(exp);  =>  if (!exp) assert(0);
dmd does currently implement it that way, but the spec explicitly says the compiler may assume it is unreachable and optimize based on that. 'halt' is what you should be calling if you want to guarantee a halt in -release mode.
Jul 30 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 06:35:06 UTC, Daniel Murphy wrote:
 The idea is you test your code with assertions enabled, and 
 then only use '-release' when you are sure your program 
 functions correctly.
It never works correctly, until proven correct formally with an automated theorem prover. As I pointed out, even if you only make a mistake in 1 out of 1000 asserts (mistake being having an assert not matching the program logic) you still get a 40% chance of complete failure. No programmer is capable of such a low error rate either. Please note that is not sufficient for the asserts to follow the specification, they must also not contradiction the logic embedded in the program. One contradictive theorem in the optimizer and it will generate garbage. For this to work without formal proofs you will have to: 1. do exhaustive unit-testing of all input, function by function. 2. the function has to be fully deterministic (no multi-threading, floats, timers etc) The key to verifying correctness is that you have 2 separate formulations of the same logic: 1. specification 2. implementation You compare the implementation to the specification. That is what verifying correctness is. If you use the specification for implementation (which is what conflating assert() with assume() is), then you only have the implementation and all discrepancies will lead to contradictions or other flaws that will lead to illegal code-gen. And undetected. This thread gives me an headache… :-(
Jul 29 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/29/2014 03:07 AM, Walter Bright wrote:
 On 7/28/2014 1:49 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 You might want to assert() that you have enough headroom in a statically
 allocated buffer when testing. Say you assert that the buffer is never
 more than
 50% full for normal loads. You obviously don't want the -release build
 to make
 such an assumption!
You're misunderstanding
He still has a point. This is just another case of the keyword not matching the semantics very well. It would be more aptly named 'assume' instead of 'assert' (and be un- safe if release mode is to trust it unconditionally.)
 and misusing assert.

 'assume' is completely redundant with 'assert'.
 ...
Only if you assume _a priori_ the program to be correct.
 To have different debug builds, use debug statements.
'version(assert) assert' is a better match here, because if one uses 'debug assert', there is the possibility of passing both -debug and -release and get the undesired behaviour.
Jul 29 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 20:07:16 UTC, Timon Gehr wrote:
 He still has a point. This is just another case of the keyword 
 not matching the semantics very well. It would be more aptly 
 named 'assume' instead of 'assert' (and be un- safe if release 
 mode is to trust it unconditionally.)
But you cannot check preconditions, postconditions and invariants with an assumption! Assumptions does not have to be checked. They have to be proved. And preferably formally verified. Sure, it might be nice to have 2-5 assumes() in a program to boost optimizers where it fails. Without a proof of correctness? Insane! Seriously, have anyone EVER read a programming book where all examples worked? And those are tiny toy programs and vetted. Heck, even Ole-Johan Dahls book on Verifiable Programming, with Hoare as editor had a fairly long errata. And it was carefully written. Anyway, if you cannot assert() with headroom then you cannot use assert loop invariants in many floating point algorithms. There are plenty of sources of indeterminism in a real execution environment, so anything more than very limited partial correctness is a pipe-dream for any complex interactive program.
 Only if you assume _a priori_ the program to be correct.
Which is insane. Having 2-3 carefully crafted assume() and 500 assert() would be ok (but I am in doubt of even that). Having 500+ assume() is crazy.
Jul 29 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 1:07 PM, Timon Gehr wrote:
 On 07/29/2014 03:07 AM, Walter Bright wrote:
 On 7/28/2014 1:49 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 You might want to assert() that you have enough headroom in a statically
 allocated buffer when testing. Say you assert that the buffer is never
 more than
 50% full for normal loads. You obviously don't want the -release build
 to make
 such an assumption!
You're misunderstanding
He still has a point. This is just another case of the keyword not matching the semantics very well. It would be more aptly named 'assume' instead of 'assert' (and be un- safe if release mode is to trust it unconditionally.)
I find this splitting of hares between assume and assert to be entirely meaningless.
 and misusing assert.

 'assume' is completely redundant with 'assert'.
Only if you assume _a priori_ the program to be correct.
I've read yours and Ola's explanations of the difference, and I still can't discern any difference, other than the spelling.
 To have different debug builds, use debug statements.
'version(assert) assert' is a better match here, because if one uses 'debug assert', there is the possibility of passing both -debug and -release and get the undesired behaviour.
That cure sounds worse than the (supposed) problem. I still have problems convincing people that assert is not to be used to validate user input. Howinell is there any hope of getting anyone to understand all this fine-grained hare-splitting? Heck, I don't see any useful difference between assert and assume.
Jul 29 2014
next sibling parent David Gileadi <gileadis NSPMgmail.com> writes:
On 7/29/14, 1:52 PM, Walter Bright wrote:
 I find this splitting of hares ... to be entirely meaningless.
Hunters claim that rabbit tastes less gamey, if we're going to be splitting anything. (Please forgive the silliness.)
Jul 29 2014
prev sibling next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 20:52:28 UTC, Walter Bright wrote:
 I've read yours and Ola's explanations of the difference, and I 
 still can't discern any difference, other than the spelling.
Here is the difference: action1(cmd){ assert( !lowercase( cmd )); //wrong theorem if(cmd=='format') format_harddisk() } action2(cmd){ assume( !lowercase( cmd )); //wrong theorem if(cmd=='format') format_harddisk() } release: action1(cmd){ if(cmd=='format') format_harddisk() } action2(cmd){ format_harddisk() }
 I still have problems convincing people that assert is not to 
 be used to validate user input.
Has nothing to do with user input. From a correctness perspective there is no such thing as user input. You only get valid input. What you almost always have is a mismatch between specification and implementation. The best you can hope to have is partial correctness. Even with a system for formal verification.
Jul 29 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 21:08:55 UTC, Ola Fosheim Grøstad 
wrote:

Sorry, got that wrong (it is late), meant to do this:

lowercase(str){
   if(...){
      assume(str=='format'); // wrong theorem
   }
    ...
}

action1(cmd){
     cmd = lowercase( cmd );
     if(cmd=='format') format_harddisk()
}

action2(cmd) // the same with assert() instead of assume()

release:

action1(cmd){
    cmd = lowercase(cmd);
    if(cmd=='format') format_harddisk()
}

action2(cmd){
    cmd = lowercase(cmd);
    format_harddisk()
}
Jul 29 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/29/2014 11:08 PM, "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 The best you can hope to have is partial correctness. Even with a system
 for formal verification.
Well, why would this be true?
Jul 29 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 29 July 2014 at 22:07:42 UTC, Timon Gehr wrote:
 On 07/29/2014 11:08 PM, "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= 
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 The best you can hope to have is partial correctness. Even 
 with a system
 for formal verification.
Well, why would this be true?
Because there is no way you can prove say OpenGL drivers to be correct. They are a black box provided by the execution environment.
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 09:22 AM, "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Tuesday, 29 July 2014 at 22:07:42 UTC, Timon Gehr wrote:
 On 07/29/2014 11:08 PM, "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?=
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 The best you can hope to have is partial correctness. Even with a system
 for formal verification.
Well, why would this be true?
Because there is no way you can prove say OpenGL drivers to be correct. They are a black box provided by the execution environment.
I see. (Though I secretly still dare to hope for verified OpenGL drivers, or something analogous: it is not completely out of reach theoretically; the machine can be given a quite precise formal specification.) Note that 'partial correctness' usually means that the program runs correctly conditional on its termination, hence my confusion.
Jul 30 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb2o9$314b$1 digitalmars.com...

 Because there is no way you can prove say OpenGL drivers to be correct.
 They are a black box provided by the execution environment.
I see. (Though I secretly still dare to hope for verified OpenGL drivers, or something analogous: it is not completely out of reach theoretically; the machine can be given a quite precise formal specification.)
But even if the drivers are verified, the hardware might be buggy! And if the hardware's verified, the power source might be unstable!
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 05:33 PM, Daniel Murphy wrote:
 "Timon Gehr"  wrote in message news:lrb2o9$314b$1 digitalmars.com...

 Because there is no way you can prove say OpenGL drivers to be correct.
 They are a black box provided by the execution environment.
I see. (Though I secretly still dare to hope for verified OpenGL drivers, or something analogous: it is not completely out of reach theoretically; the machine can be given a quite precise formal specification.)
But even if the drivers are verified, the hardware might be buggy! And if the hardware's verified,
My understanding is it often is.
 the power source might be unstable!
You should verify power source stability. On a more serious note, are you trying to argue that there are no pragmatic differences in software quality based on the obvious fact that the system running the software is implemented on top of uncertain physics?
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb5pd$1uv$1 digitalmars.com...

 On a more serious note, are you trying to argue that there are no 
 pragmatic differences in software quality based on the obvious fact that 
 the system running the software is implemented on top of uncertain 
 physics?
No, I was saying that in any verified system there will be a portion that is just trust.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 06:30 PM, Daniel Murphy wrote:
 "Timon Gehr"  wrote in message news:lrb5pd$1uv$1 digitalmars.com...

 On a more serious note, are you trying to argue that there are no
 pragmatic differences in software quality based on the obvious fact
 that the system running the software is implemented on top of
 uncertain physics?
No, I was saying that in any verified system there will be a portion that is just trust.
Obviously. (That this was the point was not obvious to me because it already holds in purely formal systems, there is not actually a need to shave off abstractions.)
Jul 30 2014
prev sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 15:24:57 UTC, Timon Gehr wrote:
 I see. (Though I secretly still dare to hope for verified 
 OpenGL drivers, or something analogous: it is not completely 
 out of reach theoretically; the machine can be given a quite 
 precise formal specification.)
There is literally no chance in hell for a verified opengl driver. The number of permutations on the state alone is astronomical and un-testable. Its made even worse by the fact that the hardware changes every year or so. Sources: I am doing an internship at nvidia right now :P
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 05:45 PM, Tofu Ninja wrote:
 On Wednesday, 30 July 2014 at 15:24:57 UTC, Timon Gehr wrote:
 I see. (Though I secretly still dare to hope for verified OpenGL
 drivers, or something analogous: it is not completely out of reach
 theoretically; the machine can be given a quite precise formal
 specification.)
There is literally no chance in hell for a verified opengl driver. The number of permutations on the state alone is astronomical and un-testable. Its made even worse by the fact that the hardware changes every year or so. Sources: I am doing an internship at nvidia right now :P
Noted. Up for a challenge? :)
Jul 30 2014
parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 17:13:47 UTC, Timon Gehr wrote:
 Noted. Up for a challenge? :)
Challenge?
Jul 30 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/29/2014 10:52 PM, Walter Bright wrote:
 On 7/29/2014 1:07 PM, Timon Gehr wrote:
 On 07/29/2014 03:07 AM, Walter Bright wrote:
 On 7/28/2014 1:49 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 You might want to assert() that you have enough headroom in a
 statically
 allocated buffer when testing. Say you assert that the buffer is never
 more than
 50% full for normal loads. You obviously don't want the -release build
 to make
 such an assumption!
You're misunderstanding
He still has a point. This is just another case of the keyword not matching the semantics very well. It would be more aptly named 'assume' instead of 'assert' (and be un- safe if release mode is to trust it unconditionally.)
I find this splitting of hares between assume and assert to be entirely meaningless. ...
They are dual concepts. Assert demands a property to hold, assume provides a property that holds. _According to the previous posts in this discussion_, in release mode, 'assert' provides a property that holds without any demands. All I was saying is that 1. This particular behaviour is characteristic for an assumption, not an assertion, according to the above characterisation, which is standard in certain communities, like people who are into verification of procedural programs. 2. Code containing such a construct must in general be monitored to ensure memory safety, hence can at most be trusted.
 and misusing assert.

 'assume' is completely redundant with 'assert'.
Only if you assume _a priori_ the program to be correct.
...
 To have different debug builds, use debug statements.
'version(assert) assert' is a better match here, because if one uses 'debug assert', there is the possibility of passing both -debug and -release and get the undesired behaviour.
That cure sounds worse than the (supposed) problem. ...
I was just pointing out how to properly prevent optimization based on disabled assertions. (Unless, of course, you want to tell me a compiler may assume that anything in a version(assert) block can be assumed to actually be part of the program by the optimizer, which is very hard to implement, and may not even make sense in all circumstances. BTW what about the following gem? version(assert){} else int x=2; assert({ static if(is(typeof(x))) enum e=loopForever(); return someExpression; }()); Should I expect it to stall compilation starting from a certain optimization level in -release mode, or what should be going on here?)
 I still have problems convincing people that assert is not to be used to
 validate user input. Howinell is there any hope of getting anyone to
 understand all this fine-grained hare-splitting? Heck, I don't see any
 useful difference between assert and assume.
I hope this post cleared it up a little.
Jul 29 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 3:02 PM, Timon Gehr wrote:
 They are dual concepts. Assert demands a property to hold, assume provides a
 property that holds.
A distinction without a difference. potayto, potahto
 1. This particular behaviour is characteristic for an assumption, not an
 assertion, according to the above characterisation, which is standard in
certain
 communities, like people who are into verification of procedural programs.

 2. Code containing such a construct must in general be monitored to ensure
 memory safety, hence can at most be  trusted.
??
 I was just pointing out how to properly prevent optimization based on disabled
 assertions.
??
 (Unless, of course, you want to tell me a compiler may assume that anything in
a
 version(assert) block can be assumed to actually be part of the program by the
 optimizer, which is very hard to implement, and may not even make sense in all
 circumstances.
I don't know what you're assuming (!) the version(assert) even does, as it is not a language feature.
 BTW what about the following gem?

 version(assert){}
 else int x=2;
 assert({
      static if(is(typeof(x))) enum e=loopForever();
      return someExpression;
 }());

 Should I expect it to stall compilation starting from a certain optimization
 level in -release mode, or what should be going on here?)
??
 I hope this post cleared it up a little.
Not a bit. The distinction utterly escapes me.
Jul 29 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 02:48 AM, Walter Bright wrote:
 On 7/29/2014 3:02 PM, Timon Gehr wrote:
 They are dual concepts. Assert demands a property to hold, assume
 provides a
 property that holds.
A distinction without a difference.
Wtf. (Imagine you are arguing with someone who keeps claiming that the distinction between trusted and safe is meaningless and you are roughly in my position.)
 potayto, potahto
 ...
potato.
 1. This particular behaviour is characteristic for an assumption, not an
 assertion, according to the above characterisation, which is standard
 in certain
 communities, like people who are into verification of procedural
 programs.

 2. Code containing such a construct must in general be monitored to
 ensure
 memory safety, hence can at most be  trusted.
?? ...
Undefined behaviour does not preserve memory safety.
 I was just pointing out how to properly prevent optimization based on
 disabled
 assertions.
?? ...
Maybe you weren't following the discussion. What do you think this discussion is about? On 07/28/2014 03:31 PM, Daniel Murphy wrote:
 "Ola Fosheim Grøstad" " wrote in message
 news:vqlvigvgcplkuohudsju forum.dlang.org...

 Please guys, you should not change code-gen based on asserts. They are
 not proofs, they are candidates for formal verification of
 correctness. They are in essence embedded break-point checks. If you
 allow asserts to affect codegen then it becomes a very unsafe feature.
 It's like having a undetected bug in a unit-test introduce bugs in the
 released program. 8-I
The compiler is allowed to not check assertions in release mode. This is because a program that would fail an assertion is a broken program, and by specifying -release you are telling the compiler to assume all assertions pass. I don't see any reason the compiler shouldn't be allowed to change code-gen based on asserts. ...
This is what spawned this subthread. Does this clear up your question marks?
 (Unless, of course, you want to tell me a compiler may assume that
 anything in a
 version(assert) block can be assumed to actually be part of the
 program by the
 optimizer, which is very hard to implement, and may not even make
 sense in all
 circumstances.
I don't know what you're assuming (!) the version(assert) even does, as it is not a language feature. ...
Of course version(assert) is a language feature. Always double-check your claims. It's even documented: http://dlang.org/version.html
...

 I hope this post cleared it up a little.
Not a bit. The distinction utterly escapes me.
This is unfortunate, but I don't know what else to say.
Jul 29 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/29/2014 7:08 PM, Timon Gehr wrote:
 Of course version(assert) is a language feature. Always double-check your
claims.

 It's even documented: http://dlang.org/version.html
You're right. My mistake. I'd forgotten about that.
 Not a bit. The distinction utterly escapes me.
This is unfortunate, but I don't know what else to say.
I don't either. I still have no idea what the difference between assume(i<6) and assert(i<6) is supposed to be.
Jul 29 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright wrote:
 On 7/29/2014 7:08 PM, Timon Gehr wrote:
 Of course version(assert) is a language feature. Always 
 double-check your claims.

 It's even documented: http://dlang.org/version.html
You're right. My mistake. I'd forgotten about that.
 Not a bit. The distinction utterly escapes me.
This is unfortunate, but I don't know what else to say.
I don't either. I still have no idea what the difference between assume(i<6) and assert(i<6) is supposed to be.
main(){ foobar(); assert(false==true) } With assert(): main(){ foobar(); } With assume() the optimizer can: a: proven_locally(main, (false==true)) no_local_dependencies(a) all_paths_go_through(a) b: proven_globally(false==true) for_all_conditional_expressions_try_to_prove_false() At this point all conditionals are false and removed. Complete wipe out. Nothing remains. here's another version: foo(){ assume(true==false); } version(RELEASE_MODE){ foobar(){ foo(); } } ... main(){ foobar(); }
Jul 30 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 12:17 AM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
[...]
This is a complete misunderstanding of what assert is. Assert means the expression must evaluate to true, if it does not, it's a program bug. This is the case regardless of release mode or not.
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 09:13:56 UTC, Walter Bright wrote:
 On 7/30/2014 12:17 AM, "Ola Fosheim Grøstad" 
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
[...]
This is a complete misunderstanding of what assert is. Assert means the expression must evaluate to true, if it does not, it's a program bug. This is the case regardless of release mode or not.
Yes, that is my argument too. But you claim it isn't. You claim it can be used for optimization as an annotation. Which is flat out wrong. This discussion will go nowhere until we both agree on what Hoare Logic is capable of and what an annotation can be used for. O-J. Dahl's book Verifiable Programming is my main reference point. I read it in 3-4 days (before an exam) so it isn't too hard, but there are probably more updated books on the topic. Wikipedia does a fair job. http://en.wikipedia.org/wiki/Hoare_logic Allowing assert(0) as an annotation is like allowing assume(true==false). Bearophile is right in disliking the semantics and wanting halt() instead. D would be much better off taking the direction of HAVOC: http://research.microsoft.com/en-us/downloads/a6d296dc-e42b-4789-a720-bd3ea7b64487/
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
Let's try to me more formal about it then.

"assert(X)" means: !(X) || bottom

"assume(X)" means: X
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 10:17:58 UTC, Ola Fosheim Grøstad 
wrote:
 Let's try to me more formal about it then.

 "assert(X)" means: !(X) || bottom

 "assume(X)" means: X
Got that wrong (so much for correctness!): "assert(X)" means: X || bottom "assume(X)" means: X
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
Here is a link to the original paper where C.A.R. Hoare 
introduces assertions. Yes "assert()" in C is the same. The D 
spec claims to provide C-style assertions. That means it should 
abide to what is described in this paper:

http://sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf

If not, call it something else.
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:ilqxnvyqwfmcasxnbjko forum.dlang.org...

 Here is a link to the original paper where C.A.R. Hoare introduces 
 assertions. Yes "assert()" in C is the same. The D spec claims to provide 
 C-style assertions. That means it should abide to what is described in 
 this paper:

 http://sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf

 If not, call it something else.
So you'll be happy if we call them D-style assertions?
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 12:11:31 UTC, Daniel Murphy wrote:
 So you'll be happy if we call them D-style assertions?
Program verification has been at the core of CS for over 40 years. This is bachelor grade stuff. If you keep inventing your own semantics for well-established terminology then nobody will take D seriously. For instance, if assert(false) is proven reachable then it means either: 1. the specification is inconsistent/contradictory (thus wrong) 2. the program has been proved incorrect The compiler should then refuse to generate code. If it is not proven reachable then emitting HALT might be ok. Basically D ought to allow a verifier to work on a D program, then only emit runtime checks for asserts it cannot handle. And also allow them to trigger as early as possible.
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:umhhokwldfouodjhvooh forum.dlang.org...

 Program verification has been at the core of CS for over 40 years. This is 
 bachelor grade stuff. If you keep inventing your own semantics for 
 well-established terminology then nobody will take D seriously.
It sure seems easy to make D not be taken seriously. Every day somebody's making this claim about something.
 For instance, if assert(false) is proven reachable then it means either:

 1. the specification is inconsistent/contradictory (thus wrong)
 2. the program has been proved incorrect

 The compiler should then refuse to generate code. If it is not proven 
 reachable then emitting HALT might be ok.
You say this as if it's a law of physics. One of the great things about working on D is that we get to assign the semantics that we decide are most useful, and don't have to follow what other people have done. A good example is D's purity. It doesn't match traditional definitions of purity, but it's useful. I'm sure that's another reason not to take D seriously.
 Basically D ought to allow a verifier to work on a D program, then only 
 emit runtime checks for asserts it cannot handle. And also allow them to 
 trigger as early as possible.
You're just saying it should work the way you think it should work. The fact that other people have defined it that way before does not outweigh the value of defining assert the way I've described IMO. I don't think the safety concerns are warranted either, due to the existing optimizer precedent. Any verifier for D would have to understand the semantics of D's assert. If the verifier assumes asserts are always replaced with a runtime check, then it will be fine as long as you don't compile with -release.
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 13:14:11 UTC, Daniel Murphy wrote:
 For instance, if assert(false) is proven reachable then it 
 means either:

 1. the specification is inconsistent/contradictory (thus wrong)
 2. the program has been proved incorrect

 The compiler should then refuse to generate code. If it is not 
 proven reachable then emitting HALT might be ok.
You say this as if it's a law of physics. One of the great things about working on D is that we get to assign the semantics that we decide are most useful, and don't have to follow what other people have done.
It follows the law of logic: http://en.wikipedia.org/wiki/Hoare_logic http://en.wikipedia.org/wiki/Propositional_calculus
 Any verifier for D would have to understand the semantics of 
 D's assert.
If D gets this it will be a general verifier adapted to D. That follows the rules of established sound logic developed over the past 2300 years. All asserts should be established as either true or unknown. Assert(false) is weird. It is basically saying that true==false and asks you to prove that over a statement/loop that may or may not terminate. http://coq.inria.fr/distrib/8.2/contribs/HoareTut.exgcd.html «Basic Hoare logic is not well-suited for reasoning about non-terminating programs. In total correctness, postconditions of non-terminating programs are not provable. In partial correctness, a non-terminating program satisfies any (unsatisfiable) postcondition.»
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:lzrtpkfytndikacweici forum.dlang.org...

 It follows the law of logic:

 http://en.wikipedia.org/wiki/Hoare_logic
 http://en.wikipedia.org/wiki/Propositional_calculus
You're missing the point - we don't have to follow those definitions. Maybe we should - but the fact that those systems are defined that way doesn't intrinsically mean we have to define asserts behaviour that way.
 Any verifier for D would have to understand the semantics of D's assert.
If D gets this it will be a general verifier adapted to D. That follows the rules of established sound logic developed over the past 2300 years.
Yes, and the adaption will have to take into account D's semantics. This doesn't mean D can't differ from other established definitions.
 All asserts should be established as either true or unknown. Assert(false) 
 is weird. It is basically saying that true==false and asks you to prove 
 that over a statement/loop that may or may not terminate.
assert(false) is saying that the condition will never be met, and that branch of execution is impossible in a correct program. (although it is often abused to mean 'unimplemented')
Jul 30 2014
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 4:17 AM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright wrote:
 On 7/29/2014 7:08 PM, Timon Gehr wrote:
 Of course version(assert) is a language feature. Always double-check
 your claims.

 It's even documented: http://dlang.org/version.html
You're right. My mistake. I'd forgotten about that.
 Not a bit. The distinction utterly escapes me.
This is unfortunate, but I don't know what else to say.
I don't either. I still have no idea what the difference between assume(i<6) and assert(i<6) is supposed to be.
main(){ foobar(); assert(false==true) } With assert(): main(){ foobar(); }
Could you show an example that's a bit more complex and useful? I'm with Walter that I don't see any difference between assert and assume. For example: --- int x = ...; int y = ...; assert(x + y == 3); writeln(x + y); --- If the assert fails then the program crashes in non-release mode. So after the assert the compiler knows that "x + y == 3" so that it can replace "writeln(x + y)" with "writeln(3)" (assuming the compiler is the smartest on earth). Now, if you compile in release mode, according to Walter, all the "asserts" are gone (which, as a side note, is something I don't like: in every case it should throw an AssertError). So the question is: can the compiler still replace that writeln call? It should, but since there's nothing there preventing x + y to be different than 3 (the assertion is gone), the compiler can't replace it anymore. With assume... what's the difference? You say the compiler should replace it anyway because that's what you assume? There's nothing left at release mode to verify that for you. Could you elaborate this example using assert and assume? Thanks!
Jul 30 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lravtd$2siq$1 digitalmars.com...

 Now, if you compile in release mode, according to Walter, all the 
 "asserts" are gone (which, as a side note, is something I don't like: in 
 every case it should throw an AssertError). So the question is: can the 
 compiler still replace that writeln call? It should, but since there's 
 nothing there preventing x + y to be different than 3 (the assertion is 
 gone), the compiler can't replace it anymore.
That's the whole point - the compiler theoretically can optimize as if the assert is checked. (This example uses assert(0) because this behaviour is actually in the spec) if (x != 3) assert(0); if (x == 3) deleteAllMyFiles(); The compiler is allowed to treat assert(0) as unreachable - and if it's unreachable then it must be impossible for x to be != 3. So it becomes: deleteAllMyFiles(); He's asking for assert to mean 'check this condition' and assume to mean 'optimize as if this is a mathematical identity'.
Jul 30 2014
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 11:44 AM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message news:lravtd$2siq$1 digitalmars.com...

 Now, if you compile in release mode, according to Walter, all the
 "asserts" are gone (which, as a side note, is something I don't like:
 in every case it should throw an AssertError). So the question is: can
 the compiler still replace that writeln call? It should, but since
 there's nothing there preventing x + y to be different than 3 (the
 assertion is gone), the compiler can't replace it anymore.
That's the whole point - the compiler theoretically can optimize as if the assert is checked. (This example uses assert(0) because this behaviour is actually in the spec) if (x != 3) assert(0); if (x == 3) deleteAllMyFiles(); The compiler is allowed to treat assert(0) as unreachable - and if it's unreachable then it must be impossible for x to be != 3. So it becomes: deleteAllMyFiles(); He's asking for assert to mean 'check this condition' and assume to mean 'optimize as if this is a mathematical identity'.
And how is that different if instead of: if (x != 3) assert(0); you write: assume(x != 3); ?
Jul 30 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lrb21p$30lf$1 digitalmars.com...

 He's asking for assert to mean 'check this condition' and assume to mean
 'optimize as if this is a mathematical identity'.
And how is that different if instead of: if (x != 3) assert(0); you write: assume(x != 3);
Because if assert only means 'check this condition' then the optimizer can't optimize based on the assumption that it's true.
Jul 30 2014
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 12:19 PM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message news:lrb21p$30lf$1 digitalmars.com...

 He's asking for assert to mean 'check this condition' and assume to
mean
 'optimize as if this is a mathematical identity'.
And how is that different if instead of: if (x != 3) assert(0); you write: assume(x != 3);
Because if assert only means 'check this condition' then the optimizer can't optimize based on the assumption that it's true.
Assert means: check this condition and terminate the program if it doesn't hold. So why can't the compiler optimize based on this?
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lrb6ev$2ln$1 digitalmars.com...

 Because if assert only means 'check this condition' then the optimizer
 can't optimize based on the assumption that it's true.
Assert means: check this condition and terminate the program if it doesn't hold. So why can't the compiler optimize based on this?
The compiler can optimize based on this. But with that definition of assert it can't optimize based on the assumption that the condition is always true, without checking it first.
Jul 30 2014
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 1:39 PM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message news:lrb6ev$2ln$1 digitalmars.com...

 Because if assert only means 'check this condition' then the optimizer
 can't optimize based on the assumption that it's true.
Assert means: check this condition and terminate the program if it doesn't hold. So why can't the compiler optimize based on this?
The compiler can optimize based on this. But with that definition of assert it can't optimize based on the assumption that the condition is always true, without checking it first.
So assume stays there in release mode and makes the program crash if it doesnt' hold?
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lrba7m$5o4$1 digitalmars.com... 

 So assume stays there in release mode and makes the program crash if it 
 doesnt' hold?
Yes. Well, might make it crash. Might make it just give the wrong result.
Jul 30 2014
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 2:47 PM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message news:lrba7m$5o4$1 digitalmars.com...
 So assume stays there in release mode and makes the program crash if
 it doesnt' hold?
Yes. Well, might make it crash. Might make it just give the wrong result.
So... it's exactly the same as assert?
Jul 30 2014
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 2:59 PM, Ary Borenszweig wrote:
 On 7/30/14, 2:47 PM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message news:lrba7m$5o4$1 digitalmars.com...
 So assume stays there in release mode and makes the program crash if
 it doesnt' hold?
Yes. Well, might make it crash. Might make it just give the wrong result.
So... it's exactly the same as assert?
Sorry, I misunderstood your answer. If assume stays in release mode then that's the difference. The problem then is that assert doesn't stay in release mode so the compiler can't make any assumption about the code that follows the "assert" because asserts are removed in release mode. In my opinion, removing asserts in release-mode is the big problem here. How expensive can an assert be? Do you really want to debug that? Wouldn't it be better to get an exception? If the compiler *never* removes asserts, then assert and assume have the same meaning.
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lrbbtl$778$1 digitalmars.com...

 If assume stays in release mode then that's the difference. The problem 
 then is that assert doesn't stay in release mode so the compiler can't 
 make any assumption about the code that follows the "assert" because 
 asserts are removed in release mode.
assume never creates a runtime check, assert does in non-release mode. assert's condition can't be 'assumed' in non-release mode, or the compiler could simply assume the check passed an non emit it.
 In my opinion, removing asserts in release-mode is the big problem here. 
 How expensive can an assert be? Do you really want to debug that? Wouldn't 
 it be better to get an exception?
That's the whole point of assert+release. If you always want an exception, simply use enforce.
 If the compiler *never* removes asserts, then assert and assume have the 
 same meaning.
No, because assert puts in a runtime check in non-release. Hopefully my table helps. I'm not sure which assert I'm talking about half the time.
Jul 30 2014
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ary Borenszweig"  wrote in message news:lrbbp8$6t2$1 digitalmars.com... 

 So... it's exactly the same as assert?
Yes! Wait, no. Sorta. http://forum.dlang.org/post/lrb608$26m$1 digitalmars.com
Jul 30 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 30 July 2014 at 15:12:58 UTC, Ary Borenszweig wrote:
 On 7/30/14, 11:44 AM, Daniel Murphy wrote:
 "Ary Borenszweig"  wrote in message 
 news:lravtd$2siq$1 digitalmars.com...

 Now, if you compile in release mode, according to Walter, all 
 the
 "asserts" are gone (which, as a side note, is something I 
 don't like:
 in every case it should throw an AssertError). So the 
 question is: can
 the compiler still replace that writeln call? It should, but 
 since
 there's nothing there preventing x + y to be different than 3 
 (the
 assertion is gone), the compiler can't replace it anymore.
That's the whole point - the compiler theoretically can optimize as if the assert is checked. (This example uses assert(0) because this behaviour is actually in the spec) if (x != 3) assert(0); if (x == 3) deleteAllMyFiles(); The compiler is allowed to treat assert(0) as unreachable - and if it's unreachable then it must be impossible for x to be != 3. So it becomes: deleteAllMyFiles(); He's asking for assert to mean 'check this condition' and assume to mean 'optimize as if this is a mathematical identity'.
And how is that different if instead of: if (x != 3) assert(0); you write: assume(x != 3); ?
assert(0) is treated as a special case, different from assert(someRuntimeExpression)
Jul 30 2014
prev sibling next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 14:36:30 UTC, Ary Borenszweig wrote:
 Could you show an example that's a bit more complex and useful? 
 I'm with Walter that I don't see any difference between assert 
 and assume.
assume provide additional axioms to the ones implicit in the program. assert provide theorems to be proven. assume provide claims that already are proven (or just defined as a requirement imposed on the environment). For instance after a system call, you might have a specification that states exactly what you can assume after it returns. That specification you can specify as assume() and you can optimize on those, safely. assert() you cannot optimize on safely. Those are theorems that are yet to be proven.
Jul 30 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
Here is a set of examples of annotated programs that have been 
formally proved correct for those interested:

http://toccata.lri.fr/gallery/why3.en.html

The advantage of formally separating what is proven from what is 
to be proved is quite obvious. You can generate annotated 
bindings for libraries and frameworks that can both increase 
correctness and provide semantic information that can be relied 
on (for optimization and other purposes).
Jul 30 2014
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Ola Fosheim Grøstad:

 Here is a set of examples of annotated programs that have been 
 formally proved correct for those interested:

 http://toccata.lri.fr/gallery/why3.en.html
I have started to read those pages, it looks interesting. From one of the first links (Sudoku solver): valid values are 0..9. 0 denotes an empty cell predicate valid_values (g:grid) = forall i. is_index i -> 0 <= g[i] <= 9 So can't they represent that the value 0 is an empty cell in the code instead of comments? (I think this is possible in Ada language). It's a bit sad that D1 has removed the literate programming feature of D1. In Haskell it's used all the time. Bye, bearophile
Jul 30 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ola Fosheim Grøstad:

 Here is a set of examples of annotated programs that have been 
 formally proved correct for those interested:

 http://toccata.lri.fr/gallery/why3.en.html
More comments: ------------------- A problem with code like this is that it's drowing in noise. The precondition/invariant/variant code in the 't3' function is obscuring what the code is actually doing on the data: http://toccata.lri.fr/gallery/queens.en.html One way to solve this problem: the editor has to show the testing code with a different background color (and collapse it away on request). (And I'd like to read the "More realistic code with bitwise operations"). ------------------- I have added a third version here: http://rosettacode.org/wiki/Dutch_national_flag_problem#More_Verified_Version Adapted from: http://toccata.lri.fr/gallery/flag.en.html D lacks the pre-state (old a) and (at a 'Init), the loop variants, the loop invariants (despite D has a invariant keyword used for struct/classe invariants), ghost variables (I have used 'riPred' and 'aInit' for the loop variants and invariants. I have used a debug{} to simulate them in D), and writing the post-condition was a bit of pain. Bye, bearophile
Jul 31 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 31 July 2014 at 11:32:11 UTC, bearophile wrote:
 A problem with code like this is that it's drowing in noise. 
 The precondition/invariant/variant code in the 't3' function is 
 obscuring what the code is actually doing on the data:
 http://toccata.lri.fr/gallery/queens.en.html
Yes, if the algorithm is a bit involved it becomes complicated. It is also expensive to get right, $100-$1000 per line of code? However, simple stuff that you often have in a standard library is usually easier on the eyes and easier to get right: http://toccata.lri.fr/gallery/power.en.html So, having a formally proven standard library would be quite within reach. And if you also have inlining + assume() you could do stuff like this inline uint floor_sqrt(long x){ assert(x>=0); uint r = _proven_floor_sqrt(x); assume(r<=x*x); assume( (r>(x-1)*(x-1)) || x==0 ); return r } Precompiled library: uint _proven_floor_sqrt(long x){ assume(x>=0); // not test necessary, use this for optimization return ... } Another nice thing is that you can replace _proven… with handwritten machine language that has been exhaustively tested (all combinations) and still let the compiler assume() the postconditions with no runtime cost. Another area where assume() is useful is for reading hardware registers that are guaranteed to have certain values so no runtime check is needed: auto x = read_hw_register(123456); assume( x==0 || x==1 || x==4 );
 I have added a third version here:
 http://rosettacode.org/wiki/Dutch_national_flag_problem#More_Verified_Version
Thanks, I like the way you go about this. Experimenting with the syntax this way.
 D lacks the pre-state (old a) and (at a 'Init), the loop 
 variants, the loop invariants (despite D has a invariant 
 keyword used for struct/classe invariants),
Yeah, I also think having invariant() in loops makes for more readable code than assert/enforce. I imagine that you could specify a reduced set of D and do this: D-source => machinetranslate => prover-source prover-source => prover => proof-source proof-source + prover-source => machinetranslate => D-source w/assume() etc Btw, here is an example of an open source operating system kernel vetted against a haskell modell of the kernel: http://sel4.systems/ https://github.com/seL4/seL4/tree/master/haskell So, this formal correctness support in one way or another is clearly a valuable direction for a system level programming language.
Jul 31 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 01:32 PM, bearophile wrote:
 More comments:

 -------------------

 A problem with code like this is that it's drowing in noise. The
 precondition/invariant/variant code in the 't3' function is obscuring
 what the code is actually doing on the data:
 http://toccata.lri.fr/gallery/queens.en.html
It is not an inherent issue with verification. One way to avoid this is to allow correctness proofs to be done in a separate place.
Jul 31 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 7:36 AM, Ary Borenszweig wrote:
 Now, if you compile in release mode, according to Walter, all the "asserts" are
 gone (which, as a side note, is something I don't like: in every case it should
 throw an AssertError). So the question is: can the compiler still replace that
 writeln call?
Yes.
Jul 30 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 20:47:30 UTC, Walter Bright wrote:
 On 7/30/2014 7:36 AM, Ary Borenszweig wrote:
 Now, if you compile in release mode, according to Walter, all 
 the "asserts" are
 gone (which, as a side note, is something I don't like: in 
 every case it should
 throw an AssertError). So the question is: can the compiler 
 still replace that
 writeln call?
Yes.
This on the other hand is a terrible, terrible misuse of assert. You need distinguish between what is assumed to hold and what is proved to hold to chain together pieces of proven programs. So what one function require (preconditions) you need to assert before calling the function. On the other hand, what the function asserts you can assume to hold after the call. So: assert(X) ---- function call to precompiled library code assume(X) ...statements assert(Y) ---- function return from precompiled library code assume(Y) Pretty clear, now huh?
Jul 30 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:06 PM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 Pretty clear, now huh?
I'm curious if you can find an existing computer language that implements both assume and assert and draws some sort of semantic distinction between them. bearophile's Microsoft C++ example isn't one of them, as it is nothing more than a workaround for the C Standard requiring assert to be a macro.
Jul 30 2014
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 5:47 PM, Walter Bright wrote:
 On 7/30/2014 7:36 AM, Ary Borenszweig wrote:
 Now, if you compile in release mode, according to Walter, all the
 "asserts" are
 gone (which, as a side note, is something I don't like: in every case
 it should
 throw an AssertError). So the question is: can the compiler still
 replace that
 writeln call?
Yes.
So if there's a logic in your program, in release mode it won't crash immediately but continue with undefined behaviour. I can't imagine any case where I would want this in my programs. I think I would always use enforce and never assert.
Jul 30 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:32 PM, Ary Borenszweig wrote:
 So if there's a logic in your program, in release mode it won't crash
 immediately but continue with undefined behaviour.
That's right.
 I can't imagine any case where I would want this in my programs.
Don't use -release, then.
Jul 30 2014
prev sibling next sibling parent reply "David Bregman" <drb sfu.ca> writes:
On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright wrote:
 I don't either. I still have no idea what the difference 
 between assume(i<6) and assert(i<6) is supposed to be.
assert: is a runtime check of the condition. is a debugging/correctness checking feature. is used when the expression is believed true, but is not proven so. (if it was proven, then there is no purpose in asserting it with a redundant runtime check that is guaranteed to never activate.) assume: passes a hint to the optimizer to allow better code generation. is used when the expression is proven to be true (by the programmer, like trusted). The only relation between the two is that if a runtime check for (x) is inserted at some point, it is safe to insert an assume(x) statement afterwards, because x is known true at that point. If assert degenerates to assume in release mode, any bugs in the program could potentially cause a lot more brittleness and unexpected/undefined behavior than they otherwise would have. In particular, code generation based on invalid assumptions could be memory unsafe.
Jul 30 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 12:54 AM, David Bregman wrote:
 On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright wrote:
 I don't either. I still have no idea what the difference between assume(i<6)
 and assert(i<6) is supposed to be.
assert: is a runtime check of the condition. is a debugging/correctness checking feature. is used when the expression is believed true, but is not proven so. (if it was proven, then there is no purpose in asserting it with a redundant runtime check that is guaranteed to never activate.) assume: passes a hint to the optimizer to allow better code generation. is used when the expression is proven to be true (by the programmer, like trusted).
It still means the same thing as assert.
 The only relation between the two is that if a runtime check for (x) is
inserted
 at some point, it is safe to insert an assume(x) statement afterwards, because
x
 is known true at that point.
I.e. they're the same thing.
 If assert degenerates to assume in release mode, any bugs in the program could
 potentially cause a lot more brittleness and unexpected/undefined behavior than
 they otherwise would have. In particular, code generation based on invalid
 assumptions could be memory unsafe.
Which is why assert can also do a runtime check.
Jul 30 2014
parent reply "David Bregman" <drb sfu.ca> writes:
On Wednesday, 30 July 2014 at 09:11:31 UTC, Walter Bright wrote:
 On 7/30/2014 12:54 AM, David Bregman wrote:
 On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright 
 wrote:
 I don't either. I still have no idea what the difference 
 between assume(i<6)
 and assert(i<6) is supposed to be.
assert: is a runtime check of the condition. is a debugging/correctness checking feature. is used when the expression is believed true, but is not proven so. (if it was proven, then there is no purpose in asserting it with a redundant runtime check that is guaranteed to never activate.) assume: passes a hint to the optimizer to allow better code generation. is used when the expression is proven to be true (by the programmer, like trusted).
It still means the same thing as assert.
 The only relation between the two is that if a runtime check 
 for (x) is inserted
 at some point, it is safe to insert an assume(x) statement 
 afterwards, because x
 is known true at that point.
I.e. they're the same thing.
 If assert degenerates to assume in release mode, any bugs in 
 the program could
 potentially cause a lot more brittleness and 
 unexpected/undefined behavior than
 they otherwise would have. In particular, code generation 
 based on invalid
 assumptions could be memory unsafe.
Which is why assert can also do a runtime check.
I think you misread, none of that follows from what I wrote. Also, "Nuh-uh, they are too the same" is not a valid argument. Can you please address the fact that assume is not safe? How do you propose to preserve memory safety in release mode if you remove runtime checks for asserts but still assume the condition for codegen?
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 1:56 PM, David Bregman wrote:
 Can you please address the fact that assume is not  safe?
 How do you propose to
 preserve memory safety in release mode if you remove runtime checks for asserts
 but still assume the condition for codegen?
D's safe feature is not semantically tied to D's assert expressions.
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 11:28 PM, Walter Bright wrote:
 On 7/30/2014 1:56 PM, David Bregman wrote:
 Can you please address the fact that assume is not  safe?
 How do you propose to
 preserve memory safety in release mode if you remove runtime checks
 for asserts
 but still assume the condition for codegen?
D's safe feature is not semantically tied to D's assert expressions.
He understands that and notes that this contradicts the promise of safe.
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 2:34 PM, Timon Gehr wrote:
 He understands that and notes that this contradicts the promise of  safe.
No, it does not. safe never promises that "all your asserts are correct". safe's promise is one of memory safety, not a promise of program correctness.
Jul 30 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 11:42 PM, Walter Bright wrote:
 On 7/30/2014 2:34 PM, Timon Gehr wrote:
 He understands that and notes that this contradicts the promise of  safe.
No, it does not. safe never promises that "all your asserts are correct". safe's promise is one of memory safety,
Indeed it is.
 not a promise of program correctness.
There is some interplay. void foo(size_t i,int[] a) safe{ assert(i<a.length); a[i] ='D'; // boom } Pass -release and the bounds check may be removed from the line annotated 'boom' based on the elided but assumed to be valid assertion, and your memory safety guarantee is out the window. Unless one thinks incorrect programs shouldn't get any guarantees from safe, this is a problem.
Jul 30 2014
prev sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/30/14 23:42, Walter Bright via Digitalmars-d wrote:
 On 7/30/2014 2:34 PM, Timon Gehr wrote:
 He understands that and notes that this contradicts the promise of  safe.
No, it does not. safe never promises that "all your asserts are correct". safe's promise is one of memory safety, not a promise of program correctness.
void f(ubyte[] a) safe { assert(a.length>99); a[88] = a[77]; } artur
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
 On 07/30/14 23:42, Walter Bright via Digitalmars-d wrote:
 On 7/30/2014 2:34 PM, Timon Gehr wrote:
 He understands that and notes that this contradicts the promise of  safe.
No, it does not. safe never promises that "all your asserts are correct". safe's promise is one of memory safety, not a promise of program correctness.
void f(ubyte[] a) safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
Jul 30 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

    void f(ubyte[] a)  safe { assert(a.length>99); a[88] = 
 a[77]; }
The compiler will insert array bounds checking for you.
But if your "assert" is the same as an assume(), then the optimizer should remove bounds checks (otherwise it's a lousy implementation of assume()) and leave no tests whatsoever inside the function f. So now you now have a safe function that is unsafe. I think you are still missing the essential difference between assume and assert. Bye, bearophile
Jul 30 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
 So now you now have a safe function that is unsafe.
Even in debug builds. Bye, bearophile
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 12:55 AM, bearophile wrote:
 So now you now have a safe function that is unsafe.
Even in debug builds. Bye, bearophile
Why?
Jul 30 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 3:40 PM, bearophile wrote:
 Walter Bright:

    void f(ubyte[] a)  safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
But if your "assert" is the same as an assume(), then the optimizer should remove bounds checks (otherwise it's a lousy implementation of assume()) and leave no tests whatsoever inside the function f. So now you now have a safe function that is unsafe.
That's a good point. You could reasonably argue that such an optimization should not happen.
 I think you are still missing the essential difference between assume and
assert.
How does assume improve the situation?
Jul 30 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 That's a good point. You could reasonably argue that such an 
 optimization should not happen.
I agree. Turning D assert() in a kind of a assert-assume hybrid will be a mistake.
 I think you are still missing the essential difference between 
 assume and assert.
How does assume improve the situation?
I didn't ask for an assume in this thread. See what I am asking for: http://forum.dlang.org/thread/jrxrmcmeksxwlyuitzqp forum.dlang.org?page=22#post-kjqjompjdhmbmzyhbzbb:40forum.dlang.org The answer I've given to Andrei is generic, but I can give more details. Bye, bearophile
Jul 30 2014
prev sibling next sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
On Wednesday, 30 July 2014 at 22:30:59 UTC, Walter Bright wrote:
 On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
    void f(ubyte[] a)  safe { assert(a.length>99); a[88] = 
 a[77]; }
The compiler will insert array bounds checking for you.
Trying to understand what your position is: In release mode, but with bounds checking enabled, would the compiler a) be allowed to replace this with a RangeError or, say, ud2 or another halt()-type instruction? b) treat any call to f() as undefined behavior? Cheers, David
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 3:41 PM, David Nadlinger wrote:
 On Wednesday, 30 July 2014 at 22:30:59 UTC, Walter Bright wrote:
 On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
    void f(ubyte[] a)  safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
Trying to understand what your position is: In release mode, but with bounds checking enabled, would the compiler a) be allowed to replace this with a RangeError or, say, ud2 or another halt()-type instruction? b) treat any call to f() as undefined behavior?
I think that's a good example. My understanding (I know it wasn't me who was asked...): the presence of assert should not influence the introduction of bounds checks. Andrei
Jul 30 2014
parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/31/14 01:14, Andrei Alexandrescu via Digitalmars-d wrote:
 On 7/30/14, 3:41 PM, David Nadlinger wrote:
 On Wednesday, 30 July 2014 at 22:30:59 UTC, Walter Bright wrote:
 On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
    void f(ubyte[] a)  safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
Trying to understand what your position is: In release mode, but with bounds checking enabled, would the compiler a) be allowed to replace this with a RangeError or, say, ud2 or another halt()-type instruction? b) treat any call to f() as undefined behavior?
I think that's a good example. My understanding (I know it wasn't me who was asked...): the presence of assert should not influence the introduction of bounds checks.
But it would. Special casing just the built-in types would only avoid the problem for built-in types. User defined types that handle the bounds checks differently would still be affected (and unsafe). artur
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 4:29 PM, Artur Skawina via Digitalmars-d wrote:
 On 07/31/14 01:14, Andrei Alexandrescu via Digitalmars-d wrote:
 On 7/30/14, 3:41 PM, David Nadlinger wrote:
 On Wednesday, 30 July 2014 at 22:30:59 UTC, Walter Bright wrote:
 On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
     void f(ubyte[] a)  safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
Trying to understand what your position is: In release mode, but with bounds checking enabled, would the compiler a) be allowed to replace this with a RangeError or, say, ud2 or another halt()-type instruction? b) treat any call to f() as undefined behavior?
I think that's a good example. My understanding (I know it wasn't me who was asked...): the presence of assert should not influence the introduction of bounds checks.
But it would. Special casing just the built-in types would only avoid the problem for built-in types. User defined types that handle the bounds checks differently would still be affected (and unsafe).
I think bounds checking is an intrinsic feature of the language, not something easily configurable. -- Andrei
Jul 30 2014
parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/31/14 02:12, Andrei Alexandrescu via Digitalmars-d wrote:

 I think bounds checking is an intrinsic feature of the language, not something
easily configurable.
The problem is with asserts that cause the runtime checks to be eliminated. An simple assert would be enough to bypass safe. artur
Jul 30 2014
prev sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/31/14 00:31, Walter Bright via Digitalmars-d wrote:
 On 7/30/2014 3:20 PM, Artur Skawina via Digitalmars-d wrote:
 On 07/30/14 23:42, Walter Bright via Digitalmars-d wrote:
  safe's promise is one of memory safety, not a promise of program correctness.
void f(ubyte[] a) safe { assert(a.length>99); a[88] = a[77]; }
The compiler will insert array bounds checking for you.
No, with the assert definition you're proposing, it won't. It would be allowed to optimize away the bounds check. And this is just one of many problems with the assert==assume approach. artur
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote:
 No, with the assert definition you're proposing, it won't. It would
 be allowed to optimize away the bounds check. And this is just one of
 many problems with the assert==assume approach.
Please explain how assume would behave any differently.
Jul 30 2014
next sibling parent reply =?UTF-8?Q?Tobias=20M=C3=BCller?= <troplin bluewin.ch> writes:
Walter Bright <newshound2 digitalmars.com> wrote:
 On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote:
 No, with the assert definition you're proposing, it won't. It would
 be allowed to optimize away the bounds check. And this is just one of
 many problems with the assert==assume approach.
Please explain how assume would behave any differently.
It wouldn't and that's the point. If you have (a more harmless) assert _and_ assume you can still use assert, which would then _not_ allow those optimization. Tobi
Jul 30 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 5:50 PM, Tobias Müller wrote:
 Walter Bright <newshound2 digitalmars.com> wrote:
 On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote:
 No, with the assert definition you're proposing, it won't. It would
 be allowed to optimize away the bounds check. And this is just one of
 many problems with the assert==assume approach.
Please explain how assume would behave any differently.
It wouldn't and that's the point.
So we're back to assert and assume being the same thing. Ok.
Jul 30 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 So we're back to assert and assume being the same thing. Ok.
They aren't, and they shouldn't be, regardless the number of times you say they are. Bye, bearophile
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 9:51 PM, bearophile wrote:
 Walter Bright:
 So we're back to assert and assume being the same thing. Ok.
They aren't, and they shouldn't be, regardless the number of times you say they are.
Show me a piece of code with different behavior. Start with the array bounds thing.
Jul 30 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Show me a piece of code with different behavior. Start with the 
 array bounds thing.
People have already shown you code that behaves differently with assert and assume. But you have redefined "assert" to mean a mix of assume and assert. So before me answering you have to switch back to use the common definition of assert(). Bye, bearophile
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 10:16 PM, bearophile wrote:
 Walter Bright:
 Show me a piece of code with different behavior. Start with the array bounds
 thing.
People have already shown you code that behaves differently with assert and assume.
I'd like to see what you are saying is different in a real example.
 But you have redefined "assert" to mean a mix of assume and assert.
I haven't redefined anything. It's always been that way. It's used that way in C/C++ (see your Microsoft C++ link).
 So before me answering you have to switch back to use the common definition of
 assert().
I'm asking what your notion of what assert and assume are, and how that would affect the array bounds checking example.
Jul 30 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 31 July 2014 at 05:56:31 UTC, Walter Bright wrote:
 On 7/30/2014 10:16 PM, bearophile wrote:
 Walter Bright:
 Show me a piece of code with different behavior. Start with 
 the array bounds
 thing.
People have already shown you code that behaves differently with assert and assume.
I'd like to see what you are saying is different in a real example.
 But you have redefined "assert" to mean a mix of assume and 
 assert.
I haven't redefined anything. It's always been that way. It's used that way in C/C++ (see your Microsoft C++ link).
No. This is safe: assert(x) { if(!x) halt(); assume(x); } This is not safe: assert(x){ assume(x); } You need to underestand what can be proven with Hoare logic. The optimizer is free to do anything you can do with it. A program + libaries contain millions of statements. Each and every of those statements is taken as something close to an axiom or multiple axioms. Basically your program contains millions of implicit assumes() that are internally consistent. Then you add thousands handwritten axioms of assume(). true == false IFF a single of those axioms contradicts another axiom either provided implicitly by the program/optimizer or explicitly by the user. That means any boolean expression in your program+libraries can be proven true or false randomly with a probability close to 100%. That means you cannot do heavy duty optimization at all! Because the probability of no axioms contradicting each other is very close to 0%! Please note that you can infer true==false if there is even the tiniest teeny weeny sign of contradiction in any pair of axioms picked from the millions upon millions of axioms provided. Even if that axiom is derived from a statement deep down in some library that most likely will never execute. assume(X) provides axiom X assert(X) provides theorem(X) to be proven You cannot mix those two. That is disaster.
Jul 31 2014
prev sibling next sibling parent reply =?UTF-8?Q?Tobias=20M=C3=BCller?= <troplin bluewin.ch> writes:
Walter Bright <newshound2 digitalmars.com> wrote:
 On 7/30/2014 10:16 PM, bearophile wrote: 
 But you have redefined "assert" to mean a mix of assume and assert.
I haven't redefined anything. It's always been that way. It's used that way in C/C++ (see your Microsoft C++ link).
Actually I cannot find anything in (the latest draft of) the C standard that would allow that. There's no mention of undefined behavior if an assertion is not met with NDEBUG defined. It's clearly defined what the macro should expnd to in that case. Quote (Source: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf): --- The header <assert.h> defines the assert and static_assert macros and refers to another macro, NDEBUG which is not defined by <assert.h>. If NDEBUG is defined as a macro name at the point in the source file where <assert.h> is included, the assert macro is defined simply as #define assert(ignore) ((void)0) The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included. --- And: --- The assert macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function — the latter are respectively the values of the preprocessing macros __FILE__ and __LINE__ and of the identifier __func__) on the standard error stream in an implementation-defined format.191) It then calls the abort function. --- Tobi
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 3:23 AM, Tobias Müller wrote:
 Walter Bright <newshound2 digitalmars.com> wrote:
 On 7/30/2014 10:16 PM, bearophile wrote:
 But you have redefined "assert" to mean a mix of assume and assert.
I haven't redefined anything. It's always been that way. It's used that way in C/C++ (see your Microsoft C++ link).
Actually I cannot find anything in (the latest draft of) the C standard that would allow that. There's no mention of undefined behavior if an assertion is not met with NDEBUG defined. It's clearly defined what the macro should expnd to in that case.
Yes, you are correct about that. But I suspect that is an artifact of the C standard, and its long history of compilers that did essentially no optimization at all (my C compiler was the first DOS C compiler to do data flow analysis). The C standard was written long after C was ubiquitous, and tended to simply document what compilers did. If you look at the Wikipedia article, http://en.wikipedia.org/wiki/Assertion_(software_development) you'll see a more high level view of what assert is all about, rather than a worm's eye view the C standard takes. (It even uses C for its examples.) Up until this thread, I've never encountered someone who thought differently about it. You might also want to consider Hoare's seminal paper on the topic published in the 1970's, which my view adheres to. Then there's the extensive literature on asserts for contract programming, again with the same view of asserts. Consider also Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 There isn't any weasel-wording there, there is no hint of an assert not actually having to be valid if the program is optimized, etc.
Jul 31 2014
parent "Andrew Godfrey" <X y.com> writes:
On Friday, 1 August 2014 at 03:58:22 UTC, Walter Bright wrote:

 If you look at the Wikipedia article,

   http://en.wikipedia.org/wiki/Assertion_(software_development)

 you'll see a more high level view of what assert is all about, 
 rather than a worm's eye view the C standard takes. (It even 
 uses C for its examples.) Up until this thread, I've never 
 encountered someone who thought differently about it.
I just read that and it matches my idea of what asserts are all about. But nowhere could I see any mention of asserts being a promise to the compiler that it could then reason from. The article mentions reasoning but I read that as human reasoning. This sentence: "The use of assertions helps the programmer design, develop, and reason about a program." To me sums it up. I dislike the idea of the compiler reasoning from the assertions because, to me, it hinders the programmer's ability to develop a program. That said: From what Jonathan has said, it sound like this argument could be recast as one about what the "-release" option means. If it's avoidable without losing other optimizations, I don't feel hindered in any way, and this is just a question about user surprise, naming and documentation.
Aug 01 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 I'd like to see what you are saying is different in a real 
 example.
(The problem is that your have defined your own idea, so what I can show you will look meaningless or not comformant to your own definition. So this discussion is going nowhere. And my original topic drowns in this assume/assert debate that is off-topic.) In the case of assume: int max(in int x, in int y) { assume(x > y); return (x > y) ? x : y; } The optimizer is free to replace that code with this, even in debug builds: int max(in int x, in int y) { return x; } In the case of assert: int max(in int x, in int y) { assert(x > y); return (x > y) ? x : y; } In debug builds gets rewritten as: int max(in int x, in int y) { if (x <= y) throw new AssertError("..."); return x; } And in release builds gets rewritten as: int max(in int x, in int y) { return (x > y) ? x : y; } Bye, bearophile
Jul 31 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
 In debug builds gets rewritten as:

 int max(in int x, in int y) {
     if (x <= y)
         throw new AssertError("...");
     return x;
 }
Sorry, I meant: In debug builds gets rewritten as: int max(in int x, in int y) { if (x <= y) throw new AssertError("..."); return (x > y) ? x : y; } Bye, bearophile
Jul 31 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 4:43 AM, bearophile wrote:
 In debug builds gets rewritten as:

 int max(in int x, in int y) {
     if (x <= y)
         throw new AssertError("...");
     return x;
 }
Sorry, I meant: In debug builds gets rewritten as: int max(in int x, in int y) { if (x <= y) throw new AssertError("..."); return (x > y) ? x : y; }
You're overlooking data flow analysis, again. Please read up on it.
Jul 31 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 4:36 AM, bearophile wrote:
 (The problem is that your have defined your own idea,
"My" idea is the conventional one for assert - see the Wikipedia entry on it. -- http://en.wikipedia.org/wiki/Assertion_(software_development) Yes, that article also says: "Under abnormal conditions, disabling assertion checking can mean that a program that would have aborted will continue to run. This is sometimes preferable." The last statement is in contradiction with the rest of the article, and I don't agree with it.
 so what I can show you
 will look meaningless or not comformant to your own definition. So this
 discussion is going nowhere. And my original topic drowns in this assume/assert
 debate that is off-topic.)


 In the case of assume:


 int max(in int x, in int y) {
      assume(x > y);
      return (x > y) ? x : y;
 }

 The optimizer is free to replace that code with this, even in debug builds:

 int max(in int x, in int y) {
      return x;
 }
That implies that the behavior is undefined if the assumption is false. A compiler is free to add checks for undefined behavior (you yourself are a huge proponent of this) and people would (very reasonably for a quality implementation) expect that the assumption is checked. Hence, it will behave like assert.
 In the case of assert:

 int max(in int x, in int y) {
      assert(x > y);
      return (x > y) ? x : y;
 }


 In debug builds gets rewritten as:

 int max(in int x, in int y) {
      if (x <= y)
          throw new AssertError("...");
      return x;
 }
Note how that behaves like assume.
 And in release builds gets rewritten as:

 int max(in int x, in int y) {
      return (x > y) ? x : y;
 }
To require that the code be valid with x>y is to misunderstand what contract programming is all about. An assert is a contract and must be valid, whether it is checked or not. -release is not to be used to deliberately change the semantics of code. For example, from the wikipedia article: "Assertions are distinct from routine error-handling. Assertions document logically impossible situations and discover programming errors: if the impossible occurs, then something fundamental is clearly wrong. This is distinct from error handling: most error conditions are possible, although some may be extremely unlikely to occur in practice. Using assertions as a general-purpose error handling mechanism is unwise: assertions do not allow for recovery from errors; an assertion failure will normally halt the program's execution abruptly." Note "LOGICALLY IMPOSSIBLE SITUATIONS", uppercased for emphasis. These are not my weird unique made-up-on-the-spot out-of-step ideas. Code that relies on assertions being false is semantically broken. In closing, Hoare's paper: http://sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf speaks of "assertions" which can be proven to be true. (It doesn't mention "assumptions".) The simplest way to prove it is to put in a runtime check. D's assert() nicely fits in with that.
Jul 31 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 31 July 2014 at 20:24:09 UTC, Walter Bright wrote:
 In closing, Hoare's paper:

    http://sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf

 speaks of "assertions" which can be proven to be true. (It 
 doesn't mention "assumptions".) The simplest way to prove it is 
 to put in a runtime check. D's assert() nicely fits in with 
 that.
Assumptions are axioms. It mentions axioms. This is an axiom: int x = 0;
Jul 31 2014
prev sibling next sibling parent "Fool" <fool dlang.org> writes:
On Thursday, 31 July 2014 at 20:24:09 UTC, Walter Bright wrote:
 On 7/31/2014 4:36 AM, bearophile wrote:
 int max(in int x, in int y) {
     assume(x > y);
     return (x > y) ? x : y;
 }

 The optimizer is free to replace that code with this, even in 
 debug builds:

 int max(in int x, in int y) {
     return x;
 }
That implies that the behavior is undefined if the assumption is false. A compiler is free to add checks for undefined behavior (you yourself are a huge proponent of this) and people would (very reasonably for a quality implementation) expect that the assumption is checked. Hence, it will behave like assert.
You are asking bearophile to give an example, he gives an example, and you redefine his definition?! The whole point of assume is that it is unchecked and unsafe.
Jul 31 2014
prev sibling next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 20:24:09 UTC, Walter Bright wrote:
 On 7/31/2014 4:36 AM, bearophile wrote:
 (The problem is that your have defined your own idea,
"My" idea is the conventional one for assert - see the Wikipedia entry on it.
That entry makes no mention of assert being used as an optimization hint.
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 2:07 PM, Tofu Ninja wrote:
 On Thursday, 31 July 2014 at 20:24:09 UTC, Walter Bright wrote:
 On 7/31/2014 4:36 AM, bearophile wrote:
 (The problem is that your have defined your own idea,
"My" idea is the conventional one for assert - see the Wikipedia entry on it.
That entry makes no mention of assert being used as an optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
Jul 31 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an 
 optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true. It says that this is a theorem to be proven true given the assumptions provided up till that point. If you: 1. have a set of preconditions (assumptions) 2. and a fully specified postcondition 3. and the code between has no sideeffects 4. and the postcondition has been proven true Only then can you use the postcondition to eliminate code that was unneccessary to prove the postcondition from the precondition. So yes, you CAN use asserts to do heavy duty optimization that go way beyond what a regular optimizer can do (even in theory), but not a priori. In theory you can reduce a general algorithm that does too much work down to the specifics of the postcondition. Doing this for an imperative language is not realistic today. DESIGN BY CONTRACT Design by contract does not mean that programmers guarantee the postconditions. Quite the opposite! Design by contract assumes 3 roles: 1. the trusted ARCHITECT who specifies the modules and pre/postconditions 2. the distrusted IMPLEMENTORS who write the code and cannot touch the contract 3. the trusted BUILD SYSTEM who guarantees that the contracts are upheld between modules, either by proof of run time checks that takes place before one module get access to another. Claiming that the programmer guarantee asserts to hold true is not design by contract. Claiming that the build system is responsible for upholding the contract despite programmers doing their utmost to break it is Design by contract.
Jul 31 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Friday, 1 August 2014 at 06:24:29 UTC, Ola Fosheim Grøstad 
wrote:
 DESIGN BY CONTRACT
BTW, there is an emerging field "program synthesis" that is based on Design by contract where the compiler automatically generates code that takes you from preconditions to postconditions and verifies it to be correct. Genetic progamming does the same. That's nice. Now you don't need those annoying programmers that cannot get things right. You only need the architect and the build system.
Jul 31 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad" 
<ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
Aug 01 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Friday, 1 August 2014 at 09:02:36 UTC, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad"
 An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software."
No. Implication is not the same as equivalence. An assert does not take a predicate. It takes a proposition that is to be turned into a proven theorem. bool test(bool x) {return x || !x} // predicate test(x) for all x in {true,false} // proposition assert(test(x) for all x in {true,false}) // prove proposition => proven theorem However, you may use assumptions from a precondition locally in a function for optimization purposes without asserting the precondition first IFF: 1. the function is pure (no side effects) 2. the optimizer is capable of detecting inconsistencies and ignore user provided assumptions when a conflict arises. 3. no code makes assumptions based on the postconditions of the function I think so, at least.
Aug 01 2014
prev sibling next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 1 August 2014 at 09:02:36 UTC, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad" 
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an 
 optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
No, the statement in this quote does not imply that it is always true. It says that there is a bug if it isn't, which obviously wouldn't make any sense if the predicate were always true. An assertion doesn't tell the compiler that a predicate is true, it tells the compiler to _check whether_ it is true.
Aug 01 2014
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 1 August 2014 at 10:42:50 UTC, Marc Schütz wrote:
 On Friday, 1 August 2014 at 09:02:36 UTC, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad" 
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an 
 optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
No, the statement in this quote does not imply that it is always true. It says that there is a bug if it isn't, which obviously wouldn't make any sense if the predicate were always true. An assertion doesn't tell the compiler that a predicate is true, it tells the compiler to _check whether_ it is true.
Even the WP article that you referred to says: "An assertion may be used to verify that an assumption made by the programmer [...] remains valid" https://en.wikipedia.org/wiki/Assertion_%28software_development%29#Assertions_for_run-time_checking It may be used to _verify_ an assumption, not to _claim_ that it is true.
Aug 01 2014
prev sibling next sibling parent reply "Don" <x nospam.com> writes:
On Friday, 1 August 2014 at 09:02:36 UTC, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad" 
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an 
 optimization hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
I would rephrase it as: "An assert says that either the predicate is always true, or else the program is in an invalid state and will not operate correctly". But I do think this entire argument seems to me to be rather misplaced. I think it's really it's about -release, not about assert(). The arguments presented by Ola et al mostly seem to be arguments against the use of the -release switch. Because it is a very dangerous flag. If you're removing all your asserts I'd say you're playing a dangerous game already. If an assert would have failed, but execution continued anyway, you're in undefined behaviour -- at the very least, you're in a condition that the programmer believed could never happen. If you are disabling your asserts, but still believe that they may fail, that means you're expecting your program to enter undefined behaviour! That seems to be a rather illogical position. I think very strongly that we should rename the "-release" switch, especially if we do start to make use of asserts. It's going to cause no end of confusion and passionate debate. --- In one of the 2013 DConf talks a lint tool was discussed that disallowed you from you writing a condition that was provably impossible based on 'in' contracts. eg: void foo( int x) in{ assert(x > 6); } body { if (x > 2) // ERROR! This is always true! ... } Which is an interesting approach. By definition, any optimisations that are performed on the basis of an assert() that could affect control flow, are detectable with 100% accuracy by a lint tool. And so, if you wanted to remove all your asserts but were worried about this issue, it's detectable at compile time.
Aug 01 2014
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Friday, 1 August 2014 at 11:53:28 UTC, Don wrote:
 I think very strongly that we should rename the "-release" 
 switch, especially if we do start to make use of asserts. It's 
 going to cause no end of confusion and passionate debate.
Pretty much summary of both threads.
Aug 01 2014
prev sibling next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Friday, 1 August 2014 at 11:53:28 UTC, Don wrote:
 The arguments presented by Ola et al mostly seem to be 
 arguments against the use of the -release switch. Because it is
No, I think I do understand where Walter is coming from now. I remember some of the incomprehensible lectures I attended as a student where the entire blackboard was filled with quantors this and that. I have spent hours every day the past few days thinking about how to explain it efficiently. I think D will benefit greatly if Walter dig into some of the theories on formal program verification, but everybody has to take rounds of the heuristic cycle to truly get down to it. So it is good that he does not accept it without an argument. It is just not a topic where you can read one article and you will shout "eureka!". So I don't think it is a good idea to just say "oh it is just about -release". It is basically about finding common ground where program verification gets the best treatment possible and in a manner that is consistent with how users with a CS background perceive correctness. I hope this gets us closer to common ground: Let's assume with have a simple program like this: int program(immutable string input){ int r = input.length + input.length; assert(r == 2* input.length); return r; } Then execute it: interpreter> run program "hi" Then we have the following situation iff it completes successfully: PROVEN: if input=='hi' then input.length + input.length == 2* input.length EQUIVALENT TO: (input != 'hi') || (input.length + input.length == 2* input.length) NOT PROVEN YET: input.length + input.length == 2* input.length for all input != 'hi' That basically means that a formal assert(x) and a runtime check has the following relationship: runtime_assert(x) is the same as formal_prove( input!=ACTUALINPUT || x ) formal_assert(x) is the same as formal_prove(x)
Aug 01 2014
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 01:53 PM, Don wrote:
 On Friday, 1 August 2014 at 09:02:36 UTC, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an optimization
 hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
I would rephrase it as: "An assert says that either the predicate is always true, or else the program is in an invalid state and will not operate correctly". ...
Bertrand _Meyer_ is not a furious proponent of undefined behaviour. He is not exactly a fan of C or C++ either and an expressed opponent of the typical 'C hacker' attitude.
 But I do think this entire argument seems to me to be rather misplaced.
 I think it's really it's about -release, not about assert().

 The arguments presented by Ola et al mostly seem to be arguments against
 the use of the -release switch. Because it is a very dangerous flag.

 If you're removing all your asserts I'd say you're playing a dangerous
 game already.
Sure, and it is /obviously/ perfectly fine to e.g. kill a tightrope walker, so this should not be prosecuted.
 If an assert would have failed, but execution continued
 anyway, you're in undefined behaviour
No. For the purpose of (maybe remote!) debugging, the programmer wants the behaviour to be _the one that the program specifies_, even if it is not the one that he _expected_.
 -- at the very least, you're in a
 condition that the programmer believed could never happen.
 ...
Yes, a condition that _some_ programmer believed could never happen. It is not even a given that this condition is not actually created somewhere and handled somewhere else, especially as software evolves.
 If you are disabling your asserts, but still believe that they may fail,
 that means you're expecting your program to enter undefined behaviour!
Nonsense. This claim is ignoring the current reality of software development. One would be expecting one's program to be buggy, but one would still think that _almost all_ assertions pass always and those that don't would be expected to pass _almost always_. How many pieces of non-trivial bug-free software did you write or _were required to work on without full knowledge about the code base_? In any case if one is _disabling_ one's asserts, one doesn't expect them to have any kind of effect whether they may fail or not.
 That seems to be a rather illogical position.
It was constructed to seem to be. For example, the expectation that some asserts are wrong was conveniently replaced by the expectation that all (or at least a murkily unspecified amount of) asserts are wrong and the existence of trade-offs was ignored. This is simply a straw man used to defend an indefensible position.
 I think very strongly that we should rename the "-release" switch,
 especially if we do start to make use of asserts. It's going to cause no
 end of confusion and passionate debate.

 ---
Disabling assertions and contracts and using them for optimization should be distinct options.
 In one of the 2013 DConf talks a lint tool was discussed that disallowed
 you from you writing a condition that was provably impossible based on
 'in' contracts.
 eg:

 void foo( int x)
 in{
     assert(x > 6);
 }
 body {
      if (x > 2)   // ERROR! This is always true!
      ...
 }

 Which is an interesting approach.

 By definition, any optimisations that are performed on the basis of an
 assert() that could affect control flow, are detectable with 100%
 accuracy by a lint tool.
By a family of lint tools indexed by the respective compiler back-ends. Furthermore, you have to understand all of those back-ends and all their passes completely and you need to track how information relating possible optimizations flows through them. You will not write all those lints in a lifetime and you need to start this undertaking again whenever someone writes a new back-end and you need to always keep the lints in sync with the back-ends (and maybe, front-ends). Besides, it is an incredibly complex solution for a completely trivial issue.
 And so, if you wanted to remove all your
 asserts but were worried about this issue, it's detectable at compile time.
This issue does not only affect people who are worried about it (and I'd guess the truth is way closer to the opposite), and in fact you yourself claimed above that it only affects people who are not worried about undefined behaviour. This is a rather illogical position to be in, even if both of the contradicting claims are not true statements. (Sorry! Couldn't resist! :-) ) In any case, please don't ignore existing complexity in order to make claims that seem pragmatic.
Aug 01 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/1/14, 8:28 AM, Timon Gehr wrote:
On 08/01/2014 01:53 PM, Don wrote:
 If you are disabling your asserts, but still believe that they may fail,
 that means you're expecting your program to enter undefined behaviour!
Nonsense. This claim is ignoring the current reality of software development. One would be expecting one's program to be buggy, but one would still think that _almost all_ assertions pass always and those that don't would be expected to pass _almost always_. How many pieces of non-trivial bug-free software did you write or _were required to work on without full knowledge about the code base_? In any case if one is _disabling_ one's asserts, one doesn't expect them to have any kind of effect whether they may fail or not.
This doesn't ring true at all in the circles I frequent. I'm with Don. -- Andrei
Aug 01 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 05:37 PM, Andrei Alexandrescu wrote:
 On 8/1/14, 8:28 AM, Timon Gehr wrote:
 On 08/01/2014 01:53 PM, Don wrote:
 If you are disabling your asserts, but still believe that they may fail,
 that means you're expecting your program to enter undefined behaviour!
Nonsense. This claim is ignoring the current reality of software development. One would be expecting one's program to be buggy, but one would still think that _almost all_ assertions pass always and those that don't would be expected to pass _almost always_. How many pieces of non-trivial bug-free software did you write or _were required to work on without full knowledge about the code base_? In any case if one is _disabling_ one's asserts, one doesn't expect them to have any kind of effect whether they may fail or not.
This doesn't ring true at all in the circles I frequent. I'm with Don. -- Andrei
It wouldn't ring true in a circle where it is popular to deny one's own imperfection, or the imperfection of one's co-workers. Such an attitude is dangerous. It puts innocent people at risk. What other circles does it not ring true in?
Aug 01 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 4:53 AM, Don wrote:
 If you're removing all your asserts I'd say you're playing a dangerous game
 already. If an assert would have failed, but execution continued anyway, you're
 in undefined behaviour -- at the very least, you're in a condition that the
 programmer believed could never happen.
Yes. (At the very least, the switch will tell you how much runtime speed the asserts cost you.) Asserts not only can detect programming bugs, they can provide optimizer hints that significantly improve code generation. It's going to be necessary to keep D competitive in high performance computing.
 If you are disabling your asserts, but still believe that they may fail, that
 means you're expecting your program to enter undefined behaviour! That seems to
 be a rather illogical position.
Of course. Don't ask the Godfather to do favors for you if you are unwilling to return the favor :-)
 I think very strongly that we should rename the "-release" switch, especially
if
 we do start to make use of asserts. It's going to cause no end of confusion and
 passionate debate.
The name came about as a result of my experience with newbies benchmarking my compilers and publishing the results. They'd spend 2 or 3 seconds scanning the documentation to figure out how to set up the compiler to generate the fastest code. -disableasserts is meaningless to them, and they won't use it, and the compiler would fare poorly. -release speaks to them "faster code", so they use that one. It's worked out well for that purpose. I would expect someone who spends more time developing code with the compiler to spend at least a little effort reading the two lines of documentation for -release and understanding that it disables the runtime assert checks. I agree that the documentation can be improved.
 In one of the 2013 DConf talks a lint tool was discussed that disallowed you
 from you writing a condition that was provably impossible based on 'in'
contracts.
 eg:

 void foo( int x)
 in{
     assert(x > 6);
 }
 body {
      if (x > 2)   // ERROR! This is always true!
      ...
 }

 Which is an interesting approach.
When writing generic code, or any generative code, these situations can come up a lot and be legitimate.
 By definition, any optimisations that are performed on the basis of an assert()
 that could affect control flow, are detectable with 100% accuracy by a lint
 tool. And so, if you wanted to remove all your asserts but were worried about
 this issue, it's detectable at compile time.
You're right, but that means the lint tool would have to replicate the data flow analysis in the optimizer, and would have to account for different DFA as implemented in each D compiler.
Aug 01 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 08:33 PM, Walter Bright wrote:
 The name came about as a result of my experience with newbies
 benchmarking my compilers and publishing the results. They'd spend 2 or
 3 seconds scanning the documentation to figure out how to set up the
 compiler to generate the fastest code. -disableasserts is meaningless to
 them, and they won't use it, and the compiler would fare poorly.
 -release speaks to them "faster code", so they use that one.

 It's worked out well for that purpose.
 ...
Throw in -inline, -noboundscheck, -assumeasserts, -O, etc. and call the entire thing ... -benchmark ! or ... -fast !
 I would expect someone who spends more time developing code with the
 compiler to spend at least a little effort reading the two lines of
 documentation for -release and understanding that it disables the
 runtime assert checks.
 ...
Argh....
 I agree that the documentation can be improved.
Aug 01 2014
prev sibling parent reply "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Friday, 1 August 2014 at 18:33:34 UTC, Walter Bright wrote:
 On 8/1/2014 4:53 AM, Don wrote:
 I think very strongly that we should rename the "-release" 
 switch, especially if
 we do start to make use of asserts. It's going to cause no end 
 of confusion and
 passionate debate.
I would expect someone who spends more time developing code with the compiler to spend at least a little effort reading the two lines of documentation for -release and understanding that it disables the runtime assert checks.
+1 I've the same reasoning every time I see big threads about installers: I simply go with the zips for every platform I use D on. --- Paolo
Aug 02 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:03 PM, Paolo Invernizzi wrote:
 On Friday, 1 August 2014 at 18:33:34 UTC, Walter Bright wrote:
 On 8/1/2014 4:53 AM, Don wrote:
 I think very strongly that we should rename the "-release" switch,
 especially if
 we do start to make use of asserts. It's going to cause no end of
 confusion and
 passionate debate.
I would expect someone who spends more time developing code with the compiler to spend at least a little effort reading the two lines of documentation for -release and understanding that it disables the runtime assert checks.
+1 I've the same reasoning every time I see big threads about installers: I simply go with the zips for every platform I use D on. --- Paolo
1. Note that the information about -release given in the above post is misleading. The new -release assigns undefined behaviour to failing assertions. 2. What has this thread to do with installers vs. zips?
Aug 02 2014
parent "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Saturday, 2 August 2014 at 16:22:07 UTC, Timon Gehr wrote:
 On 08/02/2014 06:03 PM, Paolo Invernizzi wrote:
 On Friday, 1 August 2014 at 18:33:34 UTC, Walter Bright wrote:
 On 8/1/2014 4:53 AM, Don wrote:
 I think very strongly that we should rename the "-release" 
 switch,
 especially if
 we do start to make use of asserts. It's going to cause no 
 end of
 confusion and
 passionate debate.
I would expect someone who spends more time developing code with the compiler to spend at least a little effort reading the two lines of documentation for -release and understanding that it disables the runtime assert checks.
+1 I've the same reasoning every time I see big threads about installers: I simply go with the zips for every platform I use D on. --- Paolo
1. Note that the information about -release given in the above post is misleading. The new -release assigns undefined behaviour to failing assertions. 2. What has this thread to do with installers vs. zips?
Simple answer: also if I agree with Walter that the documentation can be improved, the consequence of the -release switch over the code base is crystal clear, it's no more that what it is written in the documentation. We can passionately discuss on the philosophy of undefined behaviour, about the semantic meaning of the word 'assert', about using it for give the compiler hints about possible optimisations, and so on, but the discussion about renaming flags name does not passionate me, like discussions about simplifying the download expand a zip. --- Paolo
Aug 02 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 11:02 AM, Walter Bright wrote:
 On 7/31/2014 11:24 PM, "Ola Fosheim Grøstad"
 <ola.fosheim.grostad+dlang gmail.com>" wrote:
 On Friday, 1 August 2014 at 02:44:51 UTC, Walter Bright wrote:
 That entry makes no mention of assert being used as an optimization
 hint.
Saying that a predicate is always true means it's available to the optimizer.
An assert does not say that the predicate is always true.
Yes, it does. From Meyers' comprehensive tome on the topic "Object-Oriented Software Construction" (1997) where he writes: "A run-time assertion violation is the manifestation of a bug in the software." -- pg. 346 In fact, Meyers calls it "rule (1)" of assertions.
Sure, and _Meyer_'s "rule (1)" of software must therefore be that it contains no bugs, no?
Aug 01 2014
prev sibling next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 31 July 2014 at 20:24:09 UTC, Walter Bright wrote:
 Code that relies on assertions being false is semantically 
 broken.
Code transforms that relies on unproven theorems to be true are semantically broken. Assertions are proposed theorems. Assumptions are preconditions needed for those theorems. The contract is not fulfilled until the theorems are proven. PROVEN, not tested by sampling. Until then programming by contract (as defined) requires testing under execution, not only in debug builds. If you don't do this, then don't call it programming by contract! You should also then require the following: "supplier B guarantees postcondition of B's methods assuming client A guarantees the preconditions of those methods" http://www.cs.usfca.edu/~parrt/course/601/lectures/programming.by.contract.html So you need this structure: A(){ assert(B_preconditions); // try to optimize these away B(); assume(B_postconditions); // not required, but useful for optimization } B(){ assume(B_preconditions) …execute… assert(B_postconditions) // try to get rid of this through formal proof }
Jul 31 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 10:24 PM, Walter Bright wrote:
 Code that relies on assertions being false is semantically broken.
 ...
The code might not rely on it. I.e. the assertion might be the only thing that is broken. Turning it into an assumption will additionally break the code.
 In closing, Hoare's paper:

 http://sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf

 speaks of "assertions" which can be proven to be true. (It doesn't
 mention "assumptions".) The simplest way to prove it is to put in a
 runtime check. D's assert() nicely fits in with that.
EWD liked to say things like: 'The first moral of the story is that program testing can be used very effectively to show the presence of bugs but never to show their absence.'. Which is pedantically speaking obviously wrong without further qualification, but he still has a point. A non-exhaustive sequence of assertion checks will not be sufficient to prove that the assertion is true. However, turning the assertions into assumptions is valid only if the assertions are true. Even more importantly, to assume true without proof is very much a different operation than to assert true, for proof (or disproof!) to come later, and 'assert' awkwardly plays both roles if -release may optimize based on it.
Jul 31 2014
prev sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 02:50, schrieb Tobias Müller:
 Walter Bright <newshound2 digitalmars.com> wrote:
 On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote:
 No, with the assert definition you're proposing, it won't. It would
 be allowed to optimize away the bounds check. And this is just one of
 many problems with the assert==assume approach.
Please explain how assume would behave any differently.
It wouldn't and that's the point. If you have (a more harmless) assert _and_ assume you can still use assert, which would then _not_ allow those optimization. Tobi
I'm in favor of a "harmless" assert(). In C(++) I sometimes use things like assert(x != NULL); if(x != NULL) { x->foo = 42; // ... } I have that assertion to hopefully find bugs during development and fix them. However, no program is bug free and so it's totally possible that x *is* NULL in some circumstance in the wild (in a "release" mode binary), so I want to make sure it doesn't explode if that happens but handle the problem more gracefully. It would be rather unfortunate if the compiler removed that second check in release mode because the assertion made it assume that x can't be NULL. Cheers, Daniel
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 6:38 PM, Daniel Gibson wrote:
 I'm in favor of a "harmless" assert().
 In C(++) I sometimes use things like

 assert(x != NULL);

 if(x != NULL) {
      x->foo = 42;
      // ...
 }

 I have that assertion to hopefully find bugs during development and fix them.
 However, no program is bug free and so it's totally possible that x *is* NULL
in
 some circumstance in the wild (in a "release" mode binary), so I want to make
 sure it doesn't explode if that happens but handle the problem more gracefully.

 It would be rather unfortunate if the compiler removed that second check in
 release mode because the assertion made it assume that x can't be NULL.
Your code is doomed to having problems using assert this way. The behavior you desire here is easily handled by creating your own template to exhibit it. See the implementation of enforce() for how to do it.
Jul 30 2014
next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 02:53:11 UTC, Walter Bright wrote:
 Your code is doomed to having problems using assert this way.

 The behavior you desire here is easily handled by creating your 
 own template to exhibit it. See the implementation of enforce() 
 for how to do it.
When is the appropriate time to use an assert? If an assert should not be used on input, then any thing that can't be statically known is considered an input and anything that is derived from an input is also an input... so when can we use an assert? The only things left it seems are things know at compile time and at that point what is the the point of having assert when we have static assert...
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 8:09 PM, Tofu Ninja wrote:
 When is the appropriate time to use an assert? If an assert
 should not be used on input, then any thing that can't be
 statically known is considered an input and anything that is
 derived from an input is also an input... so when can we use an
 assert? The only things left it seems are things know at compile
 time and at that point what is the the point of having assert
 when we have static assert...
Asserts are used to verify the logic of your code is correct: x = y + y; assert(x == 2 * y);
Jul 30 2014
parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 05:05:33 UTC, Walter Bright wrote:
 On 7/30/2014 8:09 PM, Tofu Ninja wrote:
 When is the appropriate time to use an assert? If an assert
 should not be used on input, then any thing that can't be
 statically known is considered an input and anything that is
 derived from an input is also an input... so when can we use an
 assert? The only things left it seems are things know at 
 compile
 time and at that point what is the the point of having assert
 when we have static assert...
Asserts are used to verify the logic of your code is correct: x = y + y; assert(x == 2 * y);
If x and y are floats and y is nan then that assert will fail..... That assert is implicitly verifying that the input y is not nan, that is a misuse of assert by your definition. Any assert made on a piece of data that is derived from inputs is verifying some aspect of that input, which is a misuse of assert according to the current definition. So I still state that according to current definitions, assert should only be used on things that are known at compile time. What is the use of that?
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 10:49 PM, Tofu Ninja wrote:
 On Thursday, 31 July 2014 at 05:05:33 UTC, Walter Bright wrote:
 On 7/30/2014 8:09 PM, Tofu Ninja wrote:
 When is the appropriate time to use an assert? If an assert
 should not be used on input, then any thing that can't be
 statically known is considered an input and anything that is
 derived from an input is also an input... so when can we use an
 assert? The only things left it seems are things know at compile
 time and at that point what is the the point of having assert
 when we have static assert...
Asserts are used to verify the logic of your code is correct: x = y + y; assert(x == 2 * y);
If x and y are floats and y is nan then that assert will fail..... That assert is implicitly verifying that the input y is not nan, that is a misuse of assert by your definition.
If it pleases you, prepend int x,y; to the snippet.
 Any assert made on a piece of data that is derived from inputs is
 verifying some aspect of that input, which is a misuse of assert
 according to the current definition. So I still state that
 according to current definitions, assert should only be used on
 things that are known at compile time. What is the use of that?
For example, you can have a sort function, and then at the end assert that the output of the function is sorted.
Jul 31 2014
parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 07:00:01 UTC, Walter Bright wrote:
 On 7/30/2014 10:49 PM, Tofu Ninja wrote:
 On Thursday, 31 July 2014 at 05:05:33 UTC, Walter Bright wrote:
 On 7/30/2014 8:09 PM, Tofu Ninja wrote:
 When is the appropriate time to use an assert? If an assert
 should not be used on input, then any thing that can't be
 statically known is considered an input and anything that is
 derived from an input is also an input... so when can we use 
 an
 assert? The only things left it seems are things know at 
 compile
 time and at that point what is the the point of having assert
 when we have static assert...
Asserts are used to verify the logic of your code is correct: x = y + y; assert(x == 2 * y);
If x and y are floats and y is nan then that assert will fail..... That assert is implicitly verifying that the input y is not nan, that is a misuse of assert by your definition.
If it pleases you, prepend int x,y; to the snippet.
 Any assert made on a piece of data that is derived from inputs 
 is
 verifying some aspect of that input, which is a misuse of 
 assert
 according to the current definition. So I still state that
 according to current definitions, assert should only be used on
 things that are known at compile time. What is the use of that?
For example, you can have a sort function, and then at the end assert that the output of the function is sorted.
But that is verifying that the input is sort-able.... All I am saying is that the idea that assert should not be used to verify input makes no sense at all. Every program takes in input and once a little bit is in, anything derived from that input is also input. ... Also this thread has made me firmly never want to trust assert again... I have actually been going though my projects and removing them now because I don't trust them any more...
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 7:51 AM, Tofu Ninja wrote:
 For example, you can have a sort function, and then at the end assert that the
 output of the function is sorted.
But that is verifying that the input is sort-able....
Integers are sortable, period. That is not "input".
 All I am saying is that the idea that assert should not be used to verify input
 makes no sense at all. Every program takes in input and once a little bit is
in,
 anything derived from that input is also input.
You're denying the existence of mathematical identities applied to symbolic math.
 Also this thread has made me firmly never want to trust assert again... I have
 actually been going though my projects and removing them now because I don't
 trust them any more...
I suggest revisiting the notion of program logic correctness vs input verification.
Jul 31 2014
next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 19:12:04 UTC, Walter Bright wrote:
 Integers are sortable, period. That is not "input".
Ok so sorted ints are not "input", what else is not "input"? Where can I draw the line? And if I do use assert on an input, that is what? Undefined? I thought D was not supposed to have undefined behavior.
 You're denying the existence of mathematical identities applied 
 to symbolic math.
I am just going off of what you said and pointing out the consequences. You said it was a misuse to use asserts to verify inputs. So what is defined as an input? int x = getIntFromSomeWhere(); // this is an input int y = x; // Is y an input? int z = x/2; // Is z an input? real w = sin(x); // Is w an input? int a = (x == 2)?1:0; // Is a an input?
 I suggest revisiting the notion of program logic correctness vs 
 input verification.
The proposed optimizations to assert have brought into question the logical correctness of assert, that is what this whole thread is about(well not originally but that is what it is about now, sorry bearophile). Until that is resolved I am no longer going to use assert.
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 1:36 PM, Tofu Ninja wrote:
 On Thursday, 31 July 2014 at 19:12:04 UTC, Walter Bright wrote:
 Integers are sortable, period. That is not "input".
Ok so sorted ints are not "input", what else is not "input"? Where can I draw the line? And if I do use assert on an input, that is what? Undefined? I thought D was not supposed to have undefined behavior.
I've answered this so many times now, I no longer have any new words to say on the topic.
Jul 31 2014
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Friday, 1 August 2014 at 02:46:48 UTC, Walter Bright wrote:
 On 7/31/2014 1:36 PM, Tofu Ninja wrote:
 On Thursday, 31 July 2014 at 19:12:04 UTC, Walter Bright wrote:
 Integers are sortable, period. That is not "input".
Ok so sorted ints are not "input", what else is not "input"? Where can I draw the line? And if I do use assert on an input, that is what? Undefined? I thought D was not supposed to have undefined behavior.
I've answered this so many times now, I no longer have any new words to say on the topic.
I'll say some word on this, then. Yes, you cannot assert() that input has a specific value. Programs that do this are provable not correct. You can assert() that input has a specific value after the code has made sure that it has a specific value. This means the program is partially correct. Input is a priori assumed to have any value allowed by the context. Argc has an implicit assume that provides axioms describing the limits of int/C/unix/etc.
Jul 31 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 09:11 PM, Walter Bright wrote:
 On 7/31/2014 7:51 AM, Tofu Ninja wrote:
 For example, you can have a sort function, and then at the end assert
 that the
 output of the function is sorted.
But that is verifying that the input is sort-able....
Integers are sortable, period. That is not "input". ...
Data types with opCmp may not be. (In fact, yours often aren't, because the subtraction trick does not actually work.) The type and its opCmp are "inputs" to the 'sort' template. If it asserts unconditionally after sorting, some instantiations might be buggy.
 All I am saying is that the idea that assert should not be used to
 verify input
 makes no sense at all. Every program takes in input and once a little
 bit is in,
 anything derived from that input is also input.
You're denying the existence of mathematical identities applied to symbolic math.
 Also this thread has made me firmly never want to trust assert
 again... I have
 actually been going though my projects and removing them now because I
 don't
 trust them any more...
I suggest revisiting the notion of program logic correctness vs input verification.
You are denying the existence of standard terminology in logic and programming languages.
Jul 31 2014
parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
in/out contracts ought to remain in release builds.

Since debug and non-zero-assert disappear in release, I can just 
use them inside the in/out blocks when I want debug-only 
verification steps.

Compiling away contracts seems redundant, and it would help 
reduce noise to push more verification logic out of function 
bodies and into contracts.
Jul 31 2014
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 assert(x != NULL);

 if(x != NULL) {
     x->foo = 42;
     // ...
 }
...
Your code is doomed to having problems using assert this way.
That usage of assert is fine. D programs use it that way. (And you are going to break lot of D code if you will change the semantics of D assert). Bye, bearophile
Jul 30 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 9:54 PM, bearophile wrote:
 That usage of assert is fine. D programs use it that way. (And you are going to
 break lot of D code if you will change the semantics of D assert).
No, it will break code that already is broken.
Jul 30 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 No, it will break code that already is broken.
I have probably lost the grasp of this part of the discussion. But I don't see what's broken in using assert to verify that a pointer is not null. Do you think that pointer comes from "outside"? Bye, bearophile
Jul 30 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 10:19 PM, bearophile wrote:
 Walter Bright:

 No, it will break code that already is broken.
I have probably lost the grasp of this part of the discussion. But I don't see what's broken in using assert to verify that a pointer is not null. Do you think that pointer comes from "outside"?
Daniel wants his code to be in a valid state even if the assert is not true, i.e. he wants it to continue to operate as if the pointer might be null.
Jul 30 2014
prev sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 04:53, schrieb Walter Bright:
 On 7/30/2014 6:38 PM, Daniel Gibson wrote:
 I'm in favor of a "harmless" assert().
 In C(++) I sometimes use things like

 assert(x != NULL);

 if(x != NULL) {
      x->foo = 42;
      // ...
 }

 I have that assertion to hopefully find bugs during development and
 fix them.
 However, no program is bug free and so it's totally possible that x
 *is* NULL in
 some circumstance in the wild (in a "release" mode binary), so I want
 to make
 sure it doesn't explode if that happens but handle the problem more
 gracefully.

 It would be rather unfortunate if the compiler removed that second
 check in
 release mode because the assertion made it assume that x can't be NULL.
Your code is doomed to having problems using assert this way. The behavior you desire here is easily handled by creating your own template to exhibit it. See the implementation of enforce() for how to do it.
Now that's a bit surprising to me, as you wrote in the other thread:
 7. using enforce() to check for program bugs is utterly wrong.
 enforce() is a library creation, the core language does not recognize
 it."
Until now (being mostly a C/C++ guy), I saw assertions as a way to find bugs during development/testing that is completely eliminated in release mode (so I might still want to handle the asserted conditions gracefully there) - and it seems like I'm not alone with that view. Because (in C/C++) assertions just vanish when NDEBUG isn't defined, it would never occur to me that they have any influence on such (release mode) builds. Doing optimizations on this would just lead to frustration, like several kinds of optimizations recently have (e.g. this "compiler will remove bzero() on memory that isn't used afterwards" bullshit). Cheers, Daniel
Jul 31 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 6:37 AM, Daniel Gibson wrote:
 The behavior you desire here is easily handled by creating your own
 template to exhibit it. See the implementation of enforce() for how to
 do it.
Now that's a bit surprising to me, as you wrote in the other thread: > 7. using enforce() to check for program bugs is utterly wrong. > enforce() is a library creation, the core language does not recognize > it." Until now (being mostly a C/C++ guy), I saw assertions as a way to find bugs during development/testing that is completely eliminated in release mode (so I might still want to handle the asserted conditions gracefully there) - and it seems like I'm not alone with that view.
The assert will not cause code to be generated to test the assertion at runtime with -release. But the assert must still be valid, and since it is valid, the optimizer should be able to take advantage of it. assert is not meant to be used as "I want my program to be valid even if the assert is false".
 Because (in C/C++) assertions just vanish when NDEBUG isn't defined, it would
 never occur to me that they have any influence on such (release mode) builds.
 Doing optimizations on this would just lead to frustration, like several kinds
 of optimizations recently have (e.g. this "compiler will remove bzero() on
 memory that isn't used afterwards" bullshit).
That's the way assert in C/C++ conventionally worked. But this is changing. Bearophile's reference made it clear that Microsoft C++ 2013 has already changed, and I've seen discussions for doing the same with gcc and clang. In fact, the whole reason assert is a core language feature rather than a library notion is I was anticipating making use of assert for optimization hints.
Jul 31 2014
next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 21:19, schrieb Walter Bright:
 That's the way assert in C/C++ conventionally worked. But this is
 changing. Bearophile's reference made it clear that Microsoft C++ 2013
 has already changed, and I've seen discussions for doing the same with
 gcc and clang.
This will break so much code :-/
 In fact, the whole reason assert is a core language feature rather than
 a library notion is I was anticipating making use of assert for
 optimization hints.
So why is this not documented? The assert documentation isn't even clear on when an AssertError is thrown and when execution is halted (http://dlang.org/contracts.html doesn't mention halt at all). And it says "When compiling for release, the assert code is not generated." - if you implemented assert like this so the optimizer can assume the assertion to be true even when "assert code is not generated" this is certainly something developers should be very aware of - and not once you actually implement that optimization, but from day one, so they can use assert accordingly! This thread however shows that many D users (who probably have more D experience than myself) are not aware that assert() may influence optimization and would prefer to have separate syntax to tell the optimizer what values he can expect. Cheers, Daniel
Jul 31 2014
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Thu, Jul 31, 2014 at 09:37:11PM +0200, Daniel Gibson via Digitalmars-d wrote:
[...]
 This thread however shows that many D users (who probably have more D
 experience than myself) are not aware that assert() may influence
 optimization and would prefer to have separate syntax to tell the
 optimizer what values he can expect.
[...] AFAIK, the compiler currently doesn't use assert as a source of information for optimization, it's just being proposed. T -- Blunt statements really don't have a point.
Jul 31 2014
next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 21:46, schrieb H. S. Teoh via Digitalmars-d:
 On Thu, Jul 31, 2014 at 09:37:11PM +0200, Daniel Gibson via Digitalmars-d
wrote:
 [...]
 This thread however shows that many D users (who probably have more D
 experience than myself) are not aware that assert() may influence
 optimization and would prefer to have separate syntax to tell the
 optimizer what values he can expect.
[...] AFAIK, the compiler currently doesn't use assert as a source of information for optimization, it's just being proposed.
Walter said that he implemented assert() as a language feature to allow this, so it's at least planned. And, as I wrote, if this was/is planned, people should have been told about it *explicitly* in the language documentation, so they can make sure to use assert() accordingly. Cheers, Daniel
Jul 31 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Daniel Gibson:

 so they can make sure to use assert() accordingly.
What's the correct way to use the assert-assume hybrid? Bye, bearophile
Jul 31 2014
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 21:59, schrieb bearophile:
 Daniel Gibson:

 so they can make sure to use assert() accordingly.
What's the correct way to use the assert-assume hybrid?
I guess in many cases I'd avoid using assert() in fear of breaking my defensively written program (like that example from earlier: assert(x !is null); if(x) { x.foo = 42; }). All this pretty much sounds like, if I should ever write any serious software in D in the future, I'd use assert() like assume() and I'd write my own dumbAssert() that does checks in debug mode and does nothing in release mode and is ignored by the optimizer (hopefully.. until it gets too smart again and starts evaluating debug code paths in hope of inferring something about the program state in release builds). Actually, this somehow makes me afraid of D's design by contract stuff that will probably also be used by the optimizer in the same way.. Somehow all this assumes that you found all problems (at least the ones you check in assert()) by testing during development.. *I* personally wouldn't be so arrogant to assume that my code is bugfree just because it passed testing... Cheers, Daniel
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 1:11 PM, Daniel Gibson wrote:
 I guess in many cases I'd avoid using assert() in fear of breaking my
 defensively written program (like that example from earlier: assert(x !is
null);
 if(x) { x.foo = 42; }).
I just hang my head in my hands at that code :-) Really, you're much better off writing something like: if (x) { x.foo = 42; } else { writeln("Sack the QA dept. for not testing this code"); abort(); } which expresses what you intend directly and would be perfectly fine.
 Somehow all this assumes that you found all problems (at least the ones you
 check in assert()) by testing during development..
 *I* personally wouldn't be so arrogant to assume that my code is bugfree just
 because it passed testing...
No worries, I'd probably spare you and sack the fellow on your left!
Jul 31 2014
parent Daniel Gibson <metalcaedes gmail.com> writes:
Am 01.08.2014 05:27, schrieb Walter Bright:
 On 7/31/2014 1:11 PM, Daniel Gibson wrote:
 I guess in many cases I'd avoid using assert() in fear of breaking my
 defensively written program (like that example from earlier: assert(x
 !is null);
 if(x) { x.foo = 42; }).
I just hang my head in my hands at that code :-) Really, you're much better off writing something like: if (x) { x.foo = 42; } else { writeln("Sack the QA dept. for not testing this code"); abort(); } which expresses what you intend directly and would be perfectly fine.
Not exactly - in release mode I don't want it to abort. But it could be rewritten as if(check(x != null, "Sack the QA dept. for not testing this code")) { x.foo = 42; } where check throws in debug mode and returns false in release mode if the condition fails. I just never considered assert() to have the meaning you're giving it, even though maybe it was always considered to be like that but just not implemented "properly" by common languages. I wrote a bit more about this in another reply. Cheers, Daniel
Aug 01 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 12:46 PM, H. S. Teoh via Digitalmars-d wrote:
 AFAIK, the compiler currently doesn't use assert as a source of
 information for optimization, it's just being proposed.
It already does by default, the proposal is to do it for -release.
Jul 31 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 05:18 AM, Walter Bright wrote:
 On 7/31/2014 12:46 PM, H. S. Teoh via Digitalmars-d wrote:
 AFAIK, the compiler currently doesn't use assert as a source of
 information for optimization, it's just being proposed.
It already does by default,
That's good and that's obviously not a problem. If the check is there, the behaviour of the optimized code does not change.
 the proposal is to do it for -release.
(I think he is talking about -release.)
Aug 01 2014
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/31/14, 12:37 PM, Daniel Gibson wrote:
 This thread however shows that many D users (who probably have more D
 experience than myself) are not aware that assert() may influence
 optimization and would prefer to have separate syntax to tell the
 optimizer what values he can expect.
Yah, I think that's a good outcome. We must document assert better. -- Andrei
Jul 31 2014
next sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 20:57:10 UTC, Andrei Alexandrescu 
wrote:
 On 7/31/14, 12:37 PM, Daniel Gibson wrote:
 This thread however shows that many D users (who probably have 
 more D
 experience than myself) are not aware that assert() may 
 influence
 optimization and would prefer to have separate syntax to tell 
 the
 optimizer what values he can expect.
Yah, I think that's a good outcome. We must document assert better. -- Andrei
Its a little too late for that I think, asserts are already being used so to change the meaning now is wrong. Earlier I said that maybe a documentation change is all that is needed but I retract that statement.
Jul 31 2014
prev sibling next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 31.07.2014 22:57, schrieb Andrei Alexandrescu:
 On 7/31/14, 12:37 PM, Daniel Gibson wrote:
 This thread however shows that many D users (who probably have more D
 experience than myself) are not aware that assert() may influence
 optimization and would prefer to have separate syntax to tell the
 optimizer what values he can expect.
Yah, I think that's a good outcome. We must document assert better. -- Andrei
You should have done so 10 years ago.. experienced D coders (that don't follow this discussion) probably won't look up what exactly assert() does again and and code will silently break in subtle ways once the optimizer uses assert() But if you (as in "the D language implementors") *really* decide to stick to this unexpected meaning of assert(), you should indeed document this as soon as a proper definition of what assert() does and might do in the future, when enforce() vs assert() should be used. Maybe, besides enforce() and assert() there could be a check() that: * returns true if the condition is true * throws an exception in debug mode if the condition is false * returns false in release mode if the condition is false could be introduced. It could be used like if(check(x !is null, "x must not be null")) { // .. do something with x .. } to cater the usecase of "in debugmode I want to know about this problem/behavior immediately to debug it, but in releasemode I want to handle it gracefully". Cheers, Daniel
Jul 31 2014
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/31/14, 2:11 PM, Daniel Gibson wrote:
 Maybe, besides enforce() and assert() there could be a check() that:
 * returns true if the condition is true
 * throws an exception in debug mode if the condition is false
 * returns false in release mode if the condition is false
 could be introduced.
Yah, an extra non-magic function that performs the "mild assert" discussed in this thread would be a possibility. -- Andrei
Jul 31 2014
prev sibling parent reply "eles" <eles215 gzk.dot> writes:
On Thursday, 31 July 2014 at 20:57:10 UTC, Andrei Alexandrescu 
wrote:
 On 7/31/14, 12:37 PM, Daniel Gibson wrote:
 This thread however shows that many D users (who probably have 
 more D
 experience than myself) are not aware that assert() may 
 influence
 optimization and would prefer to have separate syntax to tell 
 the
 optimizer what values he can expect.
Yah, I think that's a good outcome. We must document assert better. -- Andrei
Let me try: "assert() expresses a contract that must be true at that point for the program to continue correctly. Compiler (and the optimizer therein) will generate code that works as intended as long as these contracts are true. While in Debug mode code for checking the validity of contracts is actually generated and failure of contracts will result in halting the program, in Release mode the code is no longer (guaranteed to be) generated and this results in undefined behavior. assert(0) is a special contract that requires no code for its verification, as it obviously fails. This is why the compiler will always make it a halting point, in all builds."
Jul 31 2014
next sibling parent "David Nadlinger" <code klickverbot.at> writes:
On Friday, 1 August 2014 at 04:51:06 UTC, eles wrote:
 assert(0) is a special contract that requires no code for its 
 verification, as it obviously fails. This is why the compiler 
 will always make it a halting point, in all builds."
This is wrong. As I have shown over in the other thread, the semantics Walter intended (and that are currently implemented in DMD, LDC and probably GDC) for assert(0) have nothing to do with what a false assertion would normally entail, but are merely a halt/abort/trap/… intrinsic. Cheers, David
Aug 01 2014
prev sibling parent "Wyatt" <wyatt.epp gmail.com> writes:
On Friday, 1 August 2014 at 04:51:06 UTC, eles wrote:
 While in Debug mode
Generally decent, but I don't agree that the absence of -release implies debug mode. -Wyatt
Aug 01 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 12:37 PM, Daniel Gibson wrote:
 Am 31.07.2014 21:19, schrieb Walter Bright:
 That's the way assert in C/C++ conventionally worked. But this is
 changing. Bearophile's reference made it clear that Microsoft C++ 2013
 has already changed, and I've seen discussions for doing the same with
 gcc and clang.
This will break so much code :-/
Maybe you're right. I've always thought that assert() was a simple and obvious concept, and am genuinely surprised at all the varied (and even weird) interpretations of it expressed here. I've never heard such things in my 30+ years of using assert(). I have seen some misuse of assert() before, but the author of them knew he was misusing it and didn't have an issue with that. I can't even get across the notion of what a program's inputs are. Sheesh. Or perhaps some people are just being argumentative. I can't really tell. I can tell, however, than many of these sub-threads have ceased to contain any useful discussion.
 In fact, the whole reason assert is a core language feature rather than
 a library notion is I was anticipating making use of assert for
 optimization hints.
So why is this not documented?
Frankly, it never occurred to me that it wasn't obvious. When something is ASSERTED to be true, then it is available to the optimizer. After all, that is what optimizers do - rewrite code into a mathematically equivalent form that is provably the same (but cheaper to compute). Its inputs are things that are known to be true. For example, if a piece of code ASSERTS that x is 3, thereafter the optimizer knows that x must be 3. After all, if the optimizer encounters: x = 3; do I need to then add a note saying the optimizer can now make use of that fact afterwards? The use of "assert" is a very strong word, it is not "maybe" or "possibly" or "sometimes" or "sort of". When you write: assert(x == 3); then at that point, if x is not 3, then the program is irretrievably, irredeemably, undeniably broken, and the default action is that the program is terminated. The idea expressed here by more than one that this is not the case in their code is astonishing to me.
 The assert documentation isn't even clear on when an AssertError is thrown and
 when execution is halted (http://dlang.org/contracts.html doesn't mention halt
 at all).
 And it says "When compiling for release, the assert code is not generated." -
if
 you implemented assert like this so the optimizer can assume the assertion to
be
 true even when "assert code is not generated" this is certainly something
 developers should be very aware of - and not once you actually implement that
 optimization, but from day one, so they can use assert accordingly!
I agree it is now clear that the documentation needs to be clarified on that point. What I considered as obvious apparently is not.
 This thread however shows that many D users (who probably have more D
experience
 than myself) are not aware that assert() may influence optimization and would
 prefer to have separate syntax to tell the optimizer what values he can expect.
It's also true that many D users are unclear what data flow analysis is, how it is used in compilers, and the state of the art of such optimizations. And they shouldn't need to. D would be a terrible language indeed if only compiler guys could write successful programs with it. What users do need to understand, is if they write: assert(x < 10); that at that point in the code, they are GUARANTEEING that x is less than 10, regardless of compiler switches, checked or not, and that the program is absolutely broken if it is not. And let the compiler take it from there.
Jul 31 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 1 August 2014 at 03:17:06 UTC, Walter Bright wrote:
 In fact, the whole reason assert is a core language feature 
 rather than
 a library notion is I was anticipating making use of assert 
 for
 optimization hints.
So why is this not documented?
Frankly, it never occurred to me that it wasn't obvious. When something is ASSERTED to be true, then it is available to the optimizer. After all, that is what optimizers do - rewrite code into a mathematically equivalent form that is provably the same (but cheaper to compute). Its inputs are things that are known to be true. For example, if a piece of code ASSERTS that x is 3, thereafter the optimizer knows that x must be 3. After all, if the optimizer encounters: x = 3; do I need to then add a note saying the optimizer can now make use of that fact afterwards? The use of "assert" is a very strong word, it is not "maybe" or "possibly" or "sometimes" or "sort of". When you write: assert(x == 3); then at that point, if x is not 3, then the program is irretrievably, irredeemably, undeniably broken, and the default action is that the program is terminated. The idea expressed here by more than one that this is not the case in their code is astonishing to me.
This is enough to convince me. assert - in D - is for documenting assumptions and checking them in non-release builds. It's a reasonable definition - if unexpected to some - and allows good optimisation opportunities. Do these guidelines sound reasonable: Don't want the optimiser to use the information from your asserts when the asserts are gone? Wrap them in a version block and version them out in your release builds. Write a wrapper for assert that does this if you like. You could even write a no-op wrapper for assert and call it assume, if you really want to. Don't want your defensive checks to ever be removed from a certain bit of code? Use std.exception.enforce or, if you really insist on assert, put a version(assert) {} else static assert(false, "Must be compiled with assertions enabled"); in the relevant place to prevent people accidentally disabling them.
Aug 01 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
John Colvin:

 This is enough to convince me.
Please don't feed Walter. Bye, bearophile
Aug 01 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 1:43 AM, bearophile wrote:
 John Colvin:

 This is enough to convince me.
Please don't feed Walter.
I don't care if you make such remarks about me, but I do care about the level of discourse in the forum sinking to such levels. Please refrain from such.
Aug 01 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 I don't care if you make such remarks about me, but I do care 
 about the level of discourse in the forum sinking to such 
 levels. Please refrain from such.
Yes sorry, I have lost my temper when you have written "Or perhaps some people are just being argumentative. I can't really tell.". People in this thread are not argumentative for the sake of wasting time and energy. Bye, bearophile
Aug 01 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 3:38 AM, bearophile wrote:
 Yes sorry,
No problemo, we all get a bit hot under the collar sometimes. It's because we care about what we're doing.
Aug 01 2014
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/1/14, 1:43 AM, bearophile wrote:
 John Colvin:

 This is enough to convince me.
Please don't feed Walter.
This is offensive on more than one level. -- Andrei
Aug 01 2014
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 1:31 AM, John Colvin wrote:
 Don't want the optimiser to use the information from your asserts when the
 asserts are gone?
You can always do: version(assert) { if (!exp) halt(); } and in -release mode, the compiler won't assume that exp is true. Or, more simply, just write your own myAssert() template. The compiler won't recognize it as special, it will just be ordinary code with ordinary behavior as the implementor wrote it. There's nothing difficult about it.
Aug 01 2014
prev sibling next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 01.08.2014 05:17, schrieb Walter Bright:
 Frankly, it never occurred to me that it wasn't obvious. When something
 is ASSERTED to be true, then it is available to the optimizer. After
 all, that is what optimizers do - rewrite code into a mathematically
 equivalent form that is provably the same (but cheaper to compute). Its
 inputs are things that are known to be true.

 For example, if a piece of code ASSERTS that x is 3, thereafter the
 optimizer knows that x must be 3. After all, if the optimizer encounters:

     x = 3;

 do I need to then add a note saying the optimizer can now make use of
 that fact afterwards? The use of "assert" is a very strong word, it is
 not "maybe" or "possibly" or "sometimes" or "sort of".

 When you write:

     assert(x == 3);

 then at that point, if x is not 3, then the program is irretrievably,
 irredeemably, undeniably broken, and the default action is that the
 program is terminated.

 The idea expressed here by more than one that this is not the case in
 their code is astonishing to me.
Well, this all sounds sane and makes sense in a way. The thing is, I never considered assert() to mean this up to now, which is probably influenced by the following reasons: In programming I've always encountered assert() in an "check if assertions are enabled/you're in debug mode, do nothing otherwise" way (that's what C, C++, Java and Python do). In unit tests the "checks" are also often called assertions. I'm not a native speaker.. .. but even if I were: words used for constructs/function-names/... in programming often don't 100% match their "real" meaning (as used in human communication)[1] - why should it be different for assert(), especially when not implemented/used like that in many popular programming languages? Cheers, Daniel [1] Examples for "spoken meaning" vs "programming lingo": * or (in spoken language often used meaning "xor" - "do you want milk or sugar with your coffee?" - "true" - "wtf?") * class (has many meanings in language, I guess none 100% matches the use in programming) * peek()/poke() (which thankfully get more descriptive names in D) * heap (the data structure has some kind of order, real life heaps are just chaotic piles of stuff) * iota (just some greek letter, /maybe/ "a little bit" in spoken language, in some programming languages/std libs it means "sequence of consecutive numbers" - wtf?) * exception (in real life not something that is "thrown around")
Aug 01 2014
next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 04:08:56PM +0200, Daniel Gibson via Digitalmars-d wrote:
 Am 01.08.2014 05:17, schrieb Walter Bright:
Frankly, it never occurred to me that it wasn't obvious. When
something is ASSERTED to be true, then it is available to the
optimizer. After all, that is what optimizers do - rewrite code into
a mathematically equivalent form that is provably the same (but
cheaper to compute). Its inputs are things that are known to be true.

For example, if a piece of code ASSERTS that x is 3, thereafter the
optimizer knows that x must be 3. After all, if the optimizer
encounters:

    x = 3;

do I need to then add a note saying the optimizer can now make use of
that fact afterwards? The use of "assert" is a very strong word, it
is not "maybe" or "possibly" or "sometimes" or "sort of".

When you write:

    assert(x == 3);

then at that point, if x is not 3, then the program is irretrievably,
irredeemably, undeniably broken, and the default action is that the
program is terminated.

The idea expressed here by more than one that this is not the case in
their code is astonishing to me.
Well, this all sounds sane and makes sense in a way. The thing is, I never considered assert() to mean this up to now, which is probably influenced by the following reasons: In programming I've always encountered assert() in an "check if assertions are enabled/you're in debug mode, do nothing otherwise" way (that's what C, C++, Java and Python do).
Whoa. I've never heard this before, but yeah, it explains a lot. :-O I suppose people have come to associate assert with the way it's implemented in C/C++, and may not have been aware of the rationale behind it. That's kinda scary.
 In unit tests the "checks" are also often called assertions.
[...] Yes, because if those checks failed, it means your program isn't conforming to the unittests, which means it is horribly broken and must be fixed before it's allowed to reach the customers' hands. I suppose you could interpret it as, "this unittest asserts that XYZ holds in this part of the program; if it doesn't, it means something is broken in the program logic". So it would be treated as a unittest failure, which aborts the program. T -- Written on the window of a clothing store: No shirt, no shoes, no service.
Aug 01 2014
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 7:08 AM, Daniel Gibson wrote:
 I'm not a native speaker..
I couldn't tell - your english is excellent. (I'm always careful not to read too much subtlety into word choice by non-native speakers. For a classic example, if a native speaker says "fine" it means he strongly disagrees with you. A non-native speaker likely means he thinks you have a great idea!)
 .. but even if I were: words used for constructs/function-names/... in
 programming often don't 100% match their "real" meaning (as used in human
 communication)[1] - why should it be different for assert(), especially when
not
 implemented/used like that in many popular programming languages?
Every discipline has its own jargon. For example, what would "sick" mean to a motorhead? We also had quite a struggle coming up with the name "immutable". Every term we tried seemed inadequate, until we noticed that we were always explaining "XXX means the data is immutable", and realized that "immutable" was what we were after.
Aug 01 2014
next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 01.08.2014 20:50, schrieb Walter Bright:
 On 8/1/2014 7:08 AM, Daniel Gibson wrote:
 I'm not a native speaker..
I couldn't tell - your english is excellent.
Thank you :)
 .. but even if I were: words used for constructs/function-names/... in
 programming often don't 100% match their "real" meaning (as used in human
 communication)[1] - why should it be different for assert(),
 especially when not
 implemented/used like that in many popular programming languages?
Every discipline has its own jargon.
Sure, and in programming jargon assert() until now was a runtime check that could be deactivated - even though the "spoken language" word "assert" might imply more.
 For example, what would "sick" mean
 to a motorhead?
You mean "motorhead" like in someone who likes cars or like in the the heavy metal band? :-P (Non-native speakers probably associate motorhead with the band and often don't know the original meaning)
 We also had quite a struggle coming up with the name "immutable". Every
 term we tried seemed inadequate, until we noticed that we were always
 explaining "XXX means the data is immutable", and realized that
 "immutable" was what we were after.
Yeah, coming up with terms is hard (I sometimes spend a long time thinking about the right name just for a function!), but if a term already has a meaning in your current context, redefining it should probably be avoided. Cheers, Daniel
Aug 01 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 12:06 PM, Daniel Gibson wrote:
 For example, what would "sick" mean
 to a motorhead?
You mean "motorhead" like in someone who likes cars or like in the the heavy metal band? :-P (Non-native speakers probably associate motorhead with the band and often don't know the original meaning)
"motorhead" as in someone who is happy with his head under the hood of a car working on the engine. (The band name is a reference to using amphetamine.) "sick" in this case would be a term of high praise for someone's custom hot rod.
Aug 01 2014
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 01:48:17PM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/1/2014 12:06 PM, Daniel Gibson wrote:
For example, what would "sick" mean to a motorhead?
You mean "motorhead" like in someone who likes cars or like in the the heavy metal band? :-P (Non-native speakers probably associate motorhead with the band and often don't know the original meaning)
"motorhead" as in someone who is happy with his head under the hood of a car working on the engine. (The band name is a reference to using amphetamine.) "sick" in this case would be a term of high praise for someone's custom hot rod.
And a "hot rod" in this context means a customized vehicle modified to have high performance, speed, etc., not a stick that has high temperature. :-D T -- Век живи - век учись. А дураком помрёшь.
Aug 01 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 2:00 PM, H. S. Teoh via Digitalmars-d wrote:
 And a "hot rod" in this context means a customized vehicle modified to
 have high performance, speed, etc., not a stick that has high
 temperature.  :-D
A hot rod also refers to a car with an American origin, whereas a "tuner" usually refers to a souped up imported car. https://www.youtube.com/watch?v=3R7l7nDuj1o https://www.youtube.com/watch?v=IAsdGE8XlZw
Aug 01 2014
parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 02:25:57PM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/1/2014 2:00 PM, H. S. Teoh via Digitalmars-d wrote:
And a "hot rod" in this context means a customized vehicle modified
to have high performance, speed, etc., not a stick that has high
temperature.  :-D
A hot rod also refers to a car with an American origin, whereas a "tuner" usually refers to a souped up imported car.
[...] And of course, a "tuner" means something entirely different to a musician. :-P T -- Right now I'm having amnesia and deja vu at the same time. I think I've forgotten this before.
Aug 01 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 10:48 PM, Walter Bright wrote:
 On 8/1/2014 12:06 PM, Daniel Gibson wrote:
 For example, what would "sick" mean
 to a motorhead?
You mean "motorhead" like in someone who likes cars or like in the the heavy metal band? :-P (Non-native speakers probably associate motorhead with the band and often don't know the original meaning)
"motorhead" as in someone who is happy with his head under the hood of a car working on the engine. (The band name is a reference to using amphetamine.) "sick" in this case would be a term of high praise for someone's custom hot rod.
Great. Now imagine you are a motorhead in a hospital.
Aug 01 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 11:08:53PM +0200, Timon Gehr via Digitalmars-d wrote:
 On 08/01/2014 10:48 PM, Walter Bright wrote:
On 8/1/2014 12:06 PM, Daniel Gibson wrote:
For example, what would "sick" mean
to a motorhead?
You mean "motorhead" like in someone who likes cars or like in the the heavy metal band? :-P (Non-native speakers probably associate motorhead with the band and often don't know the original meaning)
"motorhead" as in someone who is happy with his head under the hood of a car working on the engine. (The band name is a reference to using amphetamine.) "sick" in this case would be a term of high praise for someone's custom hot rod.
Great. Now imagine you are a motorhead in a hospital.
I have no trouble distinguishing between these two meanings of "sick" within the same conversation. You just have to resolve your overload sets correctly. :-D T -- Ruby is essentially Perl minus Wall.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 11:25 PM, H. S. Teoh via Digitalmars-d wrote:
 Great. Now imagine you are a motorhead in a hospital.
I have no trouble distinguishing between these two meanings of "sick" within the same conversation. You just have to resolve your overload sets correctly.:-D
The reason I was bringing this up was indeed that the current thread could be somewhat aptly summarized as one involving a motorhead who is trying to persuade a doctor that his patient is not actually sick, and that indeed, such a claim is completely meaningless; hence no medicine should be administered.
Aug 01 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 11:36:55PM +0200, Timon Gehr via Digitalmars-d wrote:
 On 08/01/2014 11:25 PM, H. S. Teoh via Digitalmars-d wrote:
Great. Now imagine you are a motorhead in a hospital.
I have no trouble distinguishing between these two meanings of "sick" within the same conversation. You just have to resolve your overload sets correctly.:-D
The reason I was bringing this up was indeed that the current thread could be somewhat aptly summarized as one involving a motorhead who is trying to persuade a doctor that his patient is not actually sick, and that indeed, such a claim is completely meaningless; hence no medicine should be administered.
To me, this thread can be summarized by n parties sharing code in a "common" language but it's actually not a common language because each party has their own incompatible definitions of all the keywords. T -- Stop staring at me like that! It's offens... no, you'll hurt your eyes!
Aug 01 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 11:45 PM, H. S. Teoh via Digitalmars-d wrote:
 On Fri, Aug 01, 2014 at 11:36:55PM +0200, Timon Gehr via Digitalmars-d wrote:
 On 08/01/2014 11:25 PM, H. S. Teoh via Digitalmars-d wrote:
 Great. Now imagine you are a motorhead in a hospital.
I have no trouble distinguishing between these two meanings of "sick" within the same conversation. You just have to resolve your overload sets correctly.:-D
The reason I was bringing this up was indeed that the current thread could be somewhat aptly summarized as one involving a motorhead who is trying to persuade a doctor that his patient is not actually sick, and that indeed, such a claim is completely meaningless; hence no medicine should be administered.
To me, this thread can be summarized by n parties sharing code in a "common" language but it's actually not a common language because each party has their own incompatible definitions of all the keywords. T
Some of the parties have stated this at the moment they entered the discussion and were successfully ignored by some of the other parties who kept asserting that their own definitions were the only sane ones and anything else does not deserve to be discussed.
Aug 01 2014
prev sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 11:50:29AM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/1/2014 7:08 AM, Daniel Gibson wrote:
I'm not a native speaker..
I couldn't tell - your english is excellent. (I'm always careful not to read too much subtlety into word choice by non-native speakers. For a classic example, if a native speaker says "fine" it means he strongly disagrees with you. A non-native speaker likely means he thinks you have a great idea!)
My favorite quote along this line: A linguistics professor was lecturing to his class one day. "In English," he said, "A double negative forms a positive. In some languages, though, such as Russian, a double negative is still a negative. However, there is no language wherein a double positive can form a negative." A voice from the back of the room piped up, "Yeah, yeah." Also, it depends on which regional dialect you speak. On the east side of the Pond, a native speaker saying "fine" means he agrees with you. West of the Pond, it *can* mean disagreement, but it can also mean concession -- it all depends on the intonation. Which, of course, is absent in online textual communications.
.. but even if I were: words used for constructs/function-names/...
in programming often don't 100% match their "real" meaning (as used
in human communication)[1] - why should it be different for assert(),
especially when not implemented/used like that in many popular
programming languages?
Every discipline has its own jargon. For example, what would "sick" mean to a motorhead?
Also keep in mind that not everyone knows what a "motorhead" is. Google and Wikipedia (*including* the WP disambiguation page) points to various music bands, but no actual definition for the word!
 We also had quite a struggle coming up with the name "immutable".
 Every term we tried seemed inadequate, until we noticed that we were
 always explaining "XXX means the data is immutable", and realized that
 "immutable" was what we were after.
If only the same amount of care was exercised when the syntax of is-expressions was designed! Oh wait, was it ever *designed*?! ;-) T -- One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"
Aug 01 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/1/2014 12:09 PM, H. S. Teoh via Digitalmars-d wrote:
 	A linguistics professor was lecturing to his class one day. "In
 	English," he said, "A double negative forms a positive. In some
 	languages, though, such as Russian, a double negative is still a
 	negative. However, there is no language wherein a double
 	positive can form a negative." A voice from the back of the room
 	piped up, "Yeah, yeah."
English is quite the merry language with this. (Reversing the meaning of "merry", ho-ho!) It's also why D doesn't support ! in version, and why I'm a strong advocate of not having negated features. Of course, D has "no-throw" and "im-mutable". Arggh.
Aug 01 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 01, 2014 at 01:55:39PM -0700, Walter Bright via Digitalmars-d wrote:
 On 8/1/2014 12:09 PM, H. S. Teoh via Digitalmars-d wrote:
	A linguistics professor was lecturing to his class one day. "In
	English," he said, "A double negative forms a positive. In some
	languages, though, such as Russian, a double negative is still a
	negative. However, there is no language wherein a double
	positive can form a negative." A voice from the back of the room
	piped up, "Yeah, yeah."
English is quite the merry language with this. (Reversing the meaning of "merry", ho-ho!) It's also why D doesn't support ! in version, and why I'm a strong advocate of not having negated features. Of course, D has "no-throw" and "im-mutable". Arggh.
Well, if we could turn back the clock and redesign D based on our experience, we'd have "throwing" and "mutable" as modifiers instead of "nothrow" and "immutable". :) Not to mention "impure" instead of "pure". T -- "Real programmers can write assembly code in any language. :-)" -- Larry Wall
Aug 01 2014
parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Friday, 1 August 2014 at 21:06:42 UTC, H. S. Teoh via
Digitalmars-d wrote:
 Well, if we could turn back the clock and redesign D based on 
 our
 experience, we'd have "throwing" and "mutable" as modifiers 
 instead of
 "nothrow" and "immutable". :)

 Not to mention "impure" instead of "pure".


 T
D3 anyone? :)
Aug 01 2014
next sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 03:07:25 UTC, Tofu Ninja wrote:
 D3 anyone? :)
Macros please. God please. I assert(macrosExist);
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 05:14 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:07:25 UTC, Tofu Ninja wrote:
 D3 anyone? :)
Macros please. God please. I assert(macrosExist);
core.exception.AssertError chris(332812126): Assertion failure ---------------- chris(_d_assertm+0x26) [0x41601a] chris() [0x415ff2] chris(_Chrismain+0xe) [0x415fd2] chris(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x1c) [0x4167ec] chris(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x416166] chris(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x3b) [0x416833] chris(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x416166] chris(main+0xd1) [0x4160f1] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f2c21507ec5] ----------------
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 04:00:01 UTC, Timon Gehr wrote:
 On 08/02/2014 05:14 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:07:25 UTC, Tofu Ninja wrote:
 D3 anyone? :)
Macros please. God please. I assert(macrosExist);
core.exception.AssertError chris(332812126): Assertion failure ---------------- ... irrelevant stuff ... ----------------
http://en.wikipedia.org/wiki/Macro_(computer_science) core.exception.AssertError timon(332812126): Assertion failure ---------------- ... irrelevant stuff unimportant to point ... ----------------
Aug 01 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:05 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 04:00:01 UTC, Timon Gehr wrote:
 On 08/02/2014 05:14 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:07:25 UTC, Tofu Ninja wrote:
 D3 anyone? :)
Macros please. God please. I assert(macrosExist);
core.exception.AssertError chris(332812126): Assertion failure ---------------- ... irrelevant stuff ... ----------------
http://en.wikipedia.org/wiki/Macro_(computer_science) core.exception.AssertError timon(332812126): Assertion failure
D's assert statement does not know about this! :o)
 ----------------
 ... irrelevant stuff unimportant to point ...
 ----------------
I thought it made it more realistic.
Aug 01 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Saturday, 2 August 2014 at 03:07:25 UTC, Tofu Ninja wrote:
 D3 anyone? :)
If "assert()" is turned into "assume()" then D will go down as the buggiest compiler in history. No point in continuing with D* then. Then again, there are plenty of other letters. E, F, G, H…
Aug 02 2014
prev sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 14:08:56 UTC, Daniel Gibson wrote:
 .. but even if I were: words used for 
 constructs/function-names/... in programming often don't 100% 
 match their "real" meaning (as used in human communication)[1] 
 - why should it be different for assert(), especially when not 
 implemented/used like that in many popular programming 
 languages?
The way Walter is suggesting assert be handled is much more in line with the real English meaning (plus all of the resources posted seem to back up his position much more strongly than the other way), so that's why I'm siding with Walter on this (mostly). Imagine my surprise when I Google'd "assert definition" to find it meant "state a fact or belief confidently and forcefully."... the definition of the word really makes it obvious what the feature was originally intended to convey. Upon reflection, the definition that everyone is suggesting for assert ("something that is proven by being checked") really doesn't make a whole lot of sense given the facts laid out about assert. Asserts are just facts that you state about the program. It's just a "nice feature" that the compiler will check your asserted facts when you're debugging your code. If you aren't stating a fact about the state/behavior of the code, you probably shouldn't be using an assert there (I feel that I've misused asserts from the beginning by not knowing this, though).
Aug 01 2014
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 11:18 PM, Chris Cain wrote:
 On Friday, 1 August 2014 at 14:08:56 UTC, Daniel Gibson wrote:
 .. but even if I were: words used for constructs/function-names/... in
 programming often don't 100% match their "real" meaning (as used in
 human communication)[1] - why should it be different for assert(),
 especially when not implemented/used like that in many popular
 programming languages?
The way Walter is suggesting assert be handled is much more in line with the real English meaning (plus all of the resources posted seem to back up his position much more strongly than the other way), so that's why I'm siding with Walter on this (mostly). Imagine my surprise when I Google'd "assert definition" to find it meant "state a fact or belief confidently and forcefully."... the definition of the word really makes it obvious what the feature was originally intended to convey. Upon reflection, the definition that everyone is suggesting for assert ("something that is proven by being checked") really doesn't make a whole lot of sense given the facts laid out about assert. Asserts are just facts that you state about the program. It's just a "nice feature" that the compiler will check your asserted facts when you're debugging your code. If you aren't stating a fact about the state/behavior of the code, you probably shouldn't be using an assert there (I feel that I've misused asserts from the beginning by not knowing this, though).
en.wikipedia.org/wiki/Evidence
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 21:29:48 UTC, Timon Gehr wrote:
 en.wikipedia.org/wiki/Evidence
http://en.wikipedia.org/wiki/Sausage ... Sorry, I don't know what you meant by that. :-)
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 11:40 PM, Chris Cain wrote:
 On Friday, 1 August 2014 at 21:29:48 UTC, Timon Gehr wrote:
 en.wikipedia.org/wiki/Evidence
http://en.wikipedia.org/wiki/Sausage ...
ingredient in dishes such as stews and casseroles ^~~~~ Almost.
 ...

 Sorry, I don't know what you meant by that. :-)
You will notice it uses the word 'assertion' in a way that is incompatible with your claim that the "assert definition" rules out such an usage.
Aug 01 2014
next sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 22:01:01 UTC, Timon Gehr wrote:
 You will notice it uses the word 'assertion' in a way that is 
 incompatible with your claim that the "assert definition" rules 
 out such an usage.
How so? It's an article on evidence. All it seems to suggest is that evidence can be used to back up assertions, not that all assertions must be backed up by evidence. Assertions are a statement of fact or belief and can be backed up with evidence. No incompatibility there.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 12:03 AM, Chris Cain wrote:
 On Friday, 1 August 2014 at 22:01:01 UTC, Timon Gehr wrote:
 You will notice it uses the word 'assertion' in a way that is
 incompatible with your claim that the "assert definition" rules out
 such an usage.
How so? It's an article on evidence. All it seems to suggest is that evidence can be used to back up assertions, not that all assertions must be backed up by evidence. Assertions are a statement of fact or belief and can be backed up with evidence. No incompatibility there.
"contradictory assertions" "To what degree of certitude must the assertion be supported?" etc. I'll not go into more details because I actually intend not to participate again in heated debate after already having shown strong evidence.
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 22:17:15 UTC, Timon Gehr wrote:
 "contradictory assertions"

 "To what degree of certitude must the assertion be supported?"

 etc.

 I'll not go into more details because I actually intend not to 
 participate again in heated debate after already having shown 
 strong evidence.
Frankly, I don't understand the point you're trying to make, so it's not really possible to rebut it. If your point is that assertions need to have evidence to be assertions, an easy counterproof of this is in your own quote: "To what degree of certitude must the assertion be supported?" ... It wouldn't have been called an assertion in that sentence unless it's something that is sure that it had been supported sufficiently (it would have been worded more along the lines of "To what degree of certitude must the assertion *candidate* be supported?") I think it's clear that the definition of assertion being "statement of fact or belief" is compatible with the usage in that wikipedia article. In particular, "contradictory 'statements of fact'" and "To what degree of certitude must the 'statements of fact' be supported?" you suggested as examples of incompatibility actually make perfect sense.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
( Source: http://www.chris.com/ascii/index.php?art=objects/explosives )

On 08/02/2014 12:26 AM, Chris Cain wrote:
 On Friday, 1 August 2014 at 22:17:15 UTC, Timon Gehr wrote:
 "contradictory assertions"

 "To what degree of certitude must the assertion be supported?"

 etc.

 I'll not go into more details because I actually intend not to
 participate again in heated debate after already having shown strong
 evidence.
Frankly, I don't understand the point you're trying to make, so it's not really possible to rebut it. If your point is that assertions need to have evidence to be assertions, an easy counterproof of this is in your own quote: "To what degree of certitude must the assertion be supported?" ... It wouldn't have been called an assertion in that sentence unless it's something that is sure that it had been supported sufficiently (it would have been worded more along the lines of "To what degree of certitude must the assertion *candidate* be supported?") ...
Look, this is a really poor piece of logical reasoning, and for today I am expressedly fed up with arguing against obvious non sequiturs and immediately summoning new ones. In any case, my easy way out is to note that this is not my assertion. To be really clear: My assertion was: It is not true that anyone who accepts the "assertion definition" as the single conclusive way to give meaning to the term 'assert' will be able to use it to distinguish the meaning given to it by Walter and the other meaning under discussion, given to it by other notable people, in such a way as to find the former sensible and the latter nonsensical. Sigh, I got involved again.
 I think it's clear that the definition of assertion being "statement of
 fact or belief" is compatible with the usage in that wikipedia article.
 ...
Yes. Please go back and read the relevant posts, find out what they assert and agree with them or argue against an assertion that was actually made. I have seen assertions such as: "the definition of the word really makes it obvious what the feature was originally intended to convey."
 In particular, "contradictory 'statements of fact'"
http://en.wikipedia.org/wiki/Fact
 [...]  actually make perfect sense.
Contradictory facts make perfect sense. Contradictory facts make no sense at all. Those two assertions expressed facts, unless this third assertion is wrong. The next assertion is wrong. The preceding assertions are statements of fact. static if(!is(typeof(x))) int x; ... ... . . . ____ __,-~~/~ `---. _/_,---( , ) __ / < / ) \___ - ------===;;;'====------------------===;;;===----- - - \/ ~"~"~"~"~"~\~"~)~"/ (_ ( \ ( > \) \_( _ < >_>' ~ `-i' ::>|--" I;|.|.| <|i::|i|`. (` ^'"`-' ")
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 23:11:17 UTC, Timon Gehr wrote:
 ( Source: 
 http://www.chris.com/ascii/index.php?art=objects/explosives )

 On 08/02/2014 12:26 AM, Chris Cain wrote:
 On Friday, 1 August 2014 at 22:17:15 UTC, Timon Gehr wrote:
 "contradictory assertions"

 "To what degree of certitude must the assertion be supported?"

 etc.

 I'll not go into more details because I actually intend not to
 participate again in heated debate after already having shown 
 strong
 evidence.
Frankly, I don't understand the point you're trying to make, so it's not really possible to rebut it. If your point is that assertions need to have evidence to be assertions, an easy counterproof of this is in your own quote: "To what degree of certitude must the assertion be supported?" ... It wouldn't have been called an assertion in that sentence unless it's something that is sure that it had been supported sufficiently (it would have been worded more along the lines of "To what degree of certitude must the assertion *candidate* be supported?") ...
Look, this is a really poor piece of logical reasoning, and for today I am expressedly fed up with arguing against obvious non sequiturs and immediately summoning new ones. In any case, my easy way out is to note that this is not my assertion.
I don't disagree that having to come up with an argument for you is poor. However, by not stating what it is you have provided "strong evidence" for, what does that leave me to do? I can simply say nothing but "what are you saying" but I had said that once already. It's a complete waste of time to argue with someone who refuses to make a clear position. Frankly, if you're going to criticize others for making a "poor piece of logical reasoning", you should at least make something beginning to resemble a piece of logical reasoning yourself. No, before you say anything, presenting evidence for a position you haven't stated isn't valid logical reasoning.
 To be really clear: My assertion was:

 It is not true that anyone who accepts the "assertion 
 definition" as the single conclusive way to give meaning to the 
 term 'assert' will be able to use it to distinguish the meaning 
 given to it by Walter and the other meaning under discussion, 
 given to it by other notable people, in such a way as to find 
 the former sensible and the latter nonsensical.
And by what evidence do you back that up with? I think the only reasonable, logical thing to do when you state a fact to a computer program is that it accepts it as a fact. So the definition of assertion very much clarifies exactly the behavior described of assert. The only thing that differs from the definition is that the compiler will insert checks for your assertion under certain circumstances, but by the definition it would not be under obligation to do so (although, the fact that it's checking your assertions when you're debugging is infinitely useful, so it makes a lot of sense for it to go against the definition slightly for pragmatism).
 Sigh, I got involved again.

 I think it's clear that the definition of assertion being 
 "statement of
 fact or belief" is compatible with the usage in that wikipedia 
 article.
 ...
Yes. Please go back and read the relevant posts, find out what they assert and agree with them or argue against an assertion that was actually made. I have seen assertions such as: "the definition of the word really makes it obvious what the feature was originally intended to convey."
 In particular, "contradictory 'statements of fact'"
http://en.wikipedia.org/wiki/Fact
I hope you don't think that "state a fact or belief confidently and forcefully" and "fact" are necessarily the same thing. If it were, then the better definition of assert would have simply been "fact".
 [...]  actually make perfect sense.
Contradictory facts make perfect sense. Contradictory facts make no sense at all. Those two assertions expressed facts, unless this third assertion is wrong. The next assertion is wrong. The preceding assertions are statements of fact.
Contradictory STATEMENTS makes perfect sense. Since assertions are STATEMENTS of facts (or beliefs, to be clear), your entire argument is broken because you've used strawman. It makes perfect sense to make contradictory assertions. Of course, your program failing to behave in a defined manner because of it (since you're, in effect, god of your program and the assertions you make will really be followed unlike people who might question your assertions and demand evidence) should be expected, just like if you wrote an incorrect if statement you can expect your program to have buggy behavior. In particular, you cannot really reasonably expect that a program with incorrect statements (asserts, ifs, function call, whatever) to behave correctly. Writing an incorrect assert will (not surprisingly) result in a bug in a program just as if you wrote the wrong if statements in a binary search algorithm.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 03:11 AM, Chris Cain wrote:
 However, by not stating what it is you have provided "strong evidence" for,
Why would I need to? It is what you were arguing against: "You will notice it uses the word 'assertion' in a way that is incompatible with your claim that the "assert definition" rules out such an usage." I think it should be clear from the context, no? Am I missing something?
 what does that leave me to do?
You can say that you still disagree but are in no position to argue further and we'll put aside the discussion. Mind you, I don't actually gain anything by convincing you, the investments have already been immense, and it would be a lot harder now since I appear to have insulted you, for which I want to express an apology.
 I think the only reasonable, logical thing to do when you state a fact to a
computer program is that it accepts it as a fact.
Indeed. Note that actually we have defined an assertion to be a particular kind of statement of a fact _or belief_, ...
 So the definition of assertion very much clarifies exactly the behavior
described of assert.
hence this conclusion is reached by a non-exhaustive case analysis on what kind of thing the assertion actually describes.
 Contradictory STATEMENTS makes perfect sense.
Yes, without further qualification, two statements may contradict each other. However, if we are e.g. talking about two statements that do not contradict each other, it would not make sense to claim them to be contradictory. There are many other qualifications that will imply that two statements do not contradict each other. The mere fact that we have two classes of STATEMENTS does not allow us to conclude that it makes sense to assume that their instances may be contradictory.
 Since assertions are
The same reservations as above apply.
 STATEMENTS of facts.
A statement of FACT is a statement that expresses a fact. I.e. there is an existing fact, and the statement expresses this fact. There is a difference between a fact and a statement of that fact, but if two statements of fact contradict each other, you are still left with two contradictory facts.
 your entire argument is broken because you've used strawman.
It is not a straw man even when assuming I actually claimed that you said contradictory facts make sense and then argued against that alternative claim because this claim you appear to think I argued against is an immediate consequence of the claim you made and which I wanted to refute.
Aug 01 2014
next sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 01:55:49 UTC, Timon Gehr wrote:
 On 08/02/2014 03:11 AM, Chris Cain wrote:
 However, by not stating what it is you have provided "strong 
 evidence" for,
Why would I need to? It is what you were arguing against: "You will notice it uses the word 'assertion' in a way that is incompatible with your claim that the "assert definition" rules out such an usage." I think it should be clear from the context, no? Am I missing something?
In one post you claim:
 In any case, my easy way out is to note that this is not my 
 assertion.
In the next you claim I *was* arguing against what you were asserting. I think the point about you lacking clarity makes itself absolutely crystal clear here. Frankly, it's too difficult to understand you and I'm tired because I've had to argue with another guy about the definition of "test" because "That's not a test, that's code!" *facepalm* I really don't want to get into that sort of argument here again. Frankly, I feel the thing you're going through is simply cognitive dissonance. I started this topic out thinking Walter was wrong but his points are far stronger and make a lot more sense when you consider more of the context behind `assert`, including the English definition (but also including the articles on assertions). So FWIW, I understand how you feel. But you're going to have to get over it and incorporate the new knowledge by arguing with yourself on the matter. Frankly, you're the person with the most to gain by casting aside misunderstandings of concepts. I don't gain anything by convincing you, so it makes more sense for you to argue with yourself, in this case. Really, I wouldn't mind doing you the favor of convincing you, but I have no tolerance for people whose cognitive dissonance is strong enough to argue against basic definitions of words (which you can verify by simply typing into Google "assert definition"). Honestly it makes it impossible for us to communicate when you won't even agree to accept a definition of a word which is widely accepted by every dictionary I can find. If you have a problem with the understanding of "assertion", Google the definition until you're satisfied with a mental model behind it. It makes absolute abundant sense of why it would mean what Walter suggests. I think you'll find it really hard to continue to disagree with 10 dictionaries, so hopefully it'll cure you of your cognitive dissonance. Of course, by some luck you might find one dictionary I haven't found that might support your position, but I hope for your sanity and personal growth that you realize that 10 to 1 definitions means there's far more evidence against that.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 04:28 AM, Chris Cain wrote:
 ...
I retract my apology.
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 02:32:45 UTC, Timon Gehr wrote:
 On 08/02/2014 04:28 AM, Chris Cain wrote:
 ...
I retract my apology.
Of course. The worst curse I could wish upon you is that you stick to your guns. So stick to your guns, my friend. :-)
Aug 01 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 04:42 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 02:32:45 UTC, Timon Gehr wrote:
 On 08/02/2014 04:28 AM, Chris Cain wrote:
 ...
I retract my apology.
Of course. The worst curse I could wish upon you is that you stick to your guns. So stick to your guns, my friend. :-)
Well, first you complained about the absence of precise logical reasoning and even asked me to provide precise logical reasoning. When I started to carefully lay down my thinking, you started to complain about the presence of the reasoning, did not seem to read it, and decided to attack me personally. I felt 1A trolled so I thought you deserve to be offended a little bit, hence my previous apology seemed not right, taking all new information into account. :o) BTW: Just to make sure, there are no bad feelings at all on my side. It is my own fault that I got involved in such a discussion again.
Aug 01 2014
prev sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 02:42:50 UTC, Chris Cain wrote:
 On Saturday, 2 August 2014 at 02:32:45 UTC, Timon Gehr wrote:
 On 08/02/2014 04:28 AM, Chris Cain wrote:
 ...
I retract my apology.
Of course. The worst curse I could wish upon you is that you stick to your guns. So stick to your guns, my friend. :-)
I don't know... maybe I can try to explain what he is trying to say. Correct me if I am wrong in either of your interpretations of assert. Your claim is that an assertion is a promise, by the person asserting, that something is always true. Meaning if you assert something, the compiler will interpret it to always be true. In essence the compiler will interpret your promise(as the programmer) as a never changing fact that can be used for optimizations. His claim is that an assertion is a claim by the person asserting. That claim has not been proven to be true or false. Meaning that as a claim, the compiler can't do anything with that information alone. The compiler can try to check if the claim is true and if it is, use that information to optimize. But if it is not checked it is merely a claim with no backing, and as such, nothing can be done with it. ... Ok that was my interpretation of both of your interpretations. I hope I didn't misinterpret. Personally I side with the argument that assert is a claim which I believe is closer to the actual meaning of the word assert and closer to how programmers use assert now. If you look at the google definition of assert... "state a fact or belief confidently and forcefully." You will see that it says an assertion is a statement of a "fact or belief". The "confidently and forcefully" portion of the definition is just describing the attitude of the asserter, so in this context is not relevant. That means that the speaker can use an assertion to state either a fact or a belief(I think in this context a belief is sufficiently close to a claim, both could be true or false). As the person being spoken to, there is no way to know if the speaker is asserting a fact or a belief. This means that as the person being spoken to, you have no choice but to come to the conclusion that what is being asserted could be either of the two and thus could either be true or false. In the context of a programmer and a compiler, the programmer is the speaker and the compiler is the thing being spoken to. This means that if the programmer asserts something the compiler has no choice but to interpret what is being asserted could either be true or false. Now you could say that the compiler implicitly trusts the programmer and as such takes all assertions as fact, but I believe that is a mistake on the compilers part. If the compiler implicitly trusted the programmer, there would be no warnings, and type checking ... ect. You could say that the compiler only implicitly trusts the programmer in the case of assert, but I still believe this to be a mistake on the compilers part.
Aug 01 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:40 AM, Tofu Ninja wrote:
 Ok that was my interpretation of both of your interpretations. I
 hope I didn't misinterpret.
Your interpretation of my interpretation is exactly right. (However, note that I am not using this reasoning to say the new semantics are wrong, I am saying the new semantics are not obviously what was intended from the beginning once given the definition of 'assert' in English. This is what this discussion is about.)
Aug 01 2014
prev sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 04:40:53 UTC, Tofu Ninja wrote:
 I don't know... maybe I can try to explain what he is trying to
 say.
 Correct me if I am wrong in either of your interpretations of
 assert.

 Your claim is that an assertion is a promise, by the person
 asserting, that something is always true. Meaning if you assert
 something, the compiler will interpret it to always be true. In
 essence the compiler will interpret your promise(as the
 programmer) as a never changing fact that can be used for
 optimizations.
Actually, I'm going to clarify this: Your assertion is *not* the promise. Your assertion is simply a statement of fact (note, that does not mean it's a fact, as that appears to be a point of confusion: a statement of fact is simply a statement that *can* be verified). An intrinsic part of programming is that whatever you write is what you intend to write (that is, it must assume that you aren't incorrect because it otherwise couldn't compile the program ... or it'd have to ask you for every line to "sign off" that it's what you intended). The obvious conclusion is that you must "promise" that you know what you're doing. As the human and good programmer, it seems that you wouldn't want to assume you're correct, but the compiler/programming language itself has no option but to assume you meant an if statement there or a function call here, and that you intended these particular arguments to be passed in this particular order. It also assume your assertions are what you meant them to be. The fact that they are checked is a bonus feature (which is really where the confusion behind assertions lies, as it was for me... I, like you, thought that assertions MUST be verified and checked, but that turns out to not be what that meant at all).
 His claim is that an assertion is a claim by the person
 asserting. That claim has not been proven to be true or false.
 Meaning that as a claim, the compiler can't do anything with 
 that
 information alone. The compiler can try to check if the claim is
 true and if it is, use that information to optimize. But if it 
 is
 not checked it is merely a claim with no backing, and as such,
 nothing can be done with it.
Of course, I can understand that interpretation. But at the same time, why would you write something and expect a compiler to do nothing with it? Is there any other construct in the language that does that? Even noops in ASM which literally mean "do nothing" actually have an effect on the intended meaning of a program.
 ...

 Ok that was my interpretation of both of your interpretations. I
 hope I didn't misinterpret.

 Personally I side with the argument that assert is a claim which
 I believe is closer to the actual meaning of the word assert and
 closer to how programmers use assert now.

 If you look at the google definition of assert...

 "state a fact or belief confidently and forcefully."

 You will see that it says an assertion is a statement of a "fact
 or belief". The "confidently and forcefully" portion of the
 definition is just describing the attitude of the asserter, so 
 in
 this context is not relevant. That means that the speaker can 
 use
 an assertion to state either a fact or a belief(I think in this
 context a belief is sufficiently close to a claim, both could be
 true or false). As the person being spoken to, there is no way 
 to
 know if the speaker is asserting a fact or a belief. This means
 that as the person being spoken to, you have no choice but to
 come to the conclusion that what is being asserted could be
 either of the two and thus could either be true or false.

 In the context of a programmer and a compiler, the programmer is
 the speaker and the compiler is the thing being spoken to. This
 means that if the programmer asserts something the compiler has
 no choice but to interpret what is being asserted could either 
 be
 true or false.

 Now you could say that the compiler implicitly trusts the
 programmer and as such takes all assertions as fact, but I
 believe that is a mistake on the compilers part. If the compiler
 implicitly trusted the programmer, there would be no warnings,
 and type checking ... ect. You could say that the compiler only
 implicitly trusts the programmer in the case of assert, but I
 still believe this to be a mistake on the compilers part.
I see it the exact opposite way. I see it as the compiler is helpful and will do as much proving as it can, but ultimately it must always logically put if statements in where you want them and function calls in where you want them. Technically, it takes some liberties with optimizations because it has good reason to believe that the two interpretations are equivalent. That said, when we pass `-O` to the compiler, we're commanding it to do that... so... *shrug* Thus when you assert something is true and the compiler can't immediately disprove you, it must follow what you say. FWIW, I feel that something like this should fail compilations: ``` int x = 1; assert(x != 1); ``` because the compiler could, in fact, disprove you at compile time. That said, it's not a scalable approach because there exists too many programs that you cannot prove the output of. Otherwise, if it can't immediately disprove what you say (by type checking, for instance), then it has no choice but to do what you say, even if you're wrong. Even if you do `x1 == x2 && y1 == x2` in a conditional somewhere, it can't/won't take liberties to "correct it" to `x1 == x2 && y1 == y2`. But if x1 is a FloatMeters and x2 is a FloatMiles, I would expect it to disprove that it's a correct comparison (unless you make statements suggesting that this is what you really mean, of course). But then again, I refer to the above where obviously illogical things should fail to compile as well. But once it compiles, I expect that it does what I say even if what I say is wrong.
Aug 01 2014
next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 05:07:58 UTC, Chris Cain wrote:

 Actually, I'm going to clarify this: Your assertion is *not* 
 the promise. Your assertion is simply a statement of fact 
 (note, that does not mean it's a fact, as that appears to be a 
 point of confusion: a statement of fact is simply a statement 
 that *can* be verified).
I am going to have to disagree, I think what you are calling a statement of fact, is actually a claim. A statement is simply a piece of communication. So if you state a belief, you are simply communicating that belief's existence. So a statement of fact is simply the communication that the fact exists. In reality you can never actually state a fact because you can only ever believe a fact is true. It comes down to the philosophical problem of "I think therefore I am", which basically says that the only thing that your mind can PROVE 100% is that you are thinking. You can state a belief, but to anyone else hearing that statement, it will be a claim. Basicly is comes down to this... *A claim is something that can be true or false *A belief is a claim that is true in the believer's mind, but if stated becomes a claim due to that possibility that the believer's is in error *A fact is something that is always true That is why you can have true statements and false statements, it is not that the statement is self is true or false, but that the claim that is being stated is true or false.
 An intrinsic part of programming is that whatever you write is 
 what you intend to write (that is, it must assume that you 
 aren't incorrect because it otherwise couldn't compile the 
 program ... or it'd have to ask you for every line to "sign 
 off" that it's what you intended). The obvious conclusion is 
 that you must "promise" that you know what you're doing.

 As the human and good programmer, it seems that you wouldn't 
 want to assume you're correct, but the compiler/programming 
 language itself has no option but to assume you meant an if 
 statement there or a function call here, and that you intended 
 these particular arguments to be passed in this particular 
 order. It also assume your assertions are what you meant them 
 to be. The fact that they are checked is a bonus feature (which 
 is really where the confusion behind assertions lies, as it was 
 for me... I, like you, thought that assertions MUST be verified 
 and checked, but that turns out to not be what that meant at 
 all).
It is not a matter of the compiler trying to determine if you meant to write what you did or not(there is no way it can). It is a matter of the compiler determining if what you wrote is what it considers to be correct input. If you try to compile "SDA #$!$SDF#$T#", the compiler has no way of knowing if you meant to write that or not, but it is still allowed to reject that.
 Of course, I can understand that interpretation. But at the 
 same time, why would you write something and expect a compiler 
 to do nothing with it? Is there any other construct in the 
 language that does that? Even noops in ASM which literally mean 
 "do nothing" actually have an effect on the intended meaning of 
 a program.
Because if the compiler actually checks the claim then it can optimize on it, but if the compiler does not check then it can not know its true and can not optimize.
 I see it the exact opposite way. I see it as the compiler is 
 helpful and will do as much proving as it can, but ultimately 
 it must always logically put if statements in where you want 
 them and function calls in where you want them. Technically, it 
 takes some liberties with optimizations because it has good 
 reason to believe that the two interpretations are equivalent. 
 That said, when we pass `-O` to the compiler, we're commanding 
 it to do that... so... *shrug*

 Thus when you assert something is true and the compiler can't 
 immediately disprove you, it must follow what you say. FWIW, I 
 feel that something like this should fail compilations:

 ```
 int x = 1;
 assert(x != 1);
 ```

 because the compiler could, in fact, disprove you at compile 
 time. That said, it's not a scalable approach because there 
 exists too many programs that you cannot prove the output of. 
 Otherwise, if it can't immediately disprove what you say (by 
 type checking, for instance), then it has no choice but to do 
 what you say, even if you're wrong. Even if you do `x1 == x2 && 
 y1 == x2` in a conditional somewhere, it can't/won't take 
 liberties to "correct it" to `x1 == x2 && y1 == y2`. But if x1 
 is a FloatMeters and x2 is a FloatMiles, I would expect it to 
 disprove that it's a correct comparison (unless you make 
 statements suggesting that this is what you really mean, of 
 course). But then again, I refer to the above where obviously 
 illogical things should fail to compile as well. But once it 
 compiles, I expect that it does what I say even if what I say 
 is wrong.
I think a point that needs to be addressed is that there is a difference between a program being defined incorrectly and a program being undefined. If the programmer defines his program incorrectly, then yes, you are correct in that the compiler has no choice but to still take the incorrect definition. The program is still defined in a way the compiler understands, its just not what the programmer was trying to say. But, if a program is undefined, then the compiler does not know what to do, which in how compilers are implemented means the compiler can literally do anything it wants. Typing "while" instead of "if" might be an incorrect definition of the program that the programer was trying to create, but is is still a valid program definition(just not the one the programmer wanted). On the other hand, having contradicting asserts(with your interpretation of assert) is not an incorrectly defined program, but an undefined program because it simply does not make sense.
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 06:08:43 UTC, Tofu Ninja wrote:
 On Saturday, 2 August 2014 at 05:07:58 UTC, Chris Cain wrote:

 Actually, I'm going to clarify this: Your assertion is *not* 
 the promise. Your assertion is simply a statement of fact 
 (note, that does not mean it's a fact, as that appears to be a 
 point of confusion: a statement of fact is simply a statement 
 that *can* be verified).
I am going to have to disagree, I think what you are calling a statement of fact, is actually a claim. A statement is simply a piece of communication. So if you state a belief, you are simply communicating that belief's existence. So a statement of fact is simply the communication that the fact exists.
Well, you can disagree but it doesn't change the fact that what I meant and what you're saying are two different things. With this knowledge you can now infer that you are putting forth effort to intentionally misunderstand me despite me trying to clarify that there is a difference, which isn't productive.
 In reality you can never actually state a fact because you can
 only ever believe a fact is true. It comes down to the
 philosophical problem of "I think therefore I am", which
 basically says that the only thing that your mind can PROVE 100%
 is that you are thinking.

 You can state a belief, but to anyone else hearing that
 statement, it will be a claim. Basicly is comes down to this...

 *A claim is something that can be true or false

 *A belief is a claim that is true in the believer's mind, but if
 stated becomes a claim due to that possibility that the
 believer's is in error

 *A fact is something that is always true

 That is why you can have true statements and false statements, 
 it
 is not that the statement is self is true or false, but that the
 claim that is being stated is true or false.
Frankly, it seems we've regressed back to making up definitions for words and phrases that are well-defined and those well-defined meanings contradict what you're trying to suggest. That's not going to help you understand why I think assert makes sense given the real definition of an assertion.
 It is not a matter of the compiler trying to determine if you
 meant to write what you did or not(there is no way it can). It 
 is
 a matter of the compiler determining if what you wrote is what 
 it
 considers to be correct input. If you try to compile
 "SDA #$!$SDF#$T#", the compiler has no way of knowing if you
 meant to write that or not, but it is still allowed to reject
 that.
Of course, but it must reject that because it couldn't possibly understand that. Furthermore, most of the things in compilers that are disprovable at compile time are disproven at compile time. Those things which cannot be disproven at compile time (see: halting problem) cannot be rejected. Hence, if statements and asserts, and why type-check failures result in a failed compilation.
 Because if the compiler actually checks the claim then it can
 optimize on it, but if the compiler does not check then it can
 not know its true and can not optimize.
But it doesn't need to check because that's not what assert means to do. You're focusing too much on the "checking" part which has nothing to do with the actual English definition of assert (which is my point for why it makes sense for assert to do what it does). A runtime check is a "nice thing to have" (it makes asserts more useful, ultimately), but it seems completely orthogonal to what assert means in this case considering the definition of assert.
 I think a point that needs to be addressed is that there is a
 difference between a program being defined incorrectly and a
 program being undefined.

 If the programmer defines his program incorrectly, then yes, you
 are correct in that the compiler has no choice but to still take
 the incorrect definition.
 The program is still defined in a way the compiler understands,
 its just not what the programmer was trying to say.

 But, if a program is undefined, then the compiler does not know
 what to do, which in how compilers are implemented means the
 compiler can literally do anything it wants.

 Typing "while" instead of "if" might be an incorrect definition
 of the program that the programer was trying to create, but is 
 is
 still a valid program definition(just not the one the programmer
 wanted).

 On the other hand, having contradicting asserts(with your
 interpretation of assert) is not an incorrectly defined program,
 but an undefined program because it simply does not make sense.
OK, but I see these as being much more similar conceptually than you're giving them credit. Despite "undefined behavior" occurring when an assertion fails, it doesn't actually mean that you can't reason about what can occur, just that there's no required definition for what will occur (that's why it's called "undefined"). That is the two interpretations of a D program are accepted by the spec: ``` assert(x != 1); //... code that doesn't have any effect on x if(x == 1) { /* ... */ } ``` ``` assert(x != 1); //... code that doesn't have any effect on x ``` The "undefined behavior" is that it allows these two to be equivalent programs. You can reason about why the program isn't doing what you want, so it's not that it's an "undefined program", just that two (or more) definitions of a program are equivalent as far as the D spec is concerned. You don't know which one you can get, but you do know that they are equivalent (because of your assertion). Actually, what's really weird is the fact that no one would be complaining if asserts were always checked, even though the above is exactly what you could get by the optimizer. The real strange thing is that you'd want the removal of checked asserts to change the way your program can be optimized.
Aug 01 2014
parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 06:35:33 UTC, Chris Cain wrote:

 Well, you can disagree but it doesn't change the fact that what 
 I meant and what you're saying are two different things. With
Yes.... I disagreed with you... so yes I am saying something different. What else is "disagreement" supposed to mean?
 this knowledge you can now infer that you are putting forth 
 effort to intentionally misunderstand me despite me trying to 
 clarify that there is a difference, which isn't productive.
I understood what you said, I just disagreed with it. Are you saying I can't disagree???
 Frankly, it seems we've regressed back to making up definitions 
 for words and phrases that are well-defined and those 
 well-defined meanings contradict what you're trying to suggest. 
 That's not going to help you understand why I think assert 
 makes sense given the real definition of an assertion.
None of these words or phrases are well defined.... if assert was well defined we would not be talking now.... I understand your argument, I just don't think it is correct. Particularly I don't agree that your interpretation of assert more closely matches the real meaning of assert. Let me reiterate why... When something is asserted, there is the asserter(the person making the assertion) and the asserti(s)(the person/people that are hearing the assertion). Given that any thing that is asserted can either be true or false, the asserti has no choice but to conclude that what is being asserted may or may not be true. In the context of the programmer(asserter) and the compiler(asserti). The programer is making an assertion that the compiler must conclude to be either true or false. Because it does not know if it is true or not, the only time it is acceptable for the compiler to optimize as if it is true is to actually check if it is true.
 Of course, but it must reject that because it couldn't possibly 
 understand that. Furthermore, most of the things in compilers 
 that are disprovable at compile time are disproven at compile 
 time. Those things which cannot be disproven at compile time 
 (see: halting problem) cannot be rejected. Hence, if statements 
 and asserts, and why type-check failures result in a failed 
 compilation.
The point is that without the check, the assertion is neither proven or disproven. If the compiler receives bad input(incorrectly defined input is not bad input), then it knows it is bad, but the compiler has no way of knowing if an assertion is good or bad. If the compiler receives two asserts that can not both be true, then there is no way it can know what to do, there is no resolution. But if the compiler is not smart enough to recognize that they are contradictory then is just compiled an uncompilable program....
 But it doesn't need to check because that's not what assert 
 means to do. You're focusing too much on the "checking" part 
 which has nothing to do with the actual English definition of 
 assert (which is my point for why it makes sense for assert to 
 do what it does).
I can understand why you think that, I just don't agree. I don't agree that an assertion in the english language means that something will be true, I interpret it as a claim that something may or may not be true.
 A runtime check is a "nice thing to have" (it makes asserts 
 more useful, ultimately), but it seems completely orthogonal to 
 what assert means in this case considering the definition of 
 assert.
 OK, but I see these as being much more similar conceptually 
 than you're giving them credit. Despite "undefined behavior" 
 occurring when an assertion fails, it doesn't actually mean 
 that you can't reason about what can occur, just that there's 
 no required definition for what will occur (that's why it's 
 called "undefined"). That is the two interpretations of a D 
 program are accepted by the spec:

 ```
 assert(x != 1);
 //... code that doesn't have any effect on x
 if(x == 1) { /* ... */ }
 ```

 ```
 assert(x != 1);
 //... code that doesn't have any effect on x
 ```
That is not an undefined program.... the code you just presented was completely defined. An an example of an undefined program with respect to assert is as follows. assert(x==1); assert(y==2); Lets say the compiler was not smart enough to see that these could not both be true. There is no way the compiler can produce and thing that is correct because they both cannot be true. There will always be sets of conditions that the compiler can not prove to be contradictory(because of the halting problem) but that are. That is an undefined program...
 The "undefined behavior" is that it allows these two to be 
 equivalent programs.
That is not the undefined behavior
 You can reason about why the program isn't doing what you want, 
 so it's not that it's an "undefined program", just that two (or 
 more) definitions of a program are equivalent as far as the D 
 spec is concerned.

 You don't know which one you can get, but you do know that they 
 are equivalent (because of your assertion).

 Actually, what's really weird is the fact that no one would be 
 complaining if asserts were always checked, even though the 
 above is exactly what you could get by the optimizer. The real 
 strange thing is that you'd want the removal of checked asserts 
 to change the way your program can be optimized.
That is actually the point, no one would be complaining because there would be nothing wrong. There would be no chance of undefined behavior. If the check is always there then the program will always know that after the assert the condition is true and would be free to do any optimizations it wants. The undefined behavior occurs when you optimized as if they are true but do not check.
Aug 02 2014
next sibling parent "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 07:36:34 UTC, Tofu Ninja wrote:
 On Saturday, 2 August 2014 at 06:35:33 UTC, Chris Cain wrote:

 Well, you can disagree but it doesn't change the fact that 
 what I meant and what you're saying are two different things. 
 With
Yes.... I disagreed with you... so yes I am saying something different. What else is "disagreement" supposed to mean?
 this knowledge you can now infer that you are putting forth 
 effort to intentionally misunderstand me despite me trying to 
 clarify that there is a difference, which isn't productive.
I understood what you said, I just disagreed with it. Are you saying I can't disagree???
It depends on what you mean. You can disagree, but you can't disagree with the fact that what I said and what you seem to suggest I am saying are two different things. So, in particular,
 So a statement of fact is
 simply the communication that the fact exists.
Is something that seems to be suggesting a meaning in my words that doesn't exist. Really specifically, I have a problem with "a statement of fact is simply the communication that the fact exists." -> It's a form of communication, but since a fact is defined as "something that is actually the case/exists" and a statement of fact actually isn't communicating that, then it makes a very real difference in the potential interpretation of the words. In particular, your definition of what I'm saying seems to imply that a "statement of fact" suggests that a proof of that fact must exist before an assertion is really an assertion, whereas a real statement of fact doesn't necessarily have a proof of true or false just that it *could be verified.* Thus an assertion without a proof is still an assertion and communicating an idea that doesn't necessarily have to be proven to finalize the communication. It's just that, in particular, the idea communicated is a statement of fact iff it were verifiable. Effectively that definition is just removing extraneous things like beliefs, "god exists", "there exists parallel universes that cease to exist the instant you attempt to observe them", etc. Things that you couldn't verify or falsify. Basically, because we've had enough problems with what is being actually being said, trying to take some liberties with what is being said and trying to subtly change it is completely out of the question. Until we start coming to an exact understanding of what each other means, it's probably best if we don't disagree with what the other person has defined as what they mean and instead try to figure out what is being said. If you want to introduce your own definitions and such, make it clear (that is, don't start your paragraph with "I think what you are calling a..." because it's prompting me to carefully consider what you're saying as potentially redefining what I'm saying). It just seemed to me that you were taking my words and trying to suggest that I don't understand my own words or something. If that wasn't what you were trying to do, I'm sorry.
 Frankly, it seems we've regressed back to making up 
 definitions for words and phrases that are well-defined and 
 those well-defined meanings contradict what you're trying to 
 suggest. That's not going to help you understand why I think 
 assert makes sense given the real definition of an assertion.
None of these words or phrases are well defined.... if assert was well defined we would not be talking now....
That's not necessarily true. Disagreements exist on well-defined definitions all the time.
 I understand your argument, I just don't think it is correct.
 Particularly I don't agree that your interpretation of assert
 more closely matches the real meaning of assert. Let me 
 reiterate
 why...

 When something is asserted, there is the asserter(the person
 making the assertion) and the asserti(s)(the person/people that
 are hearing the assertion). Given that any thing that is 
 asserted
 can either be true or false, the asserti has no choice but to
 conclude that what is being asserted may or may not be true.

 In the context of the programmer(asserter) and the
 compiler(asserti). The programer is making an assertion that the
 compiler must conclude to be either true or false. Because it
 does not know if it is true or not, the only time it is
 acceptable for the compiler to optimize as if it is true is to
 actually check if it is true.
True, iff the asserter and assertee are human and doubt the assertion. Assertions are typically taken until someone calls into question the assertion. The compiler doesn't call into question anything you do unless it has a proof that what you're doing is wrong. In particular, I take much of what you say to be truth, even if I haven't explicitly asked you to verify it before we accept it as truth. Furthermore, much of what you say isn't backed up with proof at all (and yet I still accept it without proof). In fact, the vast majority of conversations will do so (otherwise absolutely nothing productive could be accomplished). That said, if I have a reason to believe you are making an incorrect assertion, I will either ask you to verify it or prove you wrong about it. This makes conversations much faster since we often assume things to be true if asserted true by the other party, often skipping checks and verifications that would otherwise potentially be necessary. Obviously it's starting to sound a lot more like what a compiler does when optimizing a program. When you assert something to the compiler, it accepts it as true unless it has a really good reason to believe it is logically inconsistent (that also suggests that the compiler even tried to make sure it's logically consistent, which I think would be a nice feature to have).
 The point is that without the check, the assertion is neither
 proven or disproven. If the compiler receives bad
 input(incorrectly defined input is not bad input), then it knows
 it is bad, but the compiler has no way of knowing if an 
 assertion
 is good or bad.
I get your point, but I see asserts in the same class as most (all?) other mechanisms. If it does not have a proof against what you say, then it will not step in. You don't have to write proven programs in general. Since it doesn't have to prove your assertion (and it can't in general, so that's a good thing), then it must accept your assertion as good just like it accepts all of your other code as logically good unless it has a reason to believe that it's not.
 If the compiler receives two asserts that can not both be true,
 then there is no way it can know what to do, there is no
 resolution. But if the compiler is not smart enough to recognize
 that they are contradictory then is just compiled an 
 uncompilable
 program....
I've already covered that I think things that are provably false might be helpful if the compiler actually pointed out the error. That said, it's not a trivial problem to solve, so it's not surprising that it doesn't solve it.
 I can understand why you think that, I just don't agree. I don't
 agree that an assertion in the english language means that
 something will be true, I interpret it as a claim that something
 may or may not be true.
Of course. But what point is there in telling a compiler that? Obviously there's no point unless you're communicating some idea to the compiler and communicating to the compiler that "here's something that may or may not be true, so don't do anything about it" is completely odd, strange, and special (in the sense that there doesn't exist any other construct that I can think of that does that... even ASM noops, which literally mean "do nothing", have a purposeful effect on a program). I expect a compiler to help me out, but ultimately I expect it to trust my logic even if it can't verify it. Specifically, I don't mind it stepping in with counter proofs to my suggestion that I have a good program. But if it doesn't know whether my program is good or not, I expect it to assume it is good. I've already shown that your expectations for `if` statements and function calls are almost certainly the same as my expectations for all language features.
 That is not an undefined program.... the code you just presented
 was completely defined. An an example of an undefined program
 with respect to assert is as follows.

 assert(x==1);
 assert(y==2);


 Lets say the compiler was not smart enough to see that these
 could not both be true. There is no way the compiler can produce
 and thing that is correct because they both cannot be true. 
 There
 will always be sets of conditions that the compiler can not 
 prove
 to be contradictory(because of the halting problem) but that 
 are.
 That is an undefined program...

 The "undefined behavior" is that it allows these two to be 
 equivalent programs.
That is not the undefined behavior
Fine, I see what you mean. But I don't find it persuasive because I just see it as a bad program no different than one constructed from any other logic error. It'd be nice to have better constructs to help prove correctness, but we can't do it in general. But in the context of what we actually can do, asserts make sense to behave as described in this thread.
 That is actually the point, no one would be complaining because
 there would be nothing wrong. There would be no chance of
 undefined behavior. If the check is always there then the 
 program
 will always know that after the assert the condition is true and
 would be free to do any optimizations it wants. The undefined
 behavior occurs when you optimized as if they are true but do 
 not
 check.
Actually, there would be something wrong. Two *very* different programs would be compiled between an optimized build with checked assertions and a program without checked assertions. The difference of the programs with asserts as described in this thread would be precisely the asserts themselves, which is absolutely what you'd expect. No one would expect that removing asserts could completely change *everything* about the code, which is what is concluded by the behavior you describe. Of course, you could suggest that "asserts shouldn't affect optimization" -> but the problem there is that it matches no definition of the English language version of assert because it means "check to see if this is true" which is very, VERY far away from the definition of "statement of fact forcefully". Hence why I'm very eager to cast off that definition because it has a meaning that is no where near the English definition.
Aug 02 2014
prev sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 07:36:34 UTC, Tofu Ninja wrote:
 ...
Look, this is the point I'm trying to make. Given the English definition of assert (Just accept the definition, I'm tired: "statement of fact or belief confidently and forcefully"), I claim that it makes sense that a compiler will use your statement of fact to do something meaningful. The assert defined in this topic by Walter certainly aligns with what *I* would expect the compiler to do, given a statement of fact. Yes, whatever you said may be true or may not be true. Just like anything else, though, if you're wrong, your program will be buggy. Such is life of a programmer. I find the concept of not doing anything meaningful with an assert to be strange. I find the idea of confusing "checking" with "asserting" to also be pretty weird (only after this topic, to be fair). Given the English definition of assert, it seems strange that I ever believed it should work the way I conceptualized it before. But oh well. That's all I really wanted to say, I'm really tired of words and throwing things around and confusing something so simple and trivial. Simple things should stay simple. Complexity hides incorrect logic. To simplify: When I tell the compiler to do something, it does it. Thus, if I give a compiler a statement of fact, it should use that information. There should be no special case between those two. Yeah whatever, compile errors, come on man, stop missing the simple and obvious point. Stop missing the forest for the grain of dirt.
Aug 02 2014
parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 11:36, Chris Cain via Digitalmars-d wrote:
 On Saturday, 2 August 2014 at 07:36:34 UTC, Tofu Ninja wrote:
 ...
Look, this is the point I'm trying to make. Given the English definition of assert
We're not writing code in `English`, but in `D`. That is a fact. :) The english definition of 'assert' is *completely irrelevant*. Really. artur
Aug 02 2014
parent "Andrew Godfrey" <X y.com> writes:
On Saturday, 2 August 2014 at 10:21:44 UTC, Artur Skawina via 
Digitalmars-d wrote:
 On 08/02/14 11:36, Chris Cain via Digitalmars-d wrote:
 On Saturday, 2 August 2014 at 07:36:34 UTC, Tofu Ninja wrote:
 ...
Look, this is the point I'm trying to make. Given the English definition of assert
We're not writing code in `English`, but in `D`. That is a fact. :) The english definition of 'assert' is *completely irrelevant*. Really. artur
To expand on this: An army of programmers doing real work has in the past encountered this question of what 'assert' should mean in a programming language. For my my codebase decades ago parted ways with C 'assert'; it has its own which has many more features. And so the 'assume' that C's assert may or may not have had in release builds is merely a curiosity,from the POV of this codebase. The English meaning even more so. Experience with huge codebases trumps the opinion of standards or dictionaries. But of course I still would like the language to steer newcomers away from such expensive missteps.
Aug 02 2014
prev sibling next sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 2 August 2014 at 05:07:58 UTC, Chris Cain wrote:
 On Saturday, 2 August 2014 at 04:40:53 UTC, Tofu Ninja wrote:
 His claim is that an assertion is a claim by the person
 asserting. That claim has not been proven to be true or false.
 Meaning that as a claim, the compiler can't do anything with 
 that
 information alone. The compiler can try to check if the claim 
 is
 true and if it is, use that information to optimize. But if it 
 is
 not checked it is merely a claim with no backing, and as such,
 nothing can be done with it.
Of course, I can understand that interpretation. But at the same time, why would you write something and expect a compiler to do nothing with it?
But he _does_ want the compiler to do something: check whether it's true (or more precisely: check whether it's not false in this particular case). He wants it to be exactly equivalent to: version(assert) if(!(condition)) throw new AssertError(...); Now, you could ask: Why use `assert` instead of writing it like this? Well, for one, it's more concise, and secondly, it shows that your intention is to check the semantic validity of your program, and not just do an arbitrary check that is part of your algorithm.
Aug 02 2014
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 2 August 2014 at 05:07:58 UTC, Chris Cain wrote:
 Thus when you assert something is true and the compiler can't 
 immediately disprove you, it must follow what you say.
The compiler can be much better about proving things about a program than programmers probably are, especially if subtle details of the language specification need to be taken into account, because this is mostly a mechanical thing, which computers are really good at, and humans are not. If the compiler cannot prove something, it will usually err on the safe side (let's assume an error free compiler). I think whole program optimization is a much better strategy. With that, the compiler can actually prove what you just have to assume if you use manual assertions. Of course, it doesn't work across library boundaries, but I would see those as external interfaces, so it's probably acceptable.
Aug 02 2014
prev sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
Here, I'll do you the favor of giving you a few more Google 
results with hopes that you'll start developing a mental model 
behind what the definition of assertion is:

Google itself: "state a fact or belief confidently and forcefully"

http://dictionary.reference.com/browse/assert: "to state with 
assurance, confidence, or force; state strongly or positively; 
affirm"

http://www.merriam-webster.com/dictionary/assert: "to state 
(something) in a strong and definite way"

http://www.thefreedictionary.com/assert: "To state or express 
positively; affirm"

http://www.oxforddictionaries.com/us/definition/american_english/assert: 
"State a fact or belief confidently and forcefully"

http://www.macmillandictionary.com/us/dictionary/american/assert: 
"to state firmly that something is true"


As a bonus, Googling "statement of fact" in case that isn't clear 
to you what that means (maybe that's what's throwing you for a 
loop? You seem to be equating statement of fact and facts so 
you've clearly got some understanding wrong for the definition of 
those two):
http://en.wikipedia.org/wiki/False_statements_of_fact

False statement of fact... You can't possibly suggest that there 
exists false facts, but false statements of facts do exist, 
proving that statement of fact != fact.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 04:41 AM, Chris Cain wrote:
 Here, I'll do you the favor of giving you a few more Google results with hopes
that you'll
 start developing a mental model behind what the definition of assertion is:
 ...
Great, that's a lot more useful than the personal attacks. Thanks!
 Google itself: "state a fact or belief confidently and forcefully"

 http://dictionary.reference.com/browse/assert: "to state with assurance,
confidence, or force;
 state strongly or positively; affirm"

 http://www.merriam-webster.com/dictionary/assert: "to state (something) in a
strong and definite way"

 http://www.thefreedictionary.com/assert: "To state or express positively;
affirm"

 http://www.oxforddictionaries.com/us/definition/american_english/assert:
"State a fact or belief confidently and forcefully"
 ...
All of those do not imply that a fact is being expressed. Why can an assertion not be the forceful expression of e.g. a lie or a wrong belief, given those entries? Some more: http://dictionary.reference.com/browse/assertion: "a positive statement or declaration, often without support or reason: a mere assertion; an unwarranted assertion." http://www.thefreedictionary.com/assertion: "1. The act of asserting. 2. Something declared or stated positively, often with no support or attempt at proof."
 http://www.macmillandictionary.com/us/dictionary/american/assert: "to state
firmly that something is true"
 As a bonus, Googling "statement of fact" in case that isn't clear to you
 what that means (maybe that's what's throwing you for a loop?
http://en.wikipedia.org/wiki/Fact
 You seem to be equating statement of fact and facts
Well no, I explicitly affirmed that there were different concepts: On 08/02/2014 03:55 AM, Timon Gehr wrote:
 There is a difference between a fact and a statement of that fact, but ..
 so you've clearly got some
 understanding wrong for the definition of those two):
I also clarified how I understand the term, in order to give you the possibility of clearing up the misunderstanding in case this was to be the point of contention: On 08/02/2014 03:55 AM, Timon Gehr wrote:
 A statement of FACT is a statement that expresses a fact. I.e. there is
 an existing fact, and the statement expresses this fact
This is part of any well-reasoned argument. I was applying utmost care to expose it as much in its entirety as I could in order to quickly find where the disagreement was coming from.
 http://en.wikipedia.org/wiki/False_statements_of_fact
 ...
I already googled 'statement of fact' myself earlier, and found the wikipedia entry for 'fact', that I quoted back then: http://en.wikipedia.org/wiki/Fact "The usual test for a statement of fact is verifiability, that is, whether it can be demonstrated to correspond to experience." I.e. in order to determine whether something is a statement of fact, one should verify it. Do you agree that it is saying this?
 False statement of fact... You can't possibly suggest that there exists
 false facts, but false statements of facts do exist, proving that
 statement of fact != fact.
It is hard to tell from that article whether you have a point. It often uses the term 'false statement'. I.e. the term might parse like (false statement) of fact, and not false (statement of fact). Furthermore, this seems to be a legalese use. Legalese words often have distorted meanings. Do you think the legalese use of this term is relevant in the context of the current discussion? In any case, wouldn't the existence of false (statements of fact) contradict the wikipedia article on 'fact'? Furthermore, if we actually assume for a short time that we may equate statement of fact and 'assertion' as you did in a previous post: aren't you now actually arguing for the position that assertions do not necessarily express facts? There is also the following source: https://answers.yahoo.com/question/index?qid=20100816160837AAzpEBY "Most statements fall into one of two categories: statements of fact and statements of opinion. Statements of fact are falsifiable. They can be either proven or disproven. Statements of opinion cannot be falsified." This contradicts my interpretation, but I don't know what the legalese use is exactly. there is another answer that says: "Without looking it up, I'd say a "statement of fact" is simply speaking something that is true, compared to having an opinion about something. Satement [sic!] of fact: The world is not flat. Statement of opinion: The world is so messed up these days. " This definition is similar to what I used, but it is explicitly qualified as non-authoritative. Do you see why I think that the definition of 'assertion' in English is not sufficient to describe it's semantics as a programming language construct sufficiently well? Note, there is only one source that even mentions 'statement of fact' as part of the definition of 'assert', and it still leaves open alternatives so this entire sub-discussion is not very relevant to the original one. If you decide to answer, feel free to point out exactly _where_ my reasoning is wrong or _where_ it is not clear enough, attack my reasoning if you must, but please do not attack me again.
Aug 01 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 05:40 AM, Timon Gehr wrote:
 Do you see why I think that the definition of 'assertion' in English is
 not sufficient to describe it's
Argh, it's getting late.
Aug 01 2014
prev sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 03:40:47 UTC, Timon Gehr wrote:
 I already googled 'statement of fact' myself earlier, and found 
 the wikipedia entry for 'fact', that I quoted back then:
 http://en.wikipedia.org/wiki/Fact

 "The usual test for a statement of fact is verifiability, that 
 is, whether it can be demonstrated to correspond to experience."

 I.e. in order to determine whether something is a statement of 
 fact, one should verify it. Do you agree that it is saying this?
I'll just do this real quick, because it's a really easy one to show the problem with. Google "verifiable" -> http://www.merriam-webster.com/dictionary/verifiable -> "capable of being verified" That is, it's something that has some ability to be verified. Thus, 1==2 is "verifiable" (it can be shown to be either true or false). "God exists" is an example of something that cannot be a statement of fact because we cannot verify it one way or another. So no, a statement of fact can be verifiable and still false by your quote.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:11 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:40:47 UTC, Timon Gehr wrote:
 I already googled 'statement of fact' myself earlier, and found the
 wikipedia entry for 'fact', that I quoted back then:
 http://en.wikipedia.org/wiki/Fact

 "The usual test for a statement of fact is verifiability, that is,
 whether it can be demonstrated to correspond to experience."

 I.e. in order to determine whether something is a statement of fact,
 one should verify it. Do you agree that it is saying this?
I'll just do this real quick, because it's a really easy one to show the problem with. Google "verifiable" -> http://www.merriam-webster.com/dictionary/verifiable -> "capable of being verified" ...
Great, now we are getting somewhere. http://dictionary.reference.com/browse/verify?s=t "to prove the truth of, as by evidence or testimony; confirm; substantiate: Events verified his prediction." I understand "capable of being verified" as "there is a way to verify this" which is the same as "this can be proven" which would imply "this is true". What's wrong here?
 That is, it's something that has some ability to be verified. Thus, 1==2
 is "verifiable" (it can be shown to be either true or false).
 ...
If I can verify 1==2, I would prove 1==2, as per the definition above, no?
 "God exists" is an example of something that cannot be a statement of
 fact because we cannot verify it one way or another.
 ...
 So no, a statement of fact can be verifiable and still false by your quote.
It is possible that this is indeed what it tries to communicate. Thanks for bearing with me in any case! But as I wrote in my previous post, now this brings up the issue that if an assertion is a statement of fact, then it is not necessarily true. Why is it now obvious that it should be considered true?
Aug 01 2014
next sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 04:28:33 UTC, Timon Gehr wrote:
 On 08/02/2014 06:11 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:40:47 UTC, Timon Gehr wrote:
 I already googled 'statement of fact' myself earlier, and 
 found the
 wikipedia entry for 'fact', that I quoted back then:
 http://en.wikipedia.org/wiki/Fact

 "The usual test for a statement of fact is verifiability, 
 that is,
 whether it can be demonstrated to correspond to experience."

 I.e. in order to determine whether something is a statement 
 of fact,
 one should verify it. Do you agree that it is saying this?
I'll just do this real quick, because it's a really easy one to show the problem with. Google "verifiable" -> http://www.merriam-webster.com/dictionary/verifiable -> "capable of being verified" ...
Great, now we are getting somewhere. http://dictionary.reference.com/browse/verify?s=t "to prove the truth of, as by evidence or testimony; confirm; substantiate: Events verified his prediction." I understand "capable of being verified" as "there is a way to verify this" which is the same as "this can be proven" which would imply "this is true". What's wrong here?
The fact that you assume that something "can be proven" means it "has been proven" or "must be proven". Because you don't necessarily have to prove it, it doesn't necessarily mean it is true. It's a statement that you are suggesting is true but *could* be falsified/shown to be false/verified/verified to be false. The mere fact that asserts take in expressions show that something "can be proven", but there is no implication that it, therefore, must be proven. If you put an expression in an assert and it successfully compiles, you've made a statement of fact. It's useful that it is checked/proven in debug builds but not surprising that it's required to by definition.
 That is, it's something that has some ability to be verified. 
 Thus, 1==2
 is "verifiable" (it can be shown to be either true or false).
 ...
If I can verify 1==2, I would prove 1==2, as per the definition above, no?
No. You can verify it but find it to be false. Your proof would show it to be false. The fact that you can write a proof showing it to be false is a proof that it was verifiable in the first place.
 It is possible that this is indeed what it tries to 
 communicate. Thanks for bearing with me in any case!
No problem. :)
 But as I wrote in my previous post, now this brings up the 
 issue that if an assertion is a statement of fact, then it is 
 not necessarily true.

 Why is it now obvious that it should be considered true?
For the same reason that all of the other things you type into a program is accepted by a program. `if(...)` ... would it be strange if your program doubted that you really want to execute the block the if statement refers to? Of course it would. Basically, you're a god and what you say to do is law in computer programming. By default you expect the computer to not doubt you and to follow what you say. It's not like a person who will question your assertions and ask you to prove them or double check them for you. Though, the fact that it will double check them for you is helpful in debug builds, so it's an obvious enhancement for debugging purposes. Since assert is you making a statement of fact, it's logical that it should, by default, accept what you say just like it accepts every other command you give it. If you're wrong... well, it's just like if you're wrong about your if statements or if you call the wrong function or pass in the wrong variables. You'll get incorrect program behavior. Unlike those other things, since it's verifiable, there exists some sort of configurations where the program can be helpful to you by verifying your assertions.
Aug 01 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/1/14, 9:46 PM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 04:28:33 UTC, Timon Gehr wrote:
 On 08/02/2014 06:11 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:40:47 UTC, Timon Gehr wrote:
 I already googled 'statement of fact' myself earlier, and found the
 wikipedia entry for 'fact', that I quoted back then:
 http://en.wikipedia.org/wiki/Fact

 "The usual test for a statement of fact is verifiability, that is,
 whether it can be demonstrated to correspond to experience."

 I.e. in order to determine whether something is a statement of fact,
 one should verify it. Do you agree that it is saying this?
I'll just do this real quick, because it's a really easy one to show the problem with. Google "verifiable" -> http://www.merriam-webster.com/dictionary/verifiable -> "capable of being verified" ...
Great, now we are getting somewhere. http://dictionary.reference.com/browse/verify?s=t "to prove the truth of, as by evidence or testimony; confirm; substantiate: Events verified his prediction." I understand "capable of being verified" as "there is a way to verify this" which is the same as "this can be proven" which would imply "this is true". What's wrong here?
The fact that you assume that something "can be proven" means it "has been proven" or "must be proven". Because you don't necessarily have to prove it, it doesn't necessarily mean it is true. It's a statement that you are suggesting is true but *could* be falsified/shown to be false/verified/verified to be false. The mere fact that asserts take in expressions show that something "can be proven", but there is no implication that it, therefore, must be proven. If you put an expression in an assert and it successfully compiles, you've made a statement of fact. It's useful that it is checked/proven in debug builds but not surprising that it's required to by definition.
 That is, it's something that has some ability to be verified. Thus, 1==2
 is "verifiable" (it can be shown to be either true or false).
 ...
If I can verify 1==2, I would prove 1==2, as per the definition above, no?
No. You can verify it but find it to be false. Your proof would show it to be false. The fact that you can write a proof showing it to be false is a proof that it was verifiable in the first place.
 It is possible that this is indeed what it tries to communicate.
 Thanks for bearing with me in any case!
No problem. :)
 But as I wrote in my previous post, now this brings up the issue that
 if an assertion is a statement of fact, then it is not necessarily true.

 Why is it now obvious that it should be considered true?
For the same reason that all of the other things you type into a program is accepted by a program. `if(...)` ... would it be strange if your program doubted that you really want to execute the block the if statement refers to? Of course it would. Basically, you're a god and what you say to do is law in computer programming. By default you expect the computer to not doubt you and to follow what you say. It's not like a person who will question your assertions and ask you to prove them or double check them for you. Though, the fact that it will double check them for you is helpful in debug builds, so it's an obvious enhancement for debugging purposes. Since assert is you making a statement of fact, it's logical that it should, by default, accept what you say just like it accepts every other command you give it. If you're wrong... well, it's just like if you're wrong about your if statements or if you call the wrong function or pass in the wrong variables. You'll get incorrect program behavior. Unlike those other things, since it's verifiable, there exists some sort of configurations where the program can be helpful to you by verifying your assertions.
I don't think there's ever been a more majestic thread in the history of this forum. Probably up there with the best of them anywhere and anytime. It's become officially an Epic Debate. Andrei
Aug 01 2014
next sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 04:54:09 UTC, Andrei Alexandrescu
wrote:
 I don't think there's ever been a more majestic thread in the 
 history of this forum. Probably up there with the best of them 
 anywhere and anytime. It's become officially an Epic Debate.

 Andrei
I am glad our squabbling amuses you :)
Aug 01 2014
prev sibling next sibling parent "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 04:54:09 UTC, Andrei Alexandrescu 
wrote:
 I don't think there's ever been a more majestic thread in the 
 history of this forum. Probably up there with the best of them 
 anywhere and anytime. It's become officially an Epic Debate.

 Andrei
Oh by the way, how about the color of that bike shed! It really needs to be blue. :-p Sorry :)
Aug 01 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:54 AM, Andrei Alexandrescu wrote:
 I don't think there's ever been a more majestic thread in the history of
 this forum. Probably up there with the best of them anywhere and
 anytime. It's become officially an Epic Debate.

 Andrei
Wait, does this thread outclass the property debates? We should discuss property again soon!
Aug 01 2014
prev sibling next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 04:46:43 UTC, Chris Cain wrote:

 No. You can verify it but find it to be false. Your proof would 
 show it to be false. The fact that you can write a proof 
 showing it to be false is a proof that it was verifiable in the 
 first place.
I think if one says they are going to prove something, they implicitly mean they are going to prove it to be true. And if one says they are going to disprove something, they implicitly mean they are going to prove it to be false. I think that might be causing a bit of misinterpretation.
Aug 01 2014
parent "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 05:12:12 UTC, Tofu Ninja wrote:
 On Saturday, 2 August 2014 at 04:46:43 UTC, Chris Cain wrote:

 No. You can verify it but find it to be false. Your proof 
 would show it to be false. The fact that you can write a proof 
 showing it to be false is a proof that it was verifiable in 
 the first place.
I think if one says they are going to prove something, they implicitly mean they are going to prove it to be true. And if one says they are going to disprove something, they implicitly mean they are going to prove it to be false. I think that might be causing a bit of misinterpretation.
True. If someone says they are *going* to prove something ... If someone says I *can* prove it... well... http://en.wikipedia.org/wiki/Handwaving
Aug 01 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:46 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 04:28:33 UTC, Timon Gehr wrote:
 On 08/02/2014 06:11 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 03:40:47 UTC, Timon Gehr wrote:
 I already googled 'statement of fact' myself earlier, and found the
 wikipedia entry for 'fact', that I quoted back then:
 http://en.wikipedia.org/wiki/Fact

 "The usual test for a statement of fact is verifiability, that is,
 whether it can be demonstrated to correspond to experience."

 I.e. in order to determine whether something is a statement of fact,
 one should verify it. Do you agree that it is saying this?
I'll just do this real quick, because it's a really easy one to show the problem with. Google "verifiable" -> http://www.merriam-webster.com/dictionary/verifiable -> "capable of being verified" ...
Great, now we are getting somewhere. http://dictionary.reference.com/browse/verify?s=t "to prove the truth of, as by evidence or testimony; confirm; substantiate: Events verified his prediction." I understand "capable of being verified" as "there is a way to verify this" which is the same as "this can be proven" which would imply "this is true". What's wrong here?
The fact that you assume that something "can be proven" means it "has been proven" or "must be proven". Because you don't necessarily have to prove it, it doesn't necessarily mean it is true. It's a statement that you are suggesting is true but *could* be falsified/shown to be false/verified/verified to be false. The mere fact that asserts take in expressions show that something "can be proven", but there is no implication that it, therefore, must be proven. If you put an expression in an assert and it successfully compiles, you've made a statement of fact. It's useful that it is checked/proven in debug builds but not surprising that it's required to by definition. ...
Well, if there is no proof of something, how can I claim it can be proven? In fact, in my past life, when somebody told me something like '...and actually one _can prove_ that any non-planar graph contains either a K_5 or a K_{3,3} as a minor', then this invariably meant that there exists a proof, but that they will not tell me the proof now. Words are strange; apparently it is very common that they don't mean similar things to different people. Isn't it possible, that 'verifiable' just has an idiomatic usage that does not represent the obvious meaning derived from 'verify'? Or is 'verify' bivalent like that as well?
 That is, it's something that has some ability to be verified. Thus, 1==2
 is "verifiable" (it can be shown to be either true or false).
 ...
If I can verify 1==2, I would prove 1==2, as per the definition above, no?
No.
The definition above was: "to prove the truth of, as by evidence or testimony; confirm; substantiate: Events verified his prediction."
 You can verify it but find it to be false. Your proof would show it
 to be false. The fact that you can write a proof showing it to be false
 is a proof that it was verifiable in the first place.

 It is possible that this is indeed what it tries to communicate.
 Thanks for bearing with me in any case!
No problem. :)
 But as I wrote in my previous post, now this brings up the issue that
 if an assertion is a statement of fact, then it is not necessarily true.

 Why is it now obvious that it should be considered true?
For the same reason that all of the other things you type into a program is accepted by a program. ...
I see.
 `if(...)` ... would it be strange if your program doubted that you
 really want to execute the block the if statement refers to? Of course
 it would.

 Basically, you're a god and what you say to do is law in computer
 programming.
(Except if you do something that's 'invalid', at which point all your carefully crafted laws get ignored immediately.)
 By default you expect the computer to not doubt you and to
 follow what you say. It's not like a person who will question your
 assertions and ask you to prove them or double check them for you.
 ...
For me, having them double checked is the main motivation for writing down assertions. I like failing assertions when they occur. They often almost immediately tell me what I screwed up, or which prior assumptions no longer hold and which code therefore I might need to modify in order to complete the implementation of a new feature. I personally don't want the compiler to trust me regarding those issues, and that's the whole point. This is how assert works in other languages and also how it works in current D compilers. However, whenever I write an assertion down, it is still a statement of fact/opinion/whatever, and more importantly, I feel strongly about that it should be true. I don't think that if I had looked up 'assert' in a dictionary, I would have recognised an opposition between the definition in the dictionary and the 'old' semantics as described above.
 Though, the fact that it will double check them for you is helpful in
 debug builds, so it's an obvious enhancement for debugging purposes.

 Since assert is you making a statement of fact,
Note that it might just as well be a command that makes the program make a statement of fact.
 it's logical that it
 should, by default, accept what you say just like it accepts every other
 command you give it.
 ...
Yes, but what I say is: "I assert this." And _I_ do. If I do just this, this does not determine what _the compiler_ is to make of it. We need a separate operational semantics which IMO is not obvious a priori given just the definition in English and knowledge about programming without anything concerning 'assert'.
 If you're wrong... well, it's just like if you're wrong about your if
 statements or if you call the wrong function or pass in the wrong
 variables.
There is a distinct flavour to it. If I am wrong about an 'if' statement, I will still be able tell how the program will behave by inspecting the source code (if there is no other source of UB), whereas the new assert semantics deny me this possibility. I.e. my opinion is that "it's just like" is an exaggeration, also because it is not me testing the 'if' condition, but there it is obviously the program who is commanded to do it.
 You'll get incorrect program behavior. Unlike those other
 things, since it's verifiable, there exists some sort of configurations
 where the program can be helpful to you by verifying your assertions.
Type checking will be performed even in -release builds. I guess it is hard to reach consensus from here?
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 05:32:43 UTC, Timon Gehr wrote:
 Well, if there is no proof of something, how can I claim it can 
 be proven? In fact, in my past life, when somebody told me 
 something like '...and actually one _can prove_ that any 
 non-planar graph contains either a K_5 or a K_{3,3} as a 
 minor', then this invariably meant that there exists a proof, 
 but that they will not tell me the proof now.

 Words are strange; apparently it is very common that they don't 
 mean similar things to different people. Isn't it possible, 
 that 'verifiable' just has an idiomatic usage that does not 
 represent the obvious meaning derived from 'verify'? Or is 
 'verify' bivalent like that as well?
It seems to be exactly as Tofu suggested. I don't really know exactly how to explain to you that the concept of verifiability/falsifiability does not mean that something will verify as true or be falsified just to assert that they have an ability of being shown to be false or shown to be true (that is, there needn't be a proof in hand or even discovered, just that some proof could be written about it's truth or falseness, even if it has never been discovered). In the world of science in general, "falsifiability" is clearly used for any research. It means "able to be proven false", of course, but if that implied it wasn't true, then it would mean that all science is false which is truly a bizarre conclusion. http://en.wikipedia.org/wiki/Falsifiability ^^ See? It's an important part of science that there is the possibility of proving it false. That *doesn't* imply it *is* false, though. Likewise for verifiability (they're really just synonyms, which should really show you that there actually existing both a proof for truth and falseness doesn't make sense) http://www.synonym.com/synonyms/falsifiable/ -> verifiable is a synonym.
 For me, having them double checked is the main motivation for 
 writing down assertions. I like failing assertions when they 
 occur. They often almost immediately tell me what I screwed up, 
 or which prior assumptions no longer hold and which code 
 therefore I might need to modify in order to complete the 
 implementation of a new feature. I personally don't want the 
 compiler to trust me regarding those issues, and that's the 
 whole point. This is how assert works in other languages and 
 also how it works in current D compilers. However, whenever I 
 write an assertion down, it is still a statement of 
 fact/opinion/whatever, and more importantly, I feel strongly 
 about that it should be true.

 I don't think that if I had looked up 'assert' in a dictionary, 
 I would have recognised an opposition between the definition in 
 the dictionary and the 'old' semantics as described above.
I could see that. That said, I was on the opposite side of the fence. I knew the dictionary understanding but simply separated the concepts in my head before. I thought of the assert in programming languages as you currently do. However, this thread has shown me that they were always intended to be the same, and it's significantly clarified (for me) where I would use assertions and where I'd use enforcements, for instance (the boundry has always been pretty fuzzy to me... "use asserts for the purpose of program bugs" has always been somewhat unclear). I guess not everyone knew and understood the dictionary definition, so it seems that my point wasn't originally helpful.
 Note that it might just as well be a command that makes the 
 program make a statement of fact.
That's pretty much exactly what I think it's intended to be. Except I'd tweak it to say that it's a command that you use to make a statement of fact (the program isn't doing anything).
 There is a distinct flavour to it. If I am wrong about an 'if' 
 statement, I will still be able tell how the program will 
 behave by inspecting the source code (if there is no other 
 source of UB), whereas the new assert semantics deny me this 
 possibility. I.e. my opinion is that "it's just like" is an 
 exaggeration, also because it is not me testing the 'if' 
 condition, but there it is obviously the program who is 
 commanded to do it.
Sure. A bit of a different flavor, but essentially the same. Incorrect statements make incorrect program behavior (in the case of assert, I think understanding the real meaning behind it will make it far easier to reason about ... "UB" isn't quite accurate as the meaning behind what you say has a clear implication of what type of behavior will follow, it's just that currently the optimizer doesn't do all it could do)
 You'll get incorrect program behavior. Unlike those other
 things, since it's verifiable, there exists some sort of 
 configurations
 where the program can be helpful to you by verifying your 
 assertions.
Type checking will be performed even in -release builds. I guess it is hard to reach consensus from here?
Well, there's a not-so-subtle difference between type checking and assertions. Whereas assertions could only be checked at runtime, failing to use typechecking in a statically compiled program means that you simply couldn't compile the program to begin with. I'd like to reiterate that I think it would be better if the compiler COULD prove some assertion impossible at compile time, then it should. e.g. ``` int x = 1; assert(x != 1); ``` ... It'd be reasonable for this to fail to compile. Frankly, this could unify static assert and assert (though, I'm not sure if I'd feel comfortable with this... I'd, after all, prefer a static foreach and I'd also like to keep my static ifs because I'd like to enforce that these things are always handled at compile time).
Aug 01 2014
next sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 2 August 2014 at 06:09:42 UTC, Chris Cain wrote:

 Sure. A bit of a different flavor, but essentially the same. 
 Incorrect statements make incorrect program behavior (in the 
 case of assert, I think understanding the real meaning behind 
 it will make it far easier to reason about ... "UB" isn't quite 
 accurate as the meaning behind what you say has a clear 
 implication of what type of behavior will follow, it's just 
 that currently the optimizer doesn't do all it could do)
Not a different flavor, fundamentally different things, see my other post.
Aug 01 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 08:09 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 05:32:43 UTC, Timon Gehr wrote:
 Well, if there is no proof of something, how can I claim it can be
 proven? In fact, in my past life, when somebody told me something like
 '...and actually one _can prove_ that any non-planar graph contains
 either a K_5 or a K_{3,3} as a minor', then this invariably meant that
 there exists a proof, but that they will not tell me the proof now.

 Words are strange; apparently it is very common that they don't mean
 similar things to different people. Isn't it possible, that
 'verifiable' just has an idiomatic usage that does not represent the
 obvious meaning derived from 'verify'? Or is 'verify' bivalent like
 that as well?
It seems to be exactly as Tofu suggested. I don't really know exactly how to explain to you that the concept of verifiability/falsifiability ...
I actually knew and used falsifiable in this way you suggest. :) I still don't think that if I falsify a statement, that I might actually have proven it true though.
 http://en.wikipedia.org/wiki/Falsifiability

 ^^ See?
"A statement is called falsifiable if it is possible to conceive an observation or an argument which proves the statement in question to be false." If we have proven the statement true, we won't readily deem it possible to conceive an observation or argument which proves the statement in question to be false.
 It's an important part of science that there is the possibility
 of proving it false.
Not exactly. The article is stating that it should be conceivable that there might be an argument or an observation proving it false. But that often holds simply because we cannot prove properties of reality to hold. It is conceivable that gravity will not exist tomorrow and this would falsify many theories of physics. I don't really believe that this will happen, but it is conceivable.
 That *doesn't* imply it *is* false, though.
 Likewise for verifiability (they're really just synonyms, which should
 really show you that there actually existing both a proof for truth and
 falseness doesn't make sense)

 http://www.synonym.com/synonyms/falsifiable/ -> verifiable is a synonym.
 ...
Thanks! My hypothesis that verifiable/falsifiable are just idioms not extending to verify/falsify is not shattered by this though.
 .. I knew the dictionary understanding but simply separated the concepts in
 my head before. I thought of the assert in programming languages as you
 currently do. However, this thread has shown me that they were always
 intended to be the same, and it's significantly clarified (for me) where
 I would use assertions and where I'd use enforcements, for instance (the
 boundry has always been pretty fuzzy to me... "use asserts for the
 purpose of program bugs" has always been somewhat unclear).
 ...
I would actually agree with applying this reasoning for usage to 'old' assertions.
 ...

 Sure. A bit of a different flavor, but essentially the same. Incorrect
 statements make incorrect program behavior (in the case of assert, I
 think understanding the real meaning behind it will make it far easier
 to reason about ... "UB" isn't quite accurate as the meaning behind what
 you say has a clear implication of what type of behavior will follow,
 it's just that currently the optimizer doesn't do all it could do)
 ...
The type of behaviour that will follow (or indeed, precede the assertion) is dependent on whether or not the assertion may fail. If it may fail, UB will come and maybe eat your program, and chances are you won't notice immediately what happened. I guess we just disagree on the importance of this point.
 ...

 I'd like to reiterate that I think it would be better if the compiler
 COULD prove some assertion impossible at compile time, then it should.

 e.g.

 ```
 int x = 1;
 assert(x != 1);
 ```

 ... It'd be reasonable for this to fail to compile. Frankly, this could
 unify static assert and assert (though, I'm not sure if I'd feel
 comfortable with this... I'd, after all, prefer a static foreach and I'd
 also like to keep my static ifs because I'd like to enforce that these
 things are always handled at compile time).
It is not so clear where to draw the boundaries. In some languages you may need to prove the assertion true in order for it to pass the type checker.
Aug 01 2014
parent reply "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 06:36:00 UTC, Timon Gehr wrote:
 http://en.wikipedia.org/wiki/Falsifiability

 ^^ See?
"A statement is called falsifiable if it is possible to conceive an observation or an argument which proves the statement in question to be false." If we have proven the statement true, we won't readily deem it possible to conceive an observation or argument which proves the statement in question to be false.
 It's an important part of science that there is the possibility
 of proving it false.
Not exactly. The article is stating that it should be conceivable that there might be an argument or an observation proving it false. But that often holds simply because we cannot prove properties of reality to hold. It is conceivable that gravity will not exist tomorrow and this would falsify many theories of physics. I don't really believe that this will happen, but it is conceivable.
 That *doesn't* imply it *is* false, though.
 Likewise for verifiability (they're really just synonyms, 
 which should
 really show you that there actually existing both a proof for 
 truth and
 falseness doesn't make sense)

 http://www.synonym.com/synonyms/falsifiable/ -> verifiable is 
 a synonym.
 ...
Thanks! My hypothesis that verifiable/falsifiable are just idioms not extending to verify/falsify is not shattered by this though.
Perhaps I just don't understand what you're getting at. It seems throughout that you are thinking "statements of fact" has a meaning that it's inherently true and is proven or must be proven. It seems to me that you've suggested: If falsifiable -> can be proven to be false -> must be proven false -> is false and If verifiable -> can be proven to be true -> must be proven true -> is true (falsifiable == verifiable) (can be proven to be false == can be proven to be true) (false == true) is trivially false. Which must be conclusive that verifiability/falsifiability doesn't imply true/false. Thus, an assertion is a statement of fact, something which can be proven true (or false). It does not mean that you must prove it to be true for it to be an assertion. When you assert something, you're communicating a statement of fact. If you communicate a statement of fact to a compiler, what do you expect it to do? Ignore you, like it ignores your if-statements and function calls? Oh, it doesn't do that, so the obvious conclusion is that it will take your statement of fact and use it for something semantically meaningful. What is semantically meaningful about a statement of fact by a programmer? He hasn't demanded you check it or anything, he's just said something. Logically, the only thing it could do is try to use what you have said in some way. Ultimately, it makes total sense that it could effect the optimization passes. It happens to be nice that when you don't care about performance, the compiler will double check your assertions. But when you do care about performance, assertions being checked (which isn't really what you've asked for) is not ideal. There's literally no more ground to be covered here. I feel it's abundantly obvious that asserts should work this way given the definition of asserts. If you disagree with my conclusion, I don't think there's any more that we can communicate to each other about it. I totally understand why you think asserts meant that you wanted the compiler to check before (because that was my understanding originally), but this way makes much more sense and simplifies my mental model of the world. I no longer have to keep two (not-so) subtly different definitions in my head of what programming-assert means and English-assert means. Now they mean the same thing, which I'm pretty happy about overall.
 It is not so clear where to draw the boundaries. In some 
 languages you may need to prove the assertion true in order for 
 it to pass the type checker.
That would be a cool construct as well, don't get me wrong. But considering the vast majority of programs could not reasonably have such proofs, I think the two concepts are orthogonal. I'd rename that to a "prove" statement and not an "assert" because assert has nothing to do with checking and conflating the two has caused confusion.
Aug 02 2014
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 09:00 AM, Chris Cain wrote:
 On Saturday, 2 August 2014 at 06:36:00 UTC, Timon Gehr wrote:
 http://en.wikipedia.org/wiki/Falsifiability

 ^^ See?
"A statement is called falsifiable if it is possible to conceive an observation or an argument which proves the statement in question to be false." If we have proven the statement true, we won't readily deem it possible to conceive an observation or argument which proves the statement in question to be false.
 It's an important part of science that there is the possibility
 of proving it false.
Not exactly. The article is stating that it should be conceivable that there might be an argument or an observation proving it false. But that often holds simply because we cannot prove properties of reality to hold. It is conceivable that gravity will not exist tomorrow and this would falsify many theories of physics. I don't really believe that this will happen, but it is conceivable.
 That *doesn't* imply it *is* false, though.
 Likewise for verifiability (they're really just synonyms, which should
 really show you that there actually existing both a proof for truth and
 falseness doesn't make sense)

 http://www.synonym.com/synonyms/falsifiable/ -> verifiable is a synonym.
 ...
Thanks! My hypothesis that verifiable/falsifiable are just idioms not extending to verify/falsify is not shattered by this though.
Perhaps I just don't understand what you're getting at. It seems throughout that you are thinking "statements of fact" has a meaning that it's inherently true and is proven or must be proven. ...
No, this you made clear already. (However, the post with the explosions was still warranted from my viewpoint, because the terminology was accidentally changed by you and I didn't notice and just implicitly assumed the two expressions were intended to be synonyms.)
 It seems to me that you've suggested:

 If falsifiable -> can be proven to be false -> must be proven false ->
 is false
 and
 If verifiable -> can be proven to be true -> must be proven true -> is true

 (falsifiable == verifiable)
 (can be proven to be false == can be proven to be true)
 (false == true) is trivially false.
 ...
No, I have suggested that _maybe_ verify != falsify but that idiomatic usage of verifiable == falsifiable.
 ...
 If you disagree with my conclusion, I don't
 think there's any more that we can communicate to each other about it. I
 totally understand why you think asserts meant that you wanted the
 compiler to check before (because that was my understanding originally),
 but this way makes much more sense and simplifies my mental model of the
 world. I no longer have to keep two (not-so) subtly different
 definitions in my head of what programming-assert means and
 English-assert means. Now they mean the same thing, which I'm pretty
 happy about overall.
 ...
Indeed, I still disagree with this conclusion, so let's put this aside for now, unless you see another point to discuss. Thanks for having been a reasonable discussion partner.
 It is not so clear where to draw the boundaries. In some languages you
 may need to prove the assertion true in order for it to pass the type
 checker.
That would be a cool construct as well, don't get me wrong. But considering the vast majority of programs could not reasonably have such proofs, I think the two concepts are orthogonal. I'd rename that to a "prove" statement and not an "assert" because assert has nothing to do with checking and conflating the two has caused confusion.
Well, this was just noting an existing reality that many people with a CS background might have been exposed to.
Aug 02 2014
parent "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 07:23:07 UTC, Timon Gehr wrote:
 Thanks for having been a reasonable discussion partner.
Same to you. Have a good evening :)
Aug 02 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2014 12:00 AM, Chris Cain wrote:
 It is not so clear where to draw the boundaries. In some languages you may
 need to prove the assertion true in order for it to pass the type checker.
That would be a cool construct as well, don't get me wrong. But considering the vast majority of programs could not reasonably have such proofs, I think the two concepts are orthogonal. I'd rename that to a "prove" statement and not an "assert" because assert has nothing to do with checking and conflating the two has caused confusion.
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. If other languages use assert to mean "the compiler must prove this to be true" then that's fine for those languages, but it isn't what D's assert is, or can ever be. I.e. I agree with you.
Aug 02 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
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?
Aug 02 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 06:28 AM, Timon Gehr wrote:
 On 08/02/2014 06:11 AM, Chris Cain wrote:
 ...
 So no, a statement of fact can be verifiable and still false by your
 quote.
It is possible that this is indeed what it tries to communicate. Thanks for bearing with me in any case! But as I wrote in my previous post, now this brings up the issue that if an assertion is a statement of fact, then it is not necessarily true. Why is it now obvious that it should be considered true?
BTW: I missed something: On 08/01/2014 11:18 PM, Chris Cain wrote:
 Imagine my surprise when I Google'd "assert definition" to find it meant
 "state a fact or belief confidently and forcefully."
On 08/02/2014 12:03 AM, Chris Cain wrote:
 Assertions are a statement of fact or belief and can be backed up with
 evidence.
Is 'making a statement of fact' really the same as 'stating a fact'?
Aug 01 2014
parent "Chris Cain" <zshazz gmail.com> writes:
On Saturday, 2 August 2014 at 04:47:05 UTC, Timon Gehr wrote:
 BTW: I missed something:

 On 08/01/2014 11:18 PM, Chris Cain wrote:
 Imagine my surprise when I Google'd "assert definition" to 
 find it meant
 "state a fact or belief confidently and forcefully."
On 08/02/2014 12:03 AM, Chris Cain wrote:
 Assertions are a statement of fact or belief and can be backed 
 up with
 evidence.
Is 'making a statement of fact' really the same as 'stating a fact'?
Probably not. Maybe I wasn't rigorous with the first definition. That said, as far as the compiler is concerned when asserts are taken out, it's reasonable for it to just accept it as a fact even if it doesn't prove it as such. Because we're gods and all.
Aug 01 2014
prev sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 02.08.2014 00:01, schrieb Timon Gehr:
 On 08/01/2014 11:40 PM, Chris Cain wrote:
 On Friday, 1 August 2014 at 21:29:48 UTC, Timon Gehr wrote:
 en.wikipedia.org/wiki/Evidence
http://en.wikipedia.org/wiki/Sausage ...
ingredient in dishes such as stews and casseroles ^~~~~ Almost.
 ...

 Sorry, I don't know what you meant by that. :-)
You will notice it uses the word 'assertion' in a way that is incompatible with your claim that the "assert definition" rules out such an usage.
Yeah, it seems like assertion doesn't *have* to mean something like "promise", but can also be used in the sense of "claim" or "thesis", which is much weaker. Cheers, Daniel
Aug 01 2014
next sibling parent reply "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 22:05:04 UTC, Daniel Gibson wrote:
 Yeah, it seems like assertion doesn't *have* to mean something 
 like "promise"
I'd argue that it never really means "promise." It's a simple statement. In the sense of programming stating something that is incorrect will cause erroneous behavior, so you should be sure of your statements. In a sense, you "promise" your statements are correct otherwise you understand bugs will occur, but the assert itself isn't the promise you're making.
Aug 01 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 12:07 AM, Chris Cain wrote:
 On Friday, 1 August 2014 at 22:05:04 UTC, Daniel Gibson wrote:
 Yeah, it seems like assertion doesn't *have* to mean something like
 "promise"
I'd argue that it never really means "promise." ...In a sense, you "promise" your statements are correct ...
Aug 01 2014
parent "Chris Cain" <zshazz gmail.com> writes:
On Friday, 1 August 2014 at 22:20:02 UTC, Timon Gehr wrote:
 On 08/02/2014 12:07 AM, Chris Cain wrote:
 On Friday, 1 August 2014 at 22:05:04 UTC, Daniel Gibson wrote:
 Yeah, it seems like assertion doesn't *have* to mean 
 something like
 "promise"
I'd argue that it never really means "promise." ...In a sense, you "promise" your statements are correct ...
The promise is that your statements are correct, not that your assertions are the embodiment of the promise itself. I can't make that more clear and it seems abundantly obvious to me what is meant by that.
Aug 01 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/1/14, 3:05 PM, Daniel Gibson wrote:
 Yeah, it seems like assertion doesn't *have* to mean something like
 "promise", but can also be used in the sense of "claim" or "thesis",
 which is much weaker.
That said I'm perversely excited by the notion of a keyword called "thesis"... -- Andrei
Aug 01 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 01:16 AM, Andrei Alexandrescu wrote:
 On 8/1/14, 3:05 PM, Daniel Gibson wrote:
 Yeah, it seems like assertion doesn't *have* to mean something like
 "promise", but can also be used in the sense of "claim" or "thesis",
 which is much weaker.
That said I'm perversely excited by the notion of a keyword called "thesis"... -- Andrei
:D Maybe you should contact Hoare in order to extend http://en.wikipedia.org/wiki/C._A._R._Hoare#Apologies_and_retractions
Aug 01 2014
prev sibling parent reply "Andrew Godfrey" <X y.com> writes:
Suppose I call some logging function which has a faulty assertion 
in it. What about Walter's position prevents that assertion's 
effects from escaping the logging function and infecting my code? 
I know cross-module optimization is hard hence this may be 
unlikely, but still it shows something missing.

I know Walter has said repeatedly that at this point the program 
is invalid, Implying that it deserves whatever happens to it. I 
suspect this is a subtopic we should be discussing more directly. 
What are the boundaries?
Aug 01 2014
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 05:34 AM, Andrew Godfrey wrote:
 Suppose I call some logging function which has a faulty assertion in it.
 What about Walter's position prevents that assertion's effects from
 escaping the logging function and infecting my code?
Nothing. Undefined behaviour is completely non-modular.
 I know cross-module
 optimization is hard hence this may be unlikely,
Inlining may happen.
 but still it shows
 something missing.

 I know Walter has said repeatedly that at this point the program is
 invalid, Implying that it deserves whatever happens to it. I suspect
 this is a subtopic we should be discussing more directly. What are the
 boundaries?
The semantics that are proposed to be pulled into the language spec are currently summarized as: - In non-release mode, an assertion failure will abort the program (maybe by throwing an Error). - In release mode, an assertion failure leads to undefined behaviour. I.e. I think there aren't any 'boundaries', unless I am misunderstanding this term.
Aug 01 2014
parent reply "Andrew Godfrey" <X y.com> writes:
On Saturday, 2 August 2014 at 05:59:14 UTC, Timon Gehr wrote:
 On 08/02/2014 05:34 AM, Andrew Godfrey wrote:
 Suppose I call some logging function which has a faulty 
 assertion in it.
 What about Walter's position prevents that assertion's effects 
 from
 escaping the logging function and infecting my code?
Nothing. Undefined behaviour is completely non-modular.
 I know cross-module
 optimization is hard hence this may be unlikely,
Inlining may happen.
 but still it shows
 something missing.

 I know Walter has said repeatedly that at this point the 
 program is
 invalid, Implying that it deserves whatever happens to it. I 
 suspect
 this is a subtopic we should be discussing more directly. What 
 are the
 boundaries?
The semantics that are proposed to be pulled into the language spec are currently summarized as: - In non-release mode, an assertion failure will abort the program (maybe by throwing an Error). - In release mode, an assertion failure leads to undefined behaviour. I.e. I think there aren't any 'boundaries', unless I am misunderstanding this term.
So even if the assertion is incorrect and the code is correct, the caller's correctness can be compromised? This seems impractical. As in, no one will in good conscience turn it on, except when their program is very small.
Aug 01 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 08:40 AM, Andrew Godfrey wrote:
 So even if the assertion is incorrect and the code is correct, the
 caller's correctness can be compromised?
Yes. The reasoning is that if the assertion is incorrect, the program is fundamentally broken, it enters an invalid state and hence it is fair game to make the behaviour undefined.
 This seems impractical. As in,
 no one will in good conscience turn it on, except when their program is
 very small.
That was my reasoning as well, but it wasn't universally agreed with.
Aug 01 2014
prev sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 05:34, Andrew Godfrey via Digitalmars-d wrote:
 Suppose I call some logging function which has a faulty assertion in it. What
about Walter's position prevents that assertion's effects from escaping the
logging function and infecting my code?
Nothing. Walter _wants_ the assumptions to not be contained inside the assert expression.
 I know cross-module optimization is hard hence this may be unlikely, but still
it shows something missing.
Like I said in my very first post about this proposal -- this is *not* a theoretical issue. It's not some abstract problem that might surface once a sufficiently smart compiler arrives. It affects code *right now*. Fortunately, compilers are not using Walter's assert definition. But that's not because doing it would be 'hard', the support for these kind of optimization is there. Look: ass1.d: --------------------------------------------------------------------- static import gcc.attribute; enum inline = gcc.attribute.attribute("forceinline"); inline void assert_()(bool c) { import gcc.builtins; assert(c); if (!c) // *1 __builtin_unreachable(); // *1 } extern (C) void alog(int level, char* msg) { assert_(level<10); //... } extern (C) int cf(); void main() { if (!cf()) assert(0); } --------------------------------------------------------------------- ass2.c: --------------------------------------------------------------------- void alog(int level, char* msg); volatile int g = 10; int cf() { int a = /* an expression that might return 10 at RT */g; alog(a, "blah"); return a==10; } --------------------------------------------------------------------- Compile this with "gdc -O3 ass1.d ass2.c -o ass -flto -frelease" and this program will fail because the assert triggers. Now, either remove the lines in the `assert_` function marked with `*1` (it's gcc-speak for 'assume'), or fix the assert condition -- now the program will succeed. The point here is that a simple typo, an off-by-one error, an "<" instead of "<=", etc, in the assert condition gives you undefined behavior. The program can then do absolutely everything, return a wrong result, crash or execute `rm -rv /`. In this case gdc compiles it to just: 0000000000402970 <_Dmain>: 402970: 48 83 ec 08 sub $0x8,%rsp 402974: 8b 05 26 ad 25 00 mov 0x25ad26(%rip),%eax # 65d6a0 <g> 40297a: e8 91 f1 ff ff callq 401b10 <abort plt> _`assume` is extremely dangerous_. Redefining `assert` to include `assume` would result in D's `assert` being banned from the whole code base, if 'D' even would be consider a 'sane' enough language to use... artur
Aug 02 2014
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 2 August 2014 at 11:12:42 UTC, Artur Skawina via 
Digitalmars-d wrote:
 _`assume` is extremely dangerous_.
You sure can come up with an example where -release (and only with release the problem exists) results in equally dangerous behaviour by overwriting memory due to disabled bound checks.
 Redefining `assert` to include `assume`
 would result in D's `assert` being banned from the whole code 
 base, if 'D'
 even would be consider a 'sane' enough language to use...
Or you ban -release from the project.
Aug 02 2014
parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 14:12, Tobias Pankrath via Digitalmars-d wrote:
 On Saturday, 2 August 2014 at 11:12:42 UTC, Artur Skawina via Digitalmars-d
wrote:
 _`assume` is extremely dangerous_.
You sure can come up with an example where -release (and only with release the problem exists) results in equally dangerous behaviour by overwriting memory due to disabled bound checks.
`assume` (ie Walter's version of assert) is much worse because even if there are uncoditionally-enabled open-coded bounds checks, the compiler will silently skip them. This: ------------------------------------------------------------------ auto fx(ubyte* p, size_t len) safe { assert_(len>0); if (len>=1) return p[0]; return -1; } ------------------------------------------------------------------ turns into: ------------------------------------------------------------------ 00000000004029a0 < safe int fx(ubyte*, ulong)>: 4029a0: 0f b6 07 movzbl (%rdi),%eax 4029a3: c3 retq ------------------------------------------------------------------ Keep in mind that the `assert` can be elsewhere, in a different function and/or module, and can even be written in a different language. The D-asserts will propagate into C code, just like in my previous example. artur
Aug 02 2014
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 2 August 2014 at 12:44:26 UTC, Artur Skawina via 
Digitalmars-d wrote:
 ------------------------------------------------------------------

 Keep in mind that the `assert` can be elsewhere, in a different
 function and/or module, and can even be written in a different
 language. The D-asserts will propagate into C code, just like in
 my previous example.

 artur
I agree that this might hide bugs, but I don't agree that the additional trouble is bigger than the additional payoffs. If I would use -release now, I would use it after the change and vice-versa.
Aug 02 2014
parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 14:54, Tobias Pankrath via Digitalmars-d wrote:
 I agree that this might hide bugs, but I don't agree that the additional
trouble is bigger than the additional payoffs.
The bug was _introduced_ by the assert, the code was 100% correct. Imagine working on a project with dozen+ developers that use asserts extensively ("it never hurts to have more assertions"). If one of them makes a simple mistake or forgets to update an assert expression somewhere, your own perfectly fine and safe code becomes buggy and exploitable. If you're lucky the problem will be found in testing, but that's far from certain. We use high level languages to (aot) protect ourselves from our own mistakes. Just because I can write: S* p = 0x12345678; does not mean that the compiler has to accept it. artur
Aug 02 2014
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 2 August 2014 at 13:21:07 UTC, Artur Skawina via 
Digitalmars-d wrote:
 On 08/02/14 14:54, Tobias Pankrath via Digitalmars-d wrote:
 I agree that this might hide bugs, but I don't agree that the 
 additional trouble is bigger than the additional payoffs.
The bug was _introduced_ by the assert, the code was 100% correct.
If an assert fails, it's a bug in my book.
 Imagine working on a project with dozen+ developers that use 
 asserts
 extensively ("it never hurts to have more assertions"). If one 
 of them
 makes a simple mistake or forgets to update an assert expression
 somewhere, your own perfectly fine and safe code becomes buggy 
 and
 exploitable.
If there is a wrong assert in the code, it's not perfectly fine. To fail to update some if condition somewhere and to corrupt memory or to forget to fix an assert somewhere and to corrupt memory, are both bugs that will happend with the same likeihood. The first will get you with disabled bound checks, the latter might get you with this optimization. I just don't see how I would take a stand, where I care about one but not about the other.
Aug 02 2014
parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 15:32, Tobias Pankrath via Digitalmars-d wrote:
 On Saturday, 2 August 2014 at 13:21:07 UTC, Artur Skawina via Digitalmars-d
wrote:
 On 08/02/14 14:54, Tobias Pankrath via Digitalmars-d wrote:
If there is a wrong assert in the code, it's not perfectly fine.
The code is perfectly fine in isolation. The bug have leaked from some other subsystem or library. When you look at or audit this code, everything seems fine and there appears to be no problem. Of course such a program is buggy. This is about a) how easy it is to get to the buggy state; b) how hard it is to identify and find the bug; c) the impact of such a bug. `assume` introduces _user-defined_ conditions that trigger UB.
 To fail to update some if condition somewhere and to corrupt memory or to
forget to fix an assert somewhere and to corrupt memory, are both bugs that
will happend with the same likeihood.
 
 The first will get you with disabled bound checks, the latter might get you
with this optimization.
safe was supposed to protect from that. artur
Aug 02 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2014 7:11 AM, Artur Skawina via Digitalmars-d wrote:
  safe was supposed to protect from that.
Just to be pedantic, safe is supposed to provide memory safety, not protection against all UB. Your concern about assert optimizations possibly removing some safe bounds checks is valid. I don't have a solution at the moment, but will be thinking about it.
Aug 02 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Aug 02 2014
next sibling parent reply Johannes Pfau <nospam example.com> writes:
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)
Aug 02 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Aug 02 2014
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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.
Aug 02 2014
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
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
Aug 02 2014
next sibling parent reply "Andrew Godfrey" <X y.com> writes:
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.
Aug 02 2014
parent "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Saturday, 2 August 2014 at 22:00:27 UTC, Andrew Godfrey wrote:
 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.
I strongly disagree with that: if there's pressure for a release, most software in that condition has the assert _removed_ or _commented_, a bug opened, and a boss directive to do so so that it's boss responsibility having taken the risk. The assert is _reinserted_ or _uncommented_ when there's someone hunting for that bug after the release. If this operation can't be done because the failing asserts are a bazillion, compiling it in '-release' with the proposed assert/assume semantic don't change anything: from time to time, when the snowball of failed assert-optimisations will start to destroy the program logic, all that thing will explode in the face of the user. --- Paolo
Aug 03 2014
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 11:36 PM, 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? ...
According to you, what does it mean for a program to be 'broken'? - Is being 'broken' a binary property or can there be different shades of 'broken'? - Is it possible to break 'broken' software more than it was 'broken' already? - Is it fine to break 'broken' software in this way? - Should people be allowed to release 'broken' software? Are they? - Can 'broken' software be useful? - Would _you_ use software you know that is 'broken'? etc. Maybe you find other questions you can answer to exemplify what 'broken' is supposed to mean.
Aug 03 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Saturday, 2 August 2014 at 21:36:11 UTC, Tobias Pankrath wrote:
 Don't you agree, that a program that throws AssertError in non 
 -release* build is broken?

 * this is not the opposite of debug
Let's go to the definitions: Total correctness: The program can be proved to always terminate normally and return the correct result. Total correctness is extremely difficult to achieve on a regular computer. Partial correctness: The program can be proved to always return the correct result if it terminates normally. Partial correctness is what you should aim for. What goes on if it does not terminate depends on many factors. E.g. the FDIV bug in the Intel CPU: http://en.wikipedia.org/wiki/Pentium_FDIV_bug The FDIV bug is a good example that extensive testing is not enough and that you need either exhaustive testing or formal proofs to assert correctness. Equally clearly, the FDIV bug is not the result of an incorrect program. It is the result of an incorrect "axiom" in the CPU (the execution environment).
Aug 03 2014
prev sibling next sibling parent Daniel Gibson <metalcaedes gmail.com> writes:
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
Aug 02 2014
prev sibling parent reply "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Saturday, 2 August 2014 at 20:04:32 UTC, Johannes Pfau wrote:
 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.
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.
I don't buy this! JoeCoder: "Boss, I'm not able to run my code with without -release in development, because every few milliseconds an assert is triggered, but with that switch used to be very fast apart some crash and silly behaviour from time to time in production. But now I've upgraded the compiler and the bad boy working on the D language has ruined all my work!" Boss:"Stick with the old compiler version, light more candles in the Charles Babbage Altar, and you are sacked!"
 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'?
This should be a big YES.
 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.
I understand the debate of introducing assume, and keep the two face of the medal split, but I think that there's nothing not predictable in the fact that, if an assert is there, everyone ranging from the optimiser to the colleague reading the sources is expecting that the expression must be true, without doubt. That's the predictable behaviour. --- Paolo
Aug 03 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 because every few milliseconds an assert is triggered
Right, and software does not have security holes because otherwise they would obviously be exploited every few milliseconds during in-house testing.
 the colleague reading the sources is expecting that the expression must be
true, without doubt.
Poor guy. Do you support the claim that he might, if he supports your "I don't buy this!" post introduce new assertions by conjecturing they are true and then running the program for a few milliseconds?
Aug 03 2014
parent reply "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Sunday, 3 August 2014 at 10:49:39 UTC, Timon Gehr wrote:
 On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 because every few milliseconds an assert is triggered
Right, and software does not have security holes because otherwise they would obviously be exploited every few milliseconds during in-house testing.
That is a totally different matter: security holes are about things that the programmer is _totally missing_, and someone is seeing and exploiting that. I don't see how that relate with the present discussion.
 the colleague reading the sources is expecting that the  
 expression must be true, without doubt.
Poor guy. Do you support the claim that he might, if he supports your "I don't buy this!" post introduce new assertions by conjecturing they are true and then running the program for a few milliseconds?
I don't grasp what you are arguing here: can you rephrase please? --- Paolo
Aug 03 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2014 03:01 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 10:49:39 UTC, Timon Gehr wrote:
 On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 because every few milliseconds an assert is triggered
Right, and software does not have security holes because otherwise they would obviously be exploited every few milliseconds during in-house testing.
That is a totally different matter:
Well, no.
 security holes are about things that
 the programmer is _totally missing_,
The programmer(s!) may be _totally missing_ the conditions that lead to an assertion failure. In fact, unless assertions are intentionally misused, this is always the case.
 and someone is seeing and exploiting that.
(Undefined behaviour introduced in this way may be exploitable.)
 ...  can you rephrase please?
If wrong assertions would indeed fail every few milliseconds, then a way to show an assertion to be correct beyond reasonable doubt is to add the test of the condition to the program and then run it for a few milliseconds.
Aug 03 2014
parent reply "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Sunday, 3 August 2014 at 14:10:29 UTC, Timon Gehr wrote:
 On 08/03/2014 03:01 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 10:49:39 UTC, Timon Gehr wrote:
 On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 because every few milliseconds an assert is triggered
Right, and software does not have security holes because otherwise they would obviously be exploited every few milliseconds during in-house testing.
That is a totally different matter:
Well, no.
 security holes are about things that
 the programmer is _totally missing_,
The programmer(s!) may be _totally missing_ the conditions that lead to an assertion failure. In fact, unless assertions are intentionally misused, this is always the case.
 and someone is seeing and exploiting that.
(Undefined behaviour introduced in this way may be exploitable.)
If the assertion triggers, that's not undefined behaviour: it's a bug, already implanted in the code, that the assertion is surfacing _avoiding_ undefined behaviour occurring from the really next line of code. Security holes are not related to assertions at all, they are related in unpredictable state that the program has reached, outside of the view of the programmers. Assertions are only checks that the reasoning about the flow and the conditions is going in the way that was originally intended. If you have failures, and you want to cope with them, you MUST remove the failing assertions from the code, and turn them in specific code to cope with the faulty condition. Something like 'warning mate! the commented assertion is triggered from time to time, so there's definitely something somewhere in the code that we not fully understand, so here below is a dirty trick to turn the program logic back on the rails because we are in a hurry'. I've never seen a live assertion in the code without the intended behaviour of the expression being true: what would be a mess otherwise!
 ...  can you rephrase please?
If wrong assertions would indeed fail every few milliseconds, then a way to show an assertion to be correct beyond reasonable doubt is to add the test of the condition to the program and then run it for a few milliseconds.
That was a stereotypical example; what I was trying to argue it's that also if we do some dirty tricks to keep the train on the rails, if the program logic is flowed you can have an avalanche effect in some cases: everything seems to work fine for a good amount of time until the snowball comes down, violates catastrophically the program logic and boom. In that cases, also going with '-release' keeping the fingers crossed it's not a good solutions at all. --- Paolo
Aug 03 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2014 05:00 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 14:10:29 UTC, Timon Gehr wrote:
 On 08/03/2014 03:01 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 10:49:39 UTC, Timon Gehr wrote:
 On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 because every few milliseconds an assert is triggered
Right, and software does not have security holes because otherwise they would obviously be exploited every few milliseconds during in-house testing.
That is a totally different matter:
Well, no.
 security holes are about things that
 the programmer is _totally missing_,
The programmer(s!) may be _totally missing_ the conditions that lead to an assertion failure. In fact, unless assertions are intentionally misused, this is always the case.
 and someone is seeing and exploiting that.
(Undefined behaviour introduced in this way may be exploitable.)
If the assertion triggers, that's not undefined behaviour:
It will from now on be in -release, this is what this is all about.
 it's a bug,
 already implanted in the code, that the assertion is surfacing
 _avoiding_ undefined behaviour occurring from the really next line of code.
 ...
Most bugs do not lead to undefined behaviour. E.g. you can write buggy code in a language that does not have the concept.
 Security holes are not related to assertions at all, they are related in
 unpredictable state that the program has reached, outside of the view of
 the programmers.
 ...
And what do you think a wrong assertion is the manifestation of? (Hint: The assertion talks about the program state.)
 Assertions are only checks that the reasoning about the flow and the
 conditions is going in the way that was originally intended. If you have
 failures,
But that is not the scenario. You don't turn on -release in order to disable assertions that you _know_ are failing.
 and you want to cope with them, you MUST remove the failing
 assertions from the code, and turn them in specific code to cope with
 the faulty condition.

 Something like 'warning mate! the commented assertion is triggered from
 time to time,
Why do you assume they had noticed that the assertion was wrong?
 That was a stereotypical example;
You were not in the position to introduce a stereotypical example. If Johannes says that some code will break, and you say "I don't buy this", then you cannot introduce an example to argue against, where the additional circumstances are such that you have an easy point. This is a straw man. You need to argue against the existence of the broken code. I.e. you need to argue for an (approximate) universal. If you introduce an example, you need to argue that the 'example' is actually the only (likely) way that code could be broken by this change. I.e. you'd need to argue that wrong assertions are always caught before they are part of a build where they are disabled. (You might also pursue the alternative direction of admitting that this is a possibility, but saying that it is very unlikely to happen, and then justify that opinion. ("That's true, this might happen, but I don't think this change will lead to many catastrophes, because..."))
 what I was trying to argue it's that also if we do some dirty tricks to keep
the train on the rails,
(That's still part of the made up scenario.)
 if the program logic is flowed  [sic]
Maybe it hasn't been flawed in the -release build before because the faulty assertion was the only thing that was faulty, but nobody knew that it was faulty before the released system went down.
 you can have an avalanche effect in some cases:
Note again, 'some cases'. Those are again different cases than Johannes had in mind.
 everything seems to work fine for a good amount of time until the snowball
comes down,
 violates catastrophically the program logic and boom.
Again, in other cases, the -release program will operate as expected. An analogy, to be taken with a grain of salt: Planes crash sometimes, even though this is not part of their intended design. It would still be a bad idea to install bombs in some planes that explode when they seem about to crash according to _some_ of many simple tests of measured parameters proposed by one of (possibly) _many_ designers of the plane, especially if those tests were proposed without knowledge that this was going to be their purpose.
Aug 03 2014
parent reply "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Sunday, 3 August 2014 at 16:29:18 UTC, Timon Gehr wrote:
 On 08/03/2014 05:00 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 14:10:29 UTC, Timon Gehr wrote:
 On 08/03/2014 03:01 PM, Paolo Invernizzi wrote:
 On Sunday, 3 August 2014 at 10:49:39 UTC, Timon Gehr wrote:
 On 08/03/2014 11:15 AM, Paolo Invernizzi wrote:
 and someone is seeing and exploiting that.
(Undefined behaviour introduced in this way may be exploitable.)
If the assertion triggers, that's not undefined behaviour:
It will from now on be in -release, this is what this is all about.
If an assert triggers, and you want go anyway with '-release', you should remove it from the code, that's my point. No problem at all with inferring optimisations from it.
 it's a bug, already implanted in the code, that the assertion 
 is surfacing
 _avoiding_ undefined behaviour occurring from the really next 
 line of code.
 ...
Most bugs do not lead to undefined behaviour. E.g. you can write buggy code in a language that does not have the concept.
But most yes: to me, an undefined behaviour is the situation where I've developed the code for having 'a' in one place, and I have 'b'. If this is not, literally undefined behaviour, I donno how I should name it.
 Security holes are not related to assertions at all, they are 
 related in
 unpredictable state that the program has reached, outside of 
 the view of the programmers.
And what do you think a wrong assertion is the manifestation of? (Hint: The assertion talks about the program state.)
Again, the assertion will trigger on that, so I'm not entering the 'donno what happened here' state: the program will halt. No security risk at all, also if the assert expression is crappy code. If you want to keep the safety net also in '-release' just stop using asserts and use enforce, at least you are clearly signalling the developer intention. Or, simply, don't use '-release', but that to me it's a little abuse of the use of assert...
 Assertions are only checks that the reasoning about the flow 
 and the
 conditions is going in the way that was originally intended. 
 If you have failures,
But that is not the scenario. You don't turn on -release in order to disable assertions that you _know_ are failing.
 and you want to cope with them, you MUST remove the failing
 assertions from the code, and turn them in specific code to 
 cope with
 the faulty condition.

 Something like 'warning mate! the commented assertion is 
 triggered from
 time to time,
Why do you assume they had noticed that the assertion was wrong?
I don't understand now: I notice it because the program terminate with a stack trace telling me an assertion was triggered. What are you meaning? I guess it's a pretty common practise to have testers stress the application with asserts on, prior to put it in production with assertion disabled once you are confident that the program is not buggy.
 That was a stereotypical example;
You were not in the position to introduce a stereotypical example. If Johannes says that some code will break, and you say "I don't buy this", then you cannot introduce an example to argue against, where the additional circumstances are such that you have an easy point. This is a straw man.
I don't think it's a straw man, because I've not changed anything that Johannes has said.
 You need to argue against the existence of the broken code. 
 I.e. you need to argue for an (approximate) universal.
I'm arguing, like others, that to me the code was already broken, but it seems that we can't agree on what broken means.
 If you introduce an example, you need to argue that the 
 'example' is actually the only (likely) way that code could be 
 broken by this change.
 I.e. you'd need to argue that wrong assertions are always 
 caught before they are part of a build where they are disabled.
That's what usually happens, if you have a good test coverage, and a good testing period.
 (You might also pursue the alternative direction of admitting 
 that this is a possibility, but saying that it is very unlikely 
 to happen, and then justify that opinion. ("That's true, this 
 might happen, but I don't think this change will lead to many 
 catastrophes, because..."))
The point was simply that I don't think that such a change will summon voices claiming that the language has broken again some codebase. That is an easy rebuttal, because it's caused by a, IMHO, bad practical usage of the assert statement.
 what I was trying to argue it's that also if we do some dirty 
 tricks to keep the train on the rails,
(That's still part of the made up scenario.)
 if the program logic is flowed  [sic]
Maybe it hasn't been flawed in the -release build before because the faulty assertion was the only thing that was faulty, but nobody knew that it was faulty before the released system went down.
Ok, now I've understood: are you arguing, (correct me if I'm wrong, I'm not searching a strawman, really!) that probably there are bugs, and that bugs are wrong assert expressions, that are wrongly modelling the intended state of the program in an assert expression? And in that case, are you arguing that the utility of the '-release' flags is that, obliterating the assert code, it raises the quality of the code because it's some sort of "dead code elimination?". It's that?
 everything seems to work fine for a good amount of time until 
 the snowball comes down,
 violates catastrophically the program logic and boom.
Again, in other cases, the -release program will operate as expected.
If I've grasped your point in the previous reply, yes, maybe.
 An analogy, to be taken with a grain of salt: Planes crash 
 sometimes, even though this is not part of their intended 
 design. It would still be a bad idea to install bombs in some 
 planes that explode when they seem about to crash according to 
 _some_ of many simple tests of measured parameters proposed by 
 one of (possibly) _many_ designers of the plane, especially if 
 those tests were proposed without knowledge that this was going 
 to be their purpose.
I think that something similar is happening: the avionic system is disabled if the results coming out from two different implementation of "how the plane should fly" diverge. It's the same as they are running without '-release', and checking mutually the state of the flight devices and parameters. The are 'aborting', and leaving all the control to man instead of going on: it's like they are not using '-release' at all, and it's like they are using 'enforce' all over the place, no assume or assert at all. --- Paolo
Aug 03 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/03/2014 11:03 PM, Paolo Invernizzi wrote:
 ...

 But most yes: to me, an undefined behaviour is the situation where I've
 developed the code for having 'a' in one place, and I have 'b'.  If this
 is not, literally undefined behaviour, I donno how I should name it.
 ...
You could name it a bug, or a programming error. Undefined behaviour is something specific. If a program contains undefined behaviour, this means that a conforming implementation can generate any arbitrary behaviour.
 ...
 everything seems to work fine for a good amount of time until the
 snowball comes down,
 violates catastrophically the program logic and boom.
Again, in other cases, the -release program will operate as expected.
If I've grasped your point in the previous reply, yes, maybe. ...
Ok. This was Johannes' point.
Aug 03 2014
parent "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Sunday, 3 August 2014 at 21:36:44 UTC, Timon Gehr wrote:
 Again, in other cases, the -release program will operate as 
 expected.
If I've grasped your point in the previous reply, yes, maybe. ...
Ok. This was Johannes' point.
Taken, thanks for the explanation: I agree that you both that optimising on a wrongly written assert could turn in code breakage under the new '-release' semantic. --- Paolo
Aug 04 2014
prev sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
Aug 02 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2014 1:06 PM, Artur Skawina via Digitalmars-d wrote:
 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.
This seems contradictory. You say it is fine to have assume affect optimization, i.e. insert bugs if the assumes are wrong, but not fine to check at runtime that the assumes are correct?
Aug 03 2014
next sibling parent "Andrew Godfrey" <X y.com> writes:
On Sunday, 3 August 2014 at 15:06:56 UTC, Walter Bright wrote:
 On 8/2/2014 1:06 PM, Artur Skawina via Digitalmars-d wrote:
 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.
This seems contradictory. You say it is fine to have assume affect optimization, i.e. insert bugs if the assumes are wrong,
Yes
 but not fine to check at runtime that the assumes are correct?
No, it would be fine for assume to do runtime checks on debug. I.e. The semantics you want assert to have, would be fine for assume. But I'd also expect assume to be used much more conservatively than assert. And the naming is much clearer this way.
Aug 03 2014
prev sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/03/14 17:06, Walter Bright via Digitalmars-d wrote:
 On 8/2/2014 1:06 PM, Artur Skawina via Digitalmars-d wrote:
 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.
This seems contradictory. You say it is fine to have assume affect optimization, i.e. insert bugs if the assumes are wrong, but not fine to check at runtime that the assumes are correct?
I'm saying there's nothing wrong with having an assume(-like) directive; by default `assume` should of course check the condition at RT just like `assert` does [1]. I'm against _redefining_ `assert` to mean `assume`. In practice there will always be a possibility of an assert failing at RT due to eg a different environment or inputs[2]. If programs always were perfect and absolutely bug-free, asserts and diagnostics would never be required at all... Do you really think that it is unreasonable to expect that, in a language called *D*, a very well known decades old C concept isn't redefined? That wouldn't be appropriate even for a language called "Mars"... Of course everybody initially expects that an 'assert' in D acts like the C equivalent. There isn't anything in the "spec" (ie dlang.org) that even hints at D's assert being different. ("[...] if the result is false, an AssertError is thrown. If the result is true, then no exception is thrown.[...]"). I just looked at the "contracts" page for the first time ever, and found this: "assert in function bodies works by throwing an AssertError, which can be caught and handled". That could reasonably be interpreted to mean that a failing assertion in D still leaves the program in a well defined valid (!) state. Most people who are already aware of `assert` will know a definition like this one: http://pubs.opengroup.org/onlinepubs/009695399/functions/assert.html "assert - insert program diagnostics [...] The assert() macro shall insert diagnostics into programs". Nobody expects that disabling diagnostics introduces undefined behavior. Hence, slightly inaccurate or not 100% up-to-date asserts are not considered a real problem. And they are not a problem. Except in D? artur [1] An `__assume` that never checks at RT would also be useful for low-level code, where failure is not an option. [2] Asserts are not for /directly/ validating inputs, yes, but inputs are often necessary to get the program to an invalid state.
Aug 03 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Aug 02 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/02/2014 05:08 PM, 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
So far I have been under the impression that dereferencing pointers in safe is intended to be ok, but creating pointers to inexistent data is intended to be un- safe.
Aug 02 2014
prev sibling next sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/02/14 17:08, Andrei Alexandrescu via Digitalmars-d 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?
Dereferencing a pointer shouldn't be disallowed -- it would make safe almost unusable when dealing with structs. As long as it's impossible to obtain an invalid pointer (or one with a longer lifetime than the object it points to) _within_ safe, it is, well, safe. Dereferencing a null ptr is an error, but it's not a memory safety violation. [Before somebody claims that this means that the assume-based transformation of the above function isn't a problem -- this is just the a simple example; I didn't want to clutter it up with a trusted helper that would handle the data access. The bounds check would be optimized away in that case too.] artur
Aug 02 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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?
Aug 02 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Aug 02 2014
next sibling parent "David Nadlinger" <code klickverbot.at> writes:
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
Aug 02 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2014 1:23 PM, Andrei Alexandrescu wrote:
 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".
We could establish a rule for safe that function arguments that are pointers must be pointers to valid memory, not past the end.
Aug 03 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/3/14, 8:10 AM, Walter Bright wrote:
 On 8/2/2014 1:23 PM, Andrei Alexandrescu wrote:
 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".
We could establish a rule for safe that function arguments that are pointers must be pointers to valid memory, not past the end.
I think that's a good stance. -- Andrei
Aug 03 2014
parent "David Nadlinger" <code klickverbot.at> writes:
On Sunday, 3 August 2014 at 15:16:31 UTC, Andrei Alexandrescu 
wrote:
 On 8/3/14, 8:10 AM, Walter Bright wrote:
 We could establish a rule for  safe that function arguments 
 that are
 pointers must be pointers to valid memory, not past the end.
I think that's a good stance. -- Andrei
Agreed, see my other post. In fact, if I remember correctly this is not the first time that a variant of this question pops up and I think we already came to this conclusion at least once. Of course, this also entails that it must be impossible to obtain such a pointer in safe code. Right now, there are a still a few holes in that regard (see Bugzilla), e.g. someArray[$ .. $].ptr. Cheers, David
Aug 03 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/2/2014 4:12 AM, Artur Skawina via Digitalmars-d wrote:
 _`assume` is extremely dangerous_. Redefining `assert` to include `assume`
 would result in D's `assert` being banned from the whole code base, if 'D'
 even would be consider a 'sane' enough language to use...
More simply, you could just ban "-release". Keep in mind, that under the current implementation, removing asserts also removes the bug checking that the asserts presumably were inserted for. If the asserts don't hold true, the program has undetected bugs in it, it is in an unknown and invalid state, and the ability to predict what it will do next is gone. I.e. you should already have banned use of "-release".
Aug 02 2014
parent reply "Kapps" <opantm2+spam gmail.com> writes:
On Saturday, 2 August 2014 at 19:10:51 UTC, Walter Bright wrote:
 On 8/2/2014 4:12 AM, Artur Skawina via Digitalmars-d wrote:
 _`assume` is extremely dangerous_. Redefining `assert` to 
 include `assume`
 would result in D's `assert` being banned from the whole code 
 base, if 'D'
 even would be consider a 'sane' enough language to use...
More simply, you could just ban "-release". Keep in mind, that under the current implementation, removing asserts also removes the bug checking that the asserts presumably were inserted for. If the asserts don't hold true, the program has undetected bugs in it, it is in an unknown and invalid state, and the ability to predict what it will do next is gone. I.e. you should already have banned use of "-release".
There's a huge difference between removing an extra check to verify the lack of a bug versus guaranteeing the lack of a bug and optimizing off of it. The way that assert is traditionally used (C/C++, Java, C#, current D implementation, etc) is a verification of your code, not a hint to the optimizer that some expression is true. If D wishes to change this meaning then it goes against D's philosophy of that if C code compiles it should behave the same way as it did in C, and goes against every previous usage of assert. Worse, it does so in a way that would be extremely hard to detect if tests don't catch it since the error would occur in an unrelated location and only in release builds. More importantly, it's a huge security flaw. Not all bugs are equal; an assertion being false means a bug exists, but optimizing based off of this allows much more severe bugs to exist. Given a function that makes a call to a database/launches a process/returns some HTML/etc, having an early check that directly or indirectly asserts the data is valid to ease debugging will remove the runtime check that ensures there's nothing malicious in that data. Now because you had one extra assert, you have a huge security flaw and a great deal of unhappy customers that have had their accounts compromised or their information leaked. This is not an unrealistic scenario. That being said, so long as this is a separate optimization switch, it should rarely be an issue. Keep the current behaviour of -release disabling asserts, then add a new -assumeasserts or -Oassert or such that allows the optimizer to optimize with the guarantee that all asserts are true. It would also be good to be able to guarantee that some piece of code can never be optimized out (e.g., sanitation of user input). Changing the current behaviour of -release is a huge breaking change that would open up security holes and overall I feel would be a terrible thing to do.
Aug 02 2014
next sibling parent "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Sunday, 3 August 2014 at 04:29:28 UTC, Kapps wrote:
 On Saturday, 2 August 2014 at 19:10:51 UTC, Walter Bright wrote:
 On 8/2/2014 4:12 AM, Artur Skawina via Digitalmars-d wrote:
More importantly, it's a huge security flaw. Not all bugs are equal; an assertion being false means a bug exists, but optimizing based off of this allows much more severe bugs to exist. Given a function that makes a call to a database/launches a process/returns some HTML/etc, having an early check that directly or indirectly asserts the data is valid to ease debugging will remove the runtime check that ensures there's nothing malicious in that data. Now because you had one extra assert, you have a huge security flaw and a great deal of unhappy customers that have had their accounts compromised or their information leaked. This is not an unrealistic scenario.
The costumer should not be happy because an assert was used for that... --- Paolo
Aug 03 2014
prev sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 08/03/14 06:29, Kapps via Digitalmars-d wrote:
 Not all bugs are equal; an assertion being false means a bug exists, but
optimizing based off of this allows much more severe bugs to exist. 
Yes. Giving a new meaning to `assert` would also affect how it's used. Asserts would be used not only to check and document assumptions, but also to enable certain optimizations. This would add a new source of bugs. A harmless i-think-this-is-always-true assert would be indistinguishable from a potentially dangerous one. The former kind does not really need much attention, the latter requires special care and needs to be looked after even when it's not failing.
 Keep the current behaviour of -release disabling asserts, then add a new
-assumeasserts or -Oassert 
The problem with this is that it introduces a new dialect in which `assert` has a different meaning. If parts of a program are (or were) independently developed by different teams, one using asserts the traditional way (for debugging) and another using them aggressively to expose every optimization opportunity, then the debugging asserts which were supposed to be harmless will be reinterpreted. Effectively you would always have to assume that assert==assume. So a compiler switch wouldn't really improve the situation. artur
Aug 03 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 05:17 AM, Walter Bright wrote:
 On 7/31/2014 12:37 PM, Daniel Gibson wrote:
 Am 31.07.2014 21:19, schrieb Walter Bright:
 That's the way assert in C/C++ conventionally worked. But this is
 changing. Bearophile's reference made it clear that Microsoft C++ 2013
 has already changed, and I've seen discussions for doing the same with
 gcc and clang.
This will break so much code :-/
Maybe you're right.
He is.
 I've always thought that assert() was a simple and
 obvious concept,
It is.
 and am genuinely surprised at all the varied (and even
 weird) interpretations of it expressed here.
Don't throw them all in one bag.
 I've never heard such
 things in my 30+ years of using assert().

 I have seen some misuse of assert() before, but the author of them knew
 he was misusing it and didn't have an issue with that.

 I can't even get across the notion of what a program's inputs are. Sheesh.
 ...
You didn't try. You were obviously being misunderstood and just repeated the same wording.
 Or perhaps some people are just being argumentative. I can't really
 tell. I can tell, however, than many of these sub-threads have ceased to
 contain any useful discussion.
Are you now trying to generalize over opinions that are not your own as wrong by only refuting some of them? All the fallacious reasoning you have put forward in this thread is really tiring. Please don't ignore logic.
Aug 01 2014
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 That's the way assert in C/C++ conventionally worked. But this 
 is changing. Bearophile's reference made it clear that 
 Microsoft C++ 2013 has already changed,
I am against the idea of turning asserts into a dangerous assert-assume hybrid. And you have ignored some answers by Timon and others. Bye, bearophile
Jul 31 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 12:48 PM, bearophile wrote:
 I am against the idea of turning asserts into a dangerous assert-assume hybrid.
 And you have ignored some answers by Timon and others.
Every post I answer spawns 5 more responses. It's exponential. At some point, I have to give up. I've spent 2 days on this.
Jul 31 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/01/2014 05:29 AM, Walter Bright wrote:
 On 7/31/2014 12:48 PM, bearophile wrote:
 I am against the idea of turning asserts into a dangerous
 assert-assume hybrid.
 And you have ignored some answers by Timon and others.
Every post I answer spawns 5 more responses.
I am sorry but your posts were not constructed carefully enough to not warrant rebuttals.
 It's exponential.
I won't count posts now, but I think that this is not true.
 At some point, I have to give up.
Saying that you are obviously right and other people are maybe just argumentative is not 'giving up'.
 I've spent 2 days on this.
Everyone has.
Aug 01 2014
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 09:19 PM, Walter Bright wrote:
 On 7/31/2014 6:37 AM, Daniel Gibson wrote:
 The behavior you desire here is easily handled by creating your own
 template to exhibit it. See the implementation of enforce() for how to
 do it.
Now that's a bit surprising to me, as you wrote in the other thread: > 7. using enforce() to check for program bugs is utterly wrong. > enforce() is a library creation, the core language does not recognize > it." Until now (being mostly a C/C++ guy), I saw assertions as a way to find bugs during development/testing that is completely eliminated in release mode (so I might still want to handle the asserted conditions gracefully there) - and it seems like I'm not alone with that view.
The assert will not cause code to be generated to test the assertion at runtime with -release. But the assert must still be valid, and since it is valid, the optimizer should be able to take advantage of it. assert is not meant to be used as "I want my program to be valid even if the assert is false". ...
An assert does not have any bearing on program validity if assertions are disabled.
 Because (in C/C++) assertions just vanish when NDEBUG isn't defined,
 it would
 never occur to me that they have any influence on such (release mode)
 builds.
 Doing optimizations on this would just lead to frustration, like
 several kinds
 of optimizations recently have (e.g. this "compiler will remove
 bzero() on
 memory that isn't used afterwards" bullshit).
That's the way assert in C/C++ conventionally worked.
Right. Note 'conventionally' as in 'convention'. Why break the convention?
 But this is
 changing. Bearophile's reference made it clear that Microsoft C++ 2013
 has already changed,
No way, their assert macro conforms to the standard. http://msdn.microsoft.com/en-us/library/9sb57dw4.aspx
 and I've seen discussions for doing the same with gcc and clang.
 ...
And I've seen discussions for introducing silent breaking changes into D. It usually didn't happen. Why are those discussions deemed to be _more relevant than the standard_ in the first place?
 In fact, the whole reason assert is a core language feature rather than
 a library notion is I was anticipating making use of assert for
 optimization hints.
I was under the impression it was because of assert(0).
Jul 31 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 31 July 2014 at 13:37:42 UTC, Daniel Gibson wrote:
 Because (in C/C++) assertions just vanish when NDEBUG isn't 
 defined, it would never occur to me that they have any 
 influence on such (release mode) builds.
Yes, all standards require this for good reason. I don't know why Walter and Andrei thinks conforming C can do anything else than ignoring assert in release builds: « If NDEBUG is defined as a macro name before the inclusion of this header, the assert() macro shall be defined simply as: #define assert(ignore)((void) 0) » http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/assert.h.html
Jul 31 2014
prev sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/31/14 02:31, Walter Bright via Digitalmars-d wrote:
 On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote:
 No, with the assert definition you're proposing, it won't. It would
 be allowed to optimize away the bounds check. And this is just one of
 many problems with the assert==assume approach.
Please explain how assume would behave any differently.
I'm not arguing for assume [1], just against allowing information derived from assert expressions being able leak and affect other parts of the program. That just can not work (sanely); it would cause more problems than C's undefined behavior abuse. Because the UB triggers are well defined - by the language - and relatively well known. Asserts are /user-defined/. One wouldn't be able to reason about code without considering every single assert expression that was evaluated before reaching the current expression/function. An incorrect or inexact assert() hidden away somewhere could silently affect unrelated code, disable important safety checks etc. artur [1] I don't think that introducing `assume` would make a significant difference at this point - there are many more important D issues needing attention... But it could be done, would need to be system, and probably wouldn't require much work. In fact, it already exists in gdc-ese, kind of: static import gcc.attribute; enum inline = gcc.attribute.attribute("forceinline"); inline void assume()(bool c) { import gcc.builtins; if (!c) __builtin_unreachable(); } bool plain_assert(int i) { assert(i<6); return i==9; } // => "cmpl $9, %edi; sete %al; ret" bool assume_instead_of_assert(int i) { assume(i<6); return i==9; } // => "xorl %eax, %eax; ret" `assume`, unlike `assert`, may affect codegen.
Jul 30 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 12:54 AM, David Bregman wrote:
 On Wednesday, 30 July 2014 at 03:32:50 UTC, Walter Bright wrote:
 I don't either. I still have no idea what the difference between
 assume(i<6) and assert(i<6) is supposed to be.
assert: is a runtime check of the condition. is a debugging/correctness checking feature. is used when the expression is believed true, but is not proven so. (if it was proven, then there is no purpose in asserting it with a redundant runtime check that is guaranteed to never activate.) assume: passes a hint to the optimizer to allow better code generation. is used when the expression is proven to be true (by the programmer, like trusted).
Thanks for the summary! It seems to me indeed there's little assume does that can't be done with assert today.
 The only relation between the two is that if a runtime check for (x) is
 inserted at some point, it is safe to insert an assume(x) statement
 afterwards, because x is known true at that point.
So then one might redefine assert to always insert an assume right afterwards.
 If assert degenerates to assume in release mode, any bugs in the program
 could potentially cause a lot more brittleness and unexpected/undefined
 behavior than they otherwise would have. In particular, code generation
 based on invalid assumptions could be memory unsafe.
I think gcc does that. Also, it's unclear to me what the optimizer would be supposed to do if an assumption turns out to be false. Andrei
Jul 30 2014
next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu 
wrote:
 Also, it's unclear to me what the optimizer would be supposed 
 to do if an assumption turns out to be false.
Bad... bad... things...
Jul 30 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 7:55 AM, Tofu Ninja wrote:
 On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu wrote:
 Also, it's unclear to me what the optimizer would be supposed to do if
 an assumption turns out to be false.
Bad... bad... things...
So then I see nothing that assume can do that assert can't. -- Andrei
Jul 30 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Andrei Alexandrescu"  wrote in message 
news:lrb20i$30jl$1 digitalmars.com...

 So then I see nothing that assume can do that assert can't. -- Andrei
assume can avoid confusing people that think D's assert means something it doesn't.
Jul 30 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 8:21 AM, Daniel Murphy wrote:
 "Andrei Alexandrescu"  wrote in message news:lrb20i$30jl$1 digitalmars.com...

 So then I see nothing that assume can do that assert can't. -- Andrei
assume can avoid confusing people that think D's assert means something it doesn't.
This reminds me of that old Basic program: ... code ... REM halt program STOP REM if skidding STOP
Jul 30 2014
prev sibling next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jul 30, 2014 at 08:12:20AM -0700, Andrei Alexandrescu via Digitalmars-d
wrote:
 On 7/30/14, 7:55 AM, Tofu Ninja wrote:
On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu wrote:
Also, it's unclear to me what the optimizer would be supposed to do
if an assumption turns out to be false.
Bad... bad... things...
So then I see nothing that assume can do that assert can't. -- Andrei
Yeah, I think this hair-splitting between assume and assert is ... pure hair-splitting. I don't know where people got the idea that assert means "check this condition" as opposed to "assume this condition is true and generate code accordingly". My understanding of it is that it's telling the compiler (and whoever reads the code), that at that given juncture in the code, the programmer has assured that a certain condition holds, and that the following code was written with that assumption in mind. The fact that assert will fail at runtime is a secondary artifact to help catch logic errors where the programmer's assumptions somehow got broken. IOW, it's something extra the compiler throws in, in order to help with debugging; it is strictly speaking not part of the program logic. The compiler is merely saying, "OK the programmer says condition X must hold at this point. But just in case he made a mistake, I'll throw in a check that will fail at runtime so that if he *did* make a mistake, the program won't blunder onwards blindly and do stupid things because it made a wrong assumption." It's not *that* far a stretch for the compiler to also say, "OK the programmer says condition X must hold at this point. I trust him, so I'm going to optimize the following code accordingly." To me, it totally makes sense for the compiler to apply the former approach when compiling in non-release mode (which is by definition when the programmer is developing and testing the program, and would appreciate the extra help in assumptions being checked), and the latter approach when compiling in release/optimizing mode (which is by definition where the programmer wants to take maximum advantage of any optimizations the compiler can do -- so optimizations stemming from assert's are fair game as the source of possible code simplifications). T -- Written on the window of a clothing store: No shirt, no shoes, no service.
Jul 30 2014
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 05:28 PM, H. S. Teoh via Digitalmars-d wrote:
 Yeah, I think this hair-splitting between assume and assert is ... pure
 hair-splitting.
Which is pure name-calling.
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb86k$428$1 digitalmars.com...

 On 07/30/2014 05:28 PM, H. S. Teoh via Digitalmars-d wrote:
 Yeah, I think this hair-splitting between assume and assert is ... pure
 hair-splitting.
Which is pure name-calling.
Only in the sense that saying your argument is wrong is calling you a wrong-argument-maker.
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 07:15 PM, Daniel Murphy wrote:
 "Timon Gehr"  wrote in message news:lrb86k$428$1 digitalmars.com...

 On 07/30/2014 05:28 PM, H. S. Teoh via Digitalmars-d wrote:
 Yeah, I think this hair-splitting between assume and assert is ... pure
 hair-splitting.
Which is pure name-calling.
Only in the sense that saying your argument is wrong is calling you a wrong-argument-maker.
Well, no. (Not applicable here, but if it doesn't come with any justification, it might be.) The second issue is that the statement above tries to look like it is tautological by seeming to express both factual information and an opinion at the same time. In any case, I wouldn't have objected in this way to a statement like 'I think the distinction between assume and assert is not important for D.', while a statement like 'I think the distinction between assume and assert is not important and I am right about this.', which is what the above statement says, without summoning images of futile attempts to split a hair in half, I am sure, wouldn't even have been considered by the author.
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrbb2a$6du$1 digitalmars.com...

 The second issue is that the statement above tries to look like it is 
 tautological by seeming to express both factual information and an opinion 
 at the same time.
I prefer to assume statements have no deceptive intent. Almost everything on here is somebody's opinion, qualified as such or not.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 07:59 PM, Daniel Murphy wrote:
 "Timon Gehr"  wrote in message news:lrbb2a$6du$1 digitalmars.com...

 The second issue is that the statement above tries to look like it is
 tautological by seeming to express both factual information and an
 opinion at the same time.
I prefer to assume statements have no deceptive intent.
Me too and I am sure none was present. What I want to say is that the effect of the statement is deceptive.
Jul 30 2014
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 8:28 AM, H. S. Teoh via Digitalmars-d wrote:
[...]
Exactly right.
Jul 30 2014
prev sibling parent =?UTF-8?Q?Tobias=20M=C3=BCller?= <troplin bluewin.ch> writes:
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 On 7/30/14, 7:55 AM, Tofu Ninja wrote:
 On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu wrote:
 Also, it's unclear to me what the optimizer would be supposed to do if
 an assumption turns out to be false.
Bad... bad... things...
So then I see nothing that assume can do that assert can't. -- Andrei
The point is that optimizations based on asserts can have a big impact because they are leaky. By having both, a dangerous assume and a mre harmless assert (that terminates in debug and does nothing in release), the programmer can use assert a lot without many consequences if there's an error. Only if optimizations are really necessary he can use assume, but he can use it with care. It's not that assert is not powerful enough. It too dangerous to be used frequently. Tobi
Jul 30 2014
prev sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 14:55:48 UTC, Tofu Ninja wrote:
 On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu 
 wrote:
 Also, it's unclear to me what the optimizer would be supposed 
 to do if an assumption turns out to be false.
Bad... bad... things...
That is the main argument(not saying I support it) for separating assert and assume, assert acts like assume in -release, and if an assume is false then bad things can happen. Question? If an if condition throws or returns in its body is it ok for the optimizer to 'assume' that the condition is false after and make optimizations for it? If so then every one complaining that assert gets removed in -release should really just be using enforce. after all en enforce is simply if(!(cond)) // can be removed if cond is provably true, same as assert could be removed throw ...; // Can safely assume cond is true from this point on up until the first catch... The possibility for the optimizer to make the same optimizations for assert can be done for enforce, the only difference is that it does not get removed in -release....
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Tofu Ninja"  wrote in message news:dtjqnyucskwnqjvksawg forum.dlang.org...

 Question?
 If an if condition throws or returns in its body is it ok for the 
 optimizer to 'assume' that the condition is false after and make 
 optimizations for it? If so then every one complaining that assert gets 
 removed in -release should really just be using enforce.
Yes. In fact, it's required that an optimizer do this in order not to be considered garbage.
 The possibility for the optimizer to make the same optimizations for 
 assert can be done for enforce, the only difference is that it does not 
 get removed in -release....
Not quite. With enforce, it is impossible (ignoring hardware or optimizer errors) for the condition to be false if the enforce was not triggered. Because the assert is not checked, the condition could be false and the code could do something awful. Also, the optimizer can only use the enforce's assumption _after_ it has checked the condition. Since with assert it doesn't need to check, it can go backwards and assume the previous code will never produce a value that can violate the assertion. if (y > 7) // x can't possibly be >= 5, so this can't be true x = y + 1; assert(x < 5); if (y > 7) // the program will throw if >= 5, but that doesn't mean it can't be true x = y + 1; enforce(x < 5); Assert is much much more powerful.
Jul 30 2014
next sibling parent reply "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 15:49:33 UTC, Daniel Murphy wrote:
 "Tofu Ninja"  wrote in message 
 news:dtjqnyucskwnqjvksawg forum.dlang.org...

 Question?
 If an if condition throws or returns in its body is it ok for 
 the optimizer to 'assume' that the condition is false after 
 and make optimizations for it? If so then every one 
 complaining that assert gets removed in -release should really 
 just be using enforce.
Yes. In fact, it's required that an optimizer do this in order not to be considered garbage.
 The possibility for the optimizer to make the same 
 optimizations for assert can be done for enforce, the only 
 difference is that it does not get removed in -release....
Not quite. With enforce, it is impossible (ignoring hardware or optimizer errors) for the condition to be false if the enforce was not triggered. Because the assert is not checked, the condition could be false and the code could do something awful. Also, the optimizer can only use the enforce's assumption _after_ it has checked the condition. Since with assert it doesn't need to check, it can go backwards and assume the previous code will never produce a value that can violate the assertion. if (y > 7) // x can't possibly be >= 5, so this can't be true x = y + 1; assert(x < 5); if (y > 7) // the program will throw if >= 5, but that doesn't mean it can't be true x = y + 1; enforce(x < 5); Assert is much much more powerful.
Ok so what is sounds like, is that assert is really what every one claims assume is and enforce is what every one claims assert is... Maybe a documentation change on assert is all that is needed, it seems like the docs describe assert as something similar to enforce. Maybe it should be described in a way similar to assume with the added benefit that in non-release modes it will actually check that it is true at runtime. Also if that was changed then the documentation on version(assert) would need changing too.
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Tofu Ninja"  wrote in message news:nwudcquzsuyrrlawxxyu forum.dlang.org...

 Ok so what is sounds like, is that assert is really what every one claims 
 assume is and enforce is what every one claims assert is...
Does it actually check the condition is true? theoretical assert: in debug mode D's assert: in debug mode assume: no enforce: always Does it allow the compiler to remove code using normal control-flow analysis? theoretical assert: in debug mode D's assert: always assume: always enforce: always Does it allow the compiler to remove any code that disagrees with the condition? (or is unnecessary when the condition is true?) theoretical assert: no D's assert: in release mode assume: always enforce: no
 Maybe a documentation change on assert is all that is needed, it seems 
 like the docs describe assert as something similar to enforce. Maybe it 
 should be described in a way similar to assume with the added benefit that 
 in non-release modes it will actually check that it is true at runtime. 
 Also if that was changed then the documentation on version(assert) would 
 need changing too.
Yeah, it would probably be a good idea to make it very clear what the compiler is allowed to assume. The current docs are somewhat accurate, but could be more specific. If the 'assume' behaviour is possible with forms other than 'assert(0)' is not specified.
Jul 30 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 30 July 2014 at 15:49:33 UTC, Daniel Murphy wrote:
 "Tofu Ninja"  wrote in message 
 news:dtjqnyucskwnqjvksawg forum.dlang.org...

 Question?
 If an if condition throws or returns in its body is it ok for 
 the optimizer to 'assume' that the condition is false after 
 and make optimizations for it? If so then every one 
 complaining that assert gets removed in -release should really 
 just be using enforce.
Yes. In fact, it's required that an optimizer do this in order not to be considered garbage.
 The possibility for the optimizer to make the same 
 optimizations for assert can be done for enforce, the only 
 difference is that it does not get removed in -release....
Not quite. With enforce, it is impossible (ignoring hardware or optimizer errors) for the condition to be false if the enforce was not triggered. Because the assert is not checked, the condition could be false and the code could do something awful. Also, the optimizer can only use the enforce's assumption _after_ it has checked the condition. Since with assert it doesn't need to check, it can go backwards and assume the previous code will never produce a value that can violate the assertion. if (y > 7) // x can't possibly be >= 5, so this can't be true x = y + 1; assert(x < 5); if (y > 7) // the program will throw if >= 5, but that doesn't mean it can't be true x = y + 1; enforce(x < 5); Assert is much much more powerful.
So what is the recommended way of inserting a check of the sort that Ola would like? debug enforce(expr); perhaps? Seeing as that statement is completely missing outside of debug mode, the compiler can't do anything much about it. P.S. What about version(assert)? Could the optimiser work with this: if(x > 7) x++; version(assert) auto testResult = x; assert(x <= 7);
Jul 30 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 30 July 2014 at 16:25:41 UTC, John Colvin wrote:
 On Wednesday, 30 July 2014 at 15:49:33 UTC, Daniel Murphy wrote:
 "Tofu Ninja"  wrote in message 
 news:dtjqnyucskwnqjvksawg forum.dlang.org...

 Question?
 If an if condition throws or returns in its body is it ok for 
 the optimizer to 'assume' that the condition is false after 
 and make optimizations for it? If so then every one 
 complaining that assert gets removed in -release should 
 really just be using enforce.
Yes. In fact, it's required that an optimizer do this in order not to be considered garbage.
 The possibility for the optimizer to make the same 
 optimizations for assert can be done for enforce, the only 
 difference is that it does not get removed in -release....
Not quite. With enforce, it is impossible (ignoring hardware or optimizer errors) for the condition to be false if the enforce was not triggered. Because the assert is not checked, the condition could be false and the code could do something awful. Also, the optimizer can only use the enforce's assumption _after_ it has checked the condition. Since with assert it doesn't need to check, it can go backwards and assume the previous code will never produce a value that can violate the assertion. if (y > 7) // x can't possibly be >= 5, so this can't be true x = y + 1; assert(x < 5); if (y > 7) // the program will throw if >= 5, but that doesn't mean it can't be true x = y + 1; enforce(x < 5); Assert is much much more powerful.
So what is the recommended way of inserting a check of the sort that Ola would like? debug enforce(expr); perhaps? Seeing as that statement is completely missing outside of debug mode, the compiler can't do anything much about it. P.S. What about version(assert)? Could the optimiser work with this: if(x > 7) x++; version(assert) auto testResult = x; assert(x <= 7);
ugh, I made a mess of that one. Should be if(x > 7) x++; version(assert) auto testResult = x; assert(testResult <= 7);
Jul 30 2014
prev sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"John Colvin"  wrote in message news:mmnpehpddzkduycydcnh forum.dlang.org...

 So what is the recommended way of inserting a check of the sort that Ola 
 would like?

 debug enforce(expr);

 perhaps? Seeing as that statement is completely missing outside of debug 
 mode, the compiler can't do anything much about it.
Don't use -release.
 P.S. What about version(assert)? Could the optimiser work with this:

 if(x > 7) x++;
 version(assert) auto testResult = x;
 assert(x <= 7);
No, version(assert) is just about doing introspection on the compiler's configuration. In release mode that code doesn't even get semantically analysed.
Jul 30 2014
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 06:43 PM, Daniel Murphy wrote:
 "John Colvin"  wrote in message
 news:mmnpehpddzkduycydcnh forum.dlang.org...

 So what is the recommended way of inserting a check of the sort that
 Ola would like?

 debug enforce(expr);

 perhaps? Seeing as that statement is completely missing outside of
 debug mode, the compiler can't do anything much about it.
Don't use -release.
 P.S. What about version(assert)? Could the optimiser work with this:

 if(x > 7) x++;
 version(assert) auto testResult = x;
 assert(x <= 7);
No, version(assert) is just about doing introspection on the compiler's configuration. In release mode that code doesn't even get semantically analysed.
Isn't this also true for assert statements?
Jul 30 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 07:00 PM, Timon Gehr wrote:
 ...

 Isn't this also true for assert statements?
s/statement/expression
Jul 30 2014
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb8bp$428$2 digitalmars.com... 

 No, version(assert) is just about doing introspection on the compiler's
 configuration.  In release mode that code doesn't even get semantically
 analysed.
Isn't this also true for assert statements?
No.
Jul 30 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 30 July 2014 at 16:43:47 UTC, Daniel Murphy wrote:
 "John Colvin"  wrote in message 
 news:mmnpehpddzkduycydcnh forum.dlang.org...

 So what is the recommended way of inserting a check of the 
 sort that Ola would like?

 debug enforce(expr);

 perhaps? Seeing as that statement is completely missing 
 outside of debug mode, the compiler can't do anything much 
 about it.
Don't use -release.
haha yeah, or that!
 P.S. What about version(assert)? Could the optimiser work with 
 this:

 if(x > 7) x++;
 version(assert) auto testResult = x;
 assert(x <= 7);
No, version(assert) is just about doing introspection on the compiler's configuration. In release mode that code doesn't even get semantically analysed.
pity.
Jul 30 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 08:06 PM, John Colvin wrote:
 P.S. What about version(assert)? Could the optimiser work with this:

 if(x > 7) x++;
 version(assert) auto testResult = x;
 assert(x <= 7);
No, version(assert) is just about doing introspection on the compiler's configuration. In release mode that code doesn't even get semantically analysed.
pity.
assert({ ... }());
Jul 30 2014
prev sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"John Colvin"  wrote in message news:oyzjykmvgzdzkprzujzx forum.dlang.org...

 Don't use -release.
haha yeah, or that!
debug enforce(...) would also work just fine. It depends if you're happy with leaving bounds checking enabled, if you want fine-grained control over which checks get enabled, if your code needs to be nothrow, etc I often write quick scripts that rely on bounds checking and assertions to reject incorrect command line args. While this is technically an abuse of assert, it doesn't matter because I never use -release on them.
Jul 30 2014
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 30 July 2014 at 18:23:06 UTC, Daniel Murphy wrote:
 "John Colvin"  wrote in message 
 news:oyzjykmvgzdzkprzujzx forum.dlang.org...

 Don't use -release.
haha yeah, or that!
debug enforce(...) would also work just fine. It depends if you're happy with leaving bounds checking enabled, if you want fine-grained control over which checks get enabled, if your code needs to be nothrow, etc I often write quick scripts that rely on bounds checking and assertions to reject incorrect command line args. While this is technically an abuse of assert, it doesn't matter because I never use -release on them.
version(assert) {} else static assert("This module needs it's assertions"); version(D_NoBoundsChecks) static assert("This module needs it's bounds checking");
Jul 31 2014
prev sibling next sibling parent "David Bregman" <drb sfu.ca> writes:
On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu 
wrote:
 If assert degenerates to assume in release mode, any bugs in 
 the program
 could potentially cause a lot more brittleness and 
 unexpected/undefined
 behavior than they otherwise would have. In particular, code 
 generation
 based on invalid assumptions could be memory unsafe.
I think gcc does that.
It makes more sense in C because it's not memory safe anyways. In D, assume would not be safe, so to have asserts become assumes in release mode seems problematic. Perhaps the assume could be omitted in safe code, similar to how bounds checks are retained for safe code even in release.
 Also, it's unclear to me what the optimizer would be supposed 
 to do if an assumption turns out to be false.
One example is a switch statement, if we hint to the compiler (via assume) that the default case is unreachable, the compiler can potentially generate something like a jump table with no bounds check. To generate memory safe code, the compiler needs to insert the bounds check even though the assume says it's not needed.
Jul 30 2014
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 7:51 AM, Andrei Alexandrescu wrote:
 Also, it's unclear to me what the optimizer would be supposed to do if an
 assumption turns out to be false.
The program is no longer valid at that point.
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 9:20 AM, Walter Bright wrote:
 On 7/30/2014 7:51 AM, Andrei Alexandrescu wrote:
 Also, it's unclear to me what the optimizer would be supposed to do if an
 assumption turns out to be false.
The program is no longer valid at that point.
So then: assert == assume assert === assume (per proposed notation) assert is assume assert <= assume assume <= assert assert.opEquals(assume) assert.opCmp(assume) == 0 Andrei
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 07:46 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:20 AM, Walter Bright wrote:
 On 7/30/2014 7:51 AM, Andrei Alexandrescu wrote:
 Also, it's unclear to me what the optimizer would be supposed to do
 if an
 assumption turns out to be false.
The program is no longer valid at that point.
So then: assert == assume assert === assume (per proposed notation) assert is assume assert <= assume assume <= assert assert.opEquals(assume) assert.opCmp(assume) == 0 Andrei
You seem to be close to enlightenment: http://www.madore.org/~david/zen/#conc.dualism
Jul 30 2014
prev sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/30/14 05:32, Walter Bright via Digitalmars-d wrote:
 
 I still have no idea what the difference between assume(i<6) and assert(i<6)
is supposed to be.
if (!(i<6)) assert(0); // With the difference that this `assert(0)` could be omitted. vs assert(i<6); You've been suggesting exposing the assert condition and giving it meaning other than just a harmless debugging check. That would be very dangerous; a wrong assert could change perfectly fine code into a buggy and unsafe one. This is not a theoretical issue: bool plain_assert(int i) { assert(i<6); return i==9; } bool assert_abused_as_assume(int i) { if (!(i<6)) assert(0); return i==9; } The second function is already compiled into the equivalent of `return false;`. (The assert isn't removed, but that's only because of the `assert(0)` special case; for true asserts it would be) `assert` is for *verifying* assumptions. It must not allow them to leak/escape. Otherwise a single not-100%-correct assert could defeat critical runtime checks. 'assume' would be useful, but dangerous, like a reinterpret cast; it would need to be trusted. artur
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Artur Skawina via Digitalmars-d"  wrote in message 
news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Jul 30 2014
next sibling parent reply Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 07/30/14 13:56, Daniel Murphy via Digitalmars-d wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...
 
 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names,
"D - the language that redefines commonly used and universally understood terms and concepts"?
 not that it can't work the way Walter and I have described.
Possible != sane. The main problem isn't even the terminology; it's the consequences wrt safety and correctness.
  If your assertions are invalid and you're compiling with -release, the
compiler is free to generate invalid code.  -release is dangerous.  -release is
telling the compiler that the code you wrote is correct,  and it can rely on it
to be correct.
Consider a service/program that handles user supplied data. It uses several third-party libs, one for parsing and validating the inputs, another for some other processing/communication, etc. One is carefully written with security in mind and can safely deal with every possible valid or invalid input. Another was not considered security sensitive and designed to work on valid data. The input requirements are just documented and only checked via asserts. Now the programmer implementing that service only needs to make a single mistake, so that an invalid (or just unexpected) input is passed to the less hardened lib. In a production setting the asserts are not present, but the assumptions have leaked to the other libs, and some of the carefully written checks have been statically eliminated by the compiler. Code that was perfectly safe gained an invisible (!) security hole, because of an innocent looking assert statement in a different code base. artur
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Artur Skawina via Digitalmars-d"  wrote in message 
news:mailman.227.1406728603.16021.digitalmars-d puremagic.com...

 "D - the language that redefines commonly used and universally
 understood terms and concepts"?
Yes, see pure for another example. "D - the pragmatic language"
 not that it can't work the way Walter and I have described.
Possible != sane. The main problem isn't even the terminology; it's the consequences wrt safety and correctness.
Yes, this is a much more useful discussion to have than what other people have definined assert to do.
 Consider a service/program that handles user supplied data. It
 uses several third-party libs, one for parsing and validating the
 inputs, another for some other processing/communication, etc.
 One is carefully written with security in mind and can safely
 deal with every possible valid or invalid input. Another was not
 considered security sensitive and designed to work on valid data.
 The input requirements are just documented and only checked via
 asserts. Now the programmer implementing that service only needs
 to make a single mistake, so that an invalid (or just unexpected)
 input is passed to the less hardened lib. In a production setting
 the asserts are not present, but the assumptions have leaked to
 the other libs, and some of the carefully written checks have been
 statically eliminated by the compiler. Code that was perfectly safe
 gained an invisible (!) security hole, because of an innocent
 looking assert statement in a different code base.
Yes, it is a very powerful and dangerous optimization capability. If the optimization benefits are not worth the potential escalation of code wrong-ness, then don't enable it. If security is more important than speed, don't disable assertion and bounds checks. If used wrong it will do the wrong thing. This is already true of compiler optimizations. The optimizer may turn invalid code into security problems - have a google around and you'll find some examples.
Jul 30 2014
next sibling parent reply "Wyatt" <wyatt.epp gmail.com> writes:
On Wednesday, 30 July 2014 at 14:11:24 UTC, Daniel Murphy wrote:
 If used wrong it will do the wrong thing.  This is already true 
 of compiler optimizations.  The optimizer may turn invalid code 
 into security problems - have a google around and you'll find 
 some examples.
I think the point here is that usually, when the optimiser changes the semantics of valid code, it's considered a bug in the optimiser. -Wyatt
Jul 30 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Wyatt"  wrote in message news:wpyvrdoofziktwqkzqbf forum.dlang.org...

 I think the point here is that usually, when the optimiser changes the 
 semantics of valid code, it's considered a bug in the optimiser.
s/usually/always/ The thing is, code containing an assertion that is not always true is not valid code.
Jul 30 2014
parent reply "Wyatt" <wyatt.epp gmail.com> writes:
On Wednesday, 30 July 2014 at 14:46:20 UTC, Daniel Murphy wrote:
 "Wyatt"  wrote in message 
 news:wpyvrdoofziktwqkzqbf forum.dlang.org...

 I think the point here is that usually, when the optimiser 
 changes the semantics of valid code, it's considered a bug in 
 the optimiser.
s/usually/always/ The thing is, code containing an assertion that is not always true is not valid code.
Seeing this response, my Ordinary Programmer Brain says, "Well yeah, of course it's not valid once you remove the assertion; you've fundamentally changed the meaning of the whole thing! If it were fine to remove the assertion, I wouldn't have used it in the first place." Something (possibly the thing where "For fastest executables, compile with the -O -release -inline -boundscheck=off" is standard advice to anyone asking about performance) tells me this point needs to be made MUCH more clear wherever possible or the ghost of Scott Meyers will haunt us all. But that it's even a problem tells me we're facing a pattern of human error. Is there no good way to eliminate it? It seems pretty clear that there's a class of runtime check that is for debugging only that can be eliminated because you believe the code will never be used for evil; and there's a class of check where, no matter what, if some condition isn't met the application should immediately halt and catch fire lest it do something horrible. Additionally raised in this thread is a class of expression that's only evaluated at compile time for the sake of making optimisations where you're saying "It's all right, I made sure this is good, go to town". The distinction between the former two things in D apparently comes down to whether you put your assert() as its own expression or as the ThenStatement of an IfStatement, while the latter has been conflated into the first. That there's prior art regarding the terminology and semantics only confuses the issue further. Incidentally, this conversation actually forced me to look into the semantics of assert() in C and C++, and it turns out it's moderately muddy, but it seems they're only eliminated if you #define NDEBUG? -Wyatt
Jul 30 2014
next sibling parent "KoKuToru" <kokutoru gmail.com> writes:
On Wednesday, 30 July 2014 at 18:18:24 UTC, Wyatt wrote:
Incidentally, this conversation actually forced
 me to look into the semantics of assert() in C and C++, and it 
 turns out it's moderately muddy, but it seems they're only 
 eliminated if you #define NDEBUG?
Building CMake-Projects with DCMAKE_BUILD_TYPE=Release, will set -DNDEBUG and therefore disable asserts. As C++ programmer, I can't understand how somebody would want to have assert in his release-build. "Therefore, this macro is designed to capture programming errors, not user or run-time errors, since it is generally disabled after a program exits its debugging phase." http://www.cplusplus.com/reference/cassert/assert/
Jul 30 2014
prev sibling next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Wyatt"  wrote in message news:duoyilszsehayiffprls forum.dlang.org...

 Something (possibly the thing where "For fastest executables, compile with 
 the -O -release -inline -boundscheck=off" is standard advice to anyone 
 asking about performance) tells me this point needs to be made MUCH more 
 clear wherever possible or the ghost of Scott Meyers will haunt us all. 
 But that it's even a problem tells me we're facing a pattern of human 
 error.  Is there no good way to eliminate it?
Well, that will give you the fastest possible code. But there is no guarantee that small mistakes won't blow up in your face. It could be hidden behind another compiler switch (-release is really a terrible name, maybe -livefastdieyoung ? -noparachute ? -drinkthemysteyliquidreadthelabellater ?) but chances are it will be abused no matter what.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 08:39 PM, Daniel Murphy wrote:
 "Wyatt"  wrote in message news:duoyilszsehayiffprls forum.dlang.org...

 Something (possibly the thing where "For fastest executables, compile
 with the -O -release -inline -boundscheck=off" is standard advice to
 anyone asking about performance) tells me this point needs to be made
 MUCH more clear wherever possible or the ghost of Scott Meyers will
 haunt us all. But that it's even a problem tells me we're facing a
 pattern of human error.  Is there no good way to eliminate it?
Well, that will give you the fastest possible code. But there is no guarantee that small mistakes won't blow up in your face. It could be hidden behind another compiler switch (-release is really a terrible name, maybe -livefastdieyoung ? -noparachute ? -drinkthemysteyliquidreadthelabellater ?) but chances are it will be abused no matter what.
On 07/30/2014 08:42 PM, Daniel Murphy wrote:> "Dicebot" wrote in message news:kvxcdcbgjwyydrjgbijg forum.dlang.org...
 At the same time "release" is rather encouraging flag to use, it is
 not like it is called "-iamreadyfortheconsequences".
-idontcareificrashsolongasicrashfast
Maybe we should rename all D keywords in this distinctive style.
Jul 30 2014
prev sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jul 30, 2014 at 06:18:22PM +0000, Wyatt via Digitalmars-d wrote:
[...]
 It seems pretty clear that there's a class of runtime check that is
 for debugging only that can be eliminated because you believe the code
 will never be used for evil;
assert(...)
 and there's a class of check where, no matter what, if some condition
 isn't met the application should immediately halt and catch fire lest
 it do something horrible.
enforce(...)
 Additionally raised in this thread is a class of expression that's
 only evaluated at compile time for the sake of making optimisations
 where you're saying "It's all right, I made sure this is good, go to
 town".
[...] The proposal is to fold this meaning into assert() as well. I see no harm in doing this, because: 1) When compiling in non-release mode: assert(...) means "I believe condition X holds, if it doesn't I screwed up big time, my program should abort" assume(...) means as "I believe condition X holds, if it doesn't I screwed up big time, my program should abort" 2) When compiling in release/optimized mode: assert(...) means "Trust me, I've made sure condition X holds, please optimize my code by not bothering to check condition X again" assume(...) means "Trust me, I've made sure condition X holds, please optimize my code by making use of condition X" Certainly, making assert==assume extends the current meaning of assert in (2), but I don't see the incompatibility. In both cases under (2) we are *assuming*, without proof or check, that X holds, and based on that we are making some optimizations of the generated code. I can't think of a real-life scenario where you'd want to distinguish between the two kinds of optimizations in (2). Sure, in theory there's a conceptual distinction between the two cases, but I don't see what difference this makes in practice. It's splitting hairs over philosophical issues that ultimately don't matter in practice. T -- Век живи - век учись. А дураком помрёшь.
Jul 30 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 08:46 PM, H. S. Teoh via Digitalmars-d wrote:
 I can't think of a real-life scenario where you'd want to distinguish
 between the two kinds of optimizations in (2).
That was never up to debate and that distinction is indeed rather pointless.
Jul 30 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 30 July 2014 at 18:48:21 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 1) When compiling in non-release mode:
 	assert(...) means "I believe condition X holds, if it doesn't I
 		screwed up big time, my program should abort"
Assert(X) means, the specification requires theorem X to be proved by all implicit or explicit axioms/assumptions made prior to this either implicitly or explicitly.
 	assume(...) means as "I believe condition X holds, if it 
 doesn't
 		I screwed up big time, my program should abort"
Assume(X) means, the specification specifies (axiom) X (to hold).
 2) When compiling in release/optimized mode:
 	assert(...) means "Trust me, I've made sure condition X holds,
 		please optimize my code by not bothering to check
 		condition X again"
No. Assert(X) does not change any meaning. You just turned off program verification. Assumes and asserts are annotations.
 	assume(...) means "Trust me, I've made sure condition X holds,
 		please optimize my code by making use of condition X"
Assume(X) means that the specification defines X to hold at this point.
 in (2), but I don't see the incompatibility. In both cases 
 under (2) we
 are *assuming*, without proof or check, that X holds, and based 
 on that
 we are making some optimizations of the generated code.
Not really. Most of the assumes are implicit in the code. What you specify with assume are just additional axioms required by the specification in order to prove the assertions. (e.g. the ones not embedded implicitly in the code).
 I can't think of a real-life scenario where you'd want to 
 distinguish
 between the two kinds of optimizations in (2).
The difference is that "assume(X)" (or require) are the specified preconditions. It does not make the program incorrect per definition. However you don't want your program littered with preconditions. So yes, you CAN optimize based on assume() since those are restrictions the environment put on the input. But you only have a few of those.
Jul 30 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 04:11 PM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.227.1406728603.16021.digitalmars-d puremagic.com...

 "D - the language that redefines commonly used and universally
 understood terms and concepts"?
Yes, see pure for another example. "D - the pragmatic language" ...
I don't think it is a posteriori justified by pragmatism, or that this is even a way to increase conceived or actual pragmatism.
 not that it can't work the way Walter and I have described.
Possible != sane. The main problem isn't even the terminology; it's the consequences wrt safety and correctness.
Yes, this is a much more useful discussion to have than what other people have definined assert to do.
My impression has been: This is the discussion Ola wanted to have in the first place. He defined all the terminology he was using, and the distinction was relevant, because it actually captured the 'consequences wrt safety and correctness'. Then his terminology was picked up as a convenient vector for 'attack' and his point was ignored.
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb7qp$3q5$1 digitalmars.com...

 Yes, this is a much more useful discussion to have than what other
 people have definined assert to do.
My impression has been: This is the discussion Ola wanted to have in the first place.
Yes, I'm sure it was.
 He defined all the terminology he was using, and the distinction was 
 relevant, because it actually captured the 'consequences wrt safety and 
 correctness'.
He provided a different definition of assert. This certainly helped to show where he was arguing from, but...
 Then his terminology was picked up as a convenient vector for 'attack' and 
 his point was ignored.
... the fact that D's assert does not match another definition of assert, despite using the same name, is not an argument against the definition of D's assert. The fact that it's unsafe is not contested. The point is the optimization is reasonable within D's rules wrt assert and -release.
Jul 30 2014
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 05:04 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
This just moves the issue around and gives another term a non-obvious meaning (the 'release' switch, which is not called e.g. 'unsafeAssumeCorrect'. Which is still confusing, because it purports to keep memory safety intact in safe code by not disabling array bounds checks by default). This is the very topic of this discussion: some people get confused when they are assumed to use standard terms with non-standard meanings. I was objecting to the apparent attitude that this is entirely the fault of the one who gets confused, or that it is symptomatic for lack of understanding of concepts. I mean, we have at least: some terms with whacky meanings for an outsider: 'release' which does not relate to a released code version and which is not in contrast to 'debug'. 'const' which does not relate to being a constant. 'enum' which does not denote enumeration in many contexts where it is used. 'in' which does not only check for membership but rather returns a pointer to that member. 'lazy', which denotes pass by name instead of pass by need. 'pure' which denies access to mutable static variables and IO. ... (some more easily debatable ones removed) some terms with inconsistent meanings: 'alias': alias declarations and alias parameters are notably distinct: while I can alias a built-in type to a symbol, I cannot pass it by alias. The following fails: template T(alias a){ enum T=2; } pragma(msg, T!string); (Before debate ensues: I am completely aware of what each of the above actually mean and do.) To me, the apt response to a relative newcomer who gets confused by one of those or something like them, especially when used without quotation marks, is not at all similar to "You're misunderstanding and misusing this feature, stop making noise."
Jul 30 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Timon Gehr"  wrote in message news:lrb6lf$2tf$1 digitalmars.com...

 I mean, we have at least:
 <list>
You forgot 'float', which has nothing to do with levitation. This is all true, yet we have to pick names for things. We could call D's purity 'flarwurghle', but is that really better? D's purity is much more closely related to other concepts of purity than it is to flarwurghling. And don't forget int, which is not actually an integer.
 To me, the apt response to a relative newcomer who gets confused by one of 
 those or something like them, especially when used without quotation 
 marks, is not at all similar to "You're misunderstanding and misusing this 
 feature, stop making noise."
No, but that is the similar to the correct response when somebody repeatedly argues that you've defined something wrong because somebody else defined it differently. The discussion on how we _should_ define it is much more interesting, and ideally the other one would not come up at all.
Jul 30 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 06:55 PM, Daniel Murphy wrote:
 "Timon Gehr"  wrote in message news:lrb6lf$2tf$1 digitalmars.com...

 I mean, we have at least:
 <list>
You forgot 'float', which has nothing to do with levitation. ...
:D
 This is all true, yet we have to pick names for things.  We could call
 D's purity 'flarwurghle', but is that really better?  D's purity is much
 more closely related to other concepts of purity than it is to
 flarwurghling.
 ...
'flarwurghle' indeed seems a little bit off too.
 And don't forget int, which is not actually an integer.
 ...
I didn't, I though that one was too debatable to bring up because it already has become to be standard in some notable existing programming languages. :)
 To me, the apt response to a relative newcomer who gets confused by
 one of those or something like them, especially when used without
 quotation marks, is not at all similar to "You're misunderstanding and
 misusing this feature, stop making noise."
No, but that is the similar to the correct response when somebody repeatedly argues that you've defined something wrong because somebody else defined it differently. ...
I must have missed that.
 The discussion on how we _should_ define it is much more interesting,
 and ideally the other one would not come up at all.
Agreed.
Jul 30 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 9:31 AM, Timon Gehr wrote:
 On 07/30/2014 05:04 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
This just moves the issue around and gives another term a non-obvious meaning (the 'release' switch, which is not called e.g. 'unsafeAssumeCorrect'.
Well to me "-release" is "I assume my program is correct, generate the fastest code for it".
 Which is still confusing, because it purports to
 keep memory safety intact in  safe code by not disabling array bounds
 checks by default). This is the very topic of this discussion: some
 people get confused when they are assumed to use standard terms with
 non-standard meanings. I was objecting to the apparent attitude that
 this is entirely the fault of the one who gets confused, or that it is
 symptomatic for lack of understanding of concepts.
I'm not sure what would be the standard misused term in this case.
 I mean, we have at least:

 some terms with whacky meanings for an outsider:
 'release' which does not relate to a released code version and which is
 not in contrast to 'debug'.
Yeah, it's a sensible point. I don't like that either, but it's a minor annoyance at most.
 'const' which does not relate to being a constant.
"Like C++ const, but transitive".
 'enum' which does not denote enumeration in many contexts where it is used.
Sensible point, but in our use at Facebook I noticed engineers picking it up without a hitch.
 'in' which does not only check for membership but rather returns a
 pointer to that member.
It's conveniently terse.
 'lazy', which denotes pass by name instead of pass by need.
It's not pass by name.
 'pure' which denies access to mutable static variables and IO.
That's the consequence of functional purity as defined by D. I see nothing wrong with it.
 ... (some more easily debatable ones removed)


 some terms with inconsistent meanings:
 'alias': alias declarations and alias parameters are notably distinct:
 while I can alias a built-in type to a symbol, I cannot pass it by
 alias. The following fails:

 template T(alias a){ enum T=2; }
 pragma(msg, T!string);
Agreed.
 (Before debate ensues: I am completely aware of what each of the above
 actually mean and do.)
I think you got a point there but if you searched any programming language in its pockets you're liable to find a bunch of similar lint. It's the way it goes - there's a need to maximize expressiveness while keeping vocabulary and grammatical constructs low. Few of these items are near the top of my list of issues in D, and I think the same goes for your list.
 To me, the apt response to a relative newcomer who gets confused by one
 of those or something like them, especially when used without quotation
 marks, is not at all similar to "You're misunderstanding and misusing
 this feature, stop making noise."
Consider this: after considerable effort you are failing to explain your case for "assume" to the language creators. How do you think you'll fare with newcomers? Andrei
Jul 30 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 30 July 2014 at 17:57:04 UTC, Andrei Alexandrescu 
wrote:
 "I assume my program is correct, generate the fastest code for 
 it".
Sounds like description for a command that should trigger "You are fired" e-mail notification.
Jul 30 2014
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Wednesday, 30 July 2014 at 17:58:45 UTC, Dicebot wrote:
 On Wednesday, 30 July 2014 at 17:57:04 UTC, Andrei Alexandrescu 
 wrote:
 "I assume my program is correct, generate the fastest code for 
 it".
Sounds like description for a command that should trigger "You are fired" e-mail notification.
Totally depends on the situation. If you write a SAT solver you can make that assumptions without problems and just verify your results afterwards with a (way simpler) program that was compiled without -release.
Jul 30 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 30 July 2014 at 18:02:39 UTC, Tobias Pankrath wrote:
 On Wednesday, 30 July 2014 at 17:58:45 UTC, Dicebot wrote:
 On Wednesday, 30 July 2014 at 17:57:04 UTC, Andrei 
 Alexandrescu wrote:
 "I assume my program is correct, generate the fastest code 
 for it".
Sounds like description for a command that should trigger "You are fired" e-mail notification.
Totally depends on the situation. If you write a SAT solver you can make that assumptions without problems and just verify your results afterwards with a (way simpler) program that was compiled without -release.
It doesn't feel to me like SAT solvers are most common D programs out there, at least not more common than various network/web services. For pretty much any program which is not completely self-contained idea that it can be totally correct at any given point of time sounds like disaster. At the same time "release" is rather encouraging flag to use, it is not like it is called "-iamreadyfortheconsequences".
Jul 30 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Dicebot"  wrote in message news:kvxcdcbgjwyydrjgbijg forum.dlang.org... 

 At the same time "release" is rather encouraging flag to use, it 
 is not like it is called "-iamreadyfortheconsequences".
-idontcareificrashsolongasicrashfast
Jul 30 2014
prev sibling next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/30/14, 2:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 On 07/30/2014 05:04 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
This just moves the issue around and gives another term a non-obvious meaning (the 'release' switch, which is not called e.g. 'unsafeAssumeCorrect'.
Well to me "-release" is "I assume my program is correct, generate the fastest code for it".
I tried the program in debug mode in thousands of ways and apparently no assert triggers. So I'll just compile in release mode, release it and let anyone find bugs in it and allow to bypass any security or safety I put in my program with those "assert" statmenets, that would probably just take 1 nanosecond to execute anyway. Sounds really nice. (sorry for the sarcasm, removing assert is wrong to me)
Jul 30 2014
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 11:13 AM, Ary Borenszweig wrote:
 On 7/30/14, 2:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 On 07/30/2014 05:04 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
This just moves the issue around and gives another term a non-obvious meaning (the 'release' switch, which is not called e.g. 'unsafeAssumeCorrect'.
Well to me "-release" is "I assume my program is correct, generate the fastest code for it".
I tried the program in debug mode in thousands of ways and apparently no assert triggers. So I'll just compile in release mode, release it and let anyone find bugs in it and allow to bypass any security or safety I put in my program with those "assert" statmenets, that would probably just take 1 nanosecond to execute anyway. Sounds really nice. (sorry for the sarcasm, removing assert is wrong to me)
Sometimes it's wrong sometimes it's required. I think there is an understanding that sometimes every extra bit of speed is necessary. We wouldn't imagine deploying hhvm with assertions enabled. Andrei
Jul 30 2014
prev sibling next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jul 30, 2014 at 03:13:06PM -0300, Ary Borenszweig via Digitalmars-d
wrote:
 On 7/30/14, 2:56 PM, Andrei Alexandrescu wrote:
[...]
Well to me "-release" is "I assume my program is correct, generate
the fastest code for it".
I tried the program in debug mode in thousands of ways and apparently no assert triggers. So I'll just compile in release mode, release it and let anyone find bugs in it and allow to bypass any security or safety I put in my program with those "assert" statmenets, that would probably just take 1 nanosecond to execute anyway. Sounds really nice. (sorry for the sarcasm, removing assert is wrong to me)
If you want the check to always be there, use enforce, not assert. T -- Без труда не выловишь и рыбку из пруда.
Jul 30 2014
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 11:24 AM, H. S. Teoh via Digitalmars-d wrote:
 If you want the check to always be there, use enforce, not assert.
enforce is NOT for checking program logic bugs, it is for checking for possible environmental failures, like writing to a read-only file. If you want an assert to be there even in release mode, assert(exp) => exp || assert(0)
Jul 30 2014
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Walter Bright"  wrote in message news:lrbes7$9gs$1 digitalmars.com...

 enforce is NOT for checking program logic bugs, it is for checking for 
 possible environmental failures, like writing to a read-only file.

 If you want an assert to be there even in release mode,

      assert(exp) => exp || assert(0)
As I said earlier, this is valid by what dmd currently implements, but not according to the spec. The spec does not guarantee assert(0) checks will always be emitted.
Jul 30 2014
prev sibling parent "w0rp" <devw0rp gmail.com> writes:
To release software is to assume that it is correct.
Jul 30 2014
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 30 July 2014 at 18:25:43 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 If you want the check to always be there, use enforce, not 
 assert.
Doesn't help: module a; void bar(int x) { assert(x > 0); writeln("x = ", x); } // -------- module b; import a; void foo(int x) { enforce(x > 0); bar(x); } If `assert` is treated like `assume` (under Ola's definitions), then `enforce` can be optimized away.
Jul 30 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jul 30, 2014 at 07:09:41PM +0000, via Digitalmars-d wrote:
 On Wednesday, 30 July 2014 at 18:25:43 UTC, H. S. Teoh via Digitalmars-d
 wrote:
If you want the check to always be there, use enforce, not assert.
Doesn't help: module a; void bar(int x) { assert(x > 0); writeln("x = ", x); } // -------- module b; import a; void foo(int x) { enforce(x > 0); bar(x); } If `assert` is treated like `assume` (under Ola's definitions), then `enforce` can be optimized away.
Wait, what? I thought the whole point of enforce is that it will *not* be removed by the compiler, no matter what? T -- Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
Jul 30 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 09:16 PM, H. S. Teoh via Digitalmars-d wrote:
 On Wed, Jul 30, 2014 at 07:09:41PM +0000, via Digitalmars-d wrote:
 On Wednesday, 30 July 2014 at 18:25:43 UTC, H. S. Teoh via Digitalmars-d
 wrote:
 If you want the check to always be there, use enforce, not assert.
Doesn't help: module a; void bar(int x) { assert(x > 0); writeln("x = ", x); } // -------- module b; import a; void foo(int x) { enforce(x > 0); bar(x); } If `assert` is treated like `assume` (under Ola's definitions), then `enforce` can be optimized away.
Wait, what? I thought the whole point of enforce is that it will *not* be removed by the compiler, no matter what? T
That's approximately the crux of the matter, yes. :-)
Jul 30 2014
prev sibling next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"H. S. Teoh via Digitalmars-d"  wrote in message 
news:mailman.255.1406747871.16021.digitalmars-d puremagic.com...

 Wait, what? I thought the whole point of enforce is that it will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Jul 31 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Daniel Murphy"  wrote in message news:lrct2d$1me8$1 digitalmars.com...

 Wait, what? I thought the whole point of enforce is that it will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Actually, thinking about this some more... In this program the enforce can be removed assert(x < y); enforce(x < y); But not in this one: enforce(x < y); assert(x < y); because the compiler does need to take control flow into account when applying the information in the assert. In this case the assert does not actually give the compiler any new information.
Jul 31 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 31 July 2014 at 08:23:44 UTC, Daniel Murphy wrote:
 "Daniel Murphy"  wrote in message 
 news:lrct2d$1me8$1 digitalmars.com...

 Wait, what? I thought the whole point of enforce is that it 
 will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Actually, thinking about this some more... In this program the enforce can be removed assert(x < y); enforce(x < y); But not in this one: enforce(x < y); assert(x < y); because the compiler does need to take control flow into account when applying the information in the assert. In this case the assert does not actually give the compiler any new information.
Wait what? Now I'm confused. x < y is guaranteed at point B (the assert). x and y are unchanged between point A (the enforce) and point B. Therefore, x < y is guaranteed at point A No? Is there some sort of technical limitation?
Jul 31 2014
parent "Chris Cain" <zshazz gmail.com> writes:
On Thursday, 31 July 2014 at 08:36:12 UTC, John Colvin wrote:
 Wait what? Now I'm confused.

 x < y is guaranteed at point B (the assert).

 x and y are unchanged between point A (the enforce) and point B.

 Therefore, x < y is guaranteed at point A
That's not true. If x and y didn't follow x < y, then point B would never execute (enforce would throw an exception and point B would never have executed. So it's entirely possible for x >= y before point A, but never after point A. The enforce shouldn't ever be removed (but the assert technically can be without changing the behavior of the code). The same logic holds for the other way, assert(x < y); enforce(x < y); The enforce is redundant and can be removed there.
Jul 31 2014
prev sibling next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 31 July 2014 at 08:23:44 UTC, Daniel Murphy wrote:
 "Daniel Murphy"  wrote in message 
 news:lrct2d$1me8$1 digitalmars.com...

 Wait, what? I thought the whole point of enforce is that it 
 will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Actually, thinking about this some more... In this program the enforce can be removed assert(x < y); enforce(x < y); But not in this one: enforce(x < y); assert(x < y); because the compiler does need to take control flow into account when applying the information in the assert. In this case the assert does not actually give the compiler any new information.
No, if assert means "I promise that x < y where assert() is called", then "x < y" also holds when "enforce()" is called, because x and y cannot have changed between the two calls.
Jul 31 2014
next sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 31 July 2014 at 10:14:06 UTC, Marc Schütz wrote:
 On Thursday, 31 July 2014 at 08:23:44 UTC, Daniel Murphy wrote:
 "Daniel Murphy"  wrote in message 
 news:lrct2d$1me8$1 digitalmars.com...

 Wait, what? I thought the whole point of enforce is that it 
 will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Actually, thinking about this some more... In this program the enforce can be removed assert(x < y); enforce(x < y); But not in this one: enforce(x < y); assert(x < y); because the compiler does need to take control flow into account when applying the information in the assert. In this case the assert does not actually give the compiler any new information.
No, if assert means "I promise that x < y where assert() is called", then "x < y" also holds when "enforce()" is called, because x and y cannot have changed between the two calls.
Ok, I take that back. http://forum.dlang.org/thread/jrxrmcmeksxwlyuitzqp forum.dlang.org?page=26#post-wzzayaevjsulxyuhlxzh:40forum.dlang.org
Jul 31 2014
prev sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Thursday, 31 July 2014 at 10:14:06 UTC, Marc Schütz wrote:
 On Thursday, 31 July 2014 at 08:23:44 UTC, Daniel Murphy wrote:
 "Daniel Murphy"  wrote in message 
 news:lrct2d$1me8$1 digitalmars.com...

 Wait, what? I thought the whole point of enforce is that it 
 will *not*
 be removed by the compiler, no matter what?
No, the compiler is free to remove it if it can prove it will never be triggered. eg if the condition is checking a ubyte < 1000. If the assert in that example is never false, then the enforce is dead code.
Actually, thinking about this some more... In this program the enforce can be removed assert(x < y); enforce(x < y); But not in this one: enforce(x < y); assert(x < y); because the compiler does need to take control flow into account when applying the information in the assert. In this case the assert does not actually give the compiler any new information.
No, if assert means "I promise that x < y where assert() is called", then "x < y" also holds when "enforce()" is called, because x and y cannot have changed between the two calls.
I think this is the biggest problem with optimizing whilst removing the check. It seems like if you remove the check and assume that the check was true then you get really wonky stuff like checks before the assert being removed. One solution that would still provide some optimization benefits is to make the optimizations as if the check is still their. Meaning that only things after the assert could be optimized based on the contents of the assert. I think that is an extension of what Daniel is saying. The assert optimization needs to take into account control flow, but It needs to take into account its own control flow as well(even if the control flow is not actually inserted). so... enforce(x); assert(x); would not remove the enforce.... because the x would only be known to be true after the assert because of the check in assert, even if the check is not added it would optimize as if it was added.
Jul 31 2014
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/31/2014 1:18 AM, Daniel Murphy wrote:
 In this program the enforce can be removed

 assert(x < y);
 enforce(x < y);

 But not in this one:

 enforce(x < y);
 assert(x < y);

 because the compiler does need to take control flow into account when applying
 the information in the assert.  In this case the assert does not actually give
 the compiler any new information.
http://imgur.com/gallery/hzaJ4Hn
Jul 31 2014
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 30 July 2014 at 19:17:51 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 On Wed, Jul 30, 2014 at 07:09:41PM +0000, via Digitalmars-d 
 wrote:
 On Wednesday, 30 July 2014 at 18:25:43 UTC, H. S. Teoh via 
 Digitalmars-d
 wrote:
If you want the check to always be there, use enforce, not 
assert.
Doesn't help: module a; void bar(int x) { assert(x > 0); writeln("x = ", x); } // -------- module b; import a; void foo(int x) { enforce(x > 0); bar(x); } If `assert` is treated like `assume` (under Ola's definitions), then `enforce` can be optimized away.
Wait, what? I thought the whole point of enforce is that it will *not* be removed by the compiler, no matter what?
Unfortunately not under the current definition of assert :-(
Jul 31 2014
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 11:13 AM, Ary Borenszweig wrote:
 (sorry for the sarcasm, removing assert is wrong to me)
That's why it's optional and up to the developer.
Jul 30 2014
prev sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Wednesday, 30 July 2014 at 18:13:07 UTC, Ary Borenszweig wrote:
 I tried the program in debug mode in thousands of ways and 
 apparently no assert triggers. So I'll just compile in release 
 mode, release it and let anyone find bugs in it and allow to 
 bypass any security or safety I put in my program with those 
 "assert" statmenets, that would probably just take 1 nanosecond 
 to execute anyway.

 Sounds really nice.

 (sorry for the sarcasm, removing assert is wrong to me)
Use enforce...
Jul 30 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 07:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 On 07/30/2014 05:04 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 4:56 AM, Daniel Murphy wrote:
 "Artur Skawina via Digitalmars-d"  wrote in message
 news:mailman.217.1406713015.16021.digitalmars-d puremagic.com...

 `assert` is for *verifying* assumptions. It must not allow them
 to leak/escape. Otherwise a single not-100%-correct assert could
 defeat critical runtime checks.
All you're saying is you want them to have different names, not that it can't work the way Walter and I have described. If your assertions are invalid and you're compiling with -release, the compiler is free to generate invalid code. -release is dangerous. -release is telling the compiler that the code you wrote is correct, and it can rely on it to be correct.
Exactly! -- Andrei
This just moves the issue around and gives another term a non-obvious meaning (the 'release' switch, which is not called e.g. 'unsafeAssumeCorrect'.
Well to me "-release" is "I assume my program is correct, generate the fastest code for it".
 Which is still confusing, because it purports to
 keep memory safety intact in  safe code by not disabling array bounds
 checks by default). This is the very topic of this discussion: some
 people get confused when they are assumed to use standard terms with
 non-standard meanings. I was objecting to the apparent attitude that
 this is entirely the fault of the one who gets confused, or that it is
 symptomatic for lack of understanding of concepts.
I'm not sure what would be the standard misused term in this case.
 I mean, we have at least:

 some terms with whacky meanings for an outsider:
 ...
 'lazy', which denotes pass by name instead of pass by need.
It's not pass by name. ...
How so? Is it about failure to allocate a closure?
 'pure' which denies access to mutable static variables and IO.
That's the consequence of functional purity as defined by D.
Somewhat debatable, but unworthy of debate.
 I see nothing wrong with it.
 ...
Luckily, that wasn't the claim. :)
 ...
I think you got a point there but if you searched any programming language in its pockets you're liable to find a bunch of similar lint. It's the way it goes - there's a need to maximize expressiveness while keeping vocabulary and grammatical constructs low. Few of these items are near the top of my list of issues in D, and I think the same goes for your list. ...
Probably. I never wrote it down in an ordered fashion.
 To me, the apt response to a relative newcomer who gets confused by one
 of those or something like them, especially when used without quotation
 marks, is not at all similar to "You're misunderstanding and misusing
 this feature, stop making noise."
Consider this: after considerable effort you are failing to explain your case for "assume" to the language creators.
I think there was no such case (yet), only an unsuccessful attempt to clear up a misunderstanding based on terminology.
 How do you think you'll fare with newcomers?
 ...
Hopefully, awesomely. Much less preconceptions.
 Andrei
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 11:31 AM, Timon Gehr wrote:
 On 07/30/2014 07:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 'lazy', which denotes pass by name instead of pass by need.
It's not pass by name. ...
How so? Is it about failure to allocate a closure?
void fun(lazy int a) { ... } int x = 42; fun(x + 2); "x + 2" doesn't have a name.
 'pure' which denies access to mutable static variables and IO.
That's the consequence of functional purity as defined by D.
Somewhat debatable, but unworthy of debate.
Then don't mention it.
 Consider this: after considerable effort you are failing to explain your
 case for "assume" to the language creators.
I think there was no such case (yet), only an unsuccessful attempt to clear up a misunderstanding based on terminology.
My perception is you were arguing for a very subtle distinction, one that would hardly deserve a language feature.
 How do you think you'll fare with newcomers?
 ...
Hopefully, awesomely. Much less preconceptions.
May you have less snarky users than I do :o). Andrei
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2014 10:55 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 11:31 AM, Timon Gehr wrote:
 On 07/30/2014 07:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 'lazy', which denotes pass by name instead of pass by need.
It's not pass by name. ...
How so? Is it about failure to allocate a closure?
void fun(lazy int a) { ... } int x = 42; fun(x + 2); "x + 2" doesn't have a name. ...
You might just have been fooled by the name of a concept. http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name
 Consider this: after considerable effort you are failing to explain your
 case for "assume" to the language creators.
I think there was no such case (yet), only an unsuccessful attempt to clear up a misunderstanding based on terminology.
My perception is you were arguing for a very subtle distinction,
My perception is different. Why is this distinction so subtle?
 one that would hardly deserve a language feature.
 ...
version(assert) is a slight generalisation of such a language feature and it is already there. I already noted how the distinction can be implemented approximately in current D, in fact I think this was my first action in this thread. version(assert) assert(...); // assert without effects on -release code generation. This then runs into the 'funny naming' issue etc., but this would be going in circles.
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 3:06 PM, Timon Gehr wrote:
 On 07/30/2014 10:55 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 11:31 AM, Timon Gehr wrote:
 On 07/30/2014 07:56 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 9:31 AM, Timon Gehr wrote:
 'lazy', which denotes pass by name instead of pass by need.
It's not pass by name. ...
How so? Is it about failure to allocate a closure?
void fun(lazy int a) { ... } int x = 42; fun(x + 2); "x + 2" doesn't have a name. ...
You might just have been fooled by the name of a concept. http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name
Oh, yah. I'd forgotten. Mea culpa. Thanks!
 Consider this: after considerable effort you are failing to explain
 your
 case for "assume" to the language creators.
I think there was no such case (yet), only an unsuccessful attempt to clear up a misunderstanding based on terminology.
My perception is you were arguing for a very subtle distinction,
My perception is different. Why is this distinction so subtle?
Because it created a long thread in which there's little agreement.
 one that would hardly deserve a language feature.
 ...
version(assert) is a slight generalisation of such a language feature and it is already there. I already noted how the distinction can be implemented approximately in current D, in fact I think this was my first action in this thread. version(assert) assert(...); // assert without effects on -release code generation.
Maybe this is a misundersanding. version(assert) does not mean "assert is considered here, else it's completely ignored". It means "assert will effect a run-time check". Andrei
Jul 30 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/31/2014 12:17 AM, Andrei Alexandrescu wrote:
 On 7/30/14, 3:06 PM, Timon Gehr wrote:
 On 07/30/2014 10:55 PM, Andrei Alexandrescu wrote:
 On 7/30/14, 11:31 AM, Timon Gehr wrote:
 On 07/30/2014 07:56 PM, Andrei Alexandrescu wrote:
 ...
 case for "assume" to the language creators.
I think there was no such case (yet), only an unsuccessful attempt to clear up a misunderstanding based on terminology.
My perception is you were arguing for a very subtle distinction,
My perception is different. Why is this distinction so subtle?
Because it created a long thread in which there's little agreement. ...
I've seen mostly agreement so far, but mostly not from you and Walter.
 one that would hardly deserve a language feature.
 ...
version(assert) is a slight generalisation of such a language feature and it is already there. I already noted how the distinction can be implemented approximately in current D, in fact I think this was my first action in this thread. version(assert) assert(...); // assert without effects on -release code generation.
Maybe this is a misundersanding.
I don't see how.
 version(assert) does not mean "assert
 is considered here, else it's completely ignored". It means "assert will
 effect a run-time check".
 ...
Indeed. // original source: void main(){ int x=1; version(assert) assert(x==0); // ... } // after some lowering without the -release switch: void main(){ int x=1; assert(x==0); // version statement active, // check will be performed (and fail) // ... } // after some lowering with the -release switch: void main(){ int x=1; // version statement inactive, no check will be performed, // optimizer never sees the assertion // ... } I.e. no wrong assumptions are passed down to the optimizer under any circumstances if the assertion is guarded with version(assert).
Jul 30 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/30/14, 3:42 PM, Timon Gehr wrote:
 I've seen mostly agreement so far, but mostly not from you and Walter.
That's probably natural and healthy: contributors are trigger-happy about adding new and clever features, and Walter and I are conservative for good balance. I propose we all tone it down a notch. It's good to discuss potential features; conversely it's not as good to transgress in a scoring-points contest where everybody tries to out-sarcasm the previous one and have the last word. Far as I can understand yes, there is distinction between "assert" and "assume". I don't find it as material as it would need to be to make "assume" a language feature. We can refine assert's definition to reach a good compromise advantageous for all, which would be the best outcome of this discussion. I don't meant this as definitive or even prescriptive; I've been plenty wrong before. But I think everyone is in agreement that good discussion is that that pushes the state of D forward. Let's all focus on that. Thanks, Andrei
Jul 30 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 Far as I can understand yes, there is distinction between 
 "assert" and "assume". I don't find it as material as it would 
 need to be to make "assume" a language feature.
I didn't ask for an assume() in this thread. I have suggested/discussed/asked the inclusion in D of means to allow library writers to create a struct type like a SafeInt (that inside calls intrinsic functions like muls()) that manages the values range about as well as built-in types like int. I have asked this to allow optimizations typical of built-ins with library-defined types too (in particular to replace the call to muls with a regular faster multiplication). Bye, bearophile
Jul 30 2014
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/30/2014 4:56 AM, Daniel Murphy wrote:
 If your assertions are invalid and
 you're compiling with -release, the compiler is free to generate invalid code.
 -release is dangerous.  -release is telling the compiler that the code you
wrote
 is correct,  and it can rely on it to be correct.
Yes.
Jul 31 2014
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Ola Fosheim Grøstad" " wrote in message 
news:jikanohklijgfyczizmv forum.dlang.org...

 The problem is that the code is not unreachable when you compile 
 with -release.
Whether or not this is a problem depends on the meaning of assert.
 Assert says 'the program is in error if this is not true'.
enforce() says: always runtime check this (?) assert() says: this ought to hold when I do testing assume() says: I have proven this to hold prove() says: don't generate code until you can prove this to hold
This might be how you use assert, but it is not the only possible semantics we could define.
 -release says 'compile my program as if it has no errors'.
-release says: compile my program without runtime checks for correctness -no-assume might say: ignore all assumptions, I don't trust myself -assume-is-assert(): turn assumptions into runtime checks etc.
Same thing. Yes, disabling assertion checking is currently what -release does, but that doesn't mean it's the only thing it can do. What I'm proposing is a hybrid of your definitions - in release mode assert becomes assume.
 Yes, if used carefully, but the language and/or compiler have to treat 
 user provided facts differently than derived knowledge that originates 
 within the executable code. assert() is not really for providing facts, it 
 is for testing them. So the threshold for providing an assertion is low if 
 it is completely free of side effects (in release), but the threshold for 
 providing an assumption should be very high.
I'm not convinced they must be treated differently. If you define assert and release the way I have above it is perfectly valid. You've argued that it's the wrong way to do things, but all that matters is that the advantages outweigh the downsides. The optimization possibilities here are enormous. According to the spec on 'assert(0)': "The optimization and code generation phases of compilation may assume that it is unreachable code.". So we already have this in the language somewhat - you just need to write it like this: if (condition) assert(0); instead of: assert(condition); It seems like a straightforward extension to make them equivalent for this purpose.
Jul 28 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Daniel Murphy:

 One murky area is that assert(0) is currently used to mean both 
 'unreachable' and 'unimplemented'.  It's unclear what the 
 compiler is allowed to do with an assert(0) in release mode.
I'd still like to have a halt() in D, and have assert(0) with the same semantics of the other asserts. In many cases when you have a different feature it's good to also give it a different name. Bye, bearophile
Jul 28 2014
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"bearophile"  wrote in message news:tijfjtihtubozpjojgvl forum.dlang.org...

 I'd still like to have a halt() in D, and have assert(0) with the same 
 semantics of the other asserts. In many cases when you have a different 
 feature it's good to also give it a different name.
Yes, me too. The compiler could then still insert halt in place of assert(0), but it wouldn't be forced to treat them as a halt in release mode. It may be too late to change assert's behaviour.
Jul 28 2014
prev sibling next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"bearophile"  wrote in message news:tijfjtihtubozpjojgvl forum.dlang.org...

 One murky area is that assert(0) is currently used to mean both 
 'unreachable' and 'unimplemented'.  It's unclear what the compiler is 
 allowed to do with an assert(0) in release mode.
I'd still like to have a halt() in D, and have assert(0) with the same semantics of the other asserts. In many cases when you have a different feature it's good to also give it a different name.
Turns out it's not so murky according to the spec: The expression assert(0) is a special case; it signifies that it is unreachable code. Either AssertError is thrown at runtime if it is reachable, or the execution is halted (on the x86 processor, a HLT instruction can be used to halt execution). The optimization and code generation phases of compilation may assume that it is unreachable code. I'm quite happy to accept that using assert(0) as halt can only be relied on in non-release mode.
Jul 28 2014
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/28/2014 8:53 AM, bearophile wrote:
 Daniel Murphy:

 One murky area is that assert(0) is currently used to mean both 'unreachable'
 and 'unimplemented'.  It's unclear what the compiler is allowed to do with an
 assert(0) in release mode.
I'd still like to have a halt() in D, and have assert(0) with the same semantics of the other asserts. In many cases when you have a different feature it's good to also give it a different name.
The marginal utility of all these proposals is pretty much zero. assert(0) serves just fine.
Jul 28 2014