On 3/18/11 11:07 AM, Steven Schveighoffer wrote:
On Fri, 18 Mar 2011 11:35:22 -0400, spir <denis.s...@gmail.com> wrote:
On 03/18/2011 01:37 PM, Steven Schveighoffer wrote:
This is a good example of why it's difficult to decide what "user
input" is.
One could consider that the 'user' in this case is the developer
using the
library, but I don't think that's the right choice.
I'd say it's a bug, this is clearly a contract, since the data being
passed
into the ctor can easily not be user input (i.e. it's most likely two
literals
that will never depend on a user). If it is user input, the caller of
the ctor
should enforce the user input before passing it to iota.
This is indeed a difficult topic. I'm a bit bluffed when reading
people confidently asserting apparently clear positions about the use
of enforce vs assert vs contracts and such, or whether such checks
should or not stay or not in various distribution builds (mainly
-release).
I can see at least 5 cases, and am far to be sure what the proper tool
is in every case, and in which builds it should stay. In each case,
there is potential "wrong" input; but note the variety of cases does
seems orthogonal (lol) to what kind of harm it may cause:
* colleague: my code is called by code from the same app (same dev
team); typically, wrong input logically "cannot" happen
* friend: my code is called by code designed to cooperate with it;
there is a kind of moral contract
In both cases, wrong input reveals a bug; but in the first case, it's
my own (team's) bug. I guess, but am not sure, these cases are good
candidates for asserts (or contracts?), excluded from release build.
* lib call: my code is a typical lib; thus, I have zero control on
caller.
I would let the check in release mode, thus use enforce. Or, use
assert if it remains when the *caller* is compiled in debug mode.
There is something unclear here, I guess. Maybe there are two sub-cases:
~ the caller logically should be able to prove its args correct
~ or not
See, this is where I feel we have issues. The clear problem with
*always* checking is the iota example. One may use iota like this:
foreach(i; iota(0, 5))
Why should checks in iota remain for iota to prove that 0 is less than
5? It always will be less than 5, and the check is not necessary.
[snip]
This is the kind of job that the compiler could and should do. Whether
it's assert and enforce, an inlining pass followed by value range
propagation should simply eliminate the unnecessary tests.
Andrei