Safety/purity and assert/enforce error messages

Jonathan M Davis jmdavisProg at gmx.com
Thu Sep 12 13:28:54 PDT 2013


On Thursday, September 12, 2013 13:21:26 H. S. Teoh wrote:
> On Thu, Sep 12, 2013 at 04:07:24PM -0400, Jonathan M Davis wrote:
> > On Thursday, September 12, 2013 12:42:34 H. S. Teoh wrote:
> > > On Thu, Sep 12, 2013 at 09:12:18PM +0200, bearophile wrote:
> > > > H. S. Teoh:
> > > > >In phobos git HEAD, std.format has been made pure @safe nothrow
> > > > >(and CTFE-able), so you should be able to write your assert as:
> > > > >assert(condition, format("x = %s, blahblah", x));
> > > > 
> > > > With the latest DMD from updated GIT head:
> > > > 
> > > > 
> > > > import std.string: format;
> > > > void main() pure nothrow {
> > > > 
> > > > string x = "hello";
> > > > bool condition = true;
> > > > assert(condition, format("x = %s, blahblah", x));
> > > > 
> > > > }
> > > > 
> > > > 
> > > > It gives:
> > > > 
> > > > test.d(5): Error: 'std.string.format!(char, string).format' is not
> > > > nothrow
> > > > test.d(2): Error: function 'D main' is nothrow yet may throw
> > > 
> > > [...]
> > > 
> > > Oops. Apparently I wrote nothrow but forgot to test it. I did test
> > > pure and @safe, though, so at least those two should work.
> > 
> > format can't be nothrow, because it throws when you screw up the
> > format specifiers. You have to wrap it in a try-catch block and
> > assert(0) in the catch block if you want to put it in a nothrow
> > function. std.datetime does this in at least a few places.
> 
> [...]
> 
> Right. Makes me wanna suggest adding this template to std.exception:
> 
> auto assumeWontThrow(alias fun, T...)(T args) nothrow {
> try {
> return fun(args);
> } catch(Exception) {
> // You broke your promise, I die.
> assert(0);
> }
> }
> 
> Then you can write things like:
> 
> int mayThrow(int arg) {
> if (arg < 0) throw new Exception(...);
> return BBN(arg);
> }
> 
> int iWontThrow() nothrow { // <-- N.B. this function is nothrow
> static assert(123 > 0);
> return assumeWontThrow!mayThrow(123);
> }

Sounds like a good suggestion, though an actual implementation should have an 
error message in the assert(0). You could also implement it as a lazy 
parameter like enforce and assertNotThrown do (which I think is more user-
friendly), but that would likely be less efficient due to how lazy doesn't get 
optimized very well (or at least, it's my understanding that it doesn't).

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list