www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Confusion over enforce and assert - both are compiled out in release

reply Andrew Chapman <nycran gmail.com> writes:
In the docs regarding contract programming and the use of enforce 
/ assert:
https://dlang.org/library/std/exception/enforce.html

it says:

"enforce is used to throw exceptions and is therefore intended to 
aid in error handling. It is not intended for verifying the logic 
of your program. That is what assert is for. Also, do not use 
enforce inside of contracts (i.e. inside of in and out blocks and 
invariants), because they will be compiled out when compiling 
with -release. Use assert in contracts."

However, I am finding that BOTH enforce and assert are compiled 
out by dmd and ldc in release mode.  Is there a standard way of 
doing what enforce does inside an "in" contract block that will 
work in release mode?

I'm guessing I should write my own function for now.
Aug 27
parent reply ag0aep6g <anonymous example.com> writes:
On 08/27/2017 12:02 PM, Andrew Chapman wrote:
 However, I am finding that BOTH enforce and assert are compiled out by 
 dmd and ldc in release mode.  Is there a standard way of doing what 
 enforce does inside an "in" contract block that will work in release mode?
 
 I'm guessing I should write my own function for now.
The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled.
Aug 27
parent reply Andrew Chapman <nycran gmail.com> writes:
On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote:
 On 08/27/2017 12:02 PM, Andrew Chapman wrote:
 However, I am finding that BOTH enforce and assert are 
 compiled out by dmd and ldc in release mode.  Is there a 
 standard way of doing what enforce does inside an "in" 
 contract block that will work in release mode?
 
 I'm guessing I should write my own function for now.
The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled.
Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful.
Aug 27
next sibling parent Dukc <ajieskola gmail.com> writes:
On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote:
 On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote:
 On 08/27/2017 12:02 PM, Andrew Chapman wrote:
 However, I am finding that BOTH enforce and assert are 
 compiled out by dmd and ldc in release mode.  Is there a 
 standard way of doing what enforce does inside an "in" 
 contract block that will work in release mode?
 
 I'm guessing I should write my own function for now.
The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled.
Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful.
I actually think even better would be if they acted like array bounds checking -always there by default, in release mode done is safe code but not in system. And for none if bounds checking is disabled. That would let users implement custom bounds checking types. Asserts would still be always if in release version, bounds checking would be done by if ... throw.
Aug 27
prev sibling parent reply Moritz Maxeiner <moritz ucworks.org> writes:
On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote:
 On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote:
 On 08/27/2017 12:02 PM, Andrew Chapman wrote:
 However, I am finding that BOTH enforce and assert are 
 compiled out by dmd and ldc in release mode.  Is there a 
 standard way of doing what enforce does inside an "in" 
 contract block that will work in release mode?
 
 I'm guessing I should write my own function for now.
The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled.
Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful.
If you need that, you could compile using ldc in release mode (which you probably want to do anyway): --- test.d --- import std.exception; import std.stdio; void foo(int x) in { enforce(x > 0); } body { } void bar(int x) in { assert(x > 0); } body { } void baz(int x) in { if (!(x > 0)) assert(0); } body { } void main() { (-1).foo.assertThrown; (-1).bar; (-1).baz; } -------------- $ ldc2 test.d -> failed assert in bar's in contract terminates the program $ ldc2 -release test.d -> failed assertThrown in main terminates the program $ ldc2 -release -enable-contracts test.d -> failed assert in baz's in contract terminates the program $ ldc2 -release -enable-contracts -enable-asserts test.d -> failed assert in bar's in contract terminates the program
Aug 27
parent reply Andrew Chapman <nycran gmail.com> writes:
On Sunday, 27 August 2017 at 10:37:50 UTC, Moritz Maxeiner wrote:
 On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote:
 On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote:
 [...]
Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful.
If you need that, you could compile using ldc in release mode (which you probably want to do anyway): --- test.d --- import std.exception; import std.stdio; void foo(int x) in { enforce(x > 0); } body { } void bar(int x) in { assert(x > 0); } body { } void baz(int x) in { if (!(x > 0)) assert(0); } body { } void main() { (-1).foo.assertThrown; (-1).bar; (-1).baz; } -------------- $ ldc2 test.d -> failed assert in bar's in contract terminates the program $ ldc2 -release test.d -> failed assertThrown in main terminates the program $ ldc2 -release -enable-contracts test.d -> failed assert in baz's in contract terminates the program $ ldc2 -release -enable-contracts -enable-asserts test.d -> failed assert in bar's in contract terminates the program
Oh interesting. Does DUB support passing through the --enable-contracts flag to ldc? Also, if this is an ldc specific thing it's probably not a good idea i'd imagine, since in the future one may want to use a GDC, or DMD?
Aug 27
next sibling parent Moritz Maxeiner <moritz ucworks.org> writes:
On Sunday, 27 August 2017 at 10:46:53 UTC, Andrew Chapman wrote:
 On Sunday, 27 August 2017 at 10:37:50 UTC, Moritz Maxeiner 
 wrote:
 [...]
Oh interesting. Does DUB support passing through the --enable-contracts flag to ldc?
Sure, using platform specific build settings [1] such as `"dflags-ldc": ["--enable-contracts"]`.
 Also, if this is an ldc specific thing it's probably not a good 
 idea i'd imagine, since in the future one may want to use a 
 GDC, or DMD?
If you want to use another compiler that supports it, add the appropriate "dflags-COMPILER" setting to your package file. With regards to dmd: Don't use it for release builds, use gdc or ldc (better optimizations). https://code.dlang.org/package-format?lang=json#build-settings
Aug 27
prev sibling parent Moritz Maxeiner <moritz ucworks.org> writes:
On Sunday, 27 August 2017 at 10:46:53 UTC, Andrew Chapman wrote:
 [...]

 Oh interesting.  Does DUB support passing through the 
 --enable-contracts flag to ldc?  Also, if this is an ldc 
 specific thing it's probably not a good idea i'd imagine, since 
 in the future one may want to use a GDC, or DMD?
Also, with regards to gdc, its release mode `-frelease` option is explicitly specified in the manual as being shorthand for a specific set of options:
 This is equivalent to compiling with the following options:

 gdc -fno-assert -fbounds-check=safe -fno-invariants \
     -fno-postconditions -fno-preconditions -fno-switch-errors
As it doesn't seem to turn on/off any other options / optimizations, you can use `"dflags-gdc": [...]` to specify your own set of "release" options without losing anything. In particular, I would overwrite dub's default "release" build type [1] and add your own per compiler build settings, so dub won't pass `-frelease` to gdc when using `dub --build=release`. [1] https://code.dlang.org/package-format?lang=json#build-types
Aug 27